@corbat-tech/coco 2.8.0 → 2.8.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/dist/cli/index.js +228 -105
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +150 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -993,6 +993,8 @@ interface ChatOptions {
|
|
|
993
993
|
stopSequences?: string[];
|
|
994
994
|
system?: string;
|
|
995
995
|
timeout?: number;
|
|
996
|
+
/** Abort signal to cancel in-flight requests */
|
|
997
|
+
signal?: AbortSignal;
|
|
996
998
|
}
|
|
997
999
|
/**
|
|
998
1000
|
* Chat response
|
|
@@ -1030,6 +1032,7 @@ interface StreamChunk {
|
|
|
1030
1032
|
type: "text" | "tool_use_start" | "tool_use_delta" | "tool_use_end" | "done";
|
|
1031
1033
|
text?: string;
|
|
1032
1034
|
toolCall?: Partial<ToolCall>;
|
|
1035
|
+
stopReason?: "end_turn" | "max_tokens" | "stop_sequence" | "tool_use";
|
|
1033
1036
|
}
|
|
1034
1037
|
/**
|
|
1035
1038
|
* LLM Provider interface
|
package/dist/index.js
CHANGED
|
@@ -11784,22 +11784,44 @@ var AnthropicProvider = class {
|
|
|
11784
11784
|
async *stream(messages, options) {
|
|
11785
11785
|
this.ensureInitialized();
|
|
11786
11786
|
try {
|
|
11787
|
-
const stream = await this.client.messages.stream(
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11787
|
+
const stream = await this.client.messages.stream(
|
|
11788
|
+
{
|
|
11789
|
+
model: options?.model ?? this.config.model ?? DEFAULT_MODEL,
|
|
11790
|
+
max_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
11791
|
+
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
11792
|
+
system: this.extractSystem(messages, options?.system),
|
|
11793
|
+
messages: this.convertMessages(messages)
|
|
11794
|
+
},
|
|
11795
|
+
{ signal: options?.signal }
|
|
11796
|
+
);
|
|
11797
|
+
const streamTimeout = this.config.timeout ?? 12e4;
|
|
11798
|
+
let lastActivityTime = Date.now();
|
|
11799
|
+
const checkTimeout = () => {
|
|
11800
|
+
if (Date.now() - lastActivityTime > streamTimeout) {
|
|
11801
|
+
throw new Error(`Stream timeout: No response from LLM for ${streamTimeout / 1e3}s`);
|
|
11802
|
+
}
|
|
11803
|
+
};
|
|
11804
|
+
const timeoutInterval = setInterval(checkTimeout, 5e3);
|
|
11805
|
+
try {
|
|
11806
|
+
let streamStopReason;
|
|
11807
|
+
for await (const event of stream) {
|
|
11808
|
+
lastActivityTime = Date.now();
|
|
11809
|
+
if (event.type === "content_block_delta") {
|
|
11810
|
+
const delta = event.delta;
|
|
11811
|
+
if (delta.type === "text_delta" && delta.text) {
|
|
11812
|
+
yield { type: "text", text: delta.text };
|
|
11813
|
+
}
|
|
11814
|
+
} else if (event.type === "message_delta") {
|
|
11815
|
+
const delta = event.delta;
|
|
11816
|
+
if (delta.stop_reason) {
|
|
11817
|
+
streamStopReason = this.mapStopReason(delta.stop_reason);
|
|
11818
|
+
}
|
|
11799
11819
|
}
|
|
11800
11820
|
}
|
|
11821
|
+
yield { type: "done", stopReason: streamStopReason };
|
|
11822
|
+
} finally {
|
|
11823
|
+
clearInterval(timeoutInterval);
|
|
11801
11824
|
}
|
|
11802
|
-
yield { type: "done" };
|
|
11803
11825
|
} catch (error) {
|
|
11804
11826
|
throw this.handleError(error);
|
|
11805
11827
|
}
|
|
@@ -11810,90 +11832,112 @@ var AnthropicProvider = class {
|
|
|
11810
11832
|
async *streamWithTools(messages, options) {
|
|
11811
11833
|
this.ensureInitialized();
|
|
11812
11834
|
try {
|
|
11813
|
-
const stream = await this.client.messages.stream(
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11835
|
+
const stream = await this.client.messages.stream(
|
|
11836
|
+
{
|
|
11837
|
+
model: options?.model ?? this.config.model ?? DEFAULT_MODEL,
|
|
11838
|
+
max_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
11839
|
+
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
11840
|
+
system: this.extractSystem(messages, options?.system),
|
|
11841
|
+
messages: this.convertMessages(messages),
|
|
11842
|
+
tools: this.convertTools(options.tools),
|
|
11843
|
+
tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0
|
|
11844
|
+
},
|
|
11845
|
+
{ signal: options?.signal }
|
|
11846
|
+
);
|
|
11822
11847
|
let currentToolCall = null;
|
|
11823
11848
|
let currentToolInputJson = "";
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11849
|
+
const streamTimeout = this.config.timeout ?? 12e4;
|
|
11850
|
+
let lastActivityTime = Date.now();
|
|
11851
|
+
const checkTimeout = () => {
|
|
11852
|
+
if (Date.now() - lastActivityTime > streamTimeout) {
|
|
11853
|
+
throw new Error(`Stream timeout: No response from LLM for ${streamTimeout / 1e3}s`);
|
|
11854
|
+
}
|
|
11855
|
+
};
|
|
11856
|
+
const timeoutInterval = setInterval(checkTimeout, 5e3);
|
|
11857
|
+
try {
|
|
11858
|
+
let streamStopReason;
|
|
11859
|
+
for await (const event of stream) {
|
|
11860
|
+
lastActivityTime = Date.now();
|
|
11861
|
+
if (event.type === "message_delta") {
|
|
11862
|
+
const delta = event.delta;
|
|
11863
|
+
if (delta.stop_reason) {
|
|
11864
|
+
streamStopReason = this.mapStopReason(delta.stop_reason);
|
|
11865
|
+
}
|
|
11866
|
+
} else if (event.type === "content_block_start") {
|
|
11867
|
+
const contentBlock = event.content_block;
|
|
11868
|
+
if (contentBlock.type === "tool_use") {
|
|
11869
|
+
if (currentToolCall) {
|
|
11870
|
+
getLogger().warn(
|
|
11871
|
+
`[Anthropic] content_block_stop missing for tool '${currentToolCall.name}' \u2014 finalizing early to prevent data bleed.`
|
|
11872
|
+
);
|
|
11873
|
+
try {
|
|
11874
|
+
currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
|
|
11875
|
+
} catch {
|
|
11876
|
+
currentToolCall.input = {};
|
|
11877
|
+
}
|
|
11878
|
+
yield {
|
|
11879
|
+
type: "tool_use_end",
|
|
11880
|
+
toolCall: { ...currentToolCall }
|
|
11881
|
+
};
|
|
11882
|
+
}
|
|
11883
|
+
currentToolCall = {
|
|
11884
|
+
id: contentBlock.id,
|
|
11885
|
+
name: contentBlock.name
|
|
11886
|
+
};
|
|
11887
|
+
currentToolInputJson = "";
|
|
11888
|
+
yield {
|
|
11889
|
+
type: "tool_use_start",
|
|
11890
|
+
toolCall: { ...currentToolCall }
|
|
11891
|
+
};
|
|
11892
|
+
}
|
|
11893
|
+
} else if (event.type === "content_block_delta") {
|
|
11894
|
+
const delta = event.delta;
|
|
11895
|
+
if (delta.type === "text_delta" && delta.text) {
|
|
11896
|
+
yield { type: "text", text: delta.text };
|
|
11897
|
+
} else if (delta.type === "input_json_delta" && delta.partial_json) {
|
|
11898
|
+
currentToolInputJson += delta.partial_json;
|
|
11899
|
+
yield {
|
|
11900
|
+
type: "tool_use_delta",
|
|
11901
|
+
toolCall: {
|
|
11902
|
+
...currentToolCall
|
|
11903
|
+
},
|
|
11904
|
+
text: delta.partial_json
|
|
11905
|
+
};
|
|
11906
|
+
}
|
|
11907
|
+
} else if (event.type === "content_block_stop") {
|
|
11828
11908
|
if (currentToolCall) {
|
|
11829
|
-
getLogger().warn(
|
|
11830
|
-
`[Anthropic] content_block_stop missing for tool '${currentToolCall.name}' \u2014 finalizing early to prevent data bleed.`
|
|
11831
|
-
);
|
|
11832
11909
|
try {
|
|
11833
11910
|
currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
|
|
11834
11911
|
} catch {
|
|
11835
|
-
|
|
11912
|
+
let repaired = false;
|
|
11913
|
+
if (currentToolInputJson) {
|
|
11914
|
+
try {
|
|
11915
|
+
currentToolCall.input = JSON.parse(jsonrepair(currentToolInputJson));
|
|
11916
|
+
repaired = true;
|
|
11917
|
+
getLogger().debug(`Repaired JSON for tool ${currentToolCall.name}`);
|
|
11918
|
+
} catch {
|
|
11919
|
+
}
|
|
11920
|
+
}
|
|
11921
|
+
if (!repaired) {
|
|
11922
|
+
getLogger().warn(
|
|
11923
|
+
`Failed to parse tool call arguments for ${currentToolCall.name}: ${currentToolInputJson?.slice(0, 300)}`
|
|
11924
|
+
);
|
|
11925
|
+
currentToolCall.input = {};
|
|
11926
|
+
}
|
|
11836
11927
|
}
|
|
11837
11928
|
yield {
|
|
11838
11929
|
type: "tool_use_end",
|
|
11839
11930
|
toolCall: { ...currentToolCall }
|
|
11840
11931
|
};
|
|
11932
|
+
currentToolCall = null;
|
|
11933
|
+
currentToolInputJson = "";
|
|
11841
11934
|
}
|
|
11842
|
-
currentToolCall = {
|
|
11843
|
-
id: contentBlock.id,
|
|
11844
|
-
name: contentBlock.name
|
|
11845
|
-
};
|
|
11846
|
-
currentToolInputJson = "";
|
|
11847
|
-
yield {
|
|
11848
|
-
type: "tool_use_start",
|
|
11849
|
-
toolCall: { ...currentToolCall }
|
|
11850
|
-
};
|
|
11851
|
-
}
|
|
11852
|
-
} else if (event.type === "content_block_delta") {
|
|
11853
|
-
const delta = event.delta;
|
|
11854
|
-
if (delta.type === "text_delta" && delta.text) {
|
|
11855
|
-
yield { type: "text", text: delta.text };
|
|
11856
|
-
} else if (delta.type === "input_json_delta" && delta.partial_json) {
|
|
11857
|
-
currentToolInputJson += delta.partial_json;
|
|
11858
|
-
yield {
|
|
11859
|
-
type: "tool_use_delta",
|
|
11860
|
-
toolCall: {
|
|
11861
|
-
...currentToolCall
|
|
11862
|
-
},
|
|
11863
|
-
text: delta.partial_json
|
|
11864
|
-
};
|
|
11865
|
-
}
|
|
11866
|
-
} else if (event.type === "content_block_stop") {
|
|
11867
|
-
if (currentToolCall) {
|
|
11868
|
-
try {
|
|
11869
|
-
currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
|
|
11870
|
-
} catch {
|
|
11871
|
-
let repaired = false;
|
|
11872
|
-
if (currentToolInputJson) {
|
|
11873
|
-
try {
|
|
11874
|
-
currentToolCall.input = JSON.parse(jsonrepair(currentToolInputJson));
|
|
11875
|
-
repaired = true;
|
|
11876
|
-
getLogger().debug(`Repaired JSON for tool ${currentToolCall.name}`);
|
|
11877
|
-
} catch {
|
|
11878
|
-
}
|
|
11879
|
-
}
|
|
11880
|
-
if (!repaired) {
|
|
11881
|
-
getLogger().warn(
|
|
11882
|
-
`Failed to parse tool call arguments for ${currentToolCall.name}: ${currentToolInputJson?.slice(0, 300)}`
|
|
11883
|
-
);
|
|
11884
|
-
currentToolCall.input = {};
|
|
11885
|
-
}
|
|
11886
|
-
}
|
|
11887
|
-
yield {
|
|
11888
|
-
type: "tool_use_end",
|
|
11889
|
-
toolCall: { ...currentToolCall }
|
|
11890
|
-
};
|
|
11891
|
-
currentToolCall = null;
|
|
11892
|
-
currentToolInputJson = "";
|
|
11893
11935
|
}
|
|
11894
11936
|
}
|
|
11937
|
+
yield { type: "done", stopReason: streamStopReason };
|
|
11938
|
+
} finally {
|
|
11939
|
+
clearInterval(timeoutInterval);
|
|
11895
11940
|
}
|
|
11896
|
-
yield { type: "done" };
|
|
11897
11941
|
} catch (error) {
|
|
11898
11942
|
throw this.handleError(error);
|
|
11899
11943
|
}
|
|
@@ -12386,13 +12430,18 @@ var OpenAIProvider = class {
|
|
|
12386
12430
|
stream: true,
|
|
12387
12431
|
...supportsTemp && { temperature: options?.temperature ?? this.config.temperature ?? 0 }
|
|
12388
12432
|
});
|
|
12433
|
+
let streamStopReason;
|
|
12389
12434
|
for await (const chunk of stream) {
|
|
12390
12435
|
const delta = chunk.choices[0]?.delta;
|
|
12391
12436
|
if (delta?.content) {
|
|
12392
12437
|
yield { type: "text", text: delta.content };
|
|
12393
12438
|
}
|
|
12439
|
+
const finishReason = chunk.choices[0]?.finish_reason;
|
|
12440
|
+
if (finishReason) {
|
|
12441
|
+
streamStopReason = this.mapFinishReason(finishReason);
|
|
12442
|
+
}
|
|
12394
12443
|
}
|
|
12395
|
-
yield { type: "done" };
|
|
12444
|
+
yield { type: "done", stopReason: streamStopReason };
|
|
12396
12445
|
} catch (error) {
|
|
12397
12446
|
throw this.handleError(error);
|
|
12398
12447
|
}
|
|
@@ -12457,6 +12506,7 @@ var OpenAIProvider = class {
|
|
|
12457
12506
|
return input;
|
|
12458
12507
|
};
|
|
12459
12508
|
try {
|
|
12509
|
+
let streamStopReason;
|
|
12460
12510
|
for await (const chunk of stream) {
|
|
12461
12511
|
const delta = chunk.choices[0]?.delta;
|
|
12462
12512
|
if (delta?.content || delta?.tool_calls) {
|
|
@@ -12503,6 +12553,9 @@ var OpenAIProvider = class {
|
|
|
12503
12553
|
}
|
|
12504
12554
|
}
|
|
12505
12555
|
const finishReason = chunk.choices[0]?.finish_reason;
|
|
12556
|
+
if (finishReason) {
|
|
12557
|
+
streamStopReason = this.mapFinishReason(finishReason);
|
|
12558
|
+
}
|
|
12506
12559
|
if (finishReason && toolCallBuilders.size > 0) {
|
|
12507
12560
|
for (const [, builder] of toolCallBuilders) {
|
|
12508
12561
|
yield {
|
|
@@ -12527,7 +12580,7 @@ var OpenAIProvider = class {
|
|
|
12527
12580
|
}
|
|
12528
12581
|
};
|
|
12529
12582
|
}
|
|
12530
|
-
yield { type: "done" };
|
|
12583
|
+
yield { type: "done", stopReason: streamStopReason };
|
|
12531
12584
|
} finally {
|
|
12532
12585
|
clearInterval(timeoutInterval);
|
|
12533
12586
|
}
|
|
@@ -13290,7 +13343,7 @@ var CodexProvider = class {
|
|
|
13290
13343
|
}
|
|
13291
13344
|
}
|
|
13292
13345
|
}
|
|
13293
|
-
yield { type: "done" };
|
|
13346
|
+
yield { type: "done", stopReason: response.stopReason };
|
|
13294
13347
|
}
|
|
13295
13348
|
/**
|
|
13296
13349
|
* Stream a chat response with tool use
|
|
@@ -13443,13 +13496,18 @@ var GeminiProvider = class {
|
|
|
13443
13496
|
const { history, lastMessage } = this.convertMessages(messages);
|
|
13444
13497
|
const chat = model.startChat({ history });
|
|
13445
13498
|
const result = await chat.sendMessageStream(lastMessage);
|
|
13499
|
+
let streamStopReason;
|
|
13446
13500
|
for await (const chunk of result.stream) {
|
|
13447
13501
|
const text = chunk.text();
|
|
13448
13502
|
if (text) {
|
|
13449
13503
|
yield { type: "text", text };
|
|
13450
13504
|
}
|
|
13505
|
+
const finishReason = chunk.candidates?.[0]?.finishReason;
|
|
13506
|
+
if (finishReason) {
|
|
13507
|
+
streamStopReason = this.mapFinishReason(finishReason);
|
|
13508
|
+
}
|
|
13451
13509
|
}
|
|
13452
|
-
yield { type: "done" };
|
|
13510
|
+
yield { type: "done", stopReason: streamStopReason };
|
|
13453
13511
|
} catch (error) {
|
|
13454
13512
|
throw this.handleError(error);
|
|
13455
13513
|
}
|
|
@@ -13484,11 +13542,16 @@ var GeminiProvider = class {
|
|
|
13484
13542
|
const chat = model.startChat({ history });
|
|
13485
13543
|
const result = await chat.sendMessageStream(lastMessage);
|
|
13486
13544
|
const emittedToolCalls = /* @__PURE__ */ new Set();
|
|
13545
|
+
let streamStopReason;
|
|
13487
13546
|
for await (const chunk of result.stream) {
|
|
13488
13547
|
const text = chunk.text();
|
|
13489
13548
|
if (text) {
|
|
13490
13549
|
yield { type: "text", text };
|
|
13491
13550
|
}
|
|
13551
|
+
const finishReason = chunk.candidates?.[0]?.finishReason;
|
|
13552
|
+
if (finishReason) {
|
|
13553
|
+
streamStopReason = this.mapFinishReason(finishReason);
|
|
13554
|
+
}
|
|
13492
13555
|
const candidate = chunk.candidates?.[0];
|
|
13493
13556
|
if (candidate?.content?.parts) {
|
|
13494
13557
|
for (const part of candidate.content.parts) {
|
|
@@ -13522,7 +13585,7 @@ var GeminiProvider = class {
|
|
|
13522
13585
|
}
|
|
13523
13586
|
}
|
|
13524
13587
|
}
|
|
13525
|
-
yield { type: "done" };
|
|
13588
|
+
yield { type: "done", stopReason: streamStopReason };
|
|
13526
13589
|
} catch (error) {
|
|
13527
13590
|
throw this.handleError(error);
|
|
13528
13591
|
}
|