@asm-agent/agent 0.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/README.md +502 -0
- package/dist/agent-loop.d.ts +24 -0
- package/dist/agent-loop.d.ts.map +1 -0
- package/dist/agent-loop.js +656 -0
- package/dist/agent-loop.js.map +1 -0
- package/dist/agent.d.ts +109 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +442 -0
- package/dist/agent.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/proxy.d.ts +59 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +268 -0
- package/dist/proxy.js.map +1 -0
- package/dist/types.d.ts +392 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
package/dist/agent.js
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import { createAssistantMessageDiagnostic, streamSimple, } from "@asm-agent/ai";
|
|
2
|
+
import { runAgentLoop, runAgentLoopContinue } from "./agent-loop.js";
|
|
3
|
+
function defaultConvertToLlm(messages) {
|
|
4
|
+
return messages.filter((message) => message.role === "user" || message.role === "assistant" || message.role === "toolResult");
|
|
5
|
+
}
|
|
6
|
+
const EMPTY_USAGE = {
|
|
7
|
+
input: 0,
|
|
8
|
+
output: 0,
|
|
9
|
+
cacheRead: 0,
|
|
10
|
+
cacheWrite: 0,
|
|
11
|
+
totalTokens: 0,
|
|
12
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
13
|
+
};
|
|
14
|
+
const DEFAULT_MODEL = {
|
|
15
|
+
id: "unknown",
|
|
16
|
+
name: "unknown",
|
|
17
|
+
api: "unknown",
|
|
18
|
+
provider: "unknown",
|
|
19
|
+
baseUrl: "",
|
|
20
|
+
reasoning: false,
|
|
21
|
+
input: [],
|
|
22
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
23
|
+
contextWindow: 0,
|
|
24
|
+
maxTokens: 0,
|
|
25
|
+
};
|
|
26
|
+
function createMutableAgentState(initialState) {
|
|
27
|
+
let tools = initialState?.tools?.slice() ?? [];
|
|
28
|
+
let messages = initialState?.messages?.slice() ?? [];
|
|
29
|
+
return {
|
|
30
|
+
systemPrompt: initialState?.systemPrompt ?? "",
|
|
31
|
+
model: initialState?.model ?? DEFAULT_MODEL,
|
|
32
|
+
thinkingLevel: initialState?.thinkingLevel ?? "off",
|
|
33
|
+
serviceTier: initialState?.serviceTier ?? "default",
|
|
34
|
+
get tools() {
|
|
35
|
+
return tools;
|
|
36
|
+
},
|
|
37
|
+
set tools(nextTools) {
|
|
38
|
+
tools = nextTools.slice();
|
|
39
|
+
},
|
|
40
|
+
get messages() {
|
|
41
|
+
return messages;
|
|
42
|
+
},
|
|
43
|
+
set messages(nextMessages) {
|
|
44
|
+
messages = nextMessages.slice();
|
|
45
|
+
},
|
|
46
|
+
isStreaming: false,
|
|
47
|
+
streamingMessage: undefined,
|
|
48
|
+
pendingToolCalls: new Set(),
|
|
49
|
+
errorMessage: undefined,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
class PendingMessageQueue {
|
|
53
|
+
mode;
|
|
54
|
+
batches = [];
|
|
55
|
+
constructor(mode) {
|
|
56
|
+
this.mode = mode;
|
|
57
|
+
}
|
|
58
|
+
enqueue(message) {
|
|
59
|
+
const batch = Array.isArray(message) ? message.slice() : [message];
|
|
60
|
+
if (batch.length > 0) {
|
|
61
|
+
this.batches.push(batch);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
hasItems() {
|
|
65
|
+
return this.batches.length > 0;
|
|
66
|
+
}
|
|
67
|
+
drain() {
|
|
68
|
+
if (this.mode === "all") {
|
|
69
|
+
const drained = this.batches.flat();
|
|
70
|
+
this.batches = [];
|
|
71
|
+
return drained;
|
|
72
|
+
}
|
|
73
|
+
const first = this.batches[0];
|
|
74
|
+
if (!first) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
this.batches = this.batches.slice(1);
|
|
78
|
+
return first;
|
|
79
|
+
}
|
|
80
|
+
clear() {
|
|
81
|
+
this.batches = [];
|
|
82
|
+
}
|
|
83
|
+
removeWhere(predicate) {
|
|
84
|
+
const removed = [];
|
|
85
|
+
const retained = [];
|
|
86
|
+
for (const batch of this.batches) {
|
|
87
|
+
if (batch.some(predicate)) {
|
|
88
|
+
removed.push(...batch);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
retained.push(batch);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this.batches = retained;
|
|
95
|
+
return removed;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Typed precondition failure from {@link Agent.continue}, so callers classify by code instead of message text. */
|
|
99
|
+
export class AgentContinueError extends Error {
|
|
100
|
+
code;
|
|
101
|
+
constructor(code, message) {
|
|
102
|
+
super(message);
|
|
103
|
+
this.code = code;
|
|
104
|
+
this.name = "AgentContinueError";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export class Agent {
|
|
108
|
+
_state;
|
|
109
|
+
listeners = new Set();
|
|
110
|
+
steeringQueue;
|
|
111
|
+
followUpQueue;
|
|
112
|
+
convertToLlm;
|
|
113
|
+
transformContext;
|
|
114
|
+
streamFn;
|
|
115
|
+
getApiKey;
|
|
116
|
+
onPayload;
|
|
117
|
+
onResponse;
|
|
118
|
+
beforeToolCall;
|
|
119
|
+
afterToolCall;
|
|
120
|
+
shouldStopAfterTurn;
|
|
121
|
+
shouldStopBeforeTurn;
|
|
122
|
+
getContinuationMessages;
|
|
123
|
+
activeRun;
|
|
124
|
+
sessionId;
|
|
125
|
+
thinkingBudgets;
|
|
126
|
+
transport;
|
|
127
|
+
maxRetryDelayMs;
|
|
128
|
+
toolExecution;
|
|
129
|
+
constructor(options = {}) {
|
|
130
|
+
this._state = createMutableAgentState(options.initialState);
|
|
131
|
+
this.convertToLlm = options.convertToLlm ?? defaultConvertToLlm;
|
|
132
|
+
this.transformContext = options.transformContext;
|
|
133
|
+
this.streamFn = options.streamFn ?? streamSimple;
|
|
134
|
+
this.getApiKey = options.getApiKey;
|
|
135
|
+
this.onPayload = options.onPayload;
|
|
136
|
+
this.onResponse = options.onResponse;
|
|
137
|
+
this.beforeToolCall = options.beforeToolCall;
|
|
138
|
+
this.afterToolCall = options.afterToolCall;
|
|
139
|
+
this.shouldStopAfterTurn = options.shouldStopAfterTurn;
|
|
140
|
+
this.shouldStopBeforeTurn = options.shouldStopBeforeTurn;
|
|
141
|
+
this.getContinuationMessages = options.getContinuationMessages;
|
|
142
|
+
this.steeringQueue = new PendingMessageQueue(options.steeringMode ?? "one-at-a-time");
|
|
143
|
+
this.followUpQueue = new PendingMessageQueue(options.followUpMode ?? "one-at-a-time");
|
|
144
|
+
this.sessionId = options.sessionId;
|
|
145
|
+
this.thinkingBudgets = options.thinkingBudgets;
|
|
146
|
+
this.transport = options.transport ?? "auto";
|
|
147
|
+
this.maxRetryDelayMs = options.maxRetryDelayMs;
|
|
148
|
+
this.toolExecution = options.toolExecution ?? "parallel";
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Subscribe to agent lifecycle events.
|
|
152
|
+
*
|
|
153
|
+
* Listener promises are awaited in subscription order and are included in
|
|
154
|
+
* the current run's settlement. Listeners also receive the active abort
|
|
155
|
+
* signal for the current run.
|
|
156
|
+
*
|
|
157
|
+
* `agent_end` is the final emitted event for a run, but the agent does not
|
|
158
|
+
* become idle until all awaited listeners for that event have settled.
|
|
159
|
+
*/
|
|
160
|
+
subscribe(listener) {
|
|
161
|
+
this.listeners.add(listener);
|
|
162
|
+
return () => this.listeners.delete(listener);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Current agent state.
|
|
166
|
+
*
|
|
167
|
+
* Assigning `state.tools` or `state.messages` copies the provided top-level array.
|
|
168
|
+
*/
|
|
169
|
+
get state() {
|
|
170
|
+
return this._state;
|
|
171
|
+
}
|
|
172
|
+
set steeringMode(mode) {
|
|
173
|
+
this.steeringQueue.mode = mode;
|
|
174
|
+
}
|
|
175
|
+
get steeringMode() {
|
|
176
|
+
return this.steeringQueue.mode;
|
|
177
|
+
}
|
|
178
|
+
set followUpMode(mode) {
|
|
179
|
+
this.followUpQueue.mode = mode;
|
|
180
|
+
}
|
|
181
|
+
get followUpMode() {
|
|
182
|
+
return this.followUpQueue.mode;
|
|
183
|
+
}
|
|
184
|
+
/** Queue a message batch to be injected after the current assistant turn finishes. */
|
|
185
|
+
steer(message) {
|
|
186
|
+
this.steeringQueue.enqueue(message);
|
|
187
|
+
}
|
|
188
|
+
/** Queue a message batch to run only after the agent would otherwise stop. */
|
|
189
|
+
followUp(message) {
|
|
190
|
+
this.followUpQueue.enqueue(message);
|
|
191
|
+
}
|
|
192
|
+
clearSteeringQueue() {
|
|
193
|
+
this.steeringQueue.clear();
|
|
194
|
+
}
|
|
195
|
+
clearFollowUpQueue() {
|
|
196
|
+
this.followUpQueue.clear();
|
|
197
|
+
}
|
|
198
|
+
clearAllQueues() {
|
|
199
|
+
this.clearSteeringQueue();
|
|
200
|
+
this.clearFollowUpQueue();
|
|
201
|
+
}
|
|
202
|
+
removeQueuedMessages(predicate) {
|
|
203
|
+
return [...this.steeringQueue.removeWhere(predicate), ...this.followUpQueue.removeWhere(predicate)];
|
|
204
|
+
}
|
|
205
|
+
hasQueuedMessages() {
|
|
206
|
+
return this.steeringQueue.hasItems() || this.followUpQueue.hasItems();
|
|
207
|
+
}
|
|
208
|
+
get signal() {
|
|
209
|
+
return this.activeRun?.abortController.signal;
|
|
210
|
+
}
|
|
211
|
+
abort() {
|
|
212
|
+
this.activeRun?.abortController.abort();
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Resolve when the current run and all awaited event listeners have finished.
|
|
216
|
+
*
|
|
217
|
+
* This resolves after `agent_end` listeners settle.
|
|
218
|
+
*/
|
|
219
|
+
waitForIdle() {
|
|
220
|
+
return this.activeRun?.promise ?? Promise.resolve();
|
|
221
|
+
}
|
|
222
|
+
reset() {
|
|
223
|
+
this._state.messages = [];
|
|
224
|
+
this._state.isStreaming = false;
|
|
225
|
+
this._state.streamingMessage = undefined;
|
|
226
|
+
this._state.pendingToolCalls = new Set();
|
|
227
|
+
this._state.errorMessage = undefined;
|
|
228
|
+
this.clearFollowUpQueue();
|
|
229
|
+
this.clearSteeringQueue();
|
|
230
|
+
}
|
|
231
|
+
async prompt(input, images) {
|
|
232
|
+
if (this.activeRun) {
|
|
233
|
+
throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");
|
|
234
|
+
}
|
|
235
|
+
const messages = this.normalizePromptInput(input, images);
|
|
236
|
+
await this.runPromptMessages(messages);
|
|
237
|
+
}
|
|
238
|
+
/** The last message must convert to a user or tool-result message. */
|
|
239
|
+
async continue() {
|
|
240
|
+
if (this.activeRun) {
|
|
241
|
+
throw new AgentContinueError("busy", "Agent is already processing. Wait for completion before continuing.");
|
|
242
|
+
}
|
|
243
|
+
const runQueuedMessages = () => {
|
|
244
|
+
const queuedSteering = this.steeringQueue.drain();
|
|
245
|
+
if (queuedSteering.length > 0) {
|
|
246
|
+
return this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });
|
|
247
|
+
}
|
|
248
|
+
const queuedFollowUps = this.followUpQueue.drain();
|
|
249
|
+
if (queuedFollowUps.length > 0) {
|
|
250
|
+
return this.runPromptMessages(queuedFollowUps);
|
|
251
|
+
}
|
|
252
|
+
return undefined;
|
|
253
|
+
};
|
|
254
|
+
const lastMessage = this._state.messages[this._state.messages.length - 1];
|
|
255
|
+
if (!lastMessage) {
|
|
256
|
+
const queuedRun = runQueuedMessages();
|
|
257
|
+
if (queuedRun) {
|
|
258
|
+
await queuedRun;
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
throw new AgentContinueError("nothing-to-continue", "No messages to continue from");
|
|
262
|
+
}
|
|
263
|
+
if (lastMessage.role === "assistant") {
|
|
264
|
+
const queuedRun = runQueuedMessages();
|
|
265
|
+
if (queuedRun) {
|
|
266
|
+
await queuedRun;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
throw new AgentContinueError("nothing-to-continue", "Cannot continue from message role: assistant");
|
|
270
|
+
}
|
|
271
|
+
const lastMessageRole = lastMessage.role;
|
|
272
|
+
if (lastMessageRole === "custom") {
|
|
273
|
+
const queuedRun = runQueuedMessages();
|
|
274
|
+
if (queuedRun) {
|
|
275
|
+
await queuedRun;
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
await this.runContinuation();
|
|
280
|
+
}
|
|
281
|
+
normalizePromptInput(input, images) {
|
|
282
|
+
if (Array.isArray(input)) {
|
|
283
|
+
return input;
|
|
284
|
+
}
|
|
285
|
+
if (typeof input !== "string") {
|
|
286
|
+
return [input];
|
|
287
|
+
}
|
|
288
|
+
const content = [{ type: "text", text: input }];
|
|
289
|
+
if (images && images.length > 0) {
|
|
290
|
+
content.push(...images);
|
|
291
|
+
}
|
|
292
|
+
return [{ role: "user", content, timestamp: Date.now() }];
|
|
293
|
+
}
|
|
294
|
+
async runPromptMessages(messages, options = {}) {
|
|
295
|
+
await this.runWithLifecycle(async (signal) => {
|
|
296
|
+
await runAgentLoop(messages, this.createContextSnapshot(), this.createLoopConfig(options), (event) => this.processEvents(event), signal, this.streamFn);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
async runContinuation() {
|
|
300
|
+
await this.runWithLifecycle(async (signal) => {
|
|
301
|
+
await runAgentLoopContinue(this.createContextSnapshot(), this.createLoopConfig(), (event) => this.processEvents(event), signal, this.streamFn);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
createContextSnapshot() {
|
|
305
|
+
return {
|
|
306
|
+
systemPrompt: this._state.systemPrompt,
|
|
307
|
+
messages: this._state.messages.slice(),
|
|
308
|
+
tools: this._state.tools.slice(),
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
createLoopConfig(options = {}) {
|
|
312
|
+
let skipInitialSteeringPoll = options.skipInitialSteeringPoll === true;
|
|
313
|
+
return {
|
|
314
|
+
model: this._state.model,
|
|
315
|
+
reasoning: this._state.thinkingLevel,
|
|
316
|
+
serviceTier: this._state.serviceTier,
|
|
317
|
+
sessionId: this.sessionId,
|
|
318
|
+
onPayload: this.onPayload,
|
|
319
|
+
onResponse: this.onResponse,
|
|
320
|
+
transport: this.transport,
|
|
321
|
+
thinkingBudgets: this.thinkingBudgets,
|
|
322
|
+
maxRetryDelayMs: this.maxRetryDelayMs,
|
|
323
|
+
toolExecution: this.toolExecution,
|
|
324
|
+
beforeToolCall: this.beforeToolCall,
|
|
325
|
+
afterToolCall: this.afterToolCall,
|
|
326
|
+
shouldStopAfterTurn: async (context) => this.shouldStopAfterTurn?.(context) ?? false,
|
|
327
|
+
shouldStopBeforeTurn: () => this.shouldStopBeforeTurn?.() ?? false,
|
|
328
|
+
convertToLlm: this.convertToLlm,
|
|
329
|
+
transformContext: this.transformContext,
|
|
330
|
+
getSystemPrompt: () => this._state.systemPrompt,
|
|
331
|
+
getApiKey: this.getApiKey,
|
|
332
|
+
getSteeringMessages: async () => {
|
|
333
|
+
if (skipInitialSteeringPoll) {
|
|
334
|
+
skipInitialSteeringPoll = false;
|
|
335
|
+
return [];
|
|
336
|
+
}
|
|
337
|
+
return this.steeringQueue.drain();
|
|
338
|
+
},
|
|
339
|
+
getFollowUpMessages: async () => this.followUpQueue.drain(),
|
|
340
|
+
getContinuationMessages: async (context, signal) => this.getContinuationMessages?.(context, signal) ?? [],
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
async runWithLifecycle(executor) {
|
|
344
|
+
if (this.activeRun) {
|
|
345
|
+
throw new Error("Agent is already processing.");
|
|
346
|
+
}
|
|
347
|
+
const abortController = new AbortController();
|
|
348
|
+
let resolvePromise = () => { };
|
|
349
|
+
const promise = new Promise((resolve) => {
|
|
350
|
+
resolvePromise = resolve;
|
|
351
|
+
});
|
|
352
|
+
this.activeRun = { promise, resolve: resolvePromise, abortController };
|
|
353
|
+
this._state.isStreaming = true;
|
|
354
|
+
this._state.streamingMessage = undefined;
|
|
355
|
+
this._state.errorMessage = undefined;
|
|
356
|
+
try {
|
|
357
|
+
await executor(abortController.signal);
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
await this.handleRunFailure(error, abortController.signal.aborted);
|
|
361
|
+
}
|
|
362
|
+
finally {
|
|
363
|
+
this.finishRun();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
async handleRunFailure(error, aborted) {
|
|
367
|
+
const failureMessage = {
|
|
368
|
+
role: "assistant",
|
|
369
|
+
content: [{ type: "text", text: "" }],
|
|
370
|
+
api: this._state.model.api,
|
|
371
|
+
provider: this._state.model.provider,
|
|
372
|
+
model: this._state.model.id,
|
|
373
|
+
usage: EMPTY_USAGE,
|
|
374
|
+
stopReason: aborted ? "aborted" : "error",
|
|
375
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
376
|
+
diagnostics: aborted
|
|
377
|
+
? undefined
|
|
378
|
+
: [createAssistantMessageDiagnostic("agent_lifecycle_failure", error, { source: "run_with_lifecycle" })],
|
|
379
|
+
timestamp: Date.now(),
|
|
380
|
+
};
|
|
381
|
+
this._state.errorMessage = failureMessage.errorMessage;
|
|
382
|
+
await this.processEvents({ type: "message_start", message: failureMessage }).catch(() => undefined);
|
|
383
|
+
await this.processEvents({ type: "message_end", message: failureMessage }).catch(() => undefined);
|
|
384
|
+
await this.processEvents({ type: "agent_end", messages: [failureMessage] }).catch(() => undefined);
|
|
385
|
+
}
|
|
386
|
+
finishRun() {
|
|
387
|
+
this._state.isStreaming = false;
|
|
388
|
+
this._state.streamingMessage = undefined;
|
|
389
|
+
this._state.pendingToolCalls = new Set();
|
|
390
|
+
this.activeRun?.resolve();
|
|
391
|
+
this.activeRun = undefined;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Reduce internal state for a loop event, then await listeners.
|
|
395
|
+
*
|
|
396
|
+
* `agent_end` only means no further loop events will be emitted. The run is
|
|
397
|
+
* considered idle later, after all awaited listeners for `agent_end` finish
|
|
398
|
+
* and `finishRun()` clears runtime-owned state.
|
|
399
|
+
*/
|
|
400
|
+
async processEvents(event) {
|
|
401
|
+
switch (event.type) {
|
|
402
|
+
case "message_start":
|
|
403
|
+
this._state.streamingMessage = event.message;
|
|
404
|
+
break;
|
|
405
|
+
case "message_update":
|
|
406
|
+
this._state.streamingMessage = event.message;
|
|
407
|
+
break;
|
|
408
|
+
case "message_end":
|
|
409
|
+
this._state.streamingMessage = undefined;
|
|
410
|
+
this._state.messages.push(event.message);
|
|
411
|
+
break;
|
|
412
|
+
case "tool_execution_start": {
|
|
413
|
+
const pendingToolCalls = new Set(this._state.pendingToolCalls);
|
|
414
|
+
pendingToolCalls.add(event.toolCallId);
|
|
415
|
+
this._state.pendingToolCalls = pendingToolCalls;
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
case "tool_execution_end": {
|
|
419
|
+
const pendingToolCalls = new Set(this._state.pendingToolCalls);
|
|
420
|
+
pendingToolCalls.delete(event.toolCallId);
|
|
421
|
+
this._state.pendingToolCalls = pendingToolCalls;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
case "turn_end":
|
|
425
|
+
if (event.message.role === "assistant" && event.message.errorMessage) {
|
|
426
|
+
this._state.errorMessage = event.message.errorMessage;
|
|
427
|
+
}
|
|
428
|
+
break;
|
|
429
|
+
case "agent_end":
|
|
430
|
+
this._state.streamingMessage = undefined;
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
const signal = this.activeRun?.abortController.signal;
|
|
434
|
+
if (!signal) {
|
|
435
|
+
throw new Error("Agent listener invoked outside active run");
|
|
436
|
+
}
|
|
437
|
+
for (const listener of this.listeners) {
|
|
438
|
+
await listener(event, signal);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcreateAssistantMessageDiagnostic,\n\ttype ImageContent,\n\ttype Message,\n\ttype Model,\n\ttype SimpleStreamOptions,\n\tstreamSimple,\n\ttype TextContent,\n\ttype ThinkingBudgets,\n\ttype Transport,\n} from \"@asm-agent/ai\";\nimport { runAgentLoop, runAgentLoopContinue } from \"./agent-loop.js\";\nimport type {\n\tAfterToolCallContext,\n\tAfterToolCallResult,\n\tAgentContext,\n\tAgentEvent,\n\tAgentLoopConfig,\n\tAgentMessage,\n\tAgentState,\n\tAgentTool,\n\tBeforeToolCallContext,\n\tBeforeToolCallResult,\n\tGetContinuationMessagesContext,\n\tShouldStopAfterTurnContext,\n\tStreamFn,\n\tToolExecutionMode,\n} from \"./types.js\";\n\nfunction defaultConvertToLlm(messages: AgentMessage[]): Message[] {\n\treturn messages.filter(\n\t\t(message) => message.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\",\n\t);\n}\n\nconst EMPTY_USAGE = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nconst DEFAULT_MODEL = {\n\tid: \"unknown\",\n\tname: \"unknown\",\n\tapi: \"unknown\",\n\tprovider: \"unknown\",\n\tbaseUrl: \"\",\n\treasoning: false,\n\tinput: [],\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\tcontextWindow: 0,\n\tmaxTokens: 0,\n} satisfies Model<any>;\n\ntype QueueMode = \"all\" | \"one-at-a-time\";\n\ntype MutableAgentState = Omit<AgentState, \"isStreaming\" | \"streamingMessage\" | \"pendingToolCalls\" | \"errorMessage\"> & {\n\tisStreaming: boolean;\n\tstreamingMessage?: AgentMessage;\n\tpendingToolCalls: Set<string>;\n\terrorMessage?: string;\n};\n\nfunction createMutableAgentState(\n\tinitialState?: Partial<Omit<AgentState, \"pendingToolCalls\" | \"isStreaming\" | \"streamingMessage\" | \"errorMessage\">>,\n): MutableAgentState {\n\tlet tools = initialState?.tools?.slice() ?? [];\n\tlet messages = initialState?.messages?.slice() ?? [];\n\n\treturn {\n\t\tsystemPrompt: initialState?.systemPrompt ?? \"\",\n\t\tmodel: initialState?.model ?? DEFAULT_MODEL,\n\t\tthinkingLevel: initialState?.thinkingLevel ?? \"off\",\n\t\tserviceTier: initialState?.serviceTier ?? \"default\",\n\t\tget tools() {\n\t\t\treturn tools;\n\t\t},\n\t\tset tools(nextTools: AgentTool<any>[]) {\n\t\t\ttools = nextTools.slice();\n\t\t},\n\t\tget messages() {\n\t\t\treturn messages;\n\t\t},\n\t\tset messages(nextMessages: AgentMessage[]) {\n\t\t\tmessages = nextMessages.slice();\n\t\t},\n\t\tisStreaming: false,\n\t\tstreamingMessage: undefined,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terrorMessage: undefined,\n\t};\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<Omit<AgentState, \"pendingToolCalls\" | \"isStreaming\" | \"streamingMessage\" | \"errorMessage\">>;\n\tconvertToLlm?: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\ttransformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tstreamFn?: StreamFn;\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tonPayload?: SimpleStreamOptions[\"onPayload\"];\n\tonResponse?: SimpleStreamOptions[\"onResponse\"];\n\tbeforeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise<BeforeToolCallResult | undefined>;\n\tafterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise<AfterToolCallResult | undefined>;\n\tshouldStopAfterTurn?: (context: ShouldStopAfterTurnContext) => boolean | Promise<boolean>;\n\tshouldStopBeforeTurn?: () => boolean;\n\tgetContinuationMessages?: (context: GetContinuationMessagesContext, signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tsteeringMode?: QueueMode;\n\tfollowUpMode?: QueueMode;\n\tsessionId?: string;\n\tthinkingBudgets?: ThinkingBudgets;\n\ttransport?: Transport;\n\tmaxRetryDelayMs?: number;\n\ttoolExecution?: ToolExecutionMode;\n}\n\nclass PendingMessageQueue {\n\tprivate batches: AgentMessage[][] = [];\n\n\tconstructor(public mode: QueueMode) {}\n\n\tenqueue(message: AgentMessage | AgentMessage[]): void {\n\t\tconst batch = Array.isArray(message) ? message.slice() : [message];\n\t\tif (batch.length > 0) {\n\t\t\tthis.batches.push(batch);\n\t\t}\n\t}\n\n\thasItems(): boolean {\n\t\treturn this.batches.length > 0;\n\t}\n\n\tdrain(): AgentMessage[] {\n\t\tif (this.mode === \"all\") {\n\t\t\tconst drained = this.batches.flat();\n\t\t\tthis.batches = [];\n\t\t\treturn drained;\n\t\t}\n\n\t\tconst first = this.batches[0];\n\t\tif (!first) {\n\t\t\treturn [];\n\t\t}\n\t\tthis.batches = this.batches.slice(1);\n\t\treturn first;\n\t}\n\n\tclear(): void {\n\t\tthis.batches = [];\n\t}\n\n\tremoveWhere(predicate: (message: AgentMessage) => boolean): AgentMessage[] {\n\t\tconst removed: AgentMessage[] = [];\n\t\tconst retained: AgentMessage[][] = [];\n\t\tfor (const batch of this.batches) {\n\t\t\tif (batch.some(predicate)) {\n\t\t\t\tremoved.push(...batch);\n\t\t\t} else {\n\t\t\t\tretained.push(batch);\n\t\t\t}\n\t\t}\n\t\tthis.batches = retained;\n\t\treturn removed;\n\t}\n}\n\ntype ActiveRun = {\n\tpromise: Promise<void>;\n\tresolve: () => void;\n\tabortController: AbortController;\n};\n\n/** Why {@link Agent.continue} refused to start a continuation. */\nexport type AgentContinueErrorCode = \"busy\" | \"nothing-to-continue\";\n\n/** Typed precondition failure from {@link Agent.continue}, so callers classify by code instead of message text. */\nexport class AgentContinueError extends Error {\n\tconstructor(\n\t\treadonly code: AgentContinueErrorCode,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"AgentContinueError\";\n\t}\n}\n\nexport class Agent {\n\tprivate _state: MutableAgentState;\n\tprivate readonly listeners = new Set<(event: AgentEvent, signal: AbortSignal) => Promise<void> | void>();\n\tprivate readonly steeringQueue: PendingMessageQueue;\n\tprivate readonly followUpQueue: PendingMessageQueue;\n\n\tpublic convertToLlm: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\tpublic transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tpublic streamFn: StreamFn;\n\tpublic getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tpublic onPayload?: SimpleStreamOptions[\"onPayload\"];\n\tpublic onResponse?: SimpleStreamOptions[\"onResponse\"];\n\tpublic beforeToolCall?: (\n\t\tcontext: BeforeToolCallContext,\n\t\tsignal?: AbortSignal,\n\t) => Promise<BeforeToolCallResult | undefined>;\n\tpublic afterToolCall?: (\n\t\tcontext: AfterToolCallContext,\n\t\tsignal?: AbortSignal,\n\t) => Promise<AfterToolCallResult | undefined>;\n\tpublic shouldStopAfterTurn?: (context: ShouldStopAfterTurnContext) => boolean | Promise<boolean>;\n\tpublic shouldStopBeforeTurn?: () => boolean;\n\tpublic getContinuationMessages?: (\n\t\tcontext: GetContinuationMessagesContext,\n\t\tsignal?: AbortSignal,\n\t) => Promise<AgentMessage[]>;\n\tprivate activeRun?: ActiveRun;\n\tpublic sessionId?: string;\n\tpublic thinkingBudgets?: ThinkingBudgets;\n\tpublic transport: Transport;\n\tpublic maxRetryDelayMs?: number;\n\tpublic toolExecution: ToolExecutionMode;\n\n\tconstructor(options: AgentOptions = {}) {\n\t\tthis._state = createMutableAgentState(options.initialState);\n\t\tthis.convertToLlm = options.convertToLlm ?? defaultConvertToLlm;\n\t\tthis.transformContext = options.transformContext;\n\t\tthis.streamFn = options.streamFn ?? streamSimple;\n\t\tthis.getApiKey = options.getApiKey;\n\t\tthis.onPayload = options.onPayload;\n\t\tthis.onResponse = options.onResponse;\n\t\tthis.beforeToolCall = options.beforeToolCall;\n\t\tthis.afterToolCall = options.afterToolCall;\n\t\tthis.shouldStopAfterTurn = options.shouldStopAfterTurn;\n\t\tthis.shouldStopBeforeTurn = options.shouldStopBeforeTurn;\n\t\tthis.getContinuationMessages = options.getContinuationMessages;\n\t\tthis.steeringQueue = new PendingMessageQueue(options.steeringMode ?? \"one-at-a-time\");\n\t\tthis.followUpQueue = new PendingMessageQueue(options.followUpMode ?? \"one-at-a-time\");\n\t\tthis.sessionId = options.sessionId;\n\t\tthis.thinkingBudgets = options.thinkingBudgets;\n\t\tthis.transport = options.transport ?? \"auto\";\n\t\tthis.maxRetryDelayMs = options.maxRetryDelayMs;\n\t\tthis.toolExecution = options.toolExecution ?? \"parallel\";\n\t}\n\n\t/**\n\t * Subscribe to agent lifecycle events.\n\t *\n\t * Listener promises are awaited in subscription order and are included in\n\t * the current run's settlement. Listeners also receive the active abort\n\t * signal for the current run.\n\t *\n\t * `agent_end` is the final emitted event for a run, but the agent does not\n\t * become idle until all awaited listeners for that event have settled.\n\t */\n\tsubscribe(listener: (event: AgentEvent, signal: AbortSignal) => Promise<void> | void): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\n\t/**\n\t * Current agent state.\n\t *\n\t * Assigning `state.tools` or `state.messages` copies the provided top-level array.\n\t */\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tset steeringMode(mode: QueueMode) {\n\t\tthis.steeringQueue.mode = mode;\n\t}\n\n\tget steeringMode(): QueueMode {\n\t\treturn this.steeringQueue.mode;\n\t}\n\n\tset followUpMode(mode: QueueMode) {\n\t\tthis.followUpQueue.mode = mode;\n\t}\n\n\tget followUpMode(): QueueMode {\n\t\treturn this.followUpQueue.mode;\n\t}\n\n\t/** Queue a message batch to be injected after the current assistant turn finishes. */\n\tsteer(message: AgentMessage | AgentMessage[]): void {\n\t\tthis.steeringQueue.enqueue(message);\n\t}\n\n\t/** Queue a message batch to run only after the agent would otherwise stop. */\n\tfollowUp(message: AgentMessage | AgentMessage[]): void {\n\t\tthis.followUpQueue.enqueue(message);\n\t}\n\n\tclearSteeringQueue(): void {\n\t\tthis.steeringQueue.clear();\n\t}\n\n\tclearFollowUpQueue(): void {\n\t\tthis.followUpQueue.clear();\n\t}\n\n\tclearAllQueues(): void {\n\t\tthis.clearSteeringQueue();\n\t\tthis.clearFollowUpQueue();\n\t}\n\n\tremoveQueuedMessages(predicate: (message: AgentMessage) => boolean): AgentMessage[] {\n\t\treturn [...this.steeringQueue.removeWhere(predicate), ...this.followUpQueue.removeWhere(predicate)];\n\t}\n\n\thasQueuedMessages(): boolean {\n\t\treturn this.steeringQueue.hasItems() || this.followUpQueue.hasItems();\n\t}\n\n\tget signal(): AbortSignal | undefined {\n\t\treturn this.activeRun?.abortController.signal;\n\t}\n\n\tabort(): void {\n\t\tthis.activeRun?.abortController.abort();\n\t}\n\n\t/**\n\t * Resolve when the current run and all awaited event listeners have finished.\n\t *\n\t * This resolves after `agent_end` listeners settle.\n\t */\n\twaitForIdle(): Promise<void> {\n\t\treturn this.activeRun?.promise ?? Promise.resolve();\n\t}\n\n\treset(): void {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamingMessage = undefined;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.errorMessage = undefined;\n\t\tthis.clearFollowUpQueue();\n\t\tthis.clearSteeringQueue();\n\t}\n\n\tasync prompt(message: AgentMessage | AgentMessage[]): Promise<void>;\n\tasync prompt(input: string, images?: ImageContent[]): Promise<void>;\n\tasync prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.\",\n\t\t\t);\n\t\t}\n\t\tconst messages = this.normalizePromptInput(input, images);\n\t\tawait this.runPromptMessages(messages);\n\t}\n\n\t/** The last message must convert to a user or tool-result message. */\n\tasync continue(): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new AgentContinueError(\"busy\", \"Agent is already processing. Wait for completion before continuing.\");\n\t\t}\n\n\t\tconst runQueuedMessages = (): Promise<void> | undefined => {\n\t\t\tconst queuedSteering = this.steeringQueue.drain();\n\t\t\tif (queuedSteering.length > 0) {\n\t\t\t\treturn this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });\n\t\t\t}\n\n\t\t\tconst queuedFollowUps = this.followUpQueue.drain();\n\t\t\tif (queuedFollowUps.length > 0) {\n\t\t\t\treturn this.runPromptMessages(queuedFollowUps);\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t};\n\n\t\tconst lastMessage = this._state.messages[this._state.messages.length - 1];\n\t\tif (!lastMessage) {\n\t\t\tconst queuedRun = runQueuedMessages();\n\t\t\tif (queuedRun) {\n\t\t\t\tawait queuedRun;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new AgentContinueError(\"nothing-to-continue\", \"No messages to continue from\");\n\t\t}\n\n\t\tif (lastMessage.role === \"assistant\") {\n\t\t\tconst queuedRun = runQueuedMessages();\n\t\t\tif (queuedRun) {\n\t\t\t\tawait queuedRun;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new AgentContinueError(\"nothing-to-continue\", \"Cannot continue from message role: assistant\");\n\t\t}\n\n\t\tconst lastMessageRole: string = lastMessage.role;\n\t\tif (lastMessageRole === \"custom\") {\n\t\t\tconst queuedRun = runQueuedMessages();\n\t\t\tif (queuedRun) {\n\t\t\t\tawait queuedRun;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tawait this.runContinuation();\n\t}\n\n\tprivate normalizePromptInput(\n\t\tinput: string | AgentMessage | AgentMessage[],\n\t\timages?: ImageContent[],\n\t): AgentMessage[] {\n\t\tif (Array.isArray(input)) {\n\t\t\treturn input;\n\t\t}\n\n\t\tif (typeof input !== \"string\") {\n\t\t\treturn [input];\n\t\t}\n\n\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\tif (images && images.length > 0) {\n\t\t\tcontent.push(...images);\n\t\t}\n\t\treturn [{ role: \"user\", content, timestamp: Date.now() }];\n\t}\n\n\tprivate async runPromptMessages(\n\t\tmessages: AgentMessage[],\n\t\toptions: { skipInitialSteeringPoll?: boolean } = {},\n\t): Promise<void> {\n\t\tawait this.runWithLifecycle(async (signal) => {\n\t\t\tawait runAgentLoop(\n\t\t\t\tmessages,\n\t\t\t\tthis.createContextSnapshot(),\n\t\t\t\tthis.createLoopConfig(options),\n\t\t\t\t(event) => this.processEvents(event),\n\t\t\t\tsignal,\n\t\t\t\tthis.streamFn,\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async runContinuation(): Promise<void> {\n\t\tawait this.runWithLifecycle(async (signal) => {\n\t\t\tawait runAgentLoopContinue(\n\t\t\t\tthis.createContextSnapshot(),\n\t\t\t\tthis.createLoopConfig(),\n\t\t\t\t(event) => this.processEvents(event),\n\t\t\t\tsignal,\n\t\t\t\tthis.streamFn,\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate createContextSnapshot(): AgentContext {\n\t\treturn {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\tmessages: this._state.messages.slice(),\n\t\t\ttools: this._state.tools.slice(),\n\t\t};\n\t}\n\n\tprivate createLoopConfig(options: { skipInitialSteeringPoll?: boolean } = {}): AgentLoopConfig {\n\t\tlet skipInitialSteeringPoll = options.skipInitialSteeringPoll === true;\n\t\treturn {\n\t\t\tmodel: this._state.model,\n\t\t\treasoning: this._state.thinkingLevel,\n\t\t\tserviceTier: this._state.serviceTier,\n\t\t\tsessionId: this.sessionId,\n\t\t\tonPayload: this.onPayload,\n\t\t\tonResponse: this.onResponse,\n\t\t\ttransport: this.transport,\n\t\t\tthinkingBudgets: this.thinkingBudgets,\n\t\t\tmaxRetryDelayMs: this.maxRetryDelayMs,\n\t\t\ttoolExecution: this.toolExecution,\n\t\t\tbeforeToolCall: this.beforeToolCall,\n\t\t\tafterToolCall: this.afterToolCall,\n\t\t\tshouldStopAfterTurn: async (context) => this.shouldStopAfterTurn?.(context) ?? false,\n\t\t\tshouldStopBeforeTurn: () => this.shouldStopBeforeTurn?.() ?? false,\n\t\t\tconvertToLlm: this.convertToLlm,\n\t\t\ttransformContext: this.transformContext,\n\t\t\tgetSystemPrompt: () => this._state.systemPrompt,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tgetSteeringMessages: async () => {\n\t\t\t\tif (skipInitialSteeringPoll) {\n\t\t\t\t\tskipInitialSteeringPoll = false;\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\treturn this.steeringQueue.drain();\n\t\t\t},\n\t\t\tgetFollowUpMessages: async () => this.followUpQueue.drain(),\n\t\t\tgetContinuationMessages: async (context, signal) => this.getContinuationMessages?.(context, signal) ?? [],\n\t\t};\n\t}\n\n\tprivate async runWithLifecycle(executor: (signal: AbortSignal) => Promise<void>): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\"Agent is already processing.\");\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tlet resolvePromise = () => {};\n\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\tresolvePromise = resolve;\n\t\t});\n\t\tthis.activeRun = { promise, resolve: resolvePromise, abortController };\n\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamingMessage = undefined;\n\t\tthis._state.errorMessage = undefined;\n\n\t\ttry {\n\t\t\tawait executor(abortController.signal);\n\t\t} catch (error) {\n\t\t\tawait this.handleRunFailure(error, abortController.signal.aborted);\n\t\t} finally {\n\t\t\tthis.finishRun();\n\t\t}\n\t}\n\n\tprivate async handleRunFailure(error: unknown, aborted: boolean): Promise<void> {\n\t\tconst failureMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\tapi: this._state.model.api,\n\t\t\tprovider: this._state.model.provider,\n\t\t\tmodel: this._state.model.id,\n\t\t\tusage: EMPTY_USAGE,\n\t\t\tstopReason: aborted ? \"aborted\" : \"error\",\n\t\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\t\tdiagnostics: aborted\n\t\t\t\t? undefined\n\t\t\t\t: [createAssistantMessageDiagnostic(\"agent_lifecycle_failure\", error, { source: \"run_with_lifecycle\" })],\n\t\t\ttimestamp: Date.now(),\n\t\t} satisfies AgentMessage;\n\t\tthis._state.errorMessage = failureMessage.errorMessage;\n\t\tawait this.processEvents({ type: \"message_start\", message: failureMessage }).catch(() => undefined);\n\t\tawait this.processEvents({ type: \"message_end\", message: failureMessage }).catch(() => undefined);\n\t\tawait this.processEvents({ type: \"agent_end\", messages: [failureMessage] }).catch(() => undefined);\n\t}\n\n\tprivate finishRun(): void {\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamingMessage = undefined;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis.activeRun?.resolve();\n\t\tthis.activeRun = undefined;\n\t}\n\n\t/**\n\t * Reduce internal state for a loop event, then await listeners.\n\t *\n\t * `agent_end` only means no further loop events will be emitted. The run is\n\t * considered idle later, after all awaited listeners for `agent_end` finish\n\t * and `finishRun()` clears runtime-owned state.\n\t */\n\tprivate async processEvents(event: AgentEvent): Promise<void> {\n\t\tswitch (event.type) {\n\t\t\tcase \"message_start\":\n\t\t\t\tthis._state.streamingMessage = event.message;\n\t\t\t\tbreak;\n\n\t\t\tcase \"message_update\":\n\t\t\t\tthis._state.streamingMessage = event.message;\n\t\t\t\tbreak;\n\n\t\t\tcase \"message_end\":\n\t\t\t\tthis._state.streamingMessage = undefined;\n\t\t\t\tthis._state.messages.push(event.message);\n\t\t\t\tbreak;\n\n\t\t\tcase \"tool_execution_start\": {\n\t\t\t\tconst pendingToolCalls = new Set(this._state.pendingToolCalls);\n\t\t\t\tpendingToolCalls.add(event.toolCallId);\n\t\t\t\tthis._state.pendingToolCalls = pendingToolCalls;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tool_execution_end\": {\n\t\t\t\tconst pendingToolCalls = new Set(this._state.pendingToolCalls);\n\t\t\t\tpendingToolCalls.delete(event.toolCallId);\n\t\t\t\tthis._state.pendingToolCalls = pendingToolCalls;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"turn_end\":\n\t\t\t\tif (event.message.role === \"assistant\" && event.message.errorMessage) {\n\t\t\t\t\tthis._state.errorMessage = event.message.errorMessage;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"agent_end\":\n\t\t\t\tthis._state.streamingMessage = undefined;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst signal = this.activeRun?.abortController.signal;\n\t\tif (!signal) {\n\t\t\tthrow new Error(\"Agent listener invoked outside active run\");\n\t\t}\n\t\tfor (const listener of this.listeners) {\n\t\t\tawait listener(event, signal);\n\t\t}\n\t}\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./agent.js\";\nexport * from \"./agent-loop.js\";\nexport * from \"./proxy.js\";\nexport * from \"./types.js\";\n"]}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./agent.js\";\nexport * from \"./agent-loop.js\";\nexport * from \"./proxy.js\";\nexport * from \"./types.js\";\n"]}
|
package/dist/proxy.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type AssistantMessage, type AssistantMessageEvent, type Context, EventStream, type Model, type SimpleStreamOptions, type StopReason } from "@asm-agent/ai";
|
|
2
|
+
declare class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
|
|
3
|
+
constructor();
|
|
4
|
+
}
|
|
5
|
+
export type ProxyAssistantMessageEvent = {
|
|
6
|
+
type: "start";
|
|
7
|
+
} | {
|
|
8
|
+
type: "text_start";
|
|
9
|
+
contentIndex: number;
|
|
10
|
+
} | {
|
|
11
|
+
type: "text_delta";
|
|
12
|
+
contentIndex: number;
|
|
13
|
+
delta: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "text_end";
|
|
16
|
+
contentIndex: number;
|
|
17
|
+
contentSignature?: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: "thinking_start";
|
|
20
|
+
contentIndex: number;
|
|
21
|
+
} | {
|
|
22
|
+
type: "thinking_delta";
|
|
23
|
+
contentIndex: number;
|
|
24
|
+
delta: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: "thinking_end";
|
|
27
|
+
contentIndex: number;
|
|
28
|
+
contentSignature?: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "toolcall_start";
|
|
31
|
+
contentIndex: number;
|
|
32
|
+
id: string;
|
|
33
|
+
toolName: string;
|
|
34
|
+
} | {
|
|
35
|
+
type: "toolcall_delta";
|
|
36
|
+
contentIndex: number;
|
|
37
|
+
delta: string;
|
|
38
|
+
} | {
|
|
39
|
+
type: "toolcall_end";
|
|
40
|
+
contentIndex: number;
|
|
41
|
+
} | {
|
|
42
|
+
type: "done";
|
|
43
|
+
reason: Extract<StopReason, "stop" | "length" | "toolUse">;
|
|
44
|
+
usage: AssistantMessage["usage"];
|
|
45
|
+
} | {
|
|
46
|
+
type: "error";
|
|
47
|
+
reason: Extract<StopReason, "aborted" | "error">;
|
|
48
|
+
errorMessage?: string;
|
|
49
|
+
usage: AssistantMessage["usage"];
|
|
50
|
+
};
|
|
51
|
+
type ProxySerializableStreamOptions = Pick<SimpleStreamOptions, "temperature" | "maxTokens" | "reasoning" | "cacheRetention" | "sessionId" | "headers" | "metadata" | "transport" | "thinkingBudgets" | "maxRetryDelayMs">;
|
|
52
|
+
export interface ProxyStreamOptions extends ProxySerializableStreamOptions {
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
authToken: string;
|
|
55
|
+
proxyUrl: string;
|
|
56
|
+
}
|
|
57
|
+
export declare function streamProxy(model: Model<any>, context: Context, options: ProxyStreamOptions): ProxyMessageEventStream;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACZ,WAAW,EACX,KAAK,KAAK,EAEV,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAEf,MAAM,eAAe,CAAC;AAEvB,cAAM,uBAAwB,SAAQ,WAAW,CAAC,qBAAqB,EAAE,gBAAgB,CAAC;IACzF,cASC;CACD;AAED,MAAM,MAAM,0BAA0B,GACnC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9C;IACA,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC3D,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CAChC,GACD;IACA,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CAChC,CAAC;AAEL,KAAK,8BAA8B,GAAG,IAAI,CACzC,mBAAmB,EACjB,aAAa,GACb,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,WAAW,GACX,SAAS,GACT,UAAU,GACV,WAAW,GACX,iBAAiB,GACjB,iBAAiB,CACnB,CAAC;AAEF,MAAM,WAAW,kBAAmB,SAAQ,8BAA8B;IACzE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAoCD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,GAAG,uBAAuB,CAoHrH","sourcesContent":["import {\n\ttype AssistantMessage,\n\ttype AssistantMessageEvent,\n\ttype Context,\n\tEventStream,\n\ttype Model,\n\tparseStreamingJson,\n\ttype SimpleStreamOptions,\n\ttype StopReason,\n\ttype ToolCall,\n} from \"@asm-agent/ai\";\n\nclass ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {\n\tconstructor() {\n\t\tsuper(\n\t\t\t(event) => event.type === \"done\" || event.type === \"error\",\n\t\t\t(event) => {\n\t\t\t\tif (event.type === \"done\") return event.message;\n\t\t\t\tif (event.type === \"error\") return event.error;\n\t\t\t\tthrow new Error(\"Unexpected event type\");\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport type ProxyAssistantMessageEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| { type: \"thinking_end\"; contentIndex: number; contentSignature?: string }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: AssistantMessage[\"usage\"];\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<StopReason, \"aborted\" | \"error\">;\n\t\t\terrorMessage?: string;\n\t\t\tusage: AssistantMessage[\"usage\"];\n\t };\n\ntype ProxySerializableStreamOptions = Pick<\n\tSimpleStreamOptions,\n\t| \"temperature\"\n\t| \"maxTokens\"\n\t| \"reasoning\"\n\t| \"cacheRetention\"\n\t| \"sessionId\"\n\t| \"headers\"\n\t| \"metadata\"\n\t| \"transport\"\n\t| \"thinkingBudgets\"\n\t| \"maxRetryDelayMs\"\n>;\n\nexport interface ProxyStreamOptions extends ProxySerializableStreamOptions {\n\tsignal?: AbortSignal;\n\tauthToken: string;\n\tproxyUrl: string;\n}\n\n/**\n * Stream function that proxies through a server instead of calling LLM providers directly.\n * The server strips the partial field from delta events to reduce bandwidth.\n * We reconstruct the partial message client-side.\n *\n * Use this as the `streamFn` option when creating an Agent that needs to go through a proxy.\n *\n * @example\n * ```typescript\n * const agent = new Agent({\n * streamFn: (model, context, options) =>\n * streamProxy(model, context, {\n * ...options,\n * authToken: await getAuthToken(),\n * proxyUrl: \"https://genai.example.com\",\n * }),\n * });\n * ```\n */\nfunction buildProxyRequestOptions(options: ProxyStreamOptions): ProxySerializableStreamOptions {\n\treturn {\n\t\ttemperature: options.temperature,\n\t\tmaxTokens: options.maxTokens,\n\t\treasoning: options.reasoning,\n\t\tcacheRetention: options.cacheRetention,\n\t\tsessionId: options.sessionId,\n\t\theaders: options.headers,\n\t\tmetadata: options.metadata,\n\t\ttransport: options.transport,\n\t\tthinkingBudgets: options.thinkingBudgets,\n\t\tmaxRetryDelayMs: options.maxRetryDelayMs,\n\t};\n}\n\nexport function streamProxy(model: Model<any>, context: Context, options: ProxyStreamOptions): ProxyMessageEventStream {\n\tconst stream = new ProxyMessageEventStream();\n\n\t(async () => {\n\t\tconst partial: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tstopReason: \"stop\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\tlet reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\n\t\tconst abortHandler = () => {\n\t\t\tif (reader) {\n\t\t\t\treader.cancel(\"Request aborted by user\").catch(() => {});\n\t\t\t}\n\t\t};\n\n\t\tif (options.signal) {\n\t\t\toptions.signal.addEventListener(\"abort\", abortHandler);\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${options.proxyUrl}/api/stream`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${options.authToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel,\n\t\t\t\t\tcontext,\n\t\t\t\t\toptions: buildProxyRequestOptions(options),\n\t\t\t\t}),\n\t\t\t\tsignal: options.signal,\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorMessage = `Proxy error: ${response.status} ${response.statusText}`;\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData = (await response.json()) as { error?: string };\n\t\t\t\t\tif (errorData.error) {\n\t\t\t\t\t\terrorMessage = `Proxy error: ${errorData.error}`;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Keep the status-text fallback when the error body is not JSON.\n\t\t\t\t}\n\t\t\t\tthrow new Error(errorMessage);\n\t\t\t}\n\n\t\t\treader = response.body!.getReader();\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = \"\";\n\n\t\t\twhile (true) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) break;\n\n\t\t\t\tif (options.signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"Request aborted by user\");\n\t\t\t\t}\n\n\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tif (line.startsWith(\"data: \")) {\n\t\t\t\t\t\tconst data = line.slice(6).trim();\n\t\t\t\t\t\tif (data) {\n\t\t\t\t\t\t\tconst proxyEvent = JSON.parse(data) as ProxyAssistantMessageEvent;\n\t\t\t\t\t\t\tconst event = processProxyEvent(proxyEvent, partial);\n\t\t\t\t\t\t\tif (event) {\n\t\t\t\t\t\t\t\tstream.push(event);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request aborted by user\");\n\t\t\t}\n\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\tconst reason = options.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\tpartial.stopReason = reason;\n\t\t\tpartial.errorMessage = errorMessage;\n\t\t\tstream.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\treason,\n\t\t\t\terror: partial,\n\t\t\t});\n\t\t\tstream.end();\n\t\t} finally {\n\t\t\tif (options.signal) {\n\t\t\t\toptions.signal.removeEventListener(\"abort\", abortHandler);\n\t\t\t}\n\t\t}\n\t})();\n\n\treturn stream;\n}\n\nfunction processProxyEvent(\n\tproxyEvent: ProxyAssistantMessageEvent,\n\tpartial: AssistantMessage,\n): AssistantMessageEvent | undefined {\n\tswitch (proxyEvent.type) {\n\t\tcase \"start\":\n\t\t\treturn { type: \"start\", partial };\n\n\t\tcase \"text_start\":\n\t\t\tpartial.content[proxyEvent.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\treturn { type: \"text_start\", contentIndex: proxyEvent.contentIndex, partial };\n\n\t\tcase \"text_delta\": {\n\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\tif (content?.type === \"text\") {\n\t\t\t\tcontent.text += proxyEvent.delta;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\tdelta: proxyEvent.delta,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow new Error(\"Received text_delta for non-text content\");\n\t\t}\n\n\t\tcase \"text_end\": {\n\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\tif (content?.type === \"text\") {\n\t\t\t\tcontent.textSignature = proxyEvent.contentSignature;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\tcontent: content.text,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow new Error(\"Received text_end for non-text content\");\n\t\t}\n\n\t\tcase \"thinking_start\":\n\t\t\tpartial.content[proxyEvent.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\treturn { type: \"thinking_start\", contentIndex: proxyEvent.contentIndex, partial };\n\n\t\tcase \"thinking_delta\": {\n\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\tif (content?.type === \"thinking\") {\n\t\t\t\tcontent.thinking += proxyEvent.delta;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\tdelta: proxyEvent.delta,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow new Error(\"Received thinking_delta for non-thinking content\");\n\t\t}\n\n\t\tcase \"thinking_end\": {\n\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\tif (content?.type === \"thinking\") {\n\t\t\t\tcontent.thinkingSignature = proxyEvent.contentSignature;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\tcontent: content.thinking,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow new Error(\"Received thinking_end for non-thinking content\");\n\t\t}\n\n\t\tcase \"toolcall_start\":\n\t\t\tpartial.content[proxyEvent.contentIndex] = {\n\t\t\t\ttype: \"toolCall\",\n\t\t\t\tid: proxyEvent.id,\n\t\t\t\tname: proxyEvent.toolName,\n\t\t\t\targuments: {},\n\t\t\t\tpartialJson: \"\",\n\t\t\t} satisfies ToolCall & { partialJson: string } as ToolCall;\n\t\t\treturn { type: \"toolcall_start\", contentIndex: proxyEvent.contentIndex, partial };\n\n\t\tcase \"toolcall_delta\": {\n\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\tif (content?.type === \"toolCall\") {\n\t\t\t\t(content as any).partialJson += proxyEvent.delta;\n\t\t\t\tcontent.arguments = parseStreamingJson((content as any).partialJson) || {};\n\t\t\t\tpartial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\tdelta: proxyEvent.delta,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow new Error(\"Received toolcall_delta for non-toolCall content\");\n\t\t}\n\n\t\tcase \"toolcall_end\": {\n\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\tif (content?.type === \"toolCall\") {\n\t\t\t\tdelete (content as any).partialJson;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\ttoolCall: content,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tcase \"done\":\n\t\t\tpartial.stopReason = proxyEvent.reason;\n\t\t\tpartial.usage = proxyEvent.usage;\n\t\t\treturn { type: \"done\", reason: proxyEvent.reason, message: partial };\n\n\t\tcase \"error\":\n\t\t\tpartial.stopReason = proxyEvent.reason;\n\t\t\tpartial.errorMessage = proxyEvent.errorMessage;\n\t\t\tpartial.usage = proxyEvent.usage;\n\t\t\treturn { type: \"error\", reason: proxyEvent.reason, error: partial };\n\n\t\tdefault: {\n\t\t\tconst _exhaustiveCheck: never = proxyEvent;\n\t\t\tconsole.warn(`Unhandled proxy event type: ${(proxyEvent as any).type}`);\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"]}
|