diff --git a/packages/ai/AGENTS.md b/packages/ai/AGENTS.md index 95963a2b597..e748a168d71 100644 --- a/packages/ai/AGENTS.md +++ b/packages/ai/AGENTS.md @@ -213,7 +213,7 @@ Errors must be expressed as `ToolFailure`. The runtime catches it and emits a `t - Input failed the `parameters` Schema. - The handler returned a `ToolFailure`. -Provider-defined / hosted tools (Anthropic `web_search` / `code_execution` / `web_fetch`, OpenAI Responses `web_search_call` / `file_search_call` / `code_interpreter_call` / `mcp_call` / `local_shell_call` / `image_generation_call` / `computer_use_call`) pass through the runtime untouched: +Provider-defined / hosted tools (Anthropic `web_search` / `code_execution` / `web_fetch`, OpenAI Responses `web_search_call` / `file_search_call` / `code_interpreter_call` / `mcp_call` / `image_generation_call` / `computer_use_call`) pass through the runtime untouched: - Routes surface the model's call as a `tool-call` event with `providerExecuted: true`, and the provider's result as a matching `tool-result` event with `providerExecuted: true`. - Callers detect `providerExecuted` on `tool-call` and **skip local dispatch** — no handler is invoked and no `tool-error` is raised for "unknown tool". The provider already executed it. diff --git a/packages/ai/src/protocols/openai-responses.ts b/packages/ai/src/protocols/openai-responses.ts index 704b5d99375..0f381a29b9d 100644 --- a/packages/ai/src/protocols/openai-responses.ts +++ b/packages/ai/src/protocols/openai-responses.ts @@ -140,7 +140,6 @@ const HOSTED_TOOLS = { name: "mcp", input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }), }, - local_shell_call: { name: "local_shell", input: (item) => item.action ?? {} }, } as const satisfies ResponsesHostedTools.Definitions const step = (state: OpenResponses.ParserState, event: OpenResponses.Event) => { diff --git a/packages/core/src/github-copilot/responses/convert-to-openai-responses-input.ts b/packages/core/src/github-copilot/responses/convert-to-openai-responses-input.ts index bc8e3c65176..ae8f134af51 100644 --- a/packages/core/src/github-copilot/responses/convert-to-openai-responses-input.ts +++ b/packages/core/src/github-copilot/responses/convert-to-openai-responses-input.ts @@ -7,7 +7,6 @@ import { import { convertToBase64, parseProviderOptions } from "@ai-sdk/provider-utils" import { z } from "zod/v4" import type { OpenAIResponsesInput, OpenAIResponsesReasoning } from "./openai-responses-api-types.js" -import { localShellInputSchema, localShellOutputSchema } from "./tool/local-shell.js" /** * Check if a string is a file ID based on the given prefixes @@ -23,13 +22,11 @@ export async function convertToOpenAIResponsesInput({ systemMessageMode, fileIdPrefixes, store, - hasLocalShellTool = false, }: { prompt: LanguageModelV3Prompt systemMessageMode: "system" | "developer" | "remove" fileIdPrefixes?: readonly string[] store: boolean - hasLocalShellTool?: boolean }): Promise<{ input: OpenAIResponsesInput warnings: Array @@ -138,25 +135,6 @@ export async function convertToOpenAIResponsesInput({ break } - if (hasLocalShellTool && part.toolName === "local_shell") { - const parsedInput = localShellInputSchema.parse(part.input) - input.push({ - type: "local_shell_call", - call_id: part.toolCallId, - id: store ? ((part.providerOptions?.copilot?.itemId as string) ?? undefined) : undefined, - action: { - type: "exec", - command: parsedInput.action.command, - timeout_ms: parsedInput.action.timeoutMs, - user: parsedInput.action.user, - working_directory: parsedInput.action.workingDirectory, - env: parsedInput.action.env, - }, - }) - - break - } - input.push({ type: "function_call", call_id: part.toolCallId, @@ -261,15 +239,6 @@ export async function convertToOpenAIResponsesInput({ } } - if (hasLocalShellTool && part.toolName === "local_shell" && output.type === "json") { - input.push({ - type: "local_shell_call_output", - call_id: part.toolCallId, - output: localShellOutputSchema.parse(output.value).output, - }) - break - } - let contentValue: string switch (output.type) { case "text": diff --git a/packages/core/src/github-copilot/responses/openai-responses-api-types.ts b/packages/core/src/github-copilot/responses/openai-responses-api-types.ts index 5124f9ead99..4aee247bd1b 100644 --- a/packages/core/src/github-copilot/responses/openai-responses-api-types.ts +++ b/packages/core/src/github-copilot/responses/openai-responses-api-types.ts @@ -9,8 +9,6 @@ export type OpenAIResponsesInputItem = | OpenAIResponsesFunctionCall | OpenAIResponsesFunctionCallOutput | OpenAIResponsesComputerCall - | OpenAIResponsesLocalShellCall - | OpenAIResponsesLocalShellCallOutput | OpenAIResponsesReasoning | OpenAIResponsesItemReference | OpenAIResponsesMcpApprovalResponse @@ -69,26 +67,6 @@ export type OpenAIResponsesComputerCall = { status?: string } -export type OpenAIResponsesLocalShellCall = { - type: "local_shell_call" - id?: string - call_id: string - action: { - type: "exec" - command: string[] - timeout_ms?: number - user?: string - working_directory?: string - env?: Record - } -} - -export type OpenAIResponsesLocalShellCallOutput = { - type: "local_shell_call_output" - call_id: string - output: string -} - export type OpenAIResponsesItemReference = { type: "item_reference" id: string @@ -199,9 +177,6 @@ export type OpenAIResponsesTool = quality: "auto" | "low" | "medium" | "high" | undefined size: "auto" | "1024x1024" | "1024x1536" | "1536x1024" | undefined } - | { - type: "local_shell" - } export type OpenAIResponsesReasoning = { type: "reasoning" diff --git a/packages/core/src/github-copilot/responses/openai-responses-language-model.ts b/packages/core/src/github-copilot/responses/openai-responses-language-model.ts index 11d05820bc0..e306a716506 100644 --- a/packages/core/src/github-copilot/responses/openai-responses-language-model.ts +++ b/packages/core/src/github-copilot/responses/openai-responses-language-model.ts @@ -29,7 +29,6 @@ import { mapOpenAIResponseFinishReason } from "./map-openai-responses-finish-rea import type { OpenAIResponsesIncludeOptions, OpenAIResponsesIncludeValue } from "./openai-responses-api-types.js" import { prepareResponsesTools } from "./openai-responses-prepare-tools.js" import type { OpenAIResponsesModelId } from "./openai-responses-settings.js" -import { localShellInputSchema } from "./tool/local-shell.js" const webSearchCallItem = z.object({ type: z.literal("web_search_call"), @@ -86,20 +85,6 @@ const codeInterpreterCallItem = z.object({ .nullable(), }) -const localShellCallItem = z.object({ - type: z.literal("local_shell_call"), - id: z.string(), - call_id: z.string(), - action: z.object({ - type: z.literal("exec"), - command: z.array(z.string()), - timeout_ms: z.number().optional(), - user: z.string().optional(), - working_directory: z.string().optional(), - env: z.record(z.string(), z.string()).optional(), - }), -}) - const imageGenerationCallItem = z.object({ type: z.literal("image_generation_call"), id: z.string(), @@ -205,7 +190,6 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 { systemMessageMode: modelConfig.systemMessageMode, fileIdPrefixes: this.config.fileIdPrefixes, store, - hasLocalShellTool: hasOpenAITool("openai.local_shell"), }) warnings.push(...inputWarnings) @@ -462,7 +446,6 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 { fileSearchCallItem, codeInterpreterCallItem, imageGenerationCallItem, - localShellCallItem, z.object({ type: z.literal("function_call"), call_id: z.string(), @@ -560,22 +543,6 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 { break } - case "local_shell_call": { - content.push({ - type: "tool-call", - toolCallId: part.call_id, - toolName: "local_shell", - input: JSON.stringify({ action: part.action } satisfies z.infer), - providerMetadata: { - copilot: { - itemId: part.id, - }, - }, - }) - - break - } - case "message": { for (const contentPart of part.content) { if (options.providerOptions?.copilot?.logprobs && contentPart.logprobs) { @@ -1093,27 +1060,6 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 { result: value.item.result, } satisfies z.infer, }) - } else if (value.item.type === "local_shell_call") { - ongoingToolCalls[value.output_index] = undefined - - controller.enqueue({ - type: "tool-call", - toolCallId: value.item.call_id, - toolName: "local_shell", - input: JSON.stringify({ - action: { - type: "exec", - command: value.item.action.command, - timeoutMs: value.item.action.timeout_ms, - user: value.item.action.user, - workingDirectory: value.item.action.working_directory, - env: value.item.action.env, - }, - } satisfies z.infer), - providerMetadata: { - copilot: { itemId: value.item.id }, - }, - }) } else if (value.item.type === "message") { if (currentTextId) { controller.enqueue({ @@ -1528,7 +1474,6 @@ const responseOutputItemDoneSchema = z.object({ imageGenerationCallItem, webSearchCallItem, fileSearchCallItem, - localShellCallItem, z.object({ type: z.literal("computer_call"), id: z.string(), diff --git a/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts b/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts index 0ed1ea6b32d..2592636dded 100644 --- a/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts +++ b/packages/core/src/github-copilot/responses/openai-responses-prepare-tools.ts @@ -70,12 +70,6 @@ export function prepareResponsesTools({ break } - case "openai.local_shell": { - openaiTools.push({ - type: "local_shell", - }) - break - } case "openai.web_search_preview": { const args = webSearchPreviewArgsSchema.parse(tool.args) openaiTools.push({ diff --git a/packages/core/src/github-copilot/responses/tool/local-shell.ts b/packages/core/src/github-copilot/responses/tool/local-shell.ts deleted file mode 100644 index 683dd5984f5..00000000000 --- a/packages/core/src/github-copilot/responses/tool/local-shell.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { z } from "zod/v4" - -export const localShellInputSchema = z.object({ - action: z.object({ - type: z.literal("exec"), - command: z.array(z.string()), - timeoutMs: z.number().optional(), - user: z.string().optional(), - workingDirectory: z.string().optional(), - env: z.record(z.string(), z.string()).optional(), - }), -}) - -export const localShellOutputSchema = z.object({ - output: z.string(), -})