@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.
- package/CHANGELOG.md +54 -2
- package/README.md +165 -50
- package/esm/mod.d.ts +11 -3
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +7 -1
- package/esm/src/codex_app_server_debug.d.ts +1 -1
- package/esm/src/codex_app_server_debug.d.ts.map +1 -1
- package/esm/src/codex_app_server_debug.js +1 -1
- package/esm/src/codex_auth.d.ts +1 -1
- package/esm/src/codex_auth.d.ts.map +1 -1
- package/esm/src/codex_auth.js +1 -1
- package/esm/src/default_runtime.d.ts +5 -1
- package/esm/src/default_runtime.d.ts.map +1 -1
- package/esm/src/default_runtime.js +48 -29
- package/esm/src/openai_compat.d.ts.map +1 -1
- package/esm/src/openai_compat.js +111 -11
- package/esm/src/providers/claude_code.d.ts.map +1 -1
- package/esm/src/providers/claude_code.js +3 -3
- package/esm/src/providers/codex.d.ts +12 -1
- package/esm/src/providers/codex.d.ts.map +1 -1
- package/esm/src/providers/codex.js +94 -30
- package/esm/src/providers/google.d.ts.map +1 -1
- package/esm/src/providers/google.js +7 -114
- package/esm/src/providers/manifest.d.ts +2 -2
- package/esm/src/providers/manifest.d.ts.map +1 -1
- package/esm/src/providers/manifest.js +5 -5
- package/esm/src/providers/ollama.d.ts.map +1 -1
- package/esm/src/providers/ollama.js +0 -112
- package/esm/src/providers/openrouter.d.ts.map +1 -1
- package/esm/src/providers/openrouter.js +0 -264
- package/esm/src/providers/requirements.js +1 -1
- package/package.json +1 -1
- package/script/mod.d.ts +11 -3
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +15 -6
- package/script/src/codex_app_server_debug.d.ts +1 -1
- package/script/src/codex_app_server_debug.d.ts.map +1 -1
- package/script/src/codex_app_server_debug.js +1 -1
- package/script/src/codex_auth.d.ts +1 -1
- package/script/src/codex_auth.d.ts.map +1 -1
- package/script/src/codex_auth.js +1 -1
- package/script/src/default_runtime.d.ts +5 -1
- package/script/src/default_runtime.d.ts.map +1 -1
- package/script/src/default_runtime.js +48 -28
- package/script/src/openai_compat.d.ts.map +1 -1
- package/script/src/openai_compat.js +110 -10
- package/script/src/providers/claude_code.d.ts.map +1 -1
- package/script/src/providers/claude_code.js +3 -3
- package/script/src/providers/codex.d.ts +12 -1
- package/script/src/providers/codex.d.ts.map +1 -1
- package/script/src/providers/codex.js +94 -29
- package/script/src/providers/google.d.ts.map +1 -1
- package/script/src/providers/google.js +7 -114
- package/script/src/providers/manifest.d.ts +2 -2
- package/script/src/providers/manifest.d.ts.map +1 -1
- package/script/src/providers/manifest.js +5 -5
- package/script/src/providers/ollama.d.ts.map +1 -1
- package/script/src/providers/ollama.js +0 -112
- package/script/src/providers/openrouter.d.ts.map +1 -1
- package/script/src/providers/openrouter.js +0 -264
- package/script/src/providers/requirements.js +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
2
|
import * as path from "../../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
3
|
-
import { loadDeck } from "@bolt-foundry/gambit-core";
|
|
3
|
+
import { joinTextParts, loadDeck } from "@bolt-foundry/gambit-core";
|
|
4
4
|
import { logCodexAppServerDebug } from "../codex_app_server_debug.js";
|
|
5
5
|
import { ensureTempMcpDenoConfigSync } from "../mcp_deno_config.js";
|
|
6
6
|
export const CODEX_PREFIX = "codex-cli/";
|
|
@@ -13,13 +13,14 @@ const CODEX_REASONING_SUMMARY_ENV = "GAMBIT_CODEX_REASONING_SUMMARY";
|
|
|
13
13
|
const CODEX_VERBOSITY_ENV = "GAMBIT_CODEX_VERBOSITY";
|
|
14
14
|
const CODEX_BIN_ENV = "GAMBIT_CODEX_BIN";
|
|
15
15
|
const CODEX_SKIP_SANDBOX_CONFIG_ENV = "GAMBIT_CODEX_SKIP_SANDBOX_CONFIG";
|
|
16
|
+
const CODEX_DISABLE_WEBSOCKETS_ENV = "GAMBIT_CODEX_DISABLE_WEBSOCKETS";
|
|
16
17
|
const CODEX_DANGEROUS_BYPASS_ENV = "GAMBIT_CODEX_DANGEROUSLY_BYPASS_APPROVALS_AND_SANDBOX";
|
|
17
18
|
const MCP_DENO_BIN_ENV = "GAMBIT_MCP_DENO_BIN";
|
|
18
19
|
const MCP_ROOT_DECK_PATH_ENV = "GAMBIT_MCP_ROOT_DECK_PATH";
|
|
19
20
|
const EXTERNAL_TOOL_BRIDGE_ENV = "GAMBIT_EXTERNAL_TOOL_BRIDGE";
|
|
20
21
|
const MCP_DEBUG_LOG_PATH_ENV = "GAMBIT_MCP_DEBUG_LOG_PATH";
|
|
21
22
|
const DENO_DIR_ENV = "DENO_DIR";
|
|
22
|
-
const DEBUG_MCP_ENV = "
|
|
23
|
+
const DEBUG_MCP_ENV = "GAMBIT_MCP_DEBUG";
|
|
23
24
|
const MCP_SERVER_PATH = (() => {
|
|
24
25
|
try {
|
|
25
26
|
const moduleUrl = new URL(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
|
|
@@ -113,13 +114,24 @@ function shouldDebugMcpBridge() {
|
|
|
113
114
|
const raw = dntShim.Deno.env.get(DEBUG_MCP_ENV)?.trim().toLowerCase();
|
|
114
115
|
return raw === "1" || raw === "true" || raw === "yes";
|
|
115
116
|
}
|
|
117
|
+
function isCodexNativeOrGambitBuiltinTool(name) {
|
|
118
|
+
return new Set([
|
|
119
|
+
"apply_patch",
|
|
120
|
+
"exec",
|
|
121
|
+
"gambit_consume_async_action",
|
|
122
|
+
"gambit_emit_output_item",
|
|
123
|
+
"grep_files",
|
|
124
|
+
"list_dir",
|
|
125
|
+
"read_file",
|
|
126
|
+
]).has(name);
|
|
127
|
+
}
|
|
116
128
|
function logCodexMcpDebug(event, details) {
|
|
117
129
|
if (!shouldDebugMcpBridge())
|
|
118
130
|
return;
|
|
119
131
|
globalThis.console.error("[gambit-codex-mcp]", event, details ?? {});
|
|
120
132
|
}
|
|
121
133
|
function codexMcpDebugLogPath(cwd) {
|
|
122
|
-
return path.join(cwd, ".
|
|
134
|
+
return path.join(cwd, ".workloop", "runtime", "chief-runtime", "gambit-mcp-debug.log");
|
|
123
135
|
}
|
|
124
136
|
function mcpServerDenoBin() {
|
|
125
137
|
return dntShim.Deno.env.get(MCP_DENO_BIN_ENV)?.trim() || "deno";
|
|
@@ -157,6 +169,14 @@ function shouldSkipCodexSandboxConfig(params) {
|
|
|
157
169
|
const envRaw = dntShim.Deno.env.get(CODEX_SKIP_SANDBOX_CONFIG_ENV);
|
|
158
170
|
return Boolean(envRaw && parseTruthy(envRaw));
|
|
159
171
|
}
|
|
172
|
+
function shouldDisableCodexWebsockets() {
|
|
173
|
+
// Newer Codex releases reserve built-in provider IDs, so overriding
|
|
174
|
+
// `model_providers.openai.supports_websockets` now prevents app-server
|
|
175
|
+
// startup. Keep the env var harmless while the old transport workaround ages
|
|
176
|
+
// out.
|
|
177
|
+
dntShim.Deno.env.get(CODEX_DISABLE_WEBSOCKETS_ENV);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
160
180
|
function tomlString(value) {
|
|
161
181
|
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
162
182
|
}
|
|
@@ -244,6 +264,9 @@ function codexAdditionalConfigArgs(params) {
|
|
|
244
264
|
function codexConfigArgs(input) {
|
|
245
265
|
const args = [];
|
|
246
266
|
args.push(...codexAdditionalConfigArgs(input.params));
|
|
267
|
+
if (shouldDisableCodexWebsockets()) {
|
|
268
|
+
args.push("-c", "model_providers.openai.supports_websockets=false");
|
|
269
|
+
}
|
|
247
270
|
args.push("-c", `approval_policy=${tomlString("never")}`);
|
|
248
271
|
const pathEnv = dntShim.Deno.env.get("PATH")?.trim();
|
|
249
272
|
if (pathEnv) {
|
|
@@ -352,7 +375,15 @@ async function prepareCodexMcpRootDeck(input) {
|
|
|
352
375
|
return {};
|
|
353
376
|
}
|
|
354
377
|
const deck = await loadDeck(rootDeckPath);
|
|
355
|
-
|
|
378
|
+
const deckActionNames = new Set(deck.actionDecks.map((action) => action.name));
|
|
379
|
+
const deckToolNames = new Set(deck.tools.map((tool) => tool.name));
|
|
380
|
+
const extraExternalTools = (input.tools ?? [])
|
|
381
|
+
.map((tool) => tool.function)
|
|
382
|
+
.filter((tool) => tool &&
|
|
383
|
+
!isCodexNativeOrGambitBuiltinTool(tool.name) &&
|
|
384
|
+
!deckActionNames.has(tool.name) &&
|
|
385
|
+
!deckToolNames.has(tool.name));
|
|
386
|
+
if (deck.actionDecks.length === 0 && extraExternalTools.length === 0) {
|
|
356
387
|
logCodexMcpDebug("prepareRootDeck:reuseOriginal", {
|
|
357
388
|
actionCount: 0,
|
|
358
389
|
deckPath: rootDeckPath,
|
|
@@ -386,15 +417,28 @@ async function prepareCodexMcpRootDeck(input) {
|
|
|
386
417
|
}
|
|
387
418
|
frontmatter.push("");
|
|
388
419
|
}
|
|
420
|
+
for (const externalTool of extraExternalTools) {
|
|
421
|
+
frontmatter.push("[[tools]]");
|
|
422
|
+
frontmatter.push(`name = ${tomlString(externalTool.name)}`);
|
|
423
|
+
if (typeof externalTool.description === "string" &&
|
|
424
|
+
externalTool.description.trim()) {
|
|
425
|
+
frontmatter.push(`description = ${tomlString(externalTool.description.trim())}`);
|
|
426
|
+
}
|
|
427
|
+
frontmatter.push("");
|
|
428
|
+
}
|
|
389
429
|
frontmatter.push("+++", "", "Codex MCP tool surface.");
|
|
390
430
|
await dntShim.Deno.writeTextFile(tempDeckPath, frontmatter.join("\n"));
|
|
391
431
|
logCodexMcpDebug("prepareRootDeck:synthesized", {
|
|
392
432
|
actionCount: deck.actionDecks.length,
|
|
393
433
|
actionNames: deck.actionDecks.map((action) => action.name),
|
|
434
|
+
extraToolNames: extraExternalTools.map((tool) => tool.name),
|
|
394
435
|
rootDeckPath,
|
|
395
436
|
synthesizedDeckPath: tempDeckPath,
|
|
396
|
-
toolCount: deck.tools.length,
|
|
397
|
-
toolNames:
|
|
437
|
+
toolCount: deck.tools.length + extraExternalTools.length,
|
|
438
|
+
toolNames: [
|
|
439
|
+
...deck.tools.map((tool) => tool.name),
|
|
440
|
+
...extraExternalTools.map((tool) => tool.name),
|
|
441
|
+
],
|
|
398
442
|
});
|
|
399
443
|
return {
|
|
400
444
|
deckPath: tempDeckPath,
|
|
@@ -443,14 +487,22 @@ async function appServerRequestResult(input) {
|
|
|
443
487
|
}
|
|
444
488
|
if (input.method === "account/chatgptAuthTokens/refresh") {
|
|
445
489
|
const bridge = requireCodexHostAuthBridge();
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
: "
|
|
453
|
-
|
|
490
|
+
let refreshed;
|
|
491
|
+
try {
|
|
492
|
+
refreshed = await bridge.refreshAuthTokens({
|
|
493
|
+
previousAccountId: typeof input.params.previousAccountId === "string"
|
|
494
|
+
? input.params.previousAccountId
|
|
495
|
+
: null,
|
|
496
|
+
reason: typeof input.params.reason === "string" && input.params.reason
|
|
497
|
+
? input.params.reason
|
|
498
|
+
: "account/chatgptAuthTokens/refresh",
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
catch (error) {
|
|
502
|
+
return {
|
|
503
|
+
error: appServerHostRequestFailure(error),
|
|
504
|
+
};
|
|
505
|
+
}
|
|
454
506
|
return {
|
|
455
507
|
result: {
|
|
456
508
|
accessToken: refreshed.accessToken,
|
|
@@ -467,6 +519,14 @@ async function appServerRequestResult(input) {
|
|
|
467
519
|
},
|
|
468
520
|
};
|
|
469
521
|
}
|
|
522
|
+
function appServerHostRequestFailure(error) {
|
|
523
|
+
return {
|
|
524
|
+
code: -32000,
|
|
525
|
+
message: error instanceof Error && error.message
|
|
526
|
+
? error.message
|
|
527
|
+
: String(error),
|
|
528
|
+
};
|
|
529
|
+
}
|
|
470
530
|
async function bootstrapCodexExternalAuth(input) {
|
|
471
531
|
if (!codexHostAuthBridge) {
|
|
472
532
|
return;
|
|
@@ -949,7 +1009,15 @@ async function defaultAppServerTurnRunner(input) {
|
|
|
949
1009
|
method,
|
|
950
1010
|
params: safeJsonObjectFromRecord(params),
|
|
951
1011
|
});
|
|
952
|
-
|
|
1012
|
+
let response;
|
|
1013
|
+
try {
|
|
1014
|
+
response = await appServerRequestResult({ method, params });
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
response = {
|
|
1018
|
+
error: appServerHostRequestFailure(error),
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
953
1021
|
logCodexAppServerDebug("message:host_response", {
|
|
954
1022
|
method,
|
|
955
1023
|
requestId,
|
|
@@ -1350,7 +1418,7 @@ function extractTextParts(value) {
|
|
|
1350
1418
|
function extractCodexItemText(record) {
|
|
1351
1419
|
return typeof record.text === "string"
|
|
1352
1420
|
? record.text
|
|
1353
|
-
: extractTextParts(record.content)
|
|
1421
|
+
: joinTextParts(extractTextParts(record.content));
|
|
1354
1422
|
}
|
|
1355
1423
|
function requireCodexAssistantItemId(input) {
|
|
1356
1424
|
const itemId = typeof input.record.id === "string"
|
|
@@ -1459,7 +1527,7 @@ function emitCodexReasoningEvents(input) {
|
|
|
1459
1527
|
if (payloadType === "item.delta") {
|
|
1460
1528
|
const deltaText = typeof record.text === "string"
|
|
1461
1529
|
? record.text
|
|
1462
|
-
: extractTextParts(record.content)
|
|
1530
|
+
: joinTextParts(extractTextParts(record.content));
|
|
1463
1531
|
if (deltaText) {
|
|
1464
1532
|
input.emit({
|
|
1465
1533
|
type: "response.reasoning.delta",
|
|
@@ -1473,7 +1541,7 @@ function emitCodexReasoningEvents(input) {
|
|
|
1473
1541
|
if (payloadType === "item.completed" || payloadType === "item.done") {
|
|
1474
1542
|
const doneText = typeof record.text === "string"
|
|
1475
1543
|
? record.text
|
|
1476
|
-
: extractTextParts(record.content)
|
|
1544
|
+
: joinTextParts(extractTextParts(record.content));
|
|
1477
1545
|
input.emit({
|
|
1478
1546
|
type: "response.reasoning.done",
|
|
1479
1547
|
output_index: outputIndex,
|
|
@@ -1567,7 +1635,7 @@ function responseItemsToChatMessages(items, instructions) {
|
|
|
1567
1635
|
}
|
|
1568
1636
|
for (const item of items) {
|
|
1569
1637
|
if (item.type === "message") {
|
|
1570
|
-
const content = item.content.map((part) => part.text)
|
|
1638
|
+
const content = joinTextParts(item.content.map((part) => part.text));
|
|
1571
1639
|
messages.push({ role: item.role, content });
|
|
1572
1640
|
continue;
|
|
1573
1641
|
}
|
|
@@ -1855,11 +1923,13 @@ export function createCodexProvider(opts) {
|
|
|
1855
1923
|
const cwd = codexRunCwd({ deckPath: input.deckPath });
|
|
1856
1924
|
const preparedMcpRoot = await prepareCodexMcpRootDeck({
|
|
1857
1925
|
deckPath: input.deckPath,
|
|
1926
|
+
tools: input.tools,
|
|
1858
1927
|
});
|
|
1859
1928
|
try {
|
|
1860
1929
|
const result = await runAppServerTurn({
|
|
1861
1930
|
model: input.model,
|
|
1862
1931
|
messages: input.messages,
|
|
1932
|
+
tools: input.tools,
|
|
1863
1933
|
state: input.state,
|
|
1864
1934
|
params: input.params,
|
|
1865
1935
|
deckPath: preparedMcpRoot.deckPath ?? input.deckPath,
|
|
@@ -1871,7 +1941,7 @@ export function createCodexProvider(opts) {
|
|
|
1871
1941
|
cwd,
|
|
1872
1942
|
priorThreadId,
|
|
1873
1943
|
});
|
|
1874
|
-
const assistantText = result.assistantMessages.map((message) => message.text)
|
|
1944
|
+
const assistantText = joinTextParts(result.assistantMessages.map((message) => message.text));
|
|
1875
1945
|
if (input.stream && input.onStreamText && assistantText &&
|
|
1876
1946
|
!assistantState.sawAssistantTextStream) {
|
|
1877
1947
|
input.onStreamText(assistantText);
|
|
@@ -1896,15 +1966,6 @@ export function createCodexProvider(opts) {
|
|
|
1896
1966
|
await preparedMcpRoot.cleanup?.();
|
|
1897
1967
|
}
|
|
1898
1968
|
};
|
|
1899
|
-
const runChat = async (input) => {
|
|
1900
|
-
const result = await runCodexTurn(input);
|
|
1901
|
-
return {
|
|
1902
|
-
message: result.message,
|
|
1903
|
-
finishReason: result.finishReason,
|
|
1904
|
-
updatedState: result.updatedState,
|
|
1905
|
-
usage: result.usage,
|
|
1906
|
-
};
|
|
1907
|
-
};
|
|
1908
1969
|
return {
|
|
1909
1970
|
async responses(input) {
|
|
1910
1971
|
const streamHandler = input.onStreamEvent
|
|
@@ -1937,6 +1998,7 @@ export function createCodexProvider(opts) {
|
|
|
1937
1998
|
const result = await runCodexTurn({
|
|
1938
1999
|
model: input.request.model,
|
|
1939
2000
|
messages: responseItemsToChatMessages(input.request.input, input.request.instructions),
|
|
2001
|
+
tools: input.request.tools,
|
|
1940
2002
|
stream: input.request.stream,
|
|
1941
2003
|
params: input.request.params,
|
|
1942
2004
|
state: input.state,
|
|
@@ -2052,7 +2114,6 @@ export function createCodexProvider(opts) {
|
|
|
2052
2114
|
}
|
|
2053
2115
|
return response;
|
|
2054
2116
|
},
|
|
2055
|
-
chat: runChat,
|
|
2056
2117
|
};
|
|
2057
2118
|
}
|
|
2058
2119
|
export function normalizeCodexModelForTest(model) {
|
|
@@ -2070,6 +2131,9 @@ export function codexConfigArgsForTest(input) {
|
|
|
2070
2131
|
export function safeJsonForTest(text) {
|
|
2071
2132
|
return safeJsonObject(text);
|
|
2072
2133
|
}
|
|
2134
|
+
export async function appServerRequestResultForTest(input) {
|
|
2135
|
+
return await appServerRequestResult(input);
|
|
2136
|
+
}
|
|
2073
2137
|
export function sanitizeCodexSpawnArgsForTest(args) {
|
|
2074
2138
|
return sanitizeCodexSpawnArgsForDebug(args);
|
|
2075
2139
|
}
|
|
@@ -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;
|
|
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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
+
import { joinTextParts } from "@bolt-foundry/gambit-core";
|
|
2
3
|
export const GOOGLE_PREFIX = "google/";
|
|
3
4
|
const DEFAULT_GOOGLE_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/";
|
|
4
5
|
function safeJson(input) {
|
|
@@ -17,9 +18,9 @@ function extractContent(content) {
|
|
|
17
18
|
if (typeof content === "string")
|
|
18
19
|
return content;
|
|
19
20
|
if (Array.isArray(content)) {
|
|
20
|
-
return content
|
|
21
|
+
return joinTextParts(content
|
|
21
22
|
.map((part) => (typeof part === "string" ? part : part.text ?? ""))
|
|
22
|
-
.
|
|
23
|
+
.filter(Boolean));
|
|
23
24
|
}
|
|
24
25
|
return "";
|
|
25
26
|
}
|
|
@@ -53,9 +54,7 @@ function responseItemsToChatMessages(items, instructions) {
|
|
|
53
54
|
}
|
|
54
55
|
for (const item of items) {
|
|
55
56
|
if (item.type === "message") {
|
|
56
|
-
const content = item.content
|
|
57
|
-
.map((part) => part.text)
|
|
58
|
-
.join("");
|
|
57
|
+
const content = joinTextParts(item.content.map((part) => part.text));
|
|
59
58
|
messages.push({ role: item.role, content });
|
|
60
59
|
continue;
|
|
61
60
|
}
|
|
@@ -198,9 +197,9 @@ export function createGoogleProvider(opts) {
|
|
|
198
197
|
});
|
|
199
198
|
}
|
|
200
199
|
else if (Array.isArray(delta.content)) {
|
|
201
|
-
const text = delta.content
|
|
200
|
+
const text = joinTextParts(delta.content
|
|
202
201
|
.map((part) => (typeof part === "string" ? part : part.text ?? ""))
|
|
203
|
-
.
|
|
202
|
+
.filter(Boolean));
|
|
204
203
|
if (text) {
|
|
205
204
|
contentParts.push(text);
|
|
206
205
|
input.onStreamEvent?.({
|
|
@@ -238,7 +237,7 @@ export function createGoogleProvider(opts) {
|
|
|
238
237
|
}));
|
|
239
238
|
const message = normalizeMessage({
|
|
240
239
|
role: "assistant",
|
|
241
|
-
content: contentParts.length ? contentParts
|
|
240
|
+
content: contentParts.length ? joinTextParts(contentParts) : null,
|
|
242
241
|
tool_calls,
|
|
243
242
|
});
|
|
244
243
|
const toolCalls = tool_calls.length > 0
|
|
@@ -321,111 +320,5 @@ export function createGoogleProvider(opts) {
|
|
|
321
320
|
usage: mapChatUsage(response.usage),
|
|
322
321
|
};
|
|
323
322
|
},
|
|
324
|
-
async chat(input) {
|
|
325
|
-
const params = input.params ?? {};
|
|
326
|
-
if (input.stream) {
|
|
327
|
-
const stream = await client.chat.completions.create({
|
|
328
|
-
model: input.model,
|
|
329
|
-
messages: input.messages,
|
|
330
|
-
tools: input
|
|
331
|
-
// this predates the lint rule
|
|
332
|
-
.tools,
|
|
333
|
-
tool_choice: "auto",
|
|
334
|
-
stream: true,
|
|
335
|
-
...params,
|
|
336
|
-
}, input.signal ? { signal: input.signal } : undefined);
|
|
337
|
-
let finishReason = null;
|
|
338
|
-
const contentParts = [];
|
|
339
|
-
const toolCallMap = new Map();
|
|
340
|
-
for await (const chunk of stream) {
|
|
341
|
-
const choice = chunk.choices[0];
|
|
342
|
-
const fr = choice.finish_reason;
|
|
343
|
-
if (fr === "stop" || fr === "tool_calls" || fr === "length" ||
|
|
344
|
-
fr === null) {
|
|
345
|
-
finishReason = fr ?? finishReason;
|
|
346
|
-
}
|
|
347
|
-
const delta = choice.delta;
|
|
348
|
-
if (typeof delta.content === "string") {
|
|
349
|
-
contentParts.push(delta.content);
|
|
350
|
-
input.onStreamText?.(delta.content);
|
|
351
|
-
}
|
|
352
|
-
else if (Array.isArray(delta.content)) {
|
|
353
|
-
const chunkStr = delta.content
|
|
354
|
-
.map((c) => (typeof c === "string" ? c : c.text ?? ""))
|
|
355
|
-
.join("");
|
|
356
|
-
if (chunkStr) {
|
|
357
|
-
contentParts.push(chunkStr);
|
|
358
|
-
input.onStreamText?.(chunkStr);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
for (const tc of delta.tool_calls ?? []) {
|
|
362
|
-
const idx = tc.index ?? 0;
|
|
363
|
-
const existing = toolCallMap.get(idx) ??
|
|
364
|
-
{
|
|
365
|
-
id: tc.id,
|
|
366
|
-
function: { name: tc.function?.name, arguments: "" },
|
|
367
|
-
};
|
|
368
|
-
if (tc.id)
|
|
369
|
-
existing.id = tc.id;
|
|
370
|
-
if (tc.function?.name)
|
|
371
|
-
existing.function.name = tc.function.name;
|
|
372
|
-
if (tc.function?.arguments) {
|
|
373
|
-
existing.function.arguments += tc.function.arguments;
|
|
374
|
-
}
|
|
375
|
-
toolCallMap.set(idx, existing);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
const tool_calls = Array.from(toolCallMap.values()).map((tc) => ({
|
|
379
|
-
id: tc.id ?? crypto.randomUUID().replace(/-/g, "").slice(0, 24),
|
|
380
|
-
type: "function",
|
|
381
|
-
function: {
|
|
382
|
-
name: tc.function.name ?? "",
|
|
383
|
-
arguments: tc.function.arguments,
|
|
384
|
-
},
|
|
385
|
-
}));
|
|
386
|
-
const message = normalizeMessage({
|
|
387
|
-
role: "assistant",
|
|
388
|
-
content: contentParts.length ? contentParts.join("") : null,
|
|
389
|
-
tool_calls,
|
|
390
|
-
});
|
|
391
|
-
const toolCalls = tool_calls.length > 0
|
|
392
|
-
? tool_calls.map((tc) => ({
|
|
393
|
-
id: tc.id,
|
|
394
|
-
name: tc.function.name,
|
|
395
|
-
args: safeJson(tc.function.arguments),
|
|
396
|
-
}))
|
|
397
|
-
: undefined;
|
|
398
|
-
return {
|
|
399
|
-
message,
|
|
400
|
-
finishReason: finishReason ?? "stop",
|
|
401
|
-
toolCalls,
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
const response = await client.chat.completions.create({
|
|
405
|
-
model: input.model,
|
|
406
|
-
messages: input
|
|
407
|
-
// this predates the lint rule
|
|
408
|
-
.messages,
|
|
409
|
-
tools: input
|
|
410
|
-
// this predates the lint rule
|
|
411
|
-
.tools,
|
|
412
|
-
tool_choice: "auto",
|
|
413
|
-
stream: false,
|
|
414
|
-
...params,
|
|
415
|
-
}, input.signal ? { signal: input.signal } : undefined);
|
|
416
|
-
const choice = response.choices[0];
|
|
417
|
-
const message = normalizeMessage(choice.message);
|
|
418
|
-
const toolCalls = choice.message.tool_calls?.map((tc) => ({
|
|
419
|
-
id: tc.id,
|
|
420
|
-
name: tc.function.name,
|
|
421
|
-
args: safeJson(tc.function.arguments),
|
|
422
|
-
}));
|
|
423
|
-
return {
|
|
424
|
-
message,
|
|
425
|
-
finishReason: (choice.finish_reason ?? "stop"),
|
|
426
|
-
toolCalls,
|
|
427
|
-
usage: mapChatUsage(response.usage),
|
|
428
|
-
};
|
|
429
|
-
},
|
|
430
323
|
};
|
|
431
324
|
}
|
|
@@ -18,8 +18,8 @@ export type ProviderRuntimeAuthStateSource = {
|
|
|
18
18
|
kind: "json-file";
|
|
19
19
|
path: string;
|
|
20
20
|
};
|
|
21
|
-
export type ProviderStorageAuthority = "
|
|
22
|
-
export type ProviderAttachmentAuthority = "
|
|
21
|
+
export type ProviderStorageAuthority = "workloop";
|
|
22
|
+
export type ProviderAttachmentAuthority = "workloop-mitm" | "runtime-env-placeholder";
|
|
23
23
|
export type ProviderDestinationScope = "declared-destinations";
|
|
24
24
|
type BaseProviderAuthRequirements = {
|
|
25
25
|
attachmentAuthority: ProviderAttachmentAuthority;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/src/providers/manifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/src/providers/manifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC;AAElD,MAAM,MAAM,2BAA2B,GACnC,eAAe,GACf,yBAAyB,CAAC;AAE9B,MAAM,MAAM,wBAAwB,GAAG,uBAAuB,CAAC;AAE/D,KAAK,4BAA4B,GAAG;IAClC,mBAAmB,EAAE,2BAA2B,CAAC;IACjD,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C,gBAAgB,EAAE,wBAAwB,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,4BAA4B,GAAG;IAC1E,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,yCAAyC,GACjD,4BAA4B,GAC5B;IACA,IAAI,EAAE,qBAAqB,CAAC;CAC7B,CAAC;AAEJ,MAAM,MAAM,wBAAwB,GAChC,8BAA8B,GAC9B,yCAAyC,CAAC;AAE9C,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,WAAW,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,IAAI,CAAC,EAAE,wBAAwB,CAAC;IAChC,YAAY,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC;CACrD,CAAC;AAgRF,wBAAgB,oBAAoB,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAE9D;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,GACpB,gBAAgB,GAAG,IAAI,CAEzB;AAED,wBAAgB,0BAA0B,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAEzE"}
|
|
@@ -18,8 +18,8 @@ bareAlias = "codex-cli"
|
|
|
18
18
|
|
|
19
19
|
[auth]
|
|
20
20
|
mode = "chatgpt-auth-tokens"
|
|
21
|
-
storageAuthority = "
|
|
22
|
-
attachmentAuthority = "
|
|
21
|
+
storageAuthority = "workloop"
|
|
22
|
+
attachmentAuthority = "workloop-mitm"
|
|
23
23
|
destinationScope = "declared-destinations"
|
|
24
24
|
|
|
25
25
|
[[destinations]]
|
|
@@ -54,7 +54,7 @@ routingPrefix = "openrouter/"
|
|
|
54
54
|
|
|
55
55
|
[auth]
|
|
56
56
|
mode = "secret"
|
|
57
|
-
storageAuthority = "
|
|
57
|
+
storageAuthority = "workloop"
|
|
58
58
|
attachmentAuthority = "runtime-env-placeholder"
|
|
59
59
|
destinationScope = "declared-destinations"
|
|
60
60
|
|
|
@@ -71,10 +71,10 @@ function isSupportedProviderKey(value) {
|
|
|
71
71
|
value === "codex-cli" || value === "claude-code-cli";
|
|
72
72
|
}
|
|
73
73
|
function isSupportedStorageAuthority(value) {
|
|
74
|
-
return value === "
|
|
74
|
+
return value === "workloop";
|
|
75
75
|
}
|
|
76
76
|
function isSupportedAttachmentAuthority(value) {
|
|
77
|
-
return value === "
|
|
77
|
+
return value === "workloop-mitm" || value === "runtime-env-placeholder";
|
|
78
78
|
}
|
|
79
79
|
function isSupportedDestinationScope(value) {
|
|
80
80
|
return value === "declared-destinations";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/src/providers/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/src/providers/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIV,aAAa,EAOd,MAAM,2BAA2B,CAAC;AAOnC,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AAEnE,KAAK,YAAY,GAAG;IAClB,SAAS,EAAE;QACT,MAAM,EAAE,CACN,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,WAAW,CAAA;SAAE,KAC/B,OAAO,CAAC,OAAO,CAAC,CAAC;KACvB,CAAC;CACH,CAAC;AAeF,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAgBtB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,OAAO,CAAC,IAAI,CAAC,CA8Cf;AA+pBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,aAAa,CAiBhB"}
|
|
@@ -69,18 +69,6 @@ export async function ensureOllamaModel(model, baseURL) {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
function safeJson(input) {
|
|
73
|
-
try {
|
|
74
|
-
const parsed = JSON.parse(input);
|
|
75
|
-
if (parsed && typeof parsed === "object") {
|
|
76
|
-
return parsed;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// fall through
|
|
81
|
-
}
|
|
82
|
-
return {};
|
|
83
|
-
}
|
|
84
72
|
function toJsonValue(value) {
|
|
85
73
|
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
86
74
|
return value;
|
|
@@ -446,86 +434,6 @@ function toOpenAIInputItems(items) {
|
|
|
446
434
|
}
|
|
447
435
|
return mapped;
|
|
448
436
|
}
|
|
449
|
-
function chatMessagesToResponseItems(messages) {
|
|
450
|
-
const items = [];
|
|
451
|
-
for (const message of messages) {
|
|
452
|
-
if (message.role === "tool") {
|
|
453
|
-
if (message.tool_call_id &&
|
|
454
|
-
typeof message.content === "string") {
|
|
455
|
-
items.push({
|
|
456
|
-
type: "function_call_output",
|
|
457
|
-
call_id: message.tool_call_id,
|
|
458
|
-
output: message.content,
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
if (message.role === "system" || message.role === "user" ||
|
|
464
|
-
message.role === "assistant") {
|
|
465
|
-
const content = [];
|
|
466
|
-
if (typeof message.content === "string" && message.content.length > 0) {
|
|
467
|
-
content.push({
|
|
468
|
-
type: message.role === "assistant" ? "output_text" : "input_text",
|
|
469
|
-
text: message.content,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
if (content.length > 0) {
|
|
473
|
-
items.push({
|
|
474
|
-
type: "message",
|
|
475
|
-
role: message.role,
|
|
476
|
-
content,
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
if (message.role === "assistant" && message.tool_calls) {
|
|
481
|
-
for (const call of message.tool_calls) {
|
|
482
|
-
items.push({
|
|
483
|
-
type: "function_call",
|
|
484
|
-
call_id: call.id,
|
|
485
|
-
name: call.function.name,
|
|
486
|
-
arguments: call.function.arguments,
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
return items;
|
|
492
|
-
}
|
|
493
|
-
function responseItemsToChat(items) {
|
|
494
|
-
const textParts = [];
|
|
495
|
-
const toolCalls = [];
|
|
496
|
-
const messageToolCalls = [];
|
|
497
|
-
for (const item of items) {
|
|
498
|
-
if (item.type === "message" && item.role === "assistant") {
|
|
499
|
-
for (const part of item.content) {
|
|
500
|
-
if (part.type === "output_text") {
|
|
501
|
-
textParts.push(part.text);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
if (item.type === "function_call") {
|
|
506
|
-
toolCalls.push({
|
|
507
|
-
id: item.call_id,
|
|
508
|
-
name: item.name,
|
|
509
|
-
args: safeJson(item.arguments),
|
|
510
|
-
});
|
|
511
|
-
messageToolCalls.push({
|
|
512
|
-
id: item.call_id,
|
|
513
|
-
type: "function",
|
|
514
|
-
function: { name: item.name, arguments: item.arguments },
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
const content = textParts.length > 0 ? textParts.join("") : null;
|
|
519
|
-
const message = {
|
|
520
|
-
role: "assistant",
|
|
521
|
-
content,
|
|
522
|
-
tool_calls: messageToolCalls.length > 0 ? messageToolCalls : undefined,
|
|
523
|
-
};
|
|
524
|
-
return {
|
|
525
|
-
message,
|
|
526
|
-
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
437
|
async function createResponse(client, request, signal, onStreamEvent) {
|
|
530
438
|
const baseParams = {
|
|
531
439
|
model: request.model,
|
|
@@ -769,25 +677,5 @@ export function createOllamaProvider(opts) {
|
|
|
769
677
|
async responses(input) {
|
|
770
678
|
return await createResponse(client, input.request, input.signal, input.onStreamEvent);
|
|
771
679
|
},
|
|
772
|
-
async chat(input) {
|
|
773
|
-
const response = await createResponse(client, {
|
|
774
|
-
model: input.model,
|
|
775
|
-
input: chatMessagesToResponseItems(input.messages),
|
|
776
|
-
tools: input.tools,
|
|
777
|
-
stream: input.stream,
|
|
778
|
-
params: input.params ?? {},
|
|
779
|
-
}, input.signal, (event) => {
|
|
780
|
-
if (event.type === "response.output_text.delta") {
|
|
781
|
-
input.onStreamText?.(event.delta);
|
|
782
|
-
}
|
|
783
|
-
});
|
|
784
|
-
const mapped = responseItemsToChat(response.output);
|
|
785
|
-
return {
|
|
786
|
-
message: mapped.message,
|
|
787
|
-
finishReason: mapped.toolCalls ? "tool_calls" : "stop",
|
|
788
|
-
toolCalls: mapped.toolCalls,
|
|
789
|
-
usage: response.usage,
|
|
790
|
-
};
|
|
791
|
-
},
|
|
792
680
|
};
|
|
793
681
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../../src/src/providers/openrouter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../../src/src/providers/openrouter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIV,aAAa,EAOd,MAAM,2BAA2B,CAAC;AAOnC,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C,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;IACF,SAAS,EAAE;QACT,MAAM,EAAE,CACN,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,WAAW,CAAA;SAAE,KAC/B,OAAO,CAAC,OAAO,CAAC,CAAC;KACvB,CAAC;CACH,CAAC;AA8rBF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,aAAa,CAqBhB"}
|