@coder/ai-sdk-agent 0.1.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.
- package/LICENSE +202 -0
- package/README.md +188 -0
- package/dist/index.d.ts +526 -0
- package/dist/index.js +930 -0
- package/dist/index.js.map +1 -0
- package/package.json +83 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,930 @@
|
|
|
1
|
+
// src/agent/coder-agent.ts
|
|
2
|
+
import {
|
|
3
|
+
stepCountIs,
|
|
4
|
+
ToolLoopAgent
|
|
5
|
+
} from "ai";
|
|
6
|
+
|
|
7
|
+
// src/errors.ts
|
|
8
|
+
var CoderAgentError = class extends Error {
|
|
9
|
+
name = "CoderAgentError";
|
|
10
|
+
constructor(message, options) {
|
|
11
|
+
super(message, options);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var CoderApiError = class extends CoderAgentError {
|
|
15
|
+
name = "CoderApiError";
|
|
16
|
+
status;
|
|
17
|
+
detail;
|
|
18
|
+
method;
|
|
19
|
+
path;
|
|
20
|
+
constructor(args) {
|
|
21
|
+
super(
|
|
22
|
+
`Coder API ${args.method} ${args.path} failed (${args.status}): ${args.message}` + (args.detail ? ` \u2014 ${args.detail}` : "")
|
|
23
|
+
);
|
|
24
|
+
this.status = args.status;
|
|
25
|
+
this.detail = args.detail;
|
|
26
|
+
this.method = args.method;
|
|
27
|
+
this.path = args.path;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var CoderChatError = class extends CoderAgentError {
|
|
31
|
+
name = "CoderChatError";
|
|
32
|
+
kind;
|
|
33
|
+
provider;
|
|
34
|
+
retryable;
|
|
35
|
+
statusCode;
|
|
36
|
+
constructor(payload) {
|
|
37
|
+
super(payload.detail ? `${payload.message}: ${payload.detail}` : payload.message);
|
|
38
|
+
this.kind = payload.kind;
|
|
39
|
+
this.provider = payload.provider;
|
|
40
|
+
this.retryable = payload.retryable ?? false;
|
|
41
|
+
this.statusCode = payload.status_code;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/coder/types.ts
|
|
46
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
47
|
+
"waiting",
|
|
48
|
+
"completed",
|
|
49
|
+
"error",
|
|
50
|
+
"requires_action"
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
// src/coder/ws.ts
|
|
54
|
+
import NodeWebSocket from "ws";
|
|
55
|
+
var defaultFactory = (url, { headers }) => {
|
|
56
|
+
return new NodeWebSocket(url, { headers });
|
|
57
|
+
};
|
|
58
|
+
function httpToWs(baseUrl) {
|
|
59
|
+
if (baseUrl.startsWith("https://")) return `wss://${baseUrl.slice("https://".length)}`;
|
|
60
|
+
if (baseUrl.startsWith("http://")) return `ws://${baseUrl.slice("http://".length)}`;
|
|
61
|
+
return baseUrl;
|
|
62
|
+
}
|
|
63
|
+
async function* streamChatEvents(options) {
|
|
64
|
+
const { baseUrl, token, chatId, afterId, signal } = options;
|
|
65
|
+
const factory = options.webSocketFactory ?? defaultFactory;
|
|
66
|
+
const wsBase = httpToWs(baseUrl);
|
|
67
|
+
const query = afterId !== void 0 ? `?after_id=${afterId}` : "";
|
|
68
|
+
const url = `${wsBase}/api/experimental/chats/${chatId}/stream${query}`;
|
|
69
|
+
const queue = [];
|
|
70
|
+
let resolveNext;
|
|
71
|
+
let finished = false;
|
|
72
|
+
let failure;
|
|
73
|
+
const wake = () => {
|
|
74
|
+
resolveNext?.();
|
|
75
|
+
resolveNext = void 0;
|
|
76
|
+
};
|
|
77
|
+
const ws = factory(url, { headers: { "Coder-Session-Token": token } });
|
|
78
|
+
const onAbort = () => {
|
|
79
|
+
finished = true;
|
|
80
|
+
try {
|
|
81
|
+
ws.close(1e3);
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
84
|
+
wake();
|
|
85
|
+
};
|
|
86
|
+
let abortListenerAdded = false;
|
|
87
|
+
if (signal) {
|
|
88
|
+
if (signal.aborted) onAbort();
|
|
89
|
+
else {
|
|
90
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
91
|
+
abortListenerAdded = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const onMessage = (ev) => {
|
|
95
|
+
if (finished) return;
|
|
96
|
+
let batch;
|
|
97
|
+
try {
|
|
98
|
+
const data = typeof ev.data === "string" ? ev.data : String(ev.data);
|
|
99
|
+
batch = JSON.parse(data);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
failure = new CoderAgentError("failed to parse chat stream frame", { cause: err });
|
|
102
|
+
finished = true;
|
|
103
|
+
wake();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(batch)) {
|
|
107
|
+
for (const e of batch) queue.push(e);
|
|
108
|
+
} else if (batch && typeof batch === "object") {
|
|
109
|
+
queue.push(batch);
|
|
110
|
+
}
|
|
111
|
+
wake();
|
|
112
|
+
};
|
|
113
|
+
const onError = (ev) => {
|
|
114
|
+
if (finished) return;
|
|
115
|
+
const message = ev && typeof ev === "object" && "message" in ev ? String(ev.message) : "chat stream socket error";
|
|
116
|
+
failure = new CoderAgentError(message);
|
|
117
|
+
finished = true;
|
|
118
|
+
wake();
|
|
119
|
+
};
|
|
120
|
+
const onClose = () => {
|
|
121
|
+
finished = true;
|
|
122
|
+
wake();
|
|
123
|
+
};
|
|
124
|
+
ws.addEventListener("message", onMessage);
|
|
125
|
+
ws.addEventListener("error", onError);
|
|
126
|
+
ws.addEventListener("close", onClose);
|
|
127
|
+
try {
|
|
128
|
+
while (true) {
|
|
129
|
+
while (queue.length > 0) {
|
|
130
|
+
const next = queue.shift();
|
|
131
|
+
yield next;
|
|
132
|
+
}
|
|
133
|
+
if (failure) throw failure;
|
|
134
|
+
if (finished) return;
|
|
135
|
+
await new Promise((resolve) => {
|
|
136
|
+
resolveNext = resolve;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
} finally {
|
|
140
|
+
finished = true;
|
|
141
|
+
if (signal && abortListenerAdded) signal.removeEventListener("abort", onAbort);
|
|
142
|
+
ws.removeEventListener("message", onMessage);
|
|
143
|
+
ws.removeEventListener("error", onError);
|
|
144
|
+
ws.removeEventListener("close", onClose);
|
|
145
|
+
try {
|
|
146
|
+
ws.close(1e3);
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/coder/client.ts
|
|
153
|
+
var API_PREFIX = "/api/experimental/chats";
|
|
154
|
+
var CoderChatClient = class {
|
|
155
|
+
baseUrl;
|
|
156
|
+
#token;
|
|
157
|
+
#fetch;
|
|
158
|
+
#webSocketFactory;
|
|
159
|
+
constructor(options) {
|
|
160
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
161
|
+
this.#token = options.token;
|
|
162
|
+
this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
163
|
+
this.#webSocketFactory = options.webSocketFactory;
|
|
164
|
+
}
|
|
165
|
+
async #request(method, path, body, signal) {
|
|
166
|
+
const headers = { "Coder-Session-Token": this.#token };
|
|
167
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
168
|
+
const res = await this.#fetch(`${this.baseUrl}${path}`, {
|
|
169
|
+
method,
|
|
170
|
+
headers,
|
|
171
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
172
|
+
signal
|
|
173
|
+
});
|
|
174
|
+
const text = await res.text();
|
|
175
|
+
let parsed;
|
|
176
|
+
try {
|
|
177
|
+
parsed = text.length > 0 ? JSON.parse(text) : void 0;
|
|
178
|
+
} catch {
|
|
179
|
+
parsed = void 0;
|
|
180
|
+
}
|
|
181
|
+
if (!res.ok) {
|
|
182
|
+
const errObj = parsed ?? {};
|
|
183
|
+
throw new CoderApiError({
|
|
184
|
+
status: res.status,
|
|
185
|
+
method,
|
|
186
|
+
path,
|
|
187
|
+
message: errObj.message ?? res.statusText ?? "request failed",
|
|
188
|
+
detail: errObj.detail
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return parsed;
|
|
192
|
+
}
|
|
193
|
+
// --- REST -----------------------------------------------------------------
|
|
194
|
+
listModelConfigs(signal) {
|
|
195
|
+
return this.#request(
|
|
196
|
+
"GET",
|
|
197
|
+
`${API_PREFIX}/model-configs`,
|
|
198
|
+
void 0,
|
|
199
|
+
signal
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
createChat(req, signal) {
|
|
203
|
+
return this.#request("POST", API_PREFIX, req, signal);
|
|
204
|
+
}
|
|
205
|
+
getChat(chatId, signal) {
|
|
206
|
+
return this.#request("GET", `${API_PREFIX}/${chatId}`, void 0, signal);
|
|
207
|
+
}
|
|
208
|
+
createChatMessage(chatId, req, signal) {
|
|
209
|
+
return this.#request(
|
|
210
|
+
"POST",
|
|
211
|
+
`${API_PREFIX}/${chatId}/messages`,
|
|
212
|
+
req,
|
|
213
|
+
signal
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
getMessages(chatId, opts, signal) {
|
|
217
|
+
const params = new URLSearchParams();
|
|
218
|
+
if (opts?.before_id !== void 0) params.set("before_id", String(opts.before_id));
|
|
219
|
+
if (opts?.after_id !== void 0) params.set("after_id", String(opts.after_id));
|
|
220
|
+
if (opts?.limit !== void 0) params.set("limit", String(opts.limit));
|
|
221
|
+
const q = params.toString();
|
|
222
|
+
return this.#request(
|
|
223
|
+
"GET",
|
|
224
|
+
`${API_PREFIX}/${chatId}/messages${q ? `?${q}` : ""}`,
|
|
225
|
+
void 0,
|
|
226
|
+
signal
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
submitToolResults(chatId, req, signal) {
|
|
230
|
+
return this.#request("POST", `${API_PREFIX}/${chatId}/tool-results`, req, signal);
|
|
231
|
+
}
|
|
232
|
+
interruptChat(chatId, signal) {
|
|
233
|
+
return this.#request("POST", `${API_PREFIX}/${chatId}/interrupt`, void 0, signal);
|
|
234
|
+
}
|
|
235
|
+
updateChat(chatId, req, signal) {
|
|
236
|
+
return this.#request("PATCH", `${API_PREFIX}/${chatId}`, req, signal);
|
|
237
|
+
}
|
|
238
|
+
/** Convenience: archive a chat (soft-hide; safe for cleanup). */
|
|
239
|
+
archiveChat(chatId, signal) {
|
|
240
|
+
return this.updateChat(chatId, { archived: true }, signal);
|
|
241
|
+
}
|
|
242
|
+
// --- Streaming ------------------------------------------------------------
|
|
243
|
+
streamEvents(chatId, opts) {
|
|
244
|
+
return streamChatEvents({
|
|
245
|
+
baseUrl: this.baseUrl,
|
|
246
|
+
token: this.#token,
|
|
247
|
+
chatId,
|
|
248
|
+
afterId: opts?.afterId,
|
|
249
|
+
signal: opts?.signal,
|
|
250
|
+
webSocketFactory: this.#webSocketFactory
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
// --- Helpers --------------------------------------------------------------
|
|
254
|
+
/**
|
|
255
|
+
* Resolves a user-friendly model hint to a model-config UUID.
|
|
256
|
+
*
|
|
257
|
+
* Accepts: a config UUID (returned as-is), a `provider:model` id
|
|
258
|
+
* (e.g. `anthropic:claude-haiku-4-5-20251001`), a bare model id, or a
|
|
259
|
+
* display-name substring (case-insensitive). Returns `undefined` if no
|
|
260
|
+
* match is found, in which case the caller should let chatd pick the default.
|
|
261
|
+
*/
|
|
262
|
+
async resolveModelConfigId(hint, signal) {
|
|
263
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
264
|
+
if (UUID_RE.test(hint)) return hint;
|
|
265
|
+
const configs = await this.listModelConfigs(signal);
|
|
266
|
+
const lower = hint.toLowerCase();
|
|
267
|
+
const colon = hint.indexOf(":");
|
|
268
|
+
const provider = colon >= 0 ? hint.slice(0, colon).toLowerCase() : void 0;
|
|
269
|
+
const model = colon >= 0 ? hint.slice(colon + 1).toLowerCase() : lower;
|
|
270
|
+
const candidates = configs.filter((c) => c.enabled !== false);
|
|
271
|
+
const pool = candidates.length > 0 ? candidates : configs;
|
|
272
|
+
const exact = pool.find(
|
|
273
|
+
(c) => c.model.toLowerCase() === model && (provider === void 0 || c.provider.toLowerCase() === provider)
|
|
274
|
+
);
|
|
275
|
+
if (exact) return exact.id;
|
|
276
|
+
const byModel = pool.find((c) => c.model.toLowerCase() === model);
|
|
277
|
+
if (byModel) return byModel.id;
|
|
278
|
+
const byDisplay = pool.find((c) => c.display_name.toLowerCase().includes(lower));
|
|
279
|
+
if (byDisplay) return byDisplay.id;
|
|
280
|
+
const byModelSubstring = pool.find((c) => c.model.toLowerCase().includes(model));
|
|
281
|
+
return byModelSubstring?.id;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// src/model/prompt.ts
|
|
286
|
+
function extractSystemPrompt(prompt) {
|
|
287
|
+
const parts = prompt.filter(
|
|
288
|
+
(m) => m.role === "system"
|
|
289
|
+
);
|
|
290
|
+
if (parts.length === 0) return void 0;
|
|
291
|
+
const joined = parts.map((m) => m.content).join("\n\n").trim();
|
|
292
|
+
return joined.length > 0 ? joined : void 0;
|
|
293
|
+
}
|
|
294
|
+
function userContentToInputParts(message) {
|
|
295
|
+
const out = [];
|
|
296
|
+
for (const part of message.content) {
|
|
297
|
+
if (part.type === "text" && part.text.length > 0) {
|
|
298
|
+
out.push({ type: "text", text: part.text });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return out;
|
|
302
|
+
}
|
|
303
|
+
function toolResultOutputToChatd(output) {
|
|
304
|
+
switch (output.type) {
|
|
305
|
+
case "text":
|
|
306
|
+
return { value: output.value, isError: false };
|
|
307
|
+
case "json":
|
|
308
|
+
return { value: output.value, isError: false };
|
|
309
|
+
case "error-text":
|
|
310
|
+
return { value: output.value, isError: true };
|
|
311
|
+
case "error-json":
|
|
312
|
+
return { value: output.value, isError: true };
|
|
313
|
+
case "execution-denied":
|
|
314
|
+
return { value: { execution_denied: true, reason: output.reason }, isError: true };
|
|
315
|
+
case "content":
|
|
316
|
+
return { value: output.value, isError: false };
|
|
317
|
+
default:
|
|
318
|
+
return { value: output, isError: false };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function classifyTurnAction(prompt) {
|
|
322
|
+
if (prompt.length === 0) return { kind: "noop" };
|
|
323
|
+
const last = prompt[prompt.length - 1];
|
|
324
|
+
if (!last) return { kind: "noop" };
|
|
325
|
+
if (last.role === "tool") {
|
|
326
|
+
const toolResults = [];
|
|
327
|
+
for (let i = prompt.length - 1; i >= 0; i--) {
|
|
328
|
+
const m = prompt[i];
|
|
329
|
+
if (!m || m.role !== "tool") break;
|
|
330
|
+
for (const part of m.content) {
|
|
331
|
+
if (part.type !== "tool-result") continue;
|
|
332
|
+
const { value, isError } = toolResultOutputToChatd(part.output);
|
|
333
|
+
toolResults.unshift({ tool_call_id: part.toolCallId, output: value, is_error: isError });
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return { kind: "resume", toolResults };
|
|
337
|
+
}
|
|
338
|
+
if (last.role === "user") {
|
|
339
|
+
return { kind: "new-turn", content: userContentToInputParts(last) };
|
|
340
|
+
}
|
|
341
|
+
return { kind: "noop" };
|
|
342
|
+
}
|
|
343
|
+
function toolsToDynamicTools(tools) {
|
|
344
|
+
if (!tools) return [];
|
|
345
|
+
const out = [];
|
|
346
|
+
for (const tool of tools) {
|
|
347
|
+
if (tool.type !== "function") continue;
|
|
348
|
+
out.push({
|
|
349
|
+
name: tool.name,
|
|
350
|
+
description: tool.description,
|
|
351
|
+
input_schema: tool.inputSchema
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return out;
|
|
355
|
+
}
|
|
356
|
+
function dynamicToolNames(tools) {
|
|
357
|
+
const names = /* @__PURE__ */ new Set();
|
|
358
|
+
for (const tool of tools ?? []) {
|
|
359
|
+
if (tool.type === "function") names.add(tool.name);
|
|
360
|
+
}
|
|
361
|
+
return names;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// src/model/translate.ts
|
|
365
|
+
function mapUsage(u) {
|
|
366
|
+
return {
|
|
367
|
+
inputTokens: {
|
|
368
|
+
total: u?.input_tokens,
|
|
369
|
+
noCache: void 0,
|
|
370
|
+
cacheRead: u?.cache_read_tokens,
|
|
371
|
+
cacheWrite: u?.cache_creation_tokens
|
|
372
|
+
},
|
|
373
|
+
outputTokens: {
|
|
374
|
+
total: u?.output_tokens,
|
|
375
|
+
text: void 0,
|
|
376
|
+
reasoning: u?.reasoning_tokens
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function jsonResult(value) {
|
|
381
|
+
return value ?? {};
|
|
382
|
+
}
|
|
383
|
+
var TurnTranslator = class {
|
|
384
|
+
#dynamicToolNames;
|
|
385
|
+
#seq = 0;
|
|
386
|
+
#text = { id: void 0, len: 0, sawDelta: false };
|
|
387
|
+
#reasoning = { id: void 0, len: 0, sawDelta: false };
|
|
388
|
+
#currentAssistantId;
|
|
389
|
+
#serverToolCalls = /* @__PURE__ */ new Set();
|
|
390
|
+
#serverToolResults = /* @__PURE__ */ new Set();
|
|
391
|
+
#clientToolCalls = /* @__PURE__ */ new Set();
|
|
392
|
+
#clientToolCallSeen = false;
|
|
393
|
+
#usage;
|
|
394
|
+
#error;
|
|
395
|
+
#terminalStatus;
|
|
396
|
+
#maxMessageId = 0;
|
|
397
|
+
constructor(opts) {
|
|
398
|
+
this.#dynamicToolNames = opts.dynamicToolNames;
|
|
399
|
+
}
|
|
400
|
+
get terminalStatus() {
|
|
401
|
+
return this.#terminalStatus;
|
|
402
|
+
}
|
|
403
|
+
/** Whether a client (custom) tool call has been emitted this turn. */
|
|
404
|
+
get clientToolCallSeen() {
|
|
405
|
+
return this.#clientToolCallSeen;
|
|
406
|
+
}
|
|
407
|
+
get maxMessageId() {
|
|
408
|
+
return this.#maxMessageId;
|
|
409
|
+
}
|
|
410
|
+
get error() {
|
|
411
|
+
return this.#error;
|
|
412
|
+
}
|
|
413
|
+
// --- block helpers --------------------------------------------------------
|
|
414
|
+
#openText(out) {
|
|
415
|
+
if (this.#reasoning.id) this.#closeReasoning(out);
|
|
416
|
+
if (!this.#text.id) {
|
|
417
|
+
this.#text.id = `text-${++this.#seq}`;
|
|
418
|
+
this.#text.len = 0;
|
|
419
|
+
out.push({ type: "text-start", id: this.#text.id });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
#closeText(out) {
|
|
423
|
+
if (this.#text.id) {
|
|
424
|
+
out.push({ type: "text-end", id: this.#text.id });
|
|
425
|
+
this.#text.id = void 0;
|
|
426
|
+
this.#text.len = 0;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
#openReasoning(out) {
|
|
430
|
+
if (this.#text.id) this.#closeText(out);
|
|
431
|
+
if (!this.#reasoning.id) {
|
|
432
|
+
this.#reasoning.id = `reasoning-${++this.#seq}`;
|
|
433
|
+
this.#reasoning.len = 0;
|
|
434
|
+
out.push({ type: "reasoning-start", id: this.#reasoning.id });
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
#closeReasoning(out) {
|
|
438
|
+
if (this.#reasoning.id) {
|
|
439
|
+
out.push({ type: "reasoning-end", id: this.#reasoning.id });
|
|
440
|
+
this.#reasoning.id = void 0;
|
|
441
|
+
this.#reasoning.len = 0;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
#emitTextUpTo(out, full) {
|
|
445
|
+
if (full.length <= this.#text.len && this.#text.id) return;
|
|
446
|
+
this.#openText(out);
|
|
447
|
+
if (full.length > this.#text.len) {
|
|
448
|
+
out.push({
|
|
449
|
+
type: "text-delta",
|
|
450
|
+
id: this.#text.id,
|
|
451
|
+
delta: full.slice(this.#text.len)
|
|
452
|
+
});
|
|
453
|
+
this.#text.len = full.length;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
#emitReasoningUpTo(out, full) {
|
|
457
|
+
if (full.length <= this.#reasoning.len && this.#reasoning.id) return;
|
|
458
|
+
this.#openReasoning(out);
|
|
459
|
+
if (full.length > this.#reasoning.len) {
|
|
460
|
+
out.push({
|
|
461
|
+
type: "reasoning-delta",
|
|
462
|
+
id: this.#reasoning.id,
|
|
463
|
+
delta: full.slice(this.#reasoning.len)
|
|
464
|
+
});
|
|
465
|
+
this.#reasoning.len = full.length;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
// --- tool helpers ---------------------------------------------------------
|
|
469
|
+
#isClientTool(name) {
|
|
470
|
+
return name !== void 0 && this.#dynamicToolNames.has(name);
|
|
471
|
+
}
|
|
472
|
+
#emitServerToolCall(out, part) {
|
|
473
|
+
const id = part.tool_call_id;
|
|
474
|
+
const name = part.tool_name;
|
|
475
|
+
if (!id || !name) return;
|
|
476
|
+
if (part.args === void 0) return;
|
|
477
|
+
if (this.#serverToolCalls.has(id)) return;
|
|
478
|
+
this.#serverToolCalls.add(id);
|
|
479
|
+
out.push({ type: "tool-input-start", id, toolName: name, providerExecuted: true });
|
|
480
|
+
out.push({ type: "tool-input-end", id });
|
|
481
|
+
out.push({
|
|
482
|
+
type: "tool-call",
|
|
483
|
+
toolCallId: id,
|
|
484
|
+
toolName: name,
|
|
485
|
+
input: typeof part.args === "string" ? part.args : JSON.stringify(part.args),
|
|
486
|
+
providerExecuted: true
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
#emitServerToolResult(out, part) {
|
|
490
|
+
const id = part.tool_call_id;
|
|
491
|
+
const name = part.tool_name;
|
|
492
|
+
if (!id || !name) return;
|
|
493
|
+
if (part.result === void 0) return;
|
|
494
|
+
if (this.#serverToolResults.has(id)) return;
|
|
495
|
+
this.#serverToolResults.add(id);
|
|
496
|
+
out.push({
|
|
497
|
+
type: "tool-result",
|
|
498
|
+
toolCallId: id,
|
|
499
|
+
toolName: name,
|
|
500
|
+
result: jsonResult(part.result),
|
|
501
|
+
isError: part.is_error ?? false
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
// --- ingest ---------------------------------------------------------------
|
|
505
|
+
ingest(ev) {
|
|
506
|
+
const out = [];
|
|
507
|
+
switch (ev.type) {
|
|
508
|
+
case "message_part":
|
|
509
|
+
this.#ingestMessagePart(out, ev);
|
|
510
|
+
break;
|
|
511
|
+
case "message":
|
|
512
|
+
if (ev.message) this.#ingestMessage(out, ev.message);
|
|
513
|
+
break;
|
|
514
|
+
case "action_required":
|
|
515
|
+
for (const tc of ev.action_required?.tool_calls ?? []) {
|
|
516
|
+
if (this.#clientToolCalls.has(tc.tool_call_id)) continue;
|
|
517
|
+
this.#closeText(out);
|
|
518
|
+
this.#closeReasoning(out);
|
|
519
|
+
this.#clientToolCalls.add(tc.tool_call_id);
|
|
520
|
+
this.#clientToolCallSeen = true;
|
|
521
|
+
out.push({ type: "tool-input-start", id: tc.tool_call_id, toolName: tc.tool_name });
|
|
522
|
+
out.push({ type: "tool-input-end", id: tc.tool_call_id });
|
|
523
|
+
out.push({
|
|
524
|
+
type: "tool-call",
|
|
525
|
+
toolCallId: tc.tool_call_id,
|
|
526
|
+
toolName: tc.tool_name,
|
|
527
|
+
input: tc.args
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
break;
|
|
531
|
+
case "error":
|
|
532
|
+
if (ev.error) {
|
|
533
|
+
this.#error = ev.error;
|
|
534
|
+
out.push({ type: "error", error: new CoderChatError(ev.error) });
|
|
535
|
+
}
|
|
536
|
+
break;
|
|
537
|
+
case "status":
|
|
538
|
+
if (ev.status && TERMINAL_STATUSES.has(ev.status.status)) {
|
|
539
|
+
this.#terminalStatus = ev.status.status;
|
|
540
|
+
}
|
|
541
|
+
break;
|
|
542
|
+
default:
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
return out;
|
|
546
|
+
}
|
|
547
|
+
#ingestMessagePart(out, ev) {
|
|
548
|
+
const mp = ev.message_part;
|
|
549
|
+
if (!mp || mp.role !== "assistant" && mp.role !== "tool") return;
|
|
550
|
+
const part = mp.part;
|
|
551
|
+
switch (part.type) {
|
|
552
|
+
case "text":
|
|
553
|
+
this.#text.sawDelta = true;
|
|
554
|
+
this.#openText(out);
|
|
555
|
+
if (part.text) {
|
|
556
|
+
out.push({ type: "text-delta", id: this.#text.id, delta: part.text });
|
|
557
|
+
this.#text.len += part.text.length;
|
|
558
|
+
}
|
|
559
|
+
break;
|
|
560
|
+
case "reasoning":
|
|
561
|
+
this.#reasoning.sawDelta = true;
|
|
562
|
+
this.#openReasoning(out);
|
|
563
|
+
if (part.text) {
|
|
564
|
+
out.push({ type: "reasoning-delta", id: this.#reasoning.id, delta: part.text });
|
|
565
|
+
this.#reasoning.len += part.text.length;
|
|
566
|
+
}
|
|
567
|
+
break;
|
|
568
|
+
case "tool-call":
|
|
569
|
+
this.#closeText(out);
|
|
570
|
+
this.#closeReasoning(out);
|
|
571
|
+
if (!this.#isClientTool(part.tool_name)) this.#emitServerToolCall(out, part);
|
|
572
|
+
break;
|
|
573
|
+
case "tool-result":
|
|
574
|
+
if (!this.#isClientTool(part.tool_name)) this.#emitServerToolResult(out, part);
|
|
575
|
+
break;
|
|
576
|
+
default:
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
#ingestMessage(out, message) {
|
|
581
|
+
if (message.id > this.#maxMessageId) this.#maxMessageId = message.id;
|
|
582
|
+
if (message.usage && (message.role === "assistant" || message.role === "tool")) {
|
|
583
|
+
this.#usage = message.usage;
|
|
584
|
+
}
|
|
585
|
+
const content = message.content ?? [];
|
|
586
|
+
if (message.role === "assistant") {
|
|
587
|
+
if (this.#currentAssistantId !== void 0 && this.#currentAssistantId !== message.id) {
|
|
588
|
+
this.#closeText(out);
|
|
589
|
+
this.#closeReasoning(out);
|
|
590
|
+
this.#text.sawDelta = false;
|
|
591
|
+
this.#reasoning.sawDelta = false;
|
|
592
|
+
}
|
|
593
|
+
this.#currentAssistantId = message.id;
|
|
594
|
+
if (!this.#text.sawDelta) {
|
|
595
|
+
const full = content.filter((p) => p.type === "text").map((p) => p.text ?? "").join("");
|
|
596
|
+
if (full.length > 0) this.#emitTextUpTo(out, full);
|
|
597
|
+
}
|
|
598
|
+
if (!this.#reasoning.sawDelta) {
|
|
599
|
+
const full = content.filter((p) => p.type === "reasoning").map((p) => p.text ?? "").join("");
|
|
600
|
+
if (full.length > 0) this.#emitReasoningUpTo(out, full);
|
|
601
|
+
}
|
|
602
|
+
for (const part of content) {
|
|
603
|
+
if (part.type === "tool-call" && !this.#isClientTool(part.tool_name))
|
|
604
|
+
this.#emitServerToolCall(out, part);
|
|
605
|
+
else if (part.type === "tool-result" && !this.#isClientTool(part.tool_name))
|
|
606
|
+
this.#emitServerToolResult(out, part);
|
|
607
|
+
}
|
|
608
|
+
} else if (message.role === "tool") {
|
|
609
|
+
for (const part of content) {
|
|
610
|
+
if (part.type === "tool-result" && !this.#isClientTool(part.tool_name))
|
|
611
|
+
this.#emitServerToolResult(out, part);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// --- finish ---------------------------------------------------------------
|
|
616
|
+
finish() {
|
|
617
|
+
const out = [];
|
|
618
|
+
this.#closeText(out);
|
|
619
|
+
this.#closeReasoning(out);
|
|
620
|
+
let unified;
|
|
621
|
+
if (this.#error || this.#terminalStatus === "error") unified = "error";
|
|
622
|
+
else if (this.#clientToolCallSeen || this.#terminalStatus === "requires_action")
|
|
623
|
+
unified = "tool-calls";
|
|
624
|
+
else unified = "stop";
|
|
625
|
+
out.push({
|
|
626
|
+
type: "finish",
|
|
627
|
+
usage: mapUsage(this.#usage),
|
|
628
|
+
finishReason: { unified, raw: this.#terminalStatus }
|
|
629
|
+
});
|
|
630
|
+
return out;
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// src/model/language-model.ts
|
|
635
|
+
var EMPTY_USAGE = {
|
|
636
|
+
inputTokens: {
|
|
637
|
+
total: void 0,
|
|
638
|
+
noCache: void 0,
|
|
639
|
+
cacheRead: void 0,
|
|
640
|
+
cacheWrite: void 0
|
|
641
|
+
},
|
|
642
|
+
outputTokens: { total: void 0, text: void 0, reasoning: void 0 }
|
|
643
|
+
};
|
|
644
|
+
var CoderLanguageModel = class {
|
|
645
|
+
specificationVersion = "v3";
|
|
646
|
+
provider = "coder.chatd";
|
|
647
|
+
modelId;
|
|
648
|
+
supportedUrls = {};
|
|
649
|
+
#config;
|
|
650
|
+
#chatId;
|
|
651
|
+
#lastSeenMessageId = 0;
|
|
652
|
+
#resolvedModelConfigId;
|
|
653
|
+
#modelResolved = false;
|
|
654
|
+
#submittedToolCallIds = /* @__PURE__ */ new Set();
|
|
655
|
+
#inFlight = false;
|
|
656
|
+
constructor(config) {
|
|
657
|
+
this.#config = config;
|
|
658
|
+
this.modelId = config.model ?? "chatd";
|
|
659
|
+
this.#chatId = config.chatId;
|
|
660
|
+
}
|
|
661
|
+
get chatId() {
|
|
662
|
+
return this.#chatId;
|
|
663
|
+
}
|
|
664
|
+
/** Drops the current session so the next turn creates a fresh chat. */
|
|
665
|
+
resetSession() {
|
|
666
|
+
this.#chatId = void 0;
|
|
667
|
+
this.#lastSeenMessageId = 0;
|
|
668
|
+
this.#submittedToolCallIds.clear();
|
|
669
|
+
}
|
|
670
|
+
async #resolveModelConfigId(signal) {
|
|
671
|
+
if (this.#modelResolved) return this.#resolvedModelConfigId;
|
|
672
|
+
if (this.#config.model) {
|
|
673
|
+
this.#resolvedModelConfigId = await this.#config.client.resolveModelConfigId(
|
|
674
|
+
this.#config.model,
|
|
675
|
+
signal
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
this.#modelResolved = true;
|
|
679
|
+
return this.#resolvedModelConfigId;
|
|
680
|
+
}
|
|
681
|
+
async *#runTurn(options) {
|
|
682
|
+
if (this.#inFlight) {
|
|
683
|
+
throw new CoderAgentError(
|
|
684
|
+
"A generation is already in flight on this CoderAgent (single-flight). Use a separate CoderAgent instance for concurrent sessions."
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
this.#inFlight = true;
|
|
688
|
+
try {
|
|
689
|
+
const { prompt, abortSignal: signal } = options;
|
|
690
|
+
yield { type: "stream-start", warnings: [] };
|
|
691
|
+
const action = classifyTurnAction(prompt);
|
|
692
|
+
if (action.kind === "noop") {
|
|
693
|
+
throw new CoderAgentError(
|
|
694
|
+
"CoderAgent received a prompt with no user message or tool results to act on."
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
const translator = new TurnTranslator({ dynamicToolNames: dynamicToolNames(options.tools) });
|
|
698
|
+
let afterId;
|
|
699
|
+
if (action.kind === "new-turn") {
|
|
700
|
+
const modelConfigId = await this.#resolveModelConfigId(signal);
|
|
701
|
+
if (!this.#chatId) {
|
|
702
|
+
const req = {
|
|
703
|
+
organization_id: this.#config.organizationId,
|
|
704
|
+
content: action.content,
|
|
705
|
+
client_type: "api"
|
|
706
|
+
};
|
|
707
|
+
const system = extractSystemPrompt(prompt);
|
|
708
|
+
if (system) req.system_prompt = system;
|
|
709
|
+
const tools = toolsToDynamicTools(options.tools);
|
|
710
|
+
if (tools.length > 0) req.unsafe_dynamic_tools = tools;
|
|
711
|
+
if (modelConfigId) req.model_config_id = modelConfigId;
|
|
712
|
+
if (this.#config.workspaceId) req.workspace_id = this.#config.workspaceId;
|
|
713
|
+
if (this.#config.mcpServerIds?.length) req.mcp_server_ids = this.#config.mcpServerIds;
|
|
714
|
+
if (this.#config.planMode) req.plan_mode = this.#config.planMode;
|
|
715
|
+
const chat = await this.#config.client.createChat(req, signal);
|
|
716
|
+
this.#chatId = chat.id;
|
|
717
|
+
afterId = this.#lastSeenMessageId > 0 ? this.#lastSeenMessageId : void 0;
|
|
718
|
+
} else {
|
|
719
|
+
const resp = await this.#config.client.createChatMessage(
|
|
720
|
+
this.#chatId,
|
|
721
|
+
{
|
|
722
|
+
content: action.content,
|
|
723
|
+
...modelConfigId ? { model_config_id: modelConfigId } : {}
|
|
724
|
+
},
|
|
725
|
+
signal
|
|
726
|
+
);
|
|
727
|
+
afterId = resp.message?.id ?? this.#lastSeenMessageId;
|
|
728
|
+
}
|
|
729
|
+
} else {
|
|
730
|
+
if (!this.#chatId)
|
|
731
|
+
throw new CoderChatError({ message: "cannot submit tool results before a chat exists" });
|
|
732
|
+
const fresh = action.toolResults.filter(
|
|
733
|
+
(r) => !this.#submittedToolCallIds.has(r.tool_call_id)
|
|
734
|
+
);
|
|
735
|
+
if (fresh.length > 0) {
|
|
736
|
+
await this.#config.client.submitToolResults(this.#chatId, { results: fresh }, signal);
|
|
737
|
+
for (const r of fresh) this.#submittedToolCallIds.add(r.tool_call_id);
|
|
738
|
+
}
|
|
739
|
+
afterId = this.#lastSeenMessageId;
|
|
740
|
+
}
|
|
741
|
+
const chatId = this.#chatId;
|
|
742
|
+
let sinceRequiresAction = 0;
|
|
743
|
+
for await (const ev of this.#config.client.streamEvents(chatId, { afterId, signal })) {
|
|
744
|
+
for (const part of translator.ingest(ev)) yield part;
|
|
745
|
+
const status = translator.terminalStatus;
|
|
746
|
+
if (status) {
|
|
747
|
+
if (status !== "requires_action") break;
|
|
748
|
+
if (translator.clientToolCallSeen) break;
|
|
749
|
+
if (++sinceRequiresAction > 200) break;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (signal?.aborted && !translator.terminalStatus) {
|
|
753
|
+
throw signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
|
|
754
|
+
}
|
|
755
|
+
for (const part of translator.finish()) yield part;
|
|
756
|
+
if (translator.maxMessageId > this.#lastSeenMessageId)
|
|
757
|
+
this.#lastSeenMessageId = translator.maxMessageId;
|
|
758
|
+
} finally {
|
|
759
|
+
this.#inFlight = false;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
async doStream(options) {
|
|
763
|
+
const gen = this.#runTurn(options);
|
|
764
|
+
const stream = new ReadableStream({
|
|
765
|
+
async pull(controller) {
|
|
766
|
+
try {
|
|
767
|
+
const { value, done } = await gen.next();
|
|
768
|
+
if (done) controller.close();
|
|
769
|
+
else controller.enqueue(value);
|
|
770
|
+
} catch (err) {
|
|
771
|
+
controller.error(err);
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
async cancel() {
|
|
775
|
+
await gen.return();
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
return { stream };
|
|
779
|
+
}
|
|
780
|
+
async doGenerate(options) {
|
|
781
|
+
const content = [];
|
|
782
|
+
const textBuf = /* @__PURE__ */ new Map();
|
|
783
|
+
const reasoningBuf = /* @__PURE__ */ new Map();
|
|
784
|
+
let usage = EMPTY_USAGE;
|
|
785
|
+
let finishReason = {
|
|
786
|
+
unified: "stop",
|
|
787
|
+
raw: void 0
|
|
788
|
+
};
|
|
789
|
+
const warnings = [];
|
|
790
|
+
for await (const part of this.#runTurn(options)) {
|
|
791
|
+
switch (part.type) {
|
|
792
|
+
case "stream-start":
|
|
793
|
+
warnings.push(...part.warnings);
|
|
794
|
+
break;
|
|
795
|
+
case "text-start":
|
|
796
|
+
textBuf.set(part.id, "");
|
|
797
|
+
break;
|
|
798
|
+
case "text-delta":
|
|
799
|
+
textBuf.set(part.id, (textBuf.get(part.id) ?? "") + part.delta);
|
|
800
|
+
break;
|
|
801
|
+
case "text-end": {
|
|
802
|
+
const t = textBuf.get(part.id) ?? "";
|
|
803
|
+
if (t.length > 0) content.push({ type: "text", text: t });
|
|
804
|
+
textBuf.delete(part.id);
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
case "reasoning-start":
|
|
808
|
+
reasoningBuf.set(part.id, "");
|
|
809
|
+
break;
|
|
810
|
+
case "reasoning-delta":
|
|
811
|
+
reasoningBuf.set(part.id, (reasoningBuf.get(part.id) ?? "") + part.delta);
|
|
812
|
+
break;
|
|
813
|
+
case "reasoning-end": {
|
|
814
|
+
const t = reasoningBuf.get(part.id) ?? "";
|
|
815
|
+
if (t.length > 0) content.push({ type: "reasoning", text: t });
|
|
816
|
+
reasoningBuf.delete(part.id);
|
|
817
|
+
break;
|
|
818
|
+
}
|
|
819
|
+
case "tool-call":
|
|
820
|
+
case "tool-result":
|
|
821
|
+
case "source":
|
|
822
|
+
case "file":
|
|
823
|
+
content.push(part);
|
|
824
|
+
break;
|
|
825
|
+
case "finish":
|
|
826
|
+
usage = part.usage;
|
|
827
|
+
finishReason = part.finishReason;
|
|
828
|
+
break;
|
|
829
|
+
case "error":
|
|
830
|
+
throw part.error instanceof Error ? part.error : new CoderChatError({ message: String(part.error) });
|
|
831
|
+
default:
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return { content, finishReason, usage, warnings };
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
|
|
839
|
+
// src/agent/coder-agent.ts
|
|
840
|
+
var DEFAULT_STOP = stepCountIs(64);
|
|
841
|
+
var CoderAgent = class {
|
|
842
|
+
version = "agent-v1";
|
|
843
|
+
#client;
|
|
844
|
+
#model;
|
|
845
|
+
#inner;
|
|
846
|
+
constructor(settings) {
|
|
847
|
+
if (settings.client) {
|
|
848
|
+
this.#client = settings.client;
|
|
849
|
+
} else if (settings.baseUrl && settings.token) {
|
|
850
|
+
this.#client = new CoderChatClient({
|
|
851
|
+
baseUrl: settings.baseUrl,
|
|
852
|
+
token: settings.token,
|
|
853
|
+
fetch: settings.fetch,
|
|
854
|
+
webSocketFactory: settings.webSocketFactory
|
|
855
|
+
});
|
|
856
|
+
} else {
|
|
857
|
+
throw new CoderAgentError(
|
|
858
|
+
"CoderAgent requires either `client` or both `baseUrl` and `token`."
|
|
859
|
+
);
|
|
860
|
+
}
|
|
861
|
+
this.#model = new CoderLanguageModel({
|
|
862
|
+
client: this.#client,
|
|
863
|
+
organizationId: settings.organizationId,
|
|
864
|
+
model: settings.model,
|
|
865
|
+
workspaceId: settings.workspaceId,
|
|
866
|
+
mcpServerIds: settings.mcpServerIds,
|
|
867
|
+
planMode: settings.planMode,
|
|
868
|
+
chatId: settings.chatId
|
|
869
|
+
});
|
|
870
|
+
this.#inner = new ToolLoopAgent({
|
|
871
|
+
model: this.#model,
|
|
872
|
+
id: settings.id,
|
|
873
|
+
instructions: settings.instructions,
|
|
874
|
+
tools: settings.tools,
|
|
875
|
+
toolChoice: settings.toolChoice,
|
|
876
|
+
stopWhen: settings.stopWhen ?? DEFAULT_STOP,
|
|
877
|
+
maxRetries: settings.maxRetries ?? 0
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
get id() {
|
|
881
|
+
return this.#inner.id;
|
|
882
|
+
}
|
|
883
|
+
get tools() {
|
|
884
|
+
return this.#inner.tools;
|
|
885
|
+
}
|
|
886
|
+
/** The underlying chatd client. */
|
|
887
|
+
get client() {
|
|
888
|
+
return this.#client;
|
|
889
|
+
}
|
|
890
|
+
/** The current chatd chat id, once a turn has started. */
|
|
891
|
+
get chatId() {
|
|
892
|
+
return this.#model.chatId;
|
|
893
|
+
}
|
|
894
|
+
generate(options) {
|
|
895
|
+
return this.#inner.generate(options);
|
|
896
|
+
}
|
|
897
|
+
stream(options) {
|
|
898
|
+
return this.#inner.stream(options);
|
|
899
|
+
}
|
|
900
|
+
// --- session helpers ------------------------------------------------------
|
|
901
|
+
/** Start a fresh chatd chat on the next turn. */
|
|
902
|
+
resetSession() {
|
|
903
|
+
this.#model.resetSession();
|
|
904
|
+
}
|
|
905
|
+
/** Interrupt the in-flight generation, if any. */
|
|
906
|
+
async interrupt() {
|
|
907
|
+
const id = this.#model.chatId;
|
|
908
|
+
if (id) await this.#client.interruptChat(id);
|
|
909
|
+
}
|
|
910
|
+
/** Archive the underlying chat (safe cleanup; hides it from listings). */
|
|
911
|
+
async archive() {
|
|
912
|
+
const id = this.#model.chatId;
|
|
913
|
+
if (id) await this.#client.archiveChat(id);
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
export {
|
|
917
|
+
CoderAgent,
|
|
918
|
+
CoderAgentError,
|
|
919
|
+
CoderApiError,
|
|
920
|
+
CoderChatClient,
|
|
921
|
+
CoderChatError,
|
|
922
|
+
CoderLanguageModel,
|
|
923
|
+
TurnTranslator,
|
|
924
|
+
classifyTurnAction,
|
|
925
|
+
dynamicToolNames,
|
|
926
|
+
extractSystemPrompt,
|
|
927
|
+
streamChatEvents,
|
|
928
|
+
toolsToDynamicTools
|
|
929
|
+
};
|
|
930
|
+
//# sourceMappingURL=index.js.map
|