@corbat-tech/coco 2.8.0 → 2.8.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/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
package/dist/index.js CHANGED
@@ -11784,22 +11784,38 @@ 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
- model: options?.model ?? this.config.model ?? DEFAULT_MODEL,
11789
- max_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
11790
- temperature: options?.temperature ?? this.config.temperature ?? 0,
11791
- system: this.extractSystem(messages, options?.system),
11792
- messages: this.convertMessages(messages)
11793
- });
11794
- for await (const event of stream) {
11795
- if (event.type === "content_block_delta") {
11796
- const delta = event.delta;
11797
- if (delta.type === "text_delta" && delta.text) {
11798
- yield { type: "text", text: delta.text };
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
+ for await (const event of stream) {
11807
+ lastActivityTime = Date.now();
11808
+ if (event.type === "content_block_delta") {
11809
+ const delta = event.delta;
11810
+ if (delta.type === "text_delta" && delta.text) {
11811
+ yield { type: "text", text: delta.text };
11812
+ }
11799
11813
  }
11800
11814
  }
11815
+ yield { type: "done" };
11816
+ } finally {
11817
+ clearInterval(timeoutInterval);
11801
11818
  }
11802
- yield { type: "done" };
11803
11819
  } catch (error) {
11804
11820
  throw this.handleError(error);
11805
11821
  }
@@ -11810,90 +11826,106 @@ var AnthropicProvider = class {
11810
11826
  async *streamWithTools(messages, options) {
11811
11827
  this.ensureInitialized();
11812
11828
  try {
11813
- const stream = await this.client.messages.stream({
11814
- model: options?.model ?? this.config.model ?? DEFAULT_MODEL,
11815
- max_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
11816
- temperature: options?.temperature ?? this.config.temperature ?? 0,
11817
- system: this.extractSystem(messages, options?.system),
11818
- messages: this.convertMessages(messages),
11819
- tools: this.convertTools(options.tools),
11820
- tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0
11821
- });
11829
+ const stream = await this.client.messages.stream(
11830
+ {
11831
+ model: options?.model ?? this.config.model ?? DEFAULT_MODEL,
11832
+ max_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
11833
+ temperature: options?.temperature ?? this.config.temperature ?? 0,
11834
+ system: this.extractSystem(messages, options?.system),
11835
+ messages: this.convertMessages(messages),
11836
+ tools: this.convertTools(options.tools),
11837
+ tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0
11838
+ },
11839
+ { signal: options?.signal }
11840
+ );
11822
11841
  let currentToolCall = null;
11823
11842
  let currentToolInputJson = "";
11824
- for await (const event of stream) {
11825
- if (event.type === "content_block_start") {
11826
- const contentBlock = event.content_block;
11827
- if (contentBlock.type === "tool_use") {
11843
+ const streamTimeout = this.config.timeout ?? 12e4;
11844
+ let lastActivityTime = Date.now();
11845
+ const checkTimeout = () => {
11846
+ if (Date.now() - lastActivityTime > streamTimeout) {
11847
+ throw new Error(`Stream timeout: No response from LLM for ${streamTimeout / 1e3}s`);
11848
+ }
11849
+ };
11850
+ const timeoutInterval = setInterval(checkTimeout, 5e3);
11851
+ try {
11852
+ for await (const event of stream) {
11853
+ lastActivityTime = Date.now();
11854
+ if (event.type === "content_block_start") {
11855
+ const contentBlock = event.content_block;
11856
+ if (contentBlock.type === "tool_use") {
11857
+ if (currentToolCall) {
11858
+ getLogger().warn(
11859
+ `[Anthropic] content_block_stop missing for tool '${currentToolCall.name}' \u2014 finalizing early to prevent data bleed.`
11860
+ );
11861
+ try {
11862
+ currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
11863
+ } catch {
11864
+ currentToolCall.input = {};
11865
+ }
11866
+ yield {
11867
+ type: "tool_use_end",
11868
+ toolCall: { ...currentToolCall }
11869
+ };
11870
+ }
11871
+ currentToolCall = {
11872
+ id: contentBlock.id,
11873
+ name: contentBlock.name
11874
+ };
11875
+ currentToolInputJson = "";
11876
+ yield {
11877
+ type: "tool_use_start",
11878
+ toolCall: { ...currentToolCall }
11879
+ };
11880
+ }
11881
+ } else if (event.type === "content_block_delta") {
11882
+ const delta = event.delta;
11883
+ if (delta.type === "text_delta" && delta.text) {
11884
+ yield { type: "text", text: delta.text };
11885
+ } else if (delta.type === "input_json_delta" && delta.partial_json) {
11886
+ currentToolInputJson += delta.partial_json;
11887
+ yield {
11888
+ type: "tool_use_delta",
11889
+ toolCall: {
11890
+ ...currentToolCall
11891
+ },
11892
+ text: delta.partial_json
11893
+ };
11894
+ }
11895
+ } else if (event.type === "content_block_stop") {
11828
11896
  if (currentToolCall) {
11829
- getLogger().warn(
11830
- `[Anthropic] content_block_stop missing for tool '${currentToolCall.name}' \u2014 finalizing early to prevent data bleed.`
11831
- );
11832
11897
  try {
11833
11898
  currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
11834
11899
  } catch {
11835
- currentToolCall.input = {};
11900
+ let repaired = false;
11901
+ if (currentToolInputJson) {
11902
+ try {
11903
+ currentToolCall.input = JSON.parse(jsonrepair(currentToolInputJson));
11904
+ repaired = true;
11905
+ getLogger().debug(`Repaired JSON for tool ${currentToolCall.name}`);
11906
+ } catch {
11907
+ }
11908
+ }
11909
+ if (!repaired) {
11910
+ getLogger().warn(
11911
+ `Failed to parse tool call arguments for ${currentToolCall.name}: ${currentToolInputJson?.slice(0, 300)}`
11912
+ );
11913
+ currentToolCall.input = {};
11914
+ }
11836
11915
  }
11837
11916
  yield {
11838
11917
  type: "tool_use_end",
11839
11918
  toolCall: { ...currentToolCall }
11840
11919
  };
11920
+ currentToolCall = null;
11921
+ currentToolInputJson = "";
11841
11922
  }
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
11923
  }
11894
11924
  }
11925
+ yield { type: "done" };
11926
+ } finally {
11927
+ clearInterval(timeoutInterval);
11895
11928
  }
11896
- yield { type: "done" };
11897
11929
  } catch (error) {
11898
11930
  throw this.handleError(error);
11899
11931
  }