@bolt-foundry/gambit 0.8.6 → 1.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +54 -2
  2. package/README.md +165 -50
  3. package/esm/mod.d.ts +11 -3
  4. package/esm/mod.d.ts.map +1 -1
  5. package/esm/mod.js +7 -1
  6. package/esm/src/codex_app_server_debug.d.ts +1 -1
  7. package/esm/src/codex_app_server_debug.d.ts.map +1 -1
  8. package/esm/src/codex_app_server_debug.js +1 -1
  9. package/esm/src/codex_auth.d.ts +1 -1
  10. package/esm/src/codex_auth.d.ts.map +1 -1
  11. package/esm/src/codex_auth.js +1 -1
  12. package/esm/src/default_runtime.d.ts +5 -1
  13. package/esm/src/default_runtime.d.ts.map +1 -1
  14. package/esm/src/default_runtime.js +48 -29
  15. package/esm/src/openai_compat.d.ts.map +1 -1
  16. package/esm/src/openai_compat.js +111 -11
  17. package/esm/src/providers/claude_code.d.ts.map +1 -1
  18. package/esm/src/providers/claude_code.js +3 -3
  19. package/esm/src/providers/codex.d.ts +12 -1
  20. package/esm/src/providers/codex.d.ts.map +1 -1
  21. package/esm/src/providers/codex.js +94 -30
  22. package/esm/src/providers/google.d.ts.map +1 -1
  23. package/esm/src/providers/google.js +7 -114
  24. package/esm/src/providers/manifest.d.ts +2 -2
  25. package/esm/src/providers/manifest.d.ts.map +1 -1
  26. package/esm/src/providers/manifest.js +5 -5
  27. package/esm/src/providers/ollama.d.ts.map +1 -1
  28. package/esm/src/providers/ollama.js +0 -112
  29. package/esm/src/providers/openrouter.d.ts.map +1 -1
  30. package/esm/src/providers/openrouter.js +0 -264
  31. package/esm/src/providers/requirements.js +1 -1
  32. package/package.json +1 -1
  33. package/script/mod.d.ts +11 -3
  34. package/script/mod.d.ts.map +1 -1
  35. package/script/mod.js +15 -6
  36. package/script/src/codex_app_server_debug.d.ts +1 -1
  37. package/script/src/codex_app_server_debug.d.ts.map +1 -1
  38. package/script/src/codex_app_server_debug.js +1 -1
  39. package/script/src/codex_auth.d.ts +1 -1
  40. package/script/src/codex_auth.d.ts.map +1 -1
  41. package/script/src/codex_auth.js +1 -1
  42. package/script/src/default_runtime.d.ts +5 -1
  43. package/script/src/default_runtime.d.ts.map +1 -1
  44. package/script/src/default_runtime.js +48 -28
  45. package/script/src/openai_compat.d.ts.map +1 -1
  46. package/script/src/openai_compat.js +110 -10
  47. package/script/src/providers/claude_code.d.ts.map +1 -1
  48. package/script/src/providers/claude_code.js +3 -3
  49. package/script/src/providers/codex.d.ts +12 -1
  50. package/script/src/providers/codex.d.ts.map +1 -1
  51. package/script/src/providers/codex.js +94 -29
  52. package/script/src/providers/google.d.ts.map +1 -1
  53. package/script/src/providers/google.js +7 -114
  54. package/script/src/providers/manifest.d.ts +2 -2
  55. package/script/src/providers/manifest.d.ts.map +1 -1
  56. package/script/src/providers/manifest.js +5 -5
  57. package/script/src/providers/ollama.d.ts.map +1 -1
  58. package/script/src/providers/ollama.js +0 -112
  59. package/script/src/providers/openrouter.d.ts.map +1 -1
  60. package/script/src/providers/openrouter.js +0 -264
  61. package/script/src/providers/requirements.js +1 -1
@@ -50,9 +50,9 @@ function normalizeContent(content) {
50
50
  return content;
51
51
  if (!Array.isArray(content))
52
52
  return String(content);
53
- return content
53
+ return (0, gambit_core_1.joinTextParts)(content
54
54
  .map((c) => (typeof c === "string" ? c : (c.text ?? "")))
55
- .join("");
55
+ .filter(Boolean));
56
56
  }
57
57
  function normalizeMessages(input) {
58
58
  return input.map((m) => ({
@@ -65,6 +65,88 @@ function normalizeMessages(input) {
65
65
  : undefined,
66
66
  }));
67
67
  }
68
+ function responseItemsFromMessages(messages) {
69
+ return messages.flatMap((message) => {
70
+ if (message.role === "tool") {
71
+ return [{
72
+ type: "function_call_output",
73
+ call_id: message.tool_call_id ?? randomId("tool"),
74
+ output: message.content ?? "",
75
+ }];
76
+ }
77
+ const items = [];
78
+ if (message.content) {
79
+ items.push({
80
+ type: "message",
81
+ role: message.role,
82
+ content: [{
83
+ type: message.role === "assistant" ? "output_text" : "input_text",
84
+ text: message.content,
85
+ }],
86
+ });
87
+ }
88
+ if (message.role === "assistant" && message.tool_calls?.length) {
89
+ for (const toolCall of message.tool_calls) {
90
+ items.push({
91
+ type: "function_call",
92
+ call_id: toolCall.id,
93
+ name: toolCall.function.name,
94
+ arguments: toolCall.function.arguments,
95
+ });
96
+ }
97
+ }
98
+ if (items.length)
99
+ return items;
100
+ return {
101
+ type: "message",
102
+ role: message.role,
103
+ content: [],
104
+ };
105
+ });
106
+ }
107
+ function responseOutputToChatResult(output) {
108
+ const textParts = [];
109
+ const toolCalls = [];
110
+ for (const item of output) {
111
+ if (item.type === "message" && item.role === "assistant") {
112
+ for (const part of item.content) {
113
+ if (part.type === "output_text" || part.type === "summary_text" ||
114
+ part.type === "reasoning_text") {
115
+ textParts.push(part.text);
116
+ }
117
+ }
118
+ }
119
+ if (item.type === "function_call") {
120
+ let args = {};
121
+ try {
122
+ const parsed = JSON.parse(item.arguments || "{}");
123
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
124
+ args = parsed;
125
+ }
126
+ }
127
+ catch {
128
+ args = {};
129
+ }
130
+ toolCalls.push({ id: item.call_id, name: item.name, args });
131
+ }
132
+ }
133
+ const message = {
134
+ role: "assistant",
135
+ content: textParts.length ? (0, gambit_core_1.joinTextParts)(textParts) : null,
136
+ tool_calls: toolCalls.length
137
+ ? toolCalls.map((call) => ({
138
+ id: call.id,
139
+ type: "function",
140
+ function: { name: call.name, arguments: JSON.stringify(call.args) },
141
+ }))
142
+ : undefined,
143
+ };
144
+ return {
145
+ message,
146
+ finishReason: toolCalls.length ? "tool_calls" : "stop",
147
+ toolCalls: toolCalls.length ? toolCalls : undefined,
148
+ };
149
+ }
68
150
  function providerParamsFromRequest(req) {
69
151
  const out = {};
70
152
  if (req.temperature !== undefined)
@@ -168,6 +250,14 @@ function warnIfSystemMismatch(args) {
168
250
  exports.logger.warn(`[gambit] chatCompletionsWithDeck: request includes a system message that does not match the deck prompt (${args.deckPath})`);
169
251
  }
170
252
  function toolResultContent(result) {
253
+ if (result && typeof result === "object" &&
254
+ "legacyResult" in result &&
255
+ "output" in result) {
256
+ const text = (0, gambit_core_1.stringifyResponseOutput)(result.output);
257
+ if (text)
258
+ return text;
259
+ return toolResultContent(result.legacyResult);
260
+ }
171
261
  if (typeof result === "string")
172
262
  return result;
173
263
  try {
@@ -240,15 +330,25 @@ async function chatCompletionsWithDeck(args) {
240
330
  (() => {
241
331
  throw new Error("No model provided");
242
332
  })();
243
- const result = await args.modelProvider.chat({
244
- model,
245
- messages,
246
- tools: tools.length ? tools : undefined,
247
- stream: Boolean(args.request.stream),
333
+ const response = await args.modelProvider.responses({
334
+ request: {
335
+ model,
336
+ input: responseItemsFromMessages(messages),
337
+ tools: tools.length ? tools : undefined,
338
+ stream: Boolean(args.request.stream),
339
+ params: providerParamsFromRequest(args.request),
340
+ },
248
341
  deckPath: deck.path,
249
- onStreamText: args.onStreamText,
250
- params: providerParamsFromRequest(args.request),
342
+ onStreamEvent: (event) => {
343
+ if (event.type === "response.output_text.delta") {
344
+ args.onStreamText?.(event.delta);
345
+ }
346
+ },
251
347
  });
348
+ const result = {
349
+ ...responseOutputToChatResult(response.output),
350
+ usage: response.usage,
351
+ };
252
352
  messages.push(result.message);
253
353
  if (result.toolCalls && result.toolCalls.length > 0) {
254
354
  const gambitCalls = result.toolCalls.filter((c) => gambit.toolNameSet.has(c.name));
@@ -296,7 +396,7 @@ async function chatCompletionsWithDeck(args) {
296
396
  type: "openai_compat.action.permissions",
297
397
  permissions: actionPermissions.trace,
298
398
  });
299
- const childResult = await (0, gambit_core_1.runDeck)({
399
+ const childResult = await (0, gambit_core_1.runDeckResponses)({
300
400
  path: actionPath,
301
401
  input: call.args,
302
402
  modelProvider: args.modelProvider,
@@ -1 +1 @@
1
- {"version":3,"file":"claude_code.d.ts","sourceRoot":"","sources":["../../../src/src/providers/claude_code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,YAAY,EACZ,aAAa,EAKb,UAAU,EACX,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAMnD,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE;IAC3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AA2gB7B,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE;IAC9C,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B,GAAG,aAAa,CA4MhB;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC/B,GAAG,KAAK,CAAC,MAAM,CAAC,CA2BhB;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAEA"}
1
+ {"version":3,"file":"claude_code.d.ts","sourceRoot":"","sources":["../../../src/src/providers/claude_code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,YAAY,EACZ,aAAa,EAKb,UAAU,EACX,MAAM,2BAA2B,CAAC;AAGnC,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAMnD,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE;IAC3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AA2gB7B,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE;IAC9C,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B,GAAG,aAAa,CAkOhB;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC/B,GAAG,KAAK,CAAC,MAAM,CAAC,CA2BhB;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAEA"}
@@ -38,6 +38,7 @@ exports.createClaudeCodeProvider = createClaudeCodeProvider;
38
38
  exports.parseClaudeCodeArgsForTest = parseClaudeCodeArgsForTest;
39
39
  exports.parseClaudeCodeStdoutForTest = parseClaudeCodeStdoutForTest;
40
40
  const dntShim = __importStar(require("../../_dnt.shims.js"));
41
+ const gambit_core_1 = require("@bolt-foundry/gambit-core");
41
42
  exports.CLAUDE_CODE_PREFIX = "claude-code-cli/";
42
43
  exports.CLAUDE_CODE_ALIAS = "claude-code-cli";
43
44
  const CLAUDE_CODE_BIN_ENV = "GAMBIT_CLAUDE_CODE_BIN";
@@ -139,7 +140,7 @@ function extractAssistantTextFromClaudeMessage(message) {
139
140
  parts.push(text);
140
141
  }
141
142
  }
142
- return parts.join("").trim();
143
+ return (0, gambit_core_1.joinTextParts)(parts).trim();
143
144
  }
144
145
  function extractBestText(input) {
145
146
  if (typeof input === "string" && input.trim())
@@ -467,7 +468,7 @@ function responseItemsToChatMessages(items, instructions) {
467
468
  }
468
469
  for (const item of items) {
469
470
  if (item.type === "message") {
470
- const content = item.content.map((part) => part.text).join("");
471
+ const content = (0, gambit_core_1.joinTextParts)(item.content.map((part) => part.text));
471
472
  messages.push({ role: item.role, content });
472
473
  continue;
473
474
  }
@@ -699,7 +700,6 @@ function createClaudeCodeProvider(opts) {
699
700
  }
700
701
  return response;
701
702
  },
702
- chat: runChat,
703
703
  };
704
704
  }
705
705
  function parseClaudeCodeArgsForTest(input) {
@@ -1,4 +1,4 @@
1
- import type { JSONValue, ModelMessage, ModelProvider, ResponseItem, SavedState } from "@bolt-foundry/gambit-core";
1
+ import type { JSONValue, ModelMessage, ModelProvider, ResponseItem, SavedState, ToolDefinition } from "@bolt-foundry/gambit-core";
2
2
  import type { CodexChatgptAuthTokens } from "../codex_auth.js";
3
3
  export declare const CODEX_PREFIX = "codex-cli/";
4
4
  type CodexAssistantMessage = {
@@ -8,6 +8,7 @@ type CodexAssistantMessage = {
8
8
  type AppServerTurnRunnerInput = {
9
9
  model: string;
10
10
  messages: Array<ModelMessage>;
11
+ tools?: Array<ToolDefinition>;
11
12
  state?: SavedState;
12
13
  params?: Record<string, unknown>;
13
14
  deckPath?: string;
@@ -56,6 +57,16 @@ export declare function codexConfigArgsForTest(input: {
56
57
  instructions?: string;
57
58
  }): Array<string>;
58
59
  export declare function safeJsonForTest(text: string): Record<string, JSONValue>;
60
+ export declare function appServerRequestResultForTest(input: {
61
+ method: string;
62
+ params: Record<string, unknown>;
63
+ }): Promise<{
64
+ result?: Record<string, JSONValue>;
65
+ error?: {
66
+ code: number;
67
+ message: string;
68
+ };
69
+ }>;
59
70
  export declare function sanitizeCodexSpawnArgsForTest(args: Array<string>): Array<string>;
60
71
  export declare function extractCodexConfigValuesForTest(args: Array<string>, flag: string, prefix?: string): Array<string>;
61
72
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/src/providers/codex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/src/providers/codex.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,7 @@ exports.codexInstructionsForMessagesForTest = codexInstructionsForMessagesForTes
41
41
  exports.promptForCodexTurnForTest = promptForCodexTurnForTest;
42
42
  exports.codexConfigArgsForTest = codexConfigArgsForTest;
43
43
  exports.safeJsonForTest = safeJsonForTest;
44
+ exports.appServerRequestResultForTest = appServerRequestResultForTest;
44
45
  exports.sanitizeCodexSpawnArgsForTest = sanitizeCodexSpawnArgsForTest;
45
46
  exports.extractCodexConfigValuesForTest = extractCodexConfigValuesForTest;
46
47
  const dntShim = __importStar(require("../../_dnt.shims.js"));
@@ -58,13 +59,14 @@ const CODEX_REASONING_SUMMARY_ENV = "GAMBIT_CODEX_REASONING_SUMMARY";
58
59
  const CODEX_VERBOSITY_ENV = "GAMBIT_CODEX_VERBOSITY";
59
60
  const CODEX_BIN_ENV = "GAMBIT_CODEX_BIN";
60
61
  const CODEX_SKIP_SANDBOX_CONFIG_ENV = "GAMBIT_CODEX_SKIP_SANDBOX_CONFIG";
62
+ const CODEX_DISABLE_WEBSOCKETS_ENV = "GAMBIT_CODEX_DISABLE_WEBSOCKETS";
61
63
  const CODEX_DANGEROUS_BYPASS_ENV = "GAMBIT_CODEX_DANGEROUSLY_BYPASS_APPROVALS_AND_SANDBOX";
62
64
  const MCP_DENO_BIN_ENV = "GAMBIT_MCP_DENO_BIN";
63
65
  const MCP_ROOT_DECK_PATH_ENV = "GAMBIT_MCP_ROOT_DECK_PATH";
64
66
  const EXTERNAL_TOOL_BRIDGE_ENV = "GAMBIT_EXTERNAL_TOOL_BRIDGE";
65
67
  const MCP_DEBUG_LOG_PATH_ENV = "GAMBIT_MCP_DEBUG_LOG_PATH";
66
68
  const DENO_DIR_ENV = "DENO_DIR";
67
- const DEBUG_MCP_ENV = "BOLT_FOUNDRY_DESKTOP_CHIEF_RUNTIME_DEBUG_MCP";
69
+ const DEBUG_MCP_ENV = "GAMBIT_MCP_DEBUG";
68
70
  const MCP_SERVER_PATH = (() => {
69
71
  try {
70
72
  const moduleUrl = new URL(globalThis[Symbol.for("import-meta-ponyfill-commonjs")](require, module).url);
@@ -158,13 +160,24 @@ function shouldDebugMcpBridge() {
158
160
  const raw = dntShim.Deno.env.get(DEBUG_MCP_ENV)?.trim().toLowerCase();
159
161
  return raw === "1" || raw === "true" || raw === "yes";
160
162
  }
163
+ function isCodexNativeOrGambitBuiltinTool(name) {
164
+ return new Set([
165
+ "apply_patch",
166
+ "exec",
167
+ "gambit_consume_async_action",
168
+ "gambit_emit_output_item",
169
+ "grep_files",
170
+ "list_dir",
171
+ "read_file",
172
+ ]).has(name);
173
+ }
161
174
  function logCodexMcpDebug(event, details) {
162
175
  if (!shouldDebugMcpBridge())
163
176
  return;
164
177
  globalThis.console.error("[gambit-codex-mcp]", event, details ?? {});
165
178
  }
166
179
  function codexMcpDebugLogPath(cwd) {
167
- return path.join(cwd, ".boltfoundry", "runtime", "chief-runtime", "gambit-mcp-debug.log");
180
+ return path.join(cwd, ".workloop", "runtime", "chief-runtime", "gambit-mcp-debug.log");
168
181
  }
169
182
  function mcpServerDenoBin() {
170
183
  return dntShim.Deno.env.get(MCP_DENO_BIN_ENV)?.trim() || "deno";
@@ -202,6 +215,14 @@ function shouldSkipCodexSandboxConfig(params) {
202
215
  const envRaw = dntShim.Deno.env.get(CODEX_SKIP_SANDBOX_CONFIG_ENV);
203
216
  return Boolean(envRaw && parseTruthy(envRaw));
204
217
  }
218
+ function shouldDisableCodexWebsockets() {
219
+ // Newer Codex releases reserve built-in provider IDs, so overriding
220
+ // `model_providers.openai.supports_websockets` now prevents app-server
221
+ // startup. Keep the env var harmless while the old transport workaround ages
222
+ // out.
223
+ dntShim.Deno.env.get(CODEX_DISABLE_WEBSOCKETS_ENV);
224
+ return false;
225
+ }
205
226
  function tomlString(value) {
206
227
  return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
207
228
  }
@@ -289,6 +310,9 @@ function codexAdditionalConfigArgs(params) {
289
310
  function codexConfigArgs(input) {
290
311
  const args = [];
291
312
  args.push(...codexAdditionalConfigArgs(input.params));
313
+ if (shouldDisableCodexWebsockets()) {
314
+ args.push("-c", "model_providers.openai.supports_websockets=false");
315
+ }
292
316
  args.push("-c", `approval_policy=${tomlString("never")}`);
293
317
  const pathEnv = dntShim.Deno.env.get("PATH")?.trim();
294
318
  if (pathEnv) {
@@ -397,7 +421,15 @@ async function prepareCodexMcpRootDeck(input) {
397
421
  return {};
398
422
  }
399
423
  const deck = await (0, gambit_core_1.loadDeck)(rootDeckPath);
400
- if (deck.actionDecks.length === 0) {
424
+ const deckActionNames = new Set(deck.actionDecks.map((action) => action.name));
425
+ const deckToolNames = new Set(deck.tools.map((tool) => tool.name));
426
+ const extraExternalTools = (input.tools ?? [])
427
+ .map((tool) => tool.function)
428
+ .filter((tool) => tool &&
429
+ !isCodexNativeOrGambitBuiltinTool(tool.name) &&
430
+ !deckActionNames.has(tool.name) &&
431
+ !deckToolNames.has(tool.name));
432
+ if (deck.actionDecks.length === 0 && extraExternalTools.length === 0) {
401
433
  logCodexMcpDebug("prepareRootDeck:reuseOriginal", {
402
434
  actionCount: 0,
403
435
  deckPath: rootDeckPath,
@@ -431,15 +463,28 @@ async function prepareCodexMcpRootDeck(input) {
431
463
  }
432
464
  frontmatter.push("");
433
465
  }
466
+ for (const externalTool of extraExternalTools) {
467
+ frontmatter.push("[[tools]]");
468
+ frontmatter.push(`name = ${tomlString(externalTool.name)}`);
469
+ if (typeof externalTool.description === "string" &&
470
+ externalTool.description.trim()) {
471
+ frontmatter.push(`description = ${tomlString(externalTool.description.trim())}`);
472
+ }
473
+ frontmatter.push("");
474
+ }
434
475
  frontmatter.push("+++", "", "Codex MCP tool surface.");
435
476
  await dntShim.Deno.writeTextFile(tempDeckPath, frontmatter.join("\n"));
436
477
  logCodexMcpDebug("prepareRootDeck:synthesized", {
437
478
  actionCount: deck.actionDecks.length,
438
479
  actionNames: deck.actionDecks.map((action) => action.name),
480
+ extraToolNames: extraExternalTools.map((tool) => tool.name),
439
481
  rootDeckPath,
440
482
  synthesizedDeckPath: tempDeckPath,
441
- toolCount: deck.tools.length,
442
- toolNames: deck.tools.map((tool) => tool.name),
483
+ toolCount: deck.tools.length + extraExternalTools.length,
484
+ toolNames: [
485
+ ...deck.tools.map((tool) => tool.name),
486
+ ...extraExternalTools.map((tool) => tool.name),
487
+ ],
443
488
  });
444
489
  return {
445
490
  deckPath: tempDeckPath,
@@ -488,14 +533,22 @@ async function appServerRequestResult(input) {
488
533
  }
489
534
  if (input.method === "account/chatgptAuthTokens/refresh") {
490
535
  const bridge = requireCodexHostAuthBridge();
491
- const refreshed = await bridge.refreshAuthTokens({
492
- previousAccountId: typeof input.params.previousAccountId === "string"
493
- ? input.params.previousAccountId
494
- : null,
495
- reason: typeof input.params.reason === "string" && input.params.reason
496
- ? input.params.reason
497
- : "account/chatgptAuthTokens/refresh",
498
- });
536
+ let refreshed;
537
+ try {
538
+ refreshed = await bridge.refreshAuthTokens({
539
+ previousAccountId: typeof input.params.previousAccountId === "string"
540
+ ? input.params.previousAccountId
541
+ : null,
542
+ reason: typeof input.params.reason === "string" && input.params.reason
543
+ ? input.params.reason
544
+ : "account/chatgptAuthTokens/refresh",
545
+ });
546
+ }
547
+ catch (error) {
548
+ return {
549
+ error: appServerHostRequestFailure(error),
550
+ };
551
+ }
499
552
  return {
500
553
  result: {
501
554
  accessToken: refreshed.accessToken,
@@ -512,6 +565,14 @@ async function appServerRequestResult(input) {
512
565
  },
513
566
  };
514
567
  }
568
+ function appServerHostRequestFailure(error) {
569
+ return {
570
+ code: -32000,
571
+ message: error instanceof Error && error.message
572
+ ? error.message
573
+ : String(error),
574
+ };
575
+ }
515
576
  async function bootstrapCodexExternalAuth(input) {
516
577
  if (!codexHostAuthBridge) {
517
578
  return;
@@ -994,7 +1055,15 @@ async function defaultAppServerTurnRunner(input) {
994
1055
  method,
995
1056
  params: safeJsonObjectFromRecord(params),
996
1057
  });
997
- const response = await appServerRequestResult({ method, params });
1058
+ let response;
1059
+ try {
1060
+ response = await appServerRequestResult({ method, params });
1061
+ }
1062
+ catch (error) {
1063
+ response = {
1064
+ error: appServerHostRequestFailure(error),
1065
+ };
1066
+ }
998
1067
  (0, codex_app_server_debug_js_1.logCodexAppServerDebug)("message:host_response", {
999
1068
  method,
1000
1069
  requestId,
@@ -1395,7 +1464,7 @@ function extractTextParts(value) {
1395
1464
  function extractCodexItemText(record) {
1396
1465
  return typeof record.text === "string"
1397
1466
  ? record.text
1398
- : extractTextParts(record.content).join("");
1467
+ : (0, gambit_core_1.joinTextParts)(extractTextParts(record.content));
1399
1468
  }
1400
1469
  function requireCodexAssistantItemId(input) {
1401
1470
  const itemId = typeof input.record.id === "string"
@@ -1504,7 +1573,7 @@ function emitCodexReasoningEvents(input) {
1504
1573
  if (payloadType === "item.delta") {
1505
1574
  const deltaText = typeof record.text === "string"
1506
1575
  ? record.text
1507
- : extractTextParts(record.content).join("");
1576
+ : (0, gambit_core_1.joinTextParts)(extractTextParts(record.content));
1508
1577
  if (deltaText) {
1509
1578
  input.emit({
1510
1579
  type: "response.reasoning.delta",
@@ -1518,7 +1587,7 @@ function emitCodexReasoningEvents(input) {
1518
1587
  if (payloadType === "item.completed" || payloadType === "item.done") {
1519
1588
  const doneText = typeof record.text === "string"
1520
1589
  ? record.text
1521
- : extractTextParts(record.content).join("");
1590
+ : (0, gambit_core_1.joinTextParts)(extractTextParts(record.content));
1522
1591
  input.emit({
1523
1592
  type: "response.reasoning.done",
1524
1593
  output_index: outputIndex,
@@ -1612,7 +1681,7 @@ function responseItemsToChatMessages(items, instructions) {
1612
1681
  }
1613
1682
  for (const item of items) {
1614
1683
  if (item.type === "message") {
1615
- const content = item.content.map((part) => part.text).join("");
1684
+ const content = (0, gambit_core_1.joinTextParts)(item.content.map((part) => part.text));
1616
1685
  messages.push({ role: item.role, content });
1617
1686
  continue;
1618
1687
  }
@@ -1900,11 +1969,13 @@ function createCodexProvider(opts) {
1900
1969
  const cwd = codexRunCwd({ deckPath: input.deckPath });
1901
1970
  const preparedMcpRoot = await prepareCodexMcpRootDeck({
1902
1971
  deckPath: input.deckPath,
1972
+ tools: input.tools,
1903
1973
  });
1904
1974
  try {
1905
1975
  const result = await runAppServerTurn({
1906
1976
  model: input.model,
1907
1977
  messages: input.messages,
1978
+ tools: input.tools,
1908
1979
  state: input.state,
1909
1980
  params: input.params,
1910
1981
  deckPath: preparedMcpRoot.deckPath ?? input.deckPath,
@@ -1916,7 +1987,7 @@ function createCodexProvider(opts) {
1916
1987
  cwd,
1917
1988
  priorThreadId,
1918
1989
  });
1919
- const assistantText = result.assistantMessages.map((message) => message.text).join("");
1990
+ const assistantText = (0, gambit_core_1.joinTextParts)(result.assistantMessages.map((message) => message.text));
1920
1991
  if (input.stream && input.onStreamText && assistantText &&
1921
1992
  !assistantState.sawAssistantTextStream) {
1922
1993
  input.onStreamText(assistantText);
@@ -1941,15 +2012,6 @@ function createCodexProvider(opts) {
1941
2012
  await preparedMcpRoot.cleanup?.();
1942
2013
  }
1943
2014
  };
1944
- const runChat = async (input) => {
1945
- const result = await runCodexTurn(input);
1946
- return {
1947
- message: result.message,
1948
- finishReason: result.finishReason,
1949
- updatedState: result.updatedState,
1950
- usage: result.usage,
1951
- };
1952
- };
1953
2015
  return {
1954
2016
  async responses(input) {
1955
2017
  const streamHandler = input.onStreamEvent
@@ -1982,6 +2044,7 @@ function createCodexProvider(opts) {
1982
2044
  const result = await runCodexTurn({
1983
2045
  model: input.request.model,
1984
2046
  messages: responseItemsToChatMessages(input.request.input, input.request.instructions),
2047
+ tools: input.request.tools,
1985
2048
  stream: input.request.stream,
1986
2049
  params: input.request.params,
1987
2050
  state: input.state,
@@ -2097,7 +2160,6 @@ function createCodexProvider(opts) {
2097
2160
  }
2098
2161
  return response;
2099
2162
  },
2100
- chat: runChat,
2101
2163
  };
2102
2164
  }
2103
2165
  function normalizeCodexModelForTest(model) {
@@ -2115,6 +2177,9 @@ function codexConfigArgsForTest(input) {
2115
2177
  function safeJsonForTest(text) {
2116
2178
  return safeJsonObject(text);
2117
2179
  }
2180
+ async function appServerRequestResultForTest(input) {
2181
+ return await appServerRequestResult(input);
2182
+ }
2118
2183
  function sanitizeCodexSpawnArgsForTest(args) {
2119
2184
  return sanitizeCodexSpawnArgsForDebug(args);
2120
2185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/src/providers/google.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,aAAa,EAId,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,aAAa,YAAY,CAAC;AAIvC,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,MAAM,EAAE,CACN,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;gBAAE,MAAM,CAAC,EAAE,WAAW,CAAA;aAAE,KAC/B,OAAO,CAAC,OAAO,CAAC,CAAC;SACvB,CAAC;KACH,CAAC;CACH,CAAC;AA8IF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,aAAa,CA6XhB"}
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/src/providers/google.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,aAAa,EAId,MAAM,2BAA2B,CAAC;AAGnC,eAAO,MAAM,aAAa,YAAY,CAAC;AAIvC,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,MAAM,EAAE,CACN,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;gBAAE,MAAM,CAAC,EAAE,WAAW,CAAA;aAAE,KAC/B,OAAO,CAAC,OAAO,CAAC,CAAC;SACvB,CAAC;KACH,CAAC;CACH,CAAC;AA8IF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,aAAa,CA+OhB"}