@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/cli/index.js
CHANGED
|
@@ -1792,6 +1792,7 @@ var init_openai = __esm({
|
|
|
1792
1792
|
requestParams
|
|
1793
1793
|
);
|
|
1794
1794
|
const toolCallBuilders = /* @__PURE__ */ new Map();
|
|
1795
|
+
let lastToolCallKey = null;
|
|
1795
1796
|
const streamTimeout = this.config.timeout ?? 12e4;
|
|
1796
1797
|
let lastActivityTime = Date.now();
|
|
1797
1798
|
const timeoutController = new AbortController();
|
|
@@ -1841,9 +1842,9 @@ var init_openai = __esm({
|
|
|
1841
1842
|
}
|
|
1842
1843
|
if (delta?.tool_calls) {
|
|
1843
1844
|
for (const toolCallDelta of delta.tool_calls) {
|
|
1844
|
-
const
|
|
1845
|
-
if (!toolCallBuilders.has(
|
|
1846
|
-
toolCallBuilders.set(
|
|
1845
|
+
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}`;
|
|
1846
|
+
if (!toolCallBuilders.has(key)) {
|
|
1847
|
+
toolCallBuilders.set(key, {
|
|
1847
1848
|
id: toolCallDelta.id ?? "",
|
|
1848
1849
|
name: toolCallDelta.function?.name ?? "",
|
|
1849
1850
|
arguments: ""
|
|
@@ -1856,7 +1857,8 @@ var init_openai = __esm({
|
|
|
1856
1857
|
}
|
|
1857
1858
|
};
|
|
1858
1859
|
}
|
|
1859
|
-
const builder = toolCallBuilders.get(
|
|
1860
|
+
const builder = toolCallBuilders.get(key);
|
|
1861
|
+
lastToolCallKey = key;
|
|
1860
1862
|
if (toolCallDelta.id) {
|
|
1861
1863
|
builder.id = toolCallDelta.id;
|
|
1862
1864
|
}
|
|
@@ -2444,6 +2446,7 @@ var init_openai = __esm({
|
|
|
2444
2446
|
requestParams
|
|
2445
2447
|
);
|
|
2446
2448
|
const fnCallBuilders = /* @__PURE__ */ new Map();
|
|
2449
|
+
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
2447
2450
|
const streamTimeout = this.config.timeout ?? 12e4;
|
|
2448
2451
|
let lastActivityTime = Date.now();
|
|
2449
2452
|
const timeoutController = new AbortController();
|
|
@@ -2473,8 +2476,11 @@ var init_openai = __esm({
|
|
|
2473
2476
|
fnCallBuilders.set(itemKey, {
|
|
2474
2477
|
callId: fc.call_id,
|
|
2475
2478
|
name: fc.name,
|
|
2476
|
-
arguments: ""
|
|
2479
|
+
arguments: fc.arguments ?? ""
|
|
2477
2480
|
});
|
|
2481
|
+
if (typeof event.output_index === "number") {
|
|
2482
|
+
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
2483
|
+
}
|
|
2478
2484
|
yield {
|
|
2479
2485
|
type: "tool_use_start",
|
|
2480
2486
|
toolCall: { id: fc.call_id, name: fc.name }
|
|
@@ -2483,7 +2489,9 @@ var init_openai = __esm({
|
|
|
2483
2489
|
break;
|
|
2484
2490
|
case "response.function_call_arguments.delta":
|
|
2485
2491
|
{
|
|
2486
|
-
const
|
|
2492
|
+
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);
|
|
2493
|
+
if (!builderKey) break;
|
|
2494
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
2487
2495
|
if (builder) {
|
|
2488
2496
|
builder.arguments += event.delta;
|
|
2489
2497
|
}
|
|
@@ -2491,17 +2499,22 @@ var init_openai = __esm({
|
|
|
2491
2499
|
break;
|
|
2492
2500
|
case "response.function_call_arguments.done":
|
|
2493
2501
|
{
|
|
2494
|
-
const
|
|
2502
|
+
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);
|
|
2503
|
+
if (!builderKey) break;
|
|
2504
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
2495
2505
|
if (builder) {
|
|
2496
2506
|
yield {
|
|
2497
2507
|
type: "tool_use_end",
|
|
2498
2508
|
toolCall: {
|
|
2499
2509
|
id: builder.callId,
|
|
2500
2510
|
name: builder.name,
|
|
2501
|
-
input: this.parseResponsesArguments(event.arguments)
|
|
2511
|
+
input: this.parseResponsesArguments(event.arguments ?? builder.arguments)
|
|
2502
2512
|
}
|
|
2503
2513
|
};
|
|
2504
|
-
fnCallBuilders.delete(
|
|
2514
|
+
fnCallBuilders.delete(builderKey);
|
|
2515
|
+
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
2516
|
+
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
2517
|
+
}
|
|
2505
2518
|
}
|
|
2506
2519
|
}
|
|
2507
2520
|
break;
|
|
@@ -4640,6 +4653,7 @@ var init_codex = __esm({
|
|
|
4640
4653
|
let outputTokens = 0;
|
|
4641
4654
|
const toolCalls = [];
|
|
4642
4655
|
const fnCallBuilders = /* @__PURE__ */ new Map();
|
|
4656
|
+
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
4643
4657
|
await this.readSSEStream(response, (event) => {
|
|
4644
4658
|
if (event.id) responseId = event.id;
|
|
4645
4659
|
switch (event.type) {
|
|
@@ -4656,25 +4670,35 @@ var init_codex = __esm({
|
|
|
4656
4670
|
fnCallBuilders.set(itemKey, {
|
|
4657
4671
|
callId: item.call_id,
|
|
4658
4672
|
name: item.name,
|
|
4659
|
-
arguments: ""
|
|
4673
|
+
arguments: item.arguments ?? ""
|
|
4660
4674
|
});
|
|
4675
|
+
if (typeof event.output_index === "number") {
|
|
4676
|
+
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
4677
|
+
}
|
|
4661
4678
|
}
|
|
4662
4679
|
break;
|
|
4663
4680
|
}
|
|
4664
4681
|
case "response.function_call_arguments.delta": {
|
|
4665
|
-
const
|
|
4682
|
+
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);
|
|
4683
|
+
if (!builderKey) break;
|
|
4684
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
4666
4685
|
if (builder) builder.arguments += event.delta ?? "";
|
|
4667
4686
|
break;
|
|
4668
4687
|
}
|
|
4669
4688
|
case "response.function_call_arguments.done": {
|
|
4670
|
-
const
|
|
4689
|
+
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);
|
|
4690
|
+
if (!builderKey) break;
|
|
4691
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
4671
4692
|
if (builder) {
|
|
4672
4693
|
toolCalls.push({
|
|
4673
4694
|
id: builder.callId,
|
|
4674
4695
|
name: builder.name,
|
|
4675
|
-
input: parseArguments(event.arguments)
|
|
4696
|
+
input: parseArguments(event.arguments ?? builder.arguments)
|
|
4676
4697
|
});
|
|
4677
|
-
fnCallBuilders.delete(
|
|
4698
|
+
fnCallBuilders.delete(builderKey);
|
|
4699
|
+
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
4700
|
+
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
4701
|
+
}
|
|
4678
4702
|
}
|
|
4679
4703
|
break;
|
|
4680
4704
|
}
|
|
@@ -4787,6 +4811,7 @@ var init_codex = __esm({
|
|
|
4787
4811
|
const decoder = new TextDecoder();
|
|
4788
4812
|
let buffer = "";
|
|
4789
4813
|
const fnCallBuilders = /* @__PURE__ */ new Map();
|
|
4814
|
+
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
4790
4815
|
let lastActivityTime = Date.now();
|
|
4791
4816
|
const timeoutController = new AbortController();
|
|
4792
4817
|
const timeoutInterval = setInterval(() => {
|
|
@@ -4825,8 +4850,11 @@ var init_codex = __esm({
|
|
|
4825
4850
|
fnCallBuilders.set(itemKey, {
|
|
4826
4851
|
callId: item.call_id,
|
|
4827
4852
|
name: item.name,
|
|
4828
|
-
arguments: ""
|
|
4853
|
+
arguments: item.arguments ?? ""
|
|
4829
4854
|
});
|
|
4855
|
+
if (typeof event.output_index === "number") {
|
|
4856
|
+
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
4857
|
+
}
|
|
4830
4858
|
yield {
|
|
4831
4859
|
type: "tool_use_start",
|
|
4832
4860
|
toolCall: { id: item.call_id, name: item.name }
|
|
@@ -4835,14 +4863,18 @@ var init_codex = __esm({
|
|
|
4835
4863
|
break;
|
|
4836
4864
|
}
|
|
4837
4865
|
case "response.function_call_arguments.delta": {
|
|
4838
|
-
const
|
|
4866
|
+
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);
|
|
4867
|
+
if (!builderKey) break;
|
|
4868
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
4839
4869
|
if (builder) {
|
|
4840
4870
|
builder.arguments += event.delta ?? "";
|
|
4841
4871
|
}
|
|
4842
4872
|
break;
|
|
4843
4873
|
}
|
|
4844
4874
|
case "response.function_call_arguments.done": {
|
|
4845
|
-
const
|
|
4875
|
+
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);
|
|
4876
|
+
if (!builderKey) break;
|
|
4877
|
+
const builder = fnCallBuilders.get(builderKey);
|
|
4846
4878
|
if (builder) {
|
|
4847
4879
|
yield {
|
|
4848
4880
|
type: "tool_use_end",
|
|
@@ -4852,7 +4884,10 @@ var init_codex = __esm({
|
|
|
4852
4884
|
input: parseArguments(event.arguments ?? builder.arguments)
|
|
4853
4885
|
}
|
|
4854
4886
|
};
|
|
4855
|
-
fnCallBuilders.delete(
|
|
4887
|
+
fnCallBuilders.delete(builderKey);
|
|
4888
|
+
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
4889
|
+
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
4890
|
+
}
|
|
4856
4891
|
}
|
|
4857
4892
|
break;
|
|
4858
4893
|
}
|
|
@@ -5243,8 +5278,8 @@ var init_gemini = __esm({
|
|
|
5243
5278
|
const { history, lastMessage } = this.convertMessages(messages);
|
|
5244
5279
|
const chat = model.startChat({ history });
|
|
5245
5280
|
const result = await chat.sendMessageStream(lastMessage);
|
|
5246
|
-
const emittedToolCalls = /* @__PURE__ */ new Set();
|
|
5247
5281
|
let streamStopReason;
|
|
5282
|
+
let streamToolCallCounter = 0;
|
|
5248
5283
|
for await (const chunk of result.stream) {
|
|
5249
5284
|
const text13 = chunk.text();
|
|
5250
5285
|
if (text13) {
|
|
@@ -5259,30 +5294,23 @@ var init_gemini = __esm({
|
|
|
5259
5294
|
for (const part of candidate.content.parts) {
|
|
5260
5295
|
if ("functionCall" in part && part.functionCall) {
|
|
5261
5296
|
const funcCall = part.functionCall;
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
}
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
}
|
|
5280
|
-
};
|
|
5281
|
-
yield {
|
|
5282
|
-
type: "tool_use_end",
|
|
5283
|
-
toolCall
|
|
5284
|
-
};
|
|
5285
|
-
}
|
|
5297
|
+
streamToolCallCounter++;
|
|
5298
|
+
const toolCall = {
|
|
5299
|
+
id: `gemini_call_${streamToolCallCounter}`,
|
|
5300
|
+
name: funcCall.name,
|
|
5301
|
+
input: funcCall.args ?? {}
|
|
5302
|
+
};
|
|
5303
|
+
yield {
|
|
5304
|
+
type: "tool_use_start",
|
|
5305
|
+
toolCall: {
|
|
5306
|
+
id: toolCall.id,
|
|
5307
|
+
name: toolCall.name
|
|
5308
|
+
}
|
|
5309
|
+
};
|
|
5310
|
+
yield {
|
|
5311
|
+
type: "tool_use_end",
|
|
5312
|
+
toolCall
|
|
5313
|
+
};
|
|
5286
5314
|
}
|
|
5287
5315
|
}
|
|
5288
5316
|
}
|
|
@@ -5357,13 +5385,13 @@ var init_gemini = __esm({
|
|
|
5357
5385
|
* Convert messages to Gemini format
|
|
5358
5386
|
*/
|
|
5359
5387
|
convertMessages(messages) {
|
|
5388
|
+
const toolNameByUseId = this.buildToolUseNameMap(messages);
|
|
5389
|
+
const conversation = messages.filter((m) => m.role !== "system");
|
|
5360
5390
|
const history = [];
|
|
5361
5391
|
let lastUserMessage = "";
|
|
5362
|
-
for (
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
}
|
|
5366
|
-
const parts = this.convertContent(msg.content);
|
|
5392
|
+
for (let i = 0; i < conversation.length; i++) {
|
|
5393
|
+
const msg = conversation[i];
|
|
5394
|
+
const isLastMessage = i === conversation.length - 1;
|
|
5367
5395
|
if (msg.role === "user") {
|
|
5368
5396
|
if (Array.isArray(msg.content) && msg.content[0]?.type === "tool_result") {
|
|
5369
5397
|
const functionResponses = [];
|
|
@@ -5372,23 +5400,49 @@ var init_gemini = __esm({
|
|
|
5372
5400
|
const toolResult = block;
|
|
5373
5401
|
functionResponses.push({
|
|
5374
5402
|
functionResponse: {
|
|
5375
|
-
name
|
|
5376
|
-
//
|
|
5403
|
+
// Gemini expects the function name in functionResponse.name.
|
|
5404
|
+
// Recover it from prior assistant tool_use blocks when possible.
|
|
5405
|
+
name: toolNameByUseId.get(toolResult.tool_use_id) ?? toolResult.tool_use_id,
|
|
5377
5406
|
response: { result: toolResult.content }
|
|
5378
5407
|
}
|
|
5379
5408
|
});
|
|
5380
5409
|
}
|
|
5381
5410
|
}
|
|
5382
|
-
|
|
5411
|
+
if (isLastMessage) {
|
|
5412
|
+
lastUserMessage = functionResponses;
|
|
5413
|
+
} else {
|
|
5414
|
+
history.push({ role: "user", parts: functionResponses });
|
|
5415
|
+
}
|
|
5383
5416
|
} else {
|
|
5384
|
-
|
|
5417
|
+
const parts = this.convertContent(msg.content);
|
|
5418
|
+
if (isLastMessage) {
|
|
5419
|
+
lastUserMessage = parts;
|
|
5420
|
+
} else {
|
|
5421
|
+
history.push({ role: "user", parts });
|
|
5422
|
+
}
|
|
5385
5423
|
}
|
|
5386
5424
|
} else if (msg.role === "assistant") {
|
|
5425
|
+
const parts = this.convertContent(msg.content);
|
|
5387
5426
|
history.push({ role: "model", parts });
|
|
5388
5427
|
}
|
|
5389
5428
|
}
|
|
5390
5429
|
return { history, lastMessage: lastUserMessage };
|
|
5391
5430
|
}
|
|
5431
|
+
/**
|
|
5432
|
+
* Build a map from tool_use IDs to function names from assistant history.
|
|
5433
|
+
*/
|
|
5434
|
+
buildToolUseNameMap(messages) {
|
|
5435
|
+
const map = /* @__PURE__ */ new Map();
|
|
5436
|
+
for (const msg of messages) {
|
|
5437
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.content)) continue;
|
|
5438
|
+
for (const block of msg.content) {
|
|
5439
|
+
if (block.type === "tool_use") {
|
|
5440
|
+
map.set(block.id, block.name);
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5444
|
+
return map;
|
|
5445
|
+
}
|
|
5392
5446
|
/**
|
|
5393
5447
|
* Convert content to Gemini parts
|
|
5394
5448
|
*/
|
|
@@ -5465,14 +5519,15 @@ var init_gemini = __esm({
|
|
|
5465
5519
|
let textContent = "";
|
|
5466
5520
|
const toolCalls = [];
|
|
5467
5521
|
if (candidate?.content?.parts) {
|
|
5522
|
+
let toolIndex = 0;
|
|
5468
5523
|
for (const part of candidate.content.parts) {
|
|
5469
5524
|
if ("text" in part && part.text) {
|
|
5470
5525
|
textContent += part.text;
|
|
5471
5526
|
}
|
|
5472
5527
|
if ("functionCall" in part && part.functionCall) {
|
|
5528
|
+
toolIndex++;
|
|
5473
5529
|
toolCalls.push({
|
|
5474
|
-
id:
|
|
5475
|
-
// Use name as ID for Gemini
|
|
5530
|
+
id: `gemini_call_${toolIndex}`,
|
|
5476
5531
|
name: part.functionCall.name,
|
|
5477
5532
|
input: part.functionCall.args ?? {}
|
|
5478
5533
|
});
|
|
@@ -31546,6 +31601,15 @@ async function selectModelInteractively(models, currentModelId) {
|
|
|
31546
31601
|
renderMenu();
|
|
31547
31602
|
});
|
|
31548
31603
|
}
|
|
31604
|
+
async function persistModelPreference(provider, model) {
|
|
31605
|
+
try {
|
|
31606
|
+
await saveProviderPreference(provider, model);
|
|
31607
|
+
} catch (error) {
|
|
31608
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
31609
|
+
console.log(chalk2.yellow(`\u26A0 Could not persist model preference: ${reason}`));
|
|
31610
|
+
console.log(chalk2.dim(" Model changed for this session only.\n"));
|
|
31611
|
+
}
|
|
31612
|
+
}
|
|
31549
31613
|
var modelCommand = {
|
|
31550
31614
|
name: "model",
|
|
31551
31615
|
aliases: ["m"],
|
|
@@ -31594,7 +31658,7 @@ var modelCommand = {
|
|
|
31594
31658
|
return false;
|
|
31595
31659
|
}
|
|
31596
31660
|
session.config.provider.model = selectedModel;
|
|
31597
|
-
await
|
|
31661
|
+
await persistModelPreference(currentProvider, selectedModel);
|
|
31598
31662
|
const modelInfo2 = providerDef.models.find((m) => m.id === selectedModel);
|
|
31599
31663
|
console.log(chalk2.green(`\u2713 Switched to ${modelInfo2?.name ?? selectedModel}
|
|
31600
31664
|
`));
|
|
@@ -31616,7 +31680,7 @@ var modelCommand = {
|
|
|
31616
31680
|
if (!foundInProvider) {
|
|
31617
31681
|
console.log(chalk2.yellow(`Model "${newModel}" not in known list, setting anyway...`));
|
|
31618
31682
|
session.config.provider.model = newModel;
|
|
31619
|
-
await
|
|
31683
|
+
await persistModelPreference(currentProvider, newModel);
|
|
31620
31684
|
console.log(chalk2.green(`\u2713 Model set to: ${newModel}
|
|
31621
31685
|
`));
|
|
31622
31686
|
return false;
|
|
@@ -31631,7 +31695,7 @@ var modelCommand = {
|
|
|
31631
31695
|
return false;
|
|
31632
31696
|
}
|
|
31633
31697
|
session.config.provider.model = newModel;
|
|
31634
|
-
await
|
|
31698
|
+
await persistModelPreference(currentProvider, newModel);
|
|
31635
31699
|
const modelInfo = providerDef.models.find((m) => m.id === newModel);
|
|
31636
31700
|
console.log(chalk2.green(`\u2713 Switched to ${modelInfo?.name ?? newModel}
|
|
31637
31701
|
`));
|