feat(coding-agent): merge origin/main into model runtime facade

This commit is contained in:
Mario Zechner
2026-07-15 12:25:36 +02:00
119 changed files with 4275 additions and 631 deletions
@@ -78,6 +78,7 @@ const RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS = [
"app.tools.expand",
"app.thinking.toggle",
"app.editor.external",
"app.message.copy",
"app.message.followUp",
"tui.input.submit",
"tui.select.confirm",
@@ -627,6 +628,11 @@ export class ExtensionRunner {
this.shutdownHandler();
}
getActiveTools(): string[] {
this.assertActive();
return this.runtime.getActiveTools();
}
/**
* Create an ExtensionContext for use in event handlers and tool execution.
* Context values are resolved at call time, so changes via bindCore/bindUI are reflected.
@@ -1432,6 +1432,8 @@ export interface ProviderConfig {
refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials>;
/** Convert credentials to API key string for the provider. */
getApiKey(credentials: OAuthCredentials): string;
/** Legacy synchronous credential-dependent model projection. */
modifyModels?(models: Model<Api>[], credentials: OAuthCredentials): Model<Api>[];
};
}
@@ -6,7 +6,7 @@
*/
import type { AgentTool } from "@earendil-works/pi-agent-core";
import { wrapToolDefinition, wrapToolDefinitions } from "../tools/tool-definition-wrapper.ts";
import { wrapToolDefinition } from "../tools/tool-definition-wrapper.ts";
import type { ExtensionRunner } from "./runner.ts";
import type { RegisteredTool } from "./types.ts";
@@ -15,7 +15,25 @@ import type { RegisteredTool } from "./types.ts";
* Uses the runner's createContext() for consistent context across tools and event handlers.
*/
export function wrapRegisteredTool(registeredTool: RegisteredTool, runner: ExtensionRunner): AgentTool {
return wrapToolDefinition(registeredTool.definition, () => runner.createContext());
const tool = wrapToolDefinition(registeredTool.definition, () => runner.createContext());
const execute = tool.execute;
return {
...tool,
execute: async (toolCallId, params, signal, onUpdate) => {
const activeBefore = runner.getActiveTools();
const result = await execute(toolCallId, params, signal, onUpdate);
const activeAfter = runner.getActiveTools();
if (!activeBefore.every((name) => activeAfter.includes(name))) return result;
const beforeNames = new Set(activeBefore);
const addedToolNames = activeAfter.filter((name) => !beforeNames.has(name));
if (addedToolNames.length === 0) return result;
return {
...result,
addedToolNames: [...new Set([...(result.addedToolNames ?? []), ...addedToolNames])],
};
},
};
}
/**
@@ -23,8 +41,5 @@ export function wrapRegisteredTool(registeredTool: RegisteredTool, runner: Exten
* Uses the runner's createContext() for consistent context across tools and event handlers.
*/
export function wrapRegisteredTools(registeredTools: RegisteredTool[], runner: ExtensionRunner): AgentTool[] {
return wrapToolDefinitions(
registeredTools.map((registeredTool) => registeredTool.definition),
() => runner.createContext(),
);
return registeredTools.map((tool) => wrapRegisteredTool(tool, runner));
}