@deepstrike/sdk 0.1.15 → 0.2.0

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.
Files changed (57) hide show
  1. package/dist/collaboration/harness.d.ts +4 -1
  2. package/dist/collaboration/harness.js +20 -6
  3. package/dist/collaboration/modes/creator-verifier.d.ts +8 -2
  4. package/dist/collaboration/modes/creator-verifier.js +9 -3
  5. package/dist/collaboration/pool.d.ts +24 -3
  6. package/dist/collaboration/pool.js +65 -5
  7. package/dist/harness/harness.d.ts +5 -1
  8. package/dist/harness/harness.js +23 -1
  9. package/dist/index.d.ts +10 -1
  10. package/dist/index.js +5 -0
  11. package/dist/kernel.d.ts +12 -43
  12. package/dist/kernel.js +1 -1
  13. package/dist/providers/anthropic.js +7 -2
  14. package/dist/providers/base.d.ts +12 -0
  15. package/dist/providers/base.js +75 -0
  16. package/dist/providers/catalog.d.ts +3 -2
  17. package/dist/providers/catalog.js +61 -13
  18. package/dist/providers/deepseek.js +1 -1
  19. package/dist/providers/gemini.d.ts +3 -0
  20. package/dist/providers/gemini.js +26 -6
  21. package/dist/providers/glm.d.ts +9 -0
  22. package/dist/providers/glm.js +21 -0
  23. package/dist/providers/kimi.js +2 -0
  24. package/dist/providers/minimax.js +5 -0
  25. package/dist/providers/openai-responses.js +9 -0
  26. package/dist/providers/openai.js +52 -6
  27. package/dist/providers/profiles.d.ts +1304 -242
  28. package/dist/providers/profiles.js +429 -26
  29. package/dist/providers/qwen.d.ts +3 -1
  30. package/dist/providers/qwen.js +43 -13
  31. package/dist/runtime/archive.d.ts +15 -0
  32. package/dist/runtime/archive.js +35 -0
  33. package/dist/runtime/execution-plane.js +14 -4
  34. package/dist/runtime/filtered-plane.d.ts +14 -0
  35. package/dist/runtime/filtered-plane.js +45 -0
  36. package/dist/runtime/kernel-step.d.ts +88 -0
  37. package/dist/runtime/kernel-step.js +262 -0
  38. package/dist/runtime/process-sandbox-plane.d.ts +4 -4
  39. package/dist/runtime/process-sandbox-plane.js +5 -5
  40. package/dist/runtime/provider-replay.js +37 -3
  41. package/dist/runtime/replay-sanitize.d.ts +5 -0
  42. package/dist/runtime/replay-sanitize.js +25 -0
  43. package/dist/runtime/runner.d.ts +60 -4
  44. package/dist/runtime/runner.js +589 -86
  45. package/dist/runtime/session-log.d.ts +93 -1
  46. package/dist/runtime/session-repair.d.ts +37 -0
  47. package/dist/runtime/session-repair.js +77 -0
  48. package/dist/runtime/sub-agent-orchestrator.d.ts +19 -0
  49. package/dist/runtime/sub-agent-orchestrator.js +114 -0
  50. package/dist/skills/watcher.d.ts +19 -0
  51. package/dist/skills/watcher.js +38 -0
  52. package/dist/tools/index.d.ts +4 -1
  53. package/dist/tools/index.js +82 -11
  54. package/dist/types/agent.d.ts +68 -0
  55. package/dist/types/agent.js +78 -0
  56. package/dist/types.d.ts +27 -0
  57. package/package.json +2 -2
@@ -1,3 +1,4 @@
1
+ import { AnthropicProvider } from "./anthropic.js";
1
2
  import { OpenAIChatProvider } from "./openai.js";
2
3
  import { DeepSeekProvider } from "./deepseek.js";
3
4
  import { KimiProvider } from "./kimi.js";
@@ -5,20 +6,35 @@ import { OpenAIResponsesProvider } from "./openai-responses.js";
5
6
  import { MiniMaxProvider } from "./minimax.js";
6
7
  import { QwenProvider } from "./qwen.js";
7
8
  import { GeminiProvider } from "./gemini.js";
8
- import { endpointProfiles, getModelProfile } from "./profiles.js";
9
+ import { GLMProvider } from "./glm.js";
10
+ import { endpointProfiles, getModelProfile, modelProfiles } from "./profiles.js";
9
11
  export function createProvider(options) {
10
- const profile = getModelProfile(options.model);
11
- const endpointId = (options.endpoint ?? profile.defaultEndpointId);
12
+ const profile = isModelProfileId(options.model) ? getModelProfile(options.model) : undefined;
13
+ const parsedProviderId = providerPrefix(options.model);
14
+ const endpointId = (options.endpoint ?? profile?.defaultEndpointId ?? defaultEndpointForProvider(options.provider ?? parsedProviderId));
15
+ if (!endpointId) {
16
+ throw new Error(`Unknown model profile: ${options.model}. Pass provider or endpoint for custom model names.`);
17
+ }
12
18
  const endpoint = endpointProfiles[endpointId];
13
19
  if (!endpoint) {
14
20
  throw new Error(`Unknown endpoint profile: ${endpointId}`);
15
21
  }
16
- if (endpoint.providerId !== profile.providerId) {
17
- throw new Error(`Endpoint ${endpoint.id} does not belong to provider ${profile.providerId}`);
22
+ const providerId = profile?.providerId ?? options.provider ?? parsedProviderId ?? endpoint.providerId;
23
+ if (profile && options.provider && options.provider !== profile.providerId) {
24
+ throw new Error(`Model ${profile.id} belongs to provider ${profile.providerId}, not ${options.provider}`);
25
+ }
26
+ if (parsedProviderId && options.provider && parsedProviderId !== options.provider) {
27
+ throw new Error(`Model ${options.model} uses provider prefix ${parsedProviderId}, not ${options.provider}`);
28
+ }
29
+ if (endpoint.providerId !== providerId) {
30
+ throw new Error(`Endpoint ${endpoint.id} does not belong to provider ${providerId}`);
18
31
  }
19
- const model = options.model.slice(`${profile.providerId}/`.length);
32
+ const model = modelNameForProvider(options.model, providerId);
20
33
  const baseURL = options.baseURL ?? endpoint.baseURL;
21
- if (profile.providerId === "openai") {
34
+ if (providerId === "anthropic" && endpoint.protocol === "anthropic-messages") {
35
+ return new AnthropicProvider(options.apiKey, model, options.retry, { baseURL });
36
+ }
37
+ if (providerId === "openai") {
22
38
  if (endpoint.protocol === "openai-chat") {
23
39
  return new OpenAIChatProvider(options.apiKey, model, options.retry, baseURL);
24
40
  }
@@ -26,20 +42,52 @@ export function createProvider(options) {
26
42
  return new OpenAIResponsesProvider(options.apiKey, model, options.retry, baseURL);
27
43
  }
28
44
  }
29
- if (profile.providerId === "minimax" && endpoint.protocol === "anthropic-messages") {
45
+ if (providerId === "minimax" && endpoint.protocol === "anthropic-messages") {
30
46
  return new MiniMaxProvider(options.apiKey, model, options.retry, baseURL);
31
47
  }
32
- if (profile.providerId === "deepseek" && endpoint.protocol === "openai-chat") {
48
+ if (providerId === "deepseek" && endpoint.protocol === "openai-chat") {
33
49
  return new DeepSeekProvider(options.apiKey, model, options.retry, baseURL);
34
50
  }
35
- if (profile.providerId === "kimi" && endpoint.protocol === "openai-chat") {
51
+ if (providerId === "kimi" && endpoint.protocol === "openai-chat") {
36
52
  return new KimiProvider(options.apiKey, model, options.retry, baseURL);
37
53
  }
38
- if (profile.providerId === "qwen" && endpoint.protocol === "openai-chat") {
54
+ if (providerId === "qwen" && endpoint.protocol === "openai-chat") {
39
55
  return new QwenProvider(options.apiKey, model, options.retry, baseURL);
40
56
  }
41
- if (profile.providerId === "gemini" && endpoint.protocol === "gemini") {
57
+ if (providerId === "gemini" && endpoint.protocol === "gemini") {
42
58
  return new GeminiProvider(options.apiKey, model, options.retry, baseURL);
43
59
  }
44
- throw new Error(`No Node provider factory for ${profile.id} on ${endpoint.id}`);
60
+ if (providerId === "glm" && endpoint.protocol === "openai-chat") {
61
+ return new GLMProvider(options.apiKey, model, options.retry, baseURL);
62
+ }
63
+ throw new Error(`No Node provider factory for ${options.model} on ${endpoint.id}`);
64
+ }
65
+ function isModelProfileId(model) {
66
+ return Object.prototype.hasOwnProperty.call(modelProfiles, model);
67
+ }
68
+ function providerPrefix(model) {
69
+ const [prefix] = model.split("/", 1);
70
+ return providerIds().includes(prefix) ? prefix : undefined;
71
+ }
72
+ function providerIds() {
73
+ return Array.from(new Set(Object.values(endpointProfiles).map(endpoint => endpoint.providerId)));
74
+ }
75
+ function defaultEndpointForProvider(providerId) {
76
+ if (!providerId)
77
+ return undefined;
78
+ const defaults = {
79
+ anthropic: "anthropic.messages",
80
+ openai: "openai.chat",
81
+ minimax: "minimax.anthropic",
82
+ deepseek: "deepseek.openai",
83
+ kimi: "kimi.openai",
84
+ qwen: "qwen.dashscope",
85
+ gemini: "gemini.google",
86
+ glm: "glm.openai",
87
+ };
88
+ return defaults[providerId];
89
+ }
90
+ function modelNameForProvider(model, providerId) {
91
+ const prefix = `${providerId}/`;
92
+ return model.startsWith(prefix) ? model.slice(prefix.length) : model;
45
93
  }
@@ -91,7 +91,7 @@ export class DeepSeekProvider extends OpenAIChatProvider {
91
91
  const toolCalls = Object.values(toolCallBufs).map(tb => ({
92
92
  id: tb.id, name: tb.name, arguments: tb.argsBuf || "{}",
93
93
  }));
94
- if (toolCalls.length) {
94
+ if (toolCalls.length || reasoningContent) {
95
95
  this.chat.rememberReplayFields({ content: finalText, toolCalls }, { reasoning_content: reasoningContent });
96
96
  }
97
97
  for (const [index, tb] of Object.entries(toolCallBufs)) {
@@ -1,10 +1,13 @@
1
+ import { type Content } from "@google/generative-ai";
1
2
  import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy } from "../types.js";
3
+ export declare function buildContents(turns: Message[]): Content[];
2
4
  export declare class GeminiProvider implements LLMProvider {
3
5
  private readonly model;
4
6
  private genAI;
5
7
  private circuit;
6
8
  private maxRetries;
7
9
  private baseDelay;
10
+ private requestOptions;
8
11
  constructor(apiKey: string, model?: string, retry?: {
9
12
  maxRetries: number;
10
13
  baseDelay: number;
@@ -4,6 +4,9 @@ import { CircuitBreaker, normalizeToolCall } from "./base.js";
4
4
  import { endpointProfiles } from "./profiles.js";
5
5
  const GEMINI_BASE = endpointProfiles["gemini.google"].baseURL;
6
6
  const GEMINI_POLICIES = {
7
+ "gemini-3-pro-preview": { maxTurns: 50 },
8
+ "gemini-3-flash-preview": { maxTurns: 25 },
9
+ "gemini-3.5-flash": { maxTurns: 30 },
7
10
  "gemini-2.5-pro": { maxTurns: 35 },
8
11
  "gemini-2.5-flash": { maxTurns: 20 },
9
12
  "gemini-2.0-flash": { maxTurns: 15 },
@@ -11,15 +14,30 @@ const GEMINI_POLICIES = {
11
14
  "gemini-1.5-pro": { maxTurns: 30 },
12
15
  "gemini-1.5-flash": { maxTurns: 15 },
13
16
  };
14
- function buildContents(turns) {
17
+ export function buildContents(turns) {
15
18
  const contents = [];
16
19
  for (const msg of turns) {
17
20
  if (msg.role === "tool") {
18
21
  const parts = (msg.contentParts ?? [])
19
22
  .filter(p => p.type === "tool_result")
20
- .map(p => p.type === "tool_result" ? ({
21
- functionResponse: { name: p.callId, response: { output: p.output } },
22
- }) : ({ text: "" }));
23
+ .map(p => {
24
+ if (p.type !== "tool_result")
25
+ return { text: "" };
26
+ let toolName = p.callId;
27
+ for (let i = turns.length - 1; i >= 0; i--) {
28
+ const turn = turns[i];
29
+ if (turn.role === "assistant" && turn.toolCalls) {
30
+ const matched = turn.toolCalls.find(tc => tc.id === p.callId);
31
+ if (matched) {
32
+ toolName = matched.name;
33
+ break;
34
+ }
35
+ }
36
+ }
37
+ return {
38
+ functionResponse: { name: toolName, response: { output: p.output } },
39
+ };
40
+ });
23
41
  if (parts.length)
24
42
  contents.push({ role: "user", parts });
25
43
  continue;
@@ -62,12 +80,14 @@ export class GeminiProvider {
62
80
  circuit;
63
81
  maxRetries;
64
82
  baseDelay;
83
+ requestOptions;
65
84
  constructor(apiKey, model = "gemini-2.0-flash", retry = { maxRetries: 3, baseDelay: 1000 }, baseURL = GEMINI_BASE) {
66
85
  this.model = model;
67
86
  this.genAI = withServerRuntimeGuard(() => new GoogleGenerativeAI(apiKey));
68
87
  this.circuit = new CircuitBreaker();
69
88
  this.maxRetries = retry.maxRetries;
70
89
  this.baseDelay = retry.baseDelay;
90
+ this.requestOptions = { baseUrl: baseURL };
71
91
  }
72
92
  runtimePolicy() {
73
93
  return GEMINI_POLICIES[this.model] ?? {};
@@ -86,7 +106,7 @@ export class GeminiProvider {
86
106
  model: this.model,
87
107
  ...(system ? { systemInstruction: system } : {}),
88
108
  ...(geminiTools.length ? { tools: geminiTools } : {}),
89
- });
109
+ }, this.requestOptions);
90
110
  const resp = await m.generateContent({ contents });
91
111
  this.circuit.recordSuccess();
92
112
  const candidate = resp.response.candidates?.[0];
@@ -127,7 +147,7 @@ export class GeminiProvider {
127
147
  model: this.model,
128
148
  ...(system ? { systemInstruction: system } : {}),
129
149
  ...(geminiTools.length ? { tools: geminiTools } : {}),
130
- });
150
+ }, this.requestOptions);
131
151
  const result = await m.generateContentStream({ contents });
132
152
  const toolCalls = [];
133
153
  for await (const chunk of result.stream) {
@@ -0,0 +1,9 @@
1
+ import type { RuntimePolicy } from "../types.js";
2
+ import { OpenAIChatProvider } from "./openai.js";
3
+ export declare class GLMProvider extends OpenAIChatProvider {
4
+ constructor(apiKey: string, model?: string, retry?: {
5
+ maxRetries: number;
6
+ baseDelay: number;
7
+ }, baseURL?: string);
8
+ runtimePolicy(): RuntimePolicy;
9
+ }
@@ -0,0 +1,21 @@
1
+ import { OpenAIChatProvider } from "./openai.js";
2
+ import { endpointProfiles } from "./profiles.js";
3
+ const GLM_BASE = endpointProfiles["glm.openai"].baseURL;
4
+ const GLM_POLICIES = {
5
+ "glm-5.1": { maxTurns: 50 },
6
+ "glm/glm-5.1": { maxTurns: 50 },
7
+ "glm-4-plus": { maxTurns: 35 },
8
+ "glm/glm-4-plus": { maxTurns: 35 },
9
+ "glm-4-flash": { maxTurns: 15 },
10
+ "glm/glm-4-flash": { maxTurns: 15 },
11
+ "glm-4-air": { maxTurns: 20 },
12
+ "glm/glm-4-air": { maxTurns: 20 },
13
+ };
14
+ export class GLMProvider extends OpenAIChatProvider {
15
+ constructor(apiKey, model = "glm-5.1", retry, baseURL = GLM_BASE) {
16
+ super(apiKey, model, retry, baseURL);
17
+ }
18
+ runtimePolicy() {
19
+ return GLM_POLICIES[this.model] ?? {};
20
+ }
21
+ }
@@ -7,6 +7,8 @@ const KIMI_POLICIES = {
7
7
  "moonshot-v1-128k": { maxTurns: 30 },
8
8
  "kimi-k2.5": { maxTurns: 30 },
9
9
  "kimi-k2.6": { maxTurns: 35 },
10
+ "kimi-k2-thinking": { maxTurns: 50 },
11
+ "kimi-k2-thinking-turbo": { maxTurns: 40 },
10
12
  };
11
13
  export class KimiProvider extends OpenAIChatProvider {
12
14
  constructor(apiKey, model = "kimi-k2.6", retry, baseURL = MOONSHOT_BASE) {
@@ -2,7 +2,12 @@ import { AnthropicProvider } from "./anthropic.js";
2
2
  import { endpointProfiles } from "./profiles.js";
3
3
  const MINIMAX_POLICIES = {
4
4
  "MiniMax-M2.7": { maxTurns: 35 },
5
+ "MiniMax-M2.7-highspeed": { maxTurns: 35 },
5
6
  "MiniMax-M2.5": { maxTurns: 25 },
7
+ "MiniMax-M2.5-highspeed": { maxTurns: 25 },
8
+ "MiniMax-M2.1": { maxTurns: 25 },
9
+ "MiniMax-M2.1-highspeed": { maxTurns: 25 },
10
+ "MiniMax-M2": { maxTurns: 20 },
6
11
  "MiniMax-Text-01": { maxTurns: 20 },
7
12
  };
8
13
  export class MiniMaxProvider extends AnthropicProvider {
@@ -115,11 +115,20 @@ export class OpenAIResponsesProvider {
115
115
  }
116
116
  runtimePolicy() {
117
117
  const table = {
118
+ "gpt-5.5": { maxTurns: 60 },
119
+ "gpt-5.4": { maxTurns: 50 },
120
+ "gpt-5.4-mini": { maxTurns: 25 },
121
+ "gpt-5.4-nano": { maxTurns: 15 },
122
+ "gpt-5.2": { maxTurns: 50 },
123
+ "gpt-5.2-pro": { maxTurns: 60 },
124
+ "gpt-5.1": { maxTurns: 50 },
118
125
  "gpt-4.1": { maxTurns: 35 },
119
126
  "gpt-4.1-mini": { maxTurns: 20 },
120
127
  "gpt-4.1-nano": { maxTurns: 15 },
121
128
  "gpt-5": { maxTurns: 50 },
129
+ "gpt-5-pro": { maxTurns: 60 },
122
130
  "gpt-5-mini": { maxTurns: 25 },
131
+ "gpt-5-nano": { maxTurns: 15 },
123
132
  "o3": { maxTurns: 50 },
124
133
  "o3-mini": { maxTurns: 25 },
125
134
  "o4-mini": { maxTurns: 25 },
@@ -1,15 +1,24 @@
1
1
  import OpenAI from "openai";
2
2
  import { withServerRuntimeGuard } from "../runtime/server.js";
3
- import { CircuitBreaker, omitExtensionKeys } from "./base.js";
3
+ import { CircuitBreaker, omitExtensionKeys, ThinkingTagStreamExtractor } from "./base.js";
4
4
  import { OpenAIChatAdapter } from "./openai-chat.js";
5
5
  const OPENAI_POLICIES = {
6
+ "gpt-5.5": { maxTurns: 60 },
7
+ "gpt-5.4": { maxTurns: 50 },
8
+ "gpt-5.4-mini": { maxTurns: 25 },
9
+ "gpt-5.4-nano": { maxTurns: 15 },
10
+ "gpt-5.2": { maxTurns: 50 },
11
+ "gpt-5.2-pro": { maxTurns: 60 },
12
+ "gpt-5.1": { maxTurns: 50 },
6
13
  "gpt-4o": { maxTurns: 25 },
7
14
  "gpt-4o-mini": { maxTurns: 15 },
8
15
  "gpt-4.1": { maxTurns: 35 },
9
16
  "gpt-4.1-mini": { maxTurns: 20 },
10
17
  "gpt-4.1-nano": { maxTurns: 15 },
11
18
  "gpt-5": { maxTurns: 50 },
19
+ "gpt-5-pro": { maxTurns: 60 },
12
20
  "gpt-5-mini": { maxTurns: 25 },
21
+ "gpt-5-nano": { maxTurns: 15 },
13
22
  "o1": { maxTurns: 50 },
14
23
  "o1-mini": { maxTurns: 25 },
15
24
  "o3": { maxTurns: 50 },
@@ -35,12 +44,12 @@ export class OpenAIChatProvider {
35
44
  }
36
45
  peekProviderReplay(message) {
37
46
  const fields = this.chat.peekReplayFields(message);
38
- if (!fields?.reasoning_content)
47
+ if (!fields || !("reasoning_content" in fields))
39
48
  return undefined;
40
- return { reasoning_content: String(fields.reasoning_content) };
49
+ return { reasoning_content: String(fields.reasoning_content ?? "") };
41
50
  }
42
51
  seedProviderReplay(message, replay) {
43
- if (replay.reasoning_content) {
52
+ if (replay.reasoning_content !== undefined) {
44
53
  this.chat.rememberReplayFields(message, { reasoning_content: replay.reasoning_content });
45
54
  }
46
55
  }
@@ -75,6 +84,9 @@ export class OpenAIChatProvider {
75
84
  const msgs = this.chat.buildMessages(context);
76
85
  const toolCallBufs = {};
77
86
  const emittedToolCallIndexes = new Set();
87
+ const extractor = new ThinkingTagStreamExtractor();
88
+ let accumulatedReasoning = "";
89
+ let accumulatedContent = "";
78
90
  const stream = await this.client.chat.completions.create({
79
91
  ...this.requestExtensions(extensions),
80
92
  model: this.model,
@@ -93,8 +105,22 @@ export class OpenAIChatProvider {
93
105
  if (!choice)
94
106
  continue;
95
107
  const delta = choice.delta;
96
- if (delta.content)
97
- yield { type: "text_delta", delta: delta.content };
108
+ if (delta.reasoning_content) {
109
+ accumulatedReasoning += delta.reasoning_content;
110
+ yield { type: "thinking_delta", delta: delta.reasoning_content };
111
+ }
112
+ if (delta.content) {
113
+ for (const part of extractor.feed(delta.content)) {
114
+ if (part.type === "thinking") {
115
+ accumulatedReasoning += part.content;
116
+ yield { type: "thinking_delta", delta: part.content };
117
+ }
118
+ else {
119
+ accumulatedContent += part.content;
120
+ yield { type: "text_delta", delta: part.content };
121
+ }
122
+ }
123
+ }
98
124
  for (const tc of delta.tool_calls ?? []) {
99
125
  const idx = tc.index;
100
126
  if (!toolCallBufs[idx])
@@ -104,6 +130,10 @@ export class OpenAIChatProvider {
104
130
  toolCallBufs[idx].argsBuf += tc.function?.arguments ?? "";
105
131
  }
106
132
  if (choice.finish_reason === "tool_calls") {
133
+ const toolCalls = Object.values(toolCallBufs).map(tb => ({
134
+ id: tb.id, name: tb.name, arguments: tb.argsBuf || "{}",
135
+ }));
136
+ this.chat.rememberReplayFields({ content: accumulatedContent, toolCalls }, { reasoning_content: accumulatedReasoning });
107
137
  for (const [index, tb] of Object.entries(toolCallBufs)) {
108
138
  const idx = Number(index);
109
139
  if (emittedToolCallIndexes.has(idx))
@@ -120,6 +150,22 @@ export class OpenAIChatProvider {
120
150
  }
121
151
  }
122
152
  }
153
+ for (const part of extractor.flush()) {
154
+ if (part.type === "thinking") {
155
+ accumulatedReasoning += part.content;
156
+ yield { type: "thinking_delta", delta: part.content };
157
+ }
158
+ else {
159
+ accumulatedContent += part.content;
160
+ yield { type: "text_delta", delta: part.content };
161
+ }
162
+ }
163
+ const toolCalls = Object.values(toolCallBufs).map(tb => ({
164
+ id: tb.id, name: tb.name, arguments: tb.argsBuf || "{}",
165
+ }));
166
+ if (toolCalls.length || accumulatedReasoning) {
167
+ this.chat.rememberReplayFields({ content: accumulatedContent, toolCalls }, { reasoning_content: accumulatedReasoning });
168
+ }
123
169
  for (const [index, tb] of Object.entries(toolCallBufs)) {
124
170
  const idx = Number(index);
125
171
  if (emittedToolCallIndexes.has(idx))