@corbat-tech/coco 2.23.0 → 2.23.1
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/README.md +110 -372
- package/dist/cli/index.js +121 -57
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +109 -54
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13412,6 +13412,7 @@ var OpenAIProvider = class {
|
|
|
13412
13412
|
requestParams
|
|
13413
13413
|
);
|
|
13414
13414
|
const toolCallBuilders = /* @__PURE__ */ new Map();
|
|
13415
|
+
let lastToolCallKey = null;
|
|
13415
13416
|
const streamTimeout = this.config.timeout ?? 12e4;
|
|
13416
13417
|
let lastActivityTime = Date.now();
|
|
13417
13418
|
const timeoutController = new AbortController();
|
|
@@ -13461,9 +13462,9 @@ var OpenAIProvider = class {
|
|
|
13461
13462
|
}
|
|
13462
13463
|
if (delta?.tool_calls) {
|
|
13463
13464
|
for (const toolCallDelta of delta.tool_calls) {
|
|
13464
|
-
const
|
|
13465
|
-
if (!toolCallBuilders.has(
|
|
13466
|
-
toolCallBuilders.set(
|
|
13465
|
+
const key = typeof toolCallDelta.index === "number" ? `index:${toolCallDelta.index}` : typeof toolCallDelta.id === "string" && toolCallDelta.id.length > 0 ? `id:${toolCallDelta.id}` : toolCallBuilders.size === 1 ? Array.from(toolCallBuilders.keys())[0] ?? `fallback:${toolCallBuilders.size}` : lastToolCallKey ?? `fallback:${toolCallBuilders.size}`;
|
|
13466
|
+
if (!toolCallBuilders.has(key)) {
|
|
13467
|
+
toolCallBuilders.set(key, {
|
|
13467
13468
|
id: toolCallDelta.id ?? "",
|
|
13468
13469
|
name: toolCallDelta.function?.name ?? "",
|
|
13469
13470
|
arguments: ""
|
|
@@ -13476,7 +13477,8 @@ var OpenAIProvider = class {
|
|
|
13476
13477
|
}
|
|
13477
13478
|
};
|
|
13478
13479
|
}
|
|
13479
|
-
const builder = toolCallBuilders.get(
|
|
13480
|
+
const builder = toolCallBuilders.get(key);
|
|
13481
|
+
lastToolCallKey = key;
|
|
13480
13482
|
if (toolCallDelta.id) {
|
|
13481
13483
|
builder.id = toolCallDelta.id;
|
|
13482
13484
|
}
|
|
@@ -14064,6 +14066,7 @@ var OpenAIProvider = class {
|
|
|
14064
14066
|
requestParams
|
|
14065
14067
|
);
|
|
14066
14068
|
const fnCallBuilders = /* @__PURE__ */ new Map();
|
|
14069
|
+
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
14067
14070
|
const streamTimeout = this.config.timeout ?? 12e4;
|
|
14068
14071
|
let lastActivityTime = Date.now();
|
|
14069
14072
|
const timeoutController = new AbortController();
|
|
@@ -14093,8 +14096,11 @@ var OpenAIProvider = class {
|
|
|
14093
14096
|
fnCallBuilders.set(itemKey, {
|
|
14094
14097
|
callId: fc.call_id,
|
|
14095
14098
|
name: fc.name,
|
|
14096
|
-
arguments: ""
|
|
14099
|
+
arguments: fc.arguments ?? ""
|
|
14097
14100
|
});
|
|
14101
|
+
if (typeof event.output_index === "number") {
|
|
14102
|
+
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
14103
|
+
}
|
|
14098
14104
|
yield {
|
|
14099
14105
|
type: "tool_use_start",
|
|
14100
14106
|
toolCall: { id: fc.call_id, name: fc.name }
|
|
@@ -14103,7 +14109,9 @@ var OpenAIProvider = class {
|
|
|
14103
14109
|
break;
|
|
14104
14110
|
case "response.function_call_arguments.delta":
|
|
14105
14111
|
{
|
|
14106
|
-
const
|
|
14112
|
+
const builderKey = (event.item_id && fnCallBuilders.has(event.item_id) ? event.item_id : null) ?? (typeof event.output_index === "number" ? outputIndexToBuilderKey.get(event.output_index) ?? null : null) ?? (fnCallBuilders.size === 1 ? Array.from(fnCallBuilders.keys())[0] : null);
|
|
14113
|
+
if (!builderKey) break;
|
|
14114
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
14107
14115
|
if (builder) {
|
|
14108
14116
|
builder.arguments += event.delta;
|
|
14109
14117
|
}
|
|
@@ -14111,17 +14119,22 @@ var OpenAIProvider = class {
|
|
|
14111
14119
|
break;
|
|
14112
14120
|
case "response.function_call_arguments.done":
|
|
14113
14121
|
{
|
|
14114
|
-
const
|
|
14122
|
+
const builderKey = (event.item_id && fnCallBuilders.has(event.item_id) ? event.item_id : null) ?? (typeof event.output_index === "number" ? outputIndexToBuilderKey.get(event.output_index) ?? null : null) ?? (fnCallBuilders.size === 1 ? Array.from(fnCallBuilders.keys())[0] : null);
|
|
14123
|
+
if (!builderKey) break;
|
|
14124
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
14115
14125
|
if (builder) {
|
|
14116
14126
|
yield {
|
|
14117
14127
|
type: "tool_use_end",
|
|
14118
14128
|
toolCall: {
|
|
14119
14129
|
id: builder.callId,
|
|
14120
14130
|
name: builder.name,
|
|
14121
|
-
input: this.parseResponsesArguments(event.arguments)
|
|
14131
|
+
input: this.parseResponsesArguments(event.arguments ?? builder.arguments)
|
|
14122
14132
|
}
|
|
14123
14133
|
};
|
|
14124
|
-
fnCallBuilders.delete(
|
|
14134
|
+
fnCallBuilders.delete(builderKey);
|
|
14135
|
+
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
14136
|
+
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
14137
|
+
}
|
|
14125
14138
|
}
|
|
14126
14139
|
}
|
|
14127
14140
|
break;
|
|
@@ -14637,6 +14650,7 @@ var CodexProvider = class {
|
|
|
14637
14650
|
let outputTokens = 0;
|
|
14638
14651
|
const toolCalls = [];
|
|
14639
14652
|
const fnCallBuilders = /* @__PURE__ */ new Map();
|
|
14653
|
+
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
14640
14654
|
await this.readSSEStream(response, (event) => {
|
|
14641
14655
|
if (event.id) responseId = event.id;
|
|
14642
14656
|
switch (event.type) {
|
|
@@ -14653,25 +14667,35 @@ var CodexProvider = class {
|
|
|
14653
14667
|
fnCallBuilders.set(itemKey, {
|
|
14654
14668
|
callId: item.call_id,
|
|
14655
14669
|
name: item.name,
|
|
14656
|
-
arguments: ""
|
|
14670
|
+
arguments: item.arguments ?? ""
|
|
14657
14671
|
});
|
|
14672
|
+
if (typeof event.output_index === "number") {
|
|
14673
|
+
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
14674
|
+
}
|
|
14658
14675
|
}
|
|
14659
14676
|
break;
|
|
14660
14677
|
}
|
|
14661
14678
|
case "response.function_call_arguments.delta": {
|
|
14662
|
-
const
|
|
14679
|
+
const builderKey = (event.item_id && fnCallBuilders.has(event.item_id) ? event.item_id : null) ?? (typeof event.output_index === "number" ? outputIndexToBuilderKey.get(event.output_index) ?? null : null) ?? (fnCallBuilders.size === 1 ? Array.from(fnCallBuilders.keys())[0] : null);
|
|
14680
|
+
if (!builderKey) break;
|
|
14681
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
14663
14682
|
if (builder) builder.arguments += event.delta ?? "";
|
|
14664
14683
|
break;
|
|
14665
14684
|
}
|
|
14666
14685
|
case "response.function_call_arguments.done": {
|
|
14667
|
-
const
|
|
14686
|
+
const builderKey = (event.item_id && fnCallBuilders.has(event.item_id) ? event.item_id : null) ?? (typeof event.output_index === "number" ? outputIndexToBuilderKey.get(event.output_index) ?? null : null) ?? (fnCallBuilders.size === 1 ? Array.from(fnCallBuilders.keys())[0] : null);
|
|
14687
|
+
if (!builderKey) break;
|
|
14688
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
14668
14689
|
if (builder) {
|
|
14669
14690
|
toolCalls.push({
|
|
14670
14691
|
id: builder.callId,
|
|
14671
14692
|
name: builder.name,
|
|
14672
|
-
input: parseArguments(event.arguments)
|
|
14693
|
+
input: parseArguments(event.arguments ?? builder.arguments)
|
|
14673
14694
|
});
|
|
14674
|
-
fnCallBuilders.delete(
|
|
14695
|
+
fnCallBuilders.delete(builderKey);
|
|
14696
|
+
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
14697
|
+
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
14698
|
+
}
|
|
14675
14699
|
}
|
|
14676
14700
|
break;
|
|
14677
14701
|
}
|
|
@@ -14784,6 +14808,7 @@ var CodexProvider = class {
|
|
|
14784
14808
|
const decoder = new TextDecoder();
|
|
14785
14809
|
let buffer = "";
|
|
14786
14810
|
const fnCallBuilders = /* @__PURE__ */ new Map();
|
|
14811
|
+
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
14787
14812
|
let lastActivityTime = Date.now();
|
|
14788
14813
|
const timeoutController = new AbortController();
|
|
14789
14814
|
const timeoutInterval = setInterval(() => {
|
|
@@ -14822,8 +14847,11 @@ var CodexProvider = class {
|
|
|
14822
14847
|
fnCallBuilders.set(itemKey, {
|
|
14823
14848
|
callId: item.call_id,
|
|
14824
14849
|
name: item.name,
|
|
14825
|
-
arguments: ""
|
|
14850
|
+
arguments: item.arguments ?? ""
|
|
14826
14851
|
});
|
|
14852
|
+
if (typeof event.output_index === "number") {
|
|
14853
|
+
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
14854
|
+
}
|
|
14827
14855
|
yield {
|
|
14828
14856
|
type: "tool_use_start",
|
|
14829
14857
|
toolCall: { id: item.call_id, name: item.name }
|
|
@@ -14832,14 +14860,18 @@ var CodexProvider = class {
|
|
|
14832
14860
|
break;
|
|
14833
14861
|
}
|
|
14834
14862
|
case "response.function_call_arguments.delta": {
|
|
14835
|
-
const
|
|
14863
|
+
const builderKey = (event.item_id && fnCallBuilders.has(event.item_id) ? event.item_id : null) ?? (typeof event.output_index === "number" ? outputIndexToBuilderKey.get(event.output_index) ?? null : null) ?? (fnCallBuilders.size === 1 ? Array.from(fnCallBuilders.keys())[0] : null);
|
|
14864
|
+
if (!builderKey) break;
|
|
14865
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
14836
14866
|
if (builder) {
|
|
14837
14867
|
builder.arguments += event.delta ?? "";
|
|
14838
14868
|
}
|
|
14839
14869
|
break;
|
|
14840
14870
|
}
|
|
14841
14871
|
case "response.function_call_arguments.done": {
|
|
14842
|
-
const
|
|
14872
|
+
const builderKey = (event.item_id && fnCallBuilders.has(event.item_id) ? event.item_id : null) ?? (typeof event.output_index === "number" ? outputIndexToBuilderKey.get(event.output_index) ?? null : null) ?? (fnCallBuilders.size === 1 ? Array.from(fnCallBuilders.keys())[0] : null);
|
|
14873
|
+
if (!builderKey) break;
|
|
14874
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
14843
14875
|
if (builder) {
|
|
14844
14876
|
yield {
|
|
14845
14877
|
type: "tool_use_end",
|
|
@@ -14849,7 +14881,10 @@ var CodexProvider = class {
|
|
|
14849
14881
|
input: parseArguments(event.arguments ?? builder.arguments)
|
|
14850
14882
|
}
|
|
14851
14883
|
};
|
|
14852
|
-
fnCallBuilders.delete(
|
|
14884
|
+
fnCallBuilders.delete(builderKey);
|
|
14885
|
+
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
14886
|
+
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
14887
|
+
}
|
|
14853
14888
|
}
|
|
14854
14889
|
break;
|
|
14855
14890
|
}
|
|
@@ -15222,8 +15257,8 @@ var GeminiProvider = class {
|
|
|
15222
15257
|
const { history, lastMessage } = this.convertMessages(messages);
|
|
15223
15258
|
const chat = model.startChat({ history });
|
|
15224
15259
|
const result = await chat.sendMessageStream(lastMessage);
|
|
15225
|
-
const emittedToolCalls = /* @__PURE__ */ new Set();
|
|
15226
15260
|
let streamStopReason;
|
|
15261
|
+
let streamToolCallCounter = 0;
|
|
15227
15262
|
for await (const chunk of result.stream) {
|
|
15228
15263
|
const text = chunk.text();
|
|
15229
15264
|
if (text) {
|
|
@@ -15238,30 +15273,23 @@ var GeminiProvider = class {
|
|
|
15238
15273
|
for (const part of candidate.content.parts) {
|
|
15239
15274
|
if ("functionCall" in part && part.functionCall) {
|
|
15240
15275
|
const funcCall = part.functionCall;
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
}
|
|
15253
|
-
|
|
15254
|
-
|
|
15255
|
-
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
}
|
|
15259
|
-
};
|
|
15260
|
-
yield {
|
|
15261
|
-
type: "tool_use_end",
|
|
15262
|
-
toolCall
|
|
15263
|
-
};
|
|
15264
|
-
}
|
|
15276
|
+
streamToolCallCounter++;
|
|
15277
|
+
const toolCall = {
|
|
15278
|
+
id: `gemini_call_${streamToolCallCounter}`,
|
|
15279
|
+
name: funcCall.name,
|
|
15280
|
+
input: funcCall.args ?? {}
|
|
15281
|
+
};
|
|
15282
|
+
yield {
|
|
15283
|
+
type: "tool_use_start",
|
|
15284
|
+
toolCall: {
|
|
15285
|
+
id: toolCall.id,
|
|
15286
|
+
name: toolCall.name
|
|
15287
|
+
}
|
|
15288
|
+
};
|
|
15289
|
+
yield {
|
|
15290
|
+
type: "tool_use_end",
|
|
15291
|
+
toolCall
|
|
15292
|
+
};
|
|
15265
15293
|
}
|
|
15266
15294
|
}
|
|
15267
15295
|
}
|
|
@@ -15336,13 +15364,13 @@ var GeminiProvider = class {
|
|
|
15336
15364
|
* Convert messages to Gemini format
|
|
15337
15365
|
*/
|
|
15338
15366
|
convertMessages(messages) {
|
|
15367
|
+
const toolNameByUseId = this.buildToolUseNameMap(messages);
|
|
15368
|
+
const conversation = messages.filter((m) => m.role !== "system");
|
|
15339
15369
|
const history = [];
|
|
15340
15370
|
let lastUserMessage = "";
|
|
15341
|
-
for (
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
}
|
|
15345
|
-
const parts = this.convertContent(msg.content);
|
|
15371
|
+
for (let i = 0; i < conversation.length; i++) {
|
|
15372
|
+
const msg = conversation[i];
|
|
15373
|
+
const isLastMessage = i === conversation.length - 1;
|
|
15346
15374
|
if (msg.role === "user") {
|
|
15347
15375
|
if (Array.isArray(msg.content) && msg.content[0]?.type === "tool_result") {
|
|
15348
15376
|
const functionResponses = [];
|
|
@@ -15351,23 +15379,49 @@ var GeminiProvider = class {
|
|
|
15351
15379
|
const toolResult = block;
|
|
15352
15380
|
functionResponses.push({
|
|
15353
15381
|
functionResponse: {
|
|
15354
|
-
name
|
|
15355
|
-
//
|
|
15382
|
+
// Gemini expects the function name in functionResponse.name.
|
|
15383
|
+
// Recover it from prior assistant tool_use blocks when possible.
|
|
15384
|
+
name: toolNameByUseId.get(toolResult.tool_use_id) ?? toolResult.tool_use_id,
|
|
15356
15385
|
response: { result: toolResult.content }
|
|
15357
15386
|
}
|
|
15358
15387
|
});
|
|
15359
15388
|
}
|
|
15360
15389
|
}
|
|
15361
|
-
|
|
15390
|
+
if (isLastMessage) {
|
|
15391
|
+
lastUserMessage = functionResponses;
|
|
15392
|
+
} else {
|
|
15393
|
+
history.push({ role: "user", parts: functionResponses });
|
|
15394
|
+
}
|
|
15362
15395
|
} else {
|
|
15363
|
-
|
|
15396
|
+
const parts = this.convertContent(msg.content);
|
|
15397
|
+
if (isLastMessage) {
|
|
15398
|
+
lastUserMessage = parts;
|
|
15399
|
+
} else {
|
|
15400
|
+
history.push({ role: "user", parts });
|
|
15401
|
+
}
|
|
15364
15402
|
}
|
|
15365
15403
|
} else if (msg.role === "assistant") {
|
|
15404
|
+
const parts = this.convertContent(msg.content);
|
|
15366
15405
|
history.push({ role: "model", parts });
|
|
15367
15406
|
}
|
|
15368
15407
|
}
|
|
15369
15408
|
return { history, lastMessage: lastUserMessage };
|
|
15370
15409
|
}
|
|
15410
|
+
/**
|
|
15411
|
+
* Build a map from tool_use IDs to function names from assistant history.
|
|
15412
|
+
*/
|
|
15413
|
+
buildToolUseNameMap(messages) {
|
|
15414
|
+
const map = /* @__PURE__ */ new Map();
|
|
15415
|
+
for (const msg of messages) {
|
|
15416
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.content)) continue;
|
|
15417
|
+
for (const block of msg.content) {
|
|
15418
|
+
if (block.type === "tool_use") {
|
|
15419
|
+
map.set(block.id, block.name);
|
|
15420
|
+
}
|
|
15421
|
+
}
|
|
15422
|
+
}
|
|
15423
|
+
return map;
|
|
15424
|
+
}
|
|
15371
15425
|
/**
|
|
15372
15426
|
* Convert content to Gemini parts
|
|
15373
15427
|
*/
|
|
@@ -15444,14 +15498,15 @@ var GeminiProvider = class {
|
|
|
15444
15498
|
let textContent = "";
|
|
15445
15499
|
const toolCalls = [];
|
|
15446
15500
|
if (candidate?.content?.parts) {
|
|
15501
|
+
let toolIndex = 0;
|
|
15447
15502
|
for (const part of candidate.content.parts) {
|
|
15448
15503
|
if ("text" in part && part.text) {
|
|
15449
15504
|
textContent += part.text;
|
|
15450
15505
|
}
|
|
15451
15506
|
if ("functionCall" in part && part.functionCall) {
|
|
15507
|
+
toolIndex++;
|
|
15452
15508
|
toolCalls.push({
|
|
15453
|
-
id:
|
|
15454
|
-
// Use name as ID for Gemini
|
|
15509
|
+
id: `gemini_call_${toolIndex}`,
|
|
15455
15510
|
name: part.functionCall.name,
|
|
15456
15511
|
input: part.functionCall.args ?? {}
|
|
15457
15512
|
});
|