@convex-dev/agent 0.6.0-alpha.1 → 0.6.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/package.json +1 -1
- package/src/UIMessages.ts +135 -0
- package/src/client/index.ts +56 -14
- package/src/client/search.test.ts +4 -5
- package/src/client/search.ts +45 -4
- package/src/client/streaming.integration.test.ts +1206 -0
- package/src/client/streaming.ts +9 -2
- package/src/mapping.test.ts +136 -71
- package/src/mapping.ts +81 -28
- package/dist/UIMessages.d.ts +0 -46
- package/dist/UIMessages.d.ts.map +0 -1
- package/dist/UIMessages.js +0 -546
- package/dist/UIMessages.js.map +0 -1
- package/dist/client/createTool.d.ts +0 -167
- package/dist/client/createTool.d.ts.map +0 -1
- package/dist/client/createTool.js +0 -116
- package/dist/client/createTool.js.map +0 -1
- package/dist/client/defaultComponent.d.ts +0 -11
- package/dist/client/defaultComponent.d.ts.map +0 -1
- package/dist/client/defaultComponent.js +0 -7
- package/dist/client/defaultComponent.js.map +0 -1
- package/dist/client/definePlaygroundAPI.d.ts +0 -1725
- package/dist/client/definePlaygroundAPI.d.ts.map +0 -1
- package/dist/client/definePlaygroundAPI.js +0 -271
- package/dist/client/definePlaygroundAPI.js.map +0 -1
- package/dist/client/files.d.ts +0 -69
- package/dist/client/files.d.ts.map +0 -1
- package/dist/client/files.js +0 -181
- package/dist/client/files.js.map +0 -1
- package/dist/client/index.d.ts +0 -2091
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js +0 -895
- package/dist/client/index.js.map +0 -1
- package/dist/client/messages.d.ts +0 -461
- package/dist/client/messages.d.ts.map +0 -1
- package/dist/client/messages.js +0 -106
- package/dist/client/messages.js.map +0 -1
- package/dist/client/mockModel.d.ts +0 -42
- package/dist/client/mockModel.d.ts.map +0 -1
- package/dist/client/mockModel.js +0 -182
- package/dist/client/mockModel.js.map +0 -1
- package/dist/client/saveInputMessages.d.ts +0 -20
- package/dist/client/saveInputMessages.d.ts.map +0 -1
- package/dist/client/saveInputMessages.js +0 -58
- package/dist/client/saveInputMessages.js.map +0 -1
- package/dist/client/search.d.ts +0 -493
- package/dist/client/search.d.ts.map +0 -1
- package/dist/client/search.js +0 -425
- package/dist/client/search.js.map +0 -1
- package/dist/client/start.d.ts +0 -84
- package/dist/client/start.d.ts.map +0 -1
- package/dist/client/start.js +0 -185
- package/dist/client/start.js.map +0 -1
- package/dist/client/streamText.d.ts +0 -46
- package/dist/client/streamText.d.ts.map +0 -1
- package/dist/client/streamText.js +0 -117
- package/dist/client/streamText.js.map +0 -1
- package/dist/client/streaming.d.ts +0 -3778
- package/dist/client/streaming.d.ts.map +0 -1
- package/dist/client/streaming.js +0 -314
- package/dist/client/streaming.js.map +0 -1
- package/dist/client/threads.d.ts +0 -46
- package/dist/client/threads.d.ts.map +0 -1
- package/dist/client/threads.js +0 -49
- package/dist/client/threads.js.map +0 -1
- package/dist/client/types.d.ts +0 -461
- package/dist/client/types.d.ts.map +0 -1
- package/dist/client/types.js +0 -2
- package/dist/client/types.js.map +0 -1
- package/dist/client/utils.d.ts +0 -4
- package/dist/client/utils.d.ts.map +0 -1
- package/dist/client/utils.js +0 -21
- package/dist/client/utils.js.map +0 -1
- package/dist/component/_generated/api.d.ts +0 -48
- package/dist/component/_generated/api.d.ts.map +0 -1
- package/dist/component/_generated/api.js +0 -31
- package/dist/component/_generated/api.js.map +0 -1
- package/dist/component/_generated/component.d.ts +0 -3120
- package/dist/component/_generated/component.d.ts.map +0 -1
- package/dist/component/_generated/component.js +0 -11
- package/dist/component/_generated/component.js.map +0 -1
- package/dist/component/_generated/dataModel.d.ts +0 -46
- package/dist/component/_generated/dataModel.d.ts.map +0 -1
- package/dist/component/_generated/dataModel.js +0 -11
- package/dist/component/_generated/dataModel.js.map +0 -1
- package/dist/component/_generated/server.d.ts +0 -121
- package/dist/component/_generated/server.d.ts.map +0 -1
- package/dist/component/_generated/server.js +0 -78
- package/dist/component/_generated/server.js.map +0 -1
- package/dist/component/apiKeys.d.ts +0 -11
- package/dist/component/apiKeys.d.ts.map +0 -1
- package/dist/component/apiKeys.js +0 -69
- package/dist/component/apiKeys.js.map +0 -1
- package/dist/component/convex.config.d.ts +0 -3
- package/dist/component/convex.config.d.ts.map +0 -1
- package/dist/component/convex.config.js +0 -3
- package/dist/component/convex.config.js.map +0 -1
- package/dist/component/files.d.ts +0 -97
- package/dist/component/files.d.ts.map +0 -1
- package/dist/component/files.js +0 -190
- package/dist/component/files.js.map +0 -1
- package/dist/component/messages.d.ts +0 -3851
- package/dist/component/messages.d.ts.map +0 -1
- package/dist/component/messages.js +0 -757
- package/dist/component/messages.js.map +0 -1
- package/dist/component/schema.d.ts +0 -8026
- package/dist/component/schema.d.ts.map +0 -1
- package/dist/component/schema.js +0 -147
- package/dist/component/schema.js.map +0 -1
- package/dist/component/streams.d.ts +0 -128
- package/dist/component/streams.d.ts.map +0 -1
- package/dist/component/streams.js +0 -413
- package/dist/component/streams.js.map +0 -1
- package/dist/component/threads.d.ts +0 -115
- package/dist/component/threads.d.ts.map +0 -1
- package/dist/component/threads.js +0 -208
- package/dist/component/threads.js.map +0 -1
- package/dist/component/users.d.ts +0 -52
- package/dist/component/users.d.ts.map +0 -1
- package/dist/component/users.js +0 -229
- package/dist/component/users.js.map +0 -1
- package/dist/component/vector/index.d.ts +0 -61
- package/dist/component/vector/index.d.ts.map +0 -1
- package/dist/component/vector/index.js +0 -146
- package/dist/component/vector/index.js.map +0 -1
- package/dist/component/vector/tables.d.ts +0 -58
- package/dist/component/vector/tables.d.ts.map +0 -1
- package/dist/component/vector/tables.js +0 -56
- package/dist/component/vector/tables.js.map +0 -1
- package/dist/deltas.d.ts +0 -43
- package/dist/deltas.d.ts.map +0 -1
- package/dist/deltas.js +0 -446
- package/dist/deltas.js.map +0 -1
- package/dist/mapping.d.ts +0 -72
- package/dist/mapping.d.ts.map +0 -1
- package/dist/mapping.js +0 -677
- package/dist/mapping.js.map +0 -1
- package/dist/react/SmoothText.d.ts +0 -5
- package/dist/react/SmoothText.d.ts.map +0 -1
- package/dist/react/SmoothText.js +0 -6
- package/dist/react/SmoothText.js.map +0 -1
- package/dist/react/index.d.ts +0 -25
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -70
- package/dist/react/index.js.map +0 -1
- package/dist/react/optimisticallySendMessage.d.ts +0 -42
- package/dist/react/optimisticallySendMessage.d.ts.map +0 -1
- package/dist/react/optimisticallySendMessage.js +0 -74
- package/dist/react/optimisticallySendMessage.js.map +0 -1
- package/dist/react/types.d.ts +0 -12
- package/dist/react/types.d.ts.map +0 -1
- package/dist/react/types.js +0 -2
- package/dist/react/types.js.map +0 -1
- package/dist/react/useDeltaStreams.d.ts +0 -10
- package/dist/react/useDeltaStreams.d.ts.map +0 -1
- package/dist/react/useDeltaStreams.js +0 -106
- package/dist/react/useDeltaStreams.js.map +0 -1
- package/dist/react/useSmoothText.d.ts +0 -27
- package/dist/react/useSmoothText.d.ts.map +0 -1
- package/dist/react/useSmoothText.js +0 -68
- package/dist/react/useSmoothText.js.map +0 -1
- package/dist/react/useStreamingUIMessages.d.ts +0 -22
- package/dist/react/useStreamingUIMessages.d.ts.map +0 -1
- package/dist/react/useStreamingUIMessages.js +0 -92
- package/dist/react/useStreamingUIMessages.js.map +0 -1
- package/dist/react/useThreadMessages.d.ts +0 -104
- package/dist/react/useThreadMessages.d.ts.map +0 -1
- package/dist/react/useThreadMessages.js +0 -148
- package/dist/react/useThreadMessages.js.map +0 -1
- package/dist/react/useUIMessages.d.ts +0 -96
- package/dist/react/useUIMessages.d.ts.map +0 -1
- package/dist/react/useUIMessages.js +0 -108
- package/dist/react/useUIMessages.js.map +0 -1
- package/dist/shared.d.ts +0 -26
- package/dist/shared.d.ts.map +0 -1
- package/dist/shared.js +0 -67
- package/dist/shared.js.map +0 -1
- package/dist/validators.d.ts +0 -24516
- package/dist/validators.d.ts.map +0 -1
- package/dist/validators.js +0 -475
- package/dist/validators.js.map +0 -1
package/src/client/streaming.ts
CHANGED
|
@@ -293,7 +293,8 @@ export class DeltaStreamer<T> {
|
|
|
293
293
|
await this.addParts([chunk]);
|
|
294
294
|
}
|
|
295
295
|
// Skip finish if it will be handled externally (atomically with message save)
|
|
296
|
-
if (
|
|
296
|
+
// or if the stream was aborted (e.g., due to a failed delta write)
|
|
297
|
+
if (!this.#finishedExternally && !this.abortController.signal.aborted) {
|
|
297
298
|
await this.finish();
|
|
298
299
|
}
|
|
299
300
|
}
|
|
@@ -339,7 +340,7 @@ export class DeltaStreamer<T> {
|
|
|
339
340
|
e instanceof Error ? e.message : "unknown error",
|
|
340
341
|
);
|
|
341
342
|
this.abortController.abort();
|
|
342
|
-
|
|
343
|
+
return;
|
|
343
344
|
}
|
|
344
345
|
// Now that we've sent the delta, check if we need to send another one.
|
|
345
346
|
if (
|
|
@@ -375,7 +376,13 @@ export class DeltaStreamer<T> {
|
|
|
375
376
|
return;
|
|
376
377
|
}
|
|
377
378
|
await this.#ongoingWrite;
|
|
379
|
+
if (this.abortController.signal.aborted) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
378
382
|
await this.#sendDelta();
|
|
383
|
+
if (this.abortController.signal.aborted) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
379
386
|
await this.ctx.runMutation(this.component.streams.finish, {
|
|
380
387
|
streamId: this.streamId,
|
|
381
388
|
});
|
package/src/mapping.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
1
|
+
import { describe, test, expect, vi } from "vitest";
|
|
2
2
|
import {
|
|
3
3
|
guessMimeType,
|
|
4
4
|
serializeDataOrUrl,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
toModelMessage,
|
|
8
8
|
serializeContent,
|
|
9
9
|
toModelMessageContent,
|
|
10
|
-
|
|
10
|
+
autoDenyUnresolvedApprovals,
|
|
11
11
|
} from "./mapping.js";
|
|
12
12
|
import { api } from "./component/_generated/api.js";
|
|
13
13
|
import type { AgentComponent, ActionCtx } from "./client/types.js";
|
|
@@ -259,79 +259,144 @@ describe("mapping", () => {
|
|
|
259
259
|
expect((content as unknown[])[0]).toMatchObject(approvalResponse);
|
|
260
260
|
});
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
{
|
|
281
|
-
role: "tool" as const,
|
|
282
|
-
content: [
|
|
283
|
-
{ type: "tool-approval-response", approvalId: "ap2", approved: false, reason: "denied" },
|
|
284
|
-
],
|
|
285
|
-
},
|
|
286
|
-
] as any;
|
|
262
|
+
describe("autoDenyUnresolvedApprovals", () => {
|
|
263
|
+
test("returns messages unchanged when no unresolved approvals", () => {
|
|
264
|
+
const messages = [
|
|
265
|
+
{ role: "user" as const, content: "hello" },
|
|
266
|
+
{
|
|
267
|
+
role: "assistant" as const,
|
|
268
|
+
content: [
|
|
269
|
+
{ type: "tool-call", toolCallId: "tc1", toolName: "a", input: {} },
|
|
270
|
+
{ type: "tool-approval-request", approvalId: "ap1", toolCallId: "tc1" },
|
|
271
|
+
],
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
role: "tool" as const,
|
|
275
|
+
content: [
|
|
276
|
+
{ type: "tool-approval-response", approvalId: "ap1", approved: true },
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
] as any;
|
|
287
280
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const toolContent = merged[2].content as Array<{ type: string; approvalId: string }>;
|
|
292
|
-
expect(toolContent).toHaveLength(2);
|
|
293
|
-
expect(toolContent[0].approvalId).toBe("ap1");
|
|
294
|
-
expect(toolContent[1].approvalId).toBe("ap2");
|
|
295
|
-
});
|
|
281
|
+
const result = autoDenyUnresolvedApprovals(messages);
|
|
282
|
+
expect(result).toBe(messages); // same reference, no changes
|
|
283
|
+
});
|
|
296
284
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
285
|
+
test("injects synthetic denial for a single unresolved approval", () => {
|
|
286
|
+
const messages = [
|
|
287
|
+
{ role: "user" as const, content: "hello" },
|
|
288
|
+
{
|
|
289
|
+
role: "assistant" as const,
|
|
290
|
+
content: [
|
|
291
|
+
{ type: "tool-call", toolCallId: "tc1", toolName: "a", input: {} },
|
|
292
|
+
{ type: "tool-approval-request", approvalId: "ap1", toolCallId: "tc1" },
|
|
293
|
+
],
|
|
294
|
+
},
|
|
295
|
+
{ role: "user" as const, content: "new message" },
|
|
296
|
+
] as any;
|
|
308
297
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
298
|
+
const result = autoDenyUnresolvedApprovals(messages);
|
|
299
|
+
expect(result).toHaveLength(4); // original 3 + 1 synthetic tool message
|
|
300
|
+
// Synthetic denial should be inserted right after the assistant message (index 1)
|
|
301
|
+
expect(result[2].role).toBe("tool");
|
|
302
|
+
const denialContent = result[2].content as any[];
|
|
303
|
+
expect(denialContent).toHaveLength(1);
|
|
304
|
+
expect(denialContent[0].type).toBe("tool-approval-response");
|
|
305
|
+
expect(denialContent[0].approvalId).toBe("ap1");
|
|
306
|
+
expect(denialContent[0].approved).toBe(false);
|
|
307
|
+
expect(denialContent[0].reason).toBe("auto-denied: new generation started");
|
|
308
|
+
// The new user message should follow
|
|
309
|
+
expect(result[3].role).toBe("user");
|
|
310
|
+
expect(result[3].content).toBe("new message");
|
|
311
|
+
});
|
|
317
312
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
313
|
+
test("groups multiple unresolved approvals from the same step into a single synthetic message", () => {
|
|
314
|
+
const messages = [
|
|
315
|
+
{
|
|
316
|
+
role: "assistant" as const,
|
|
317
|
+
content: [
|
|
318
|
+
{ type: "tool-call", toolCallId: "tc1", toolName: "a", input: {} },
|
|
319
|
+
{ type: "tool-call", toolCallId: "tc2", toolName: "b", input: {} },
|
|
320
|
+
{ type: "tool-approval-request", approvalId: "ap1", toolCallId: "tc1" },
|
|
321
|
+
{ type: "tool-approval-request", approvalId: "ap2", toolCallId: "tc2" },
|
|
322
|
+
],
|
|
323
|
+
},
|
|
324
|
+
] as any;
|
|
325
|
+
|
|
326
|
+
const result = autoDenyUnresolvedApprovals(messages);
|
|
327
|
+
expect(result).toHaveLength(2); // assistant + 1 synthetic tool message
|
|
328
|
+
expect(result[1].role).toBe("tool");
|
|
329
|
+
const denialContent = result[1].content as any[];
|
|
330
|
+
expect(denialContent).toHaveLength(2);
|
|
331
|
+
expect(denialContent[0].approvalId).toBe("ap1");
|
|
332
|
+
expect(denialContent[0].approved).toBe(false);
|
|
333
|
+
expect(denialContent[1].approvalId).toBe("ap2");
|
|
334
|
+
expect(denialContent[1].approved).toBe(false);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
test("only auto-denies unresolved approvals, leaves resolved ones alone", () => {
|
|
338
|
+
const messages = [
|
|
339
|
+
{
|
|
340
|
+
role: "assistant" as const,
|
|
341
|
+
content: [
|
|
342
|
+
{ type: "tool-call", toolCallId: "tc1", toolName: "a", input: {} },
|
|
343
|
+
{ type: "tool-call", toolCallId: "tc2", toolName: "b", input: {} },
|
|
344
|
+
{ type: "tool-approval-request", approvalId: "ap1", toolCallId: "tc1" },
|
|
345
|
+
{ type: "tool-approval-request", approvalId: "ap2", toolCallId: "tc2" },
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
role: "tool" as const,
|
|
350
|
+
content: [
|
|
351
|
+
{ type: "tool-approval-response", approvalId: "ap1", approved: true },
|
|
352
|
+
],
|
|
353
|
+
},
|
|
354
|
+
{ role: "user" as const, content: "next question" },
|
|
355
|
+
] as any;
|
|
356
|
+
|
|
357
|
+
const result = autoDenyUnresolvedApprovals(messages);
|
|
358
|
+
// Should inject a denial for ap2 (unresolved) after the assistant message
|
|
359
|
+
expect(result).toHaveLength(4); // assistant + existing tool + synthetic denial + user
|
|
360
|
+
// The synthetic denial is inserted after the assistant (index 0)
|
|
361
|
+
expect(result[0].role).toBe("assistant");
|
|
362
|
+
expect(result[1].role).toBe("tool"); // synthetic denial for ap2
|
|
363
|
+
const denialContent = result[1].content as any[];
|
|
364
|
+
expect(denialContent).toHaveLength(1);
|
|
365
|
+
expect(denialContent[0].approvalId).toBe("ap2");
|
|
366
|
+
expect(denialContent[0].approved).toBe(false);
|
|
367
|
+
// Original tool message (ap1 response) follows
|
|
368
|
+
expect(result[2].role).toBe("tool");
|
|
369
|
+
const originalToolContent = result[2].content as any[];
|
|
370
|
+
expect(originalToolContent[0].approvalId).toBe("ap1");
|
|
371
|
+
expect(originalToolContent[0].approved).toBe(true);
|
|
372
|
+
// User message last
|
|
373
|
+
expect(result[3].role).toBe("user");
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test("emits console.warn for each auto-denied approval", () => {
|
|
377
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
378
|
+
const messages = [
|
|
379
|
+
{
|
|
380
|
+
role: "assistant" as const,
|
|
381
|
+
content: [
|
|
382
|
+
{ type: "tool-call", toolCallId: "tc1", toolName: "a", input: {} },
|
|
383
|
+
{ type: "tool-call", toolCallId: "tc2", toolName: "b", input: {} },
|
|
384
|
+
{ type: "tool-approval-request", approvalId: "ap1", toolCallId: "tc1" },
|
|
385
|
+
{ type: "tool-approval-request", approvalId: "ap2", toolCallId: "tc2" },
|
|
386
|
+
],
|
|
387
|
+
},
|
|
388
|
+
] as any;
|
|
389
|
+
|
|
390
|
+
autoDenyUnresolvedApprovals(messages);
|
|
333
391
|
|
|
334
|
-
|
|
335
|
-
|
|
392
|
+
expect(warnSpy).toHaveBeenCalledTimes(2);
|
|
393
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
394
|
+
expect.stringContaining("ap1"),
|
|
395
|
+
);
|
|
396
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
397
|
+
expect.stringContaining("ap2"),
|
|
398
|
+
);
|
|
399
|
+
warnSpy.mockRestore();
|
|
400
|
+
});
|
|
336
401
|
});
|
|
337
402
|
});
|
package/src/mapping.ts
CHANGED
|
@@ -140,41 +140,94 @@ export function docsToModelMessages(messages: MessageDoc[]): ModelMessage[] {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
143
|
+
* Scan messages for unresolved `tool-approval-request` parts and inject
|
|
144
|
+
* synthetic `tool-approval-response` denials so that the AI SDK receives
|
|
145
|
+
* a complete history (every tool-call has a corresponding result or denial).
|
|
146
|
+
*
|
|
147
|
+
* This handles the case where a user sends a new message instead of
|
|
148
|
+
* resolving pending approvals — the old approvals are auto-denied rather
|
|
149
|
+
* than silently dropped.
|
|
148
150
|
*/
|
|
149
|
-
export function
|
|
151
|
+
export function autoDenyUnresolvedApprovals(
|
|
150
152
|
messages: ModelMessage[],
|
|
151
153
|
): ModelMessage[] {
|
|
154
|
+
// Collect all approval requests: approvalId → { toolCallId, messageIndex }
|
|
155
|
+
const requests = new Map<
|
|
156
|
+
string,
|
|
157
|
+
{ toolCallId: string; messageIndex: number }
|
|
158
|
+
>();
|
|
159
|
+
// Collect all resolved approval IDs
|
|
160
|
+
const resolvedIds = new Set<string>();
|
|
161
|
+
|
|
162
|
+
for (let i = 0; i < messages.length; i++) {
|
|
163
|
+
const msg = messages[i];
|
|
164
|
+
if (!Array.isArray(msg.content)) continue;
|
|
165
|
+
for (const part of msg.content as any[]) {
|
|
166
|
+
if (part.type === "tool-approval-request") {
|
|
167
|
+
requests.set(part.approvalId, {
|
|
168
|
+
toolCallId: part.toolCallId,
|
|
169
|
+
messageIndex: i,
|
|
170
|
+
});
|
|
171
|
+
} else if (part.type === "tool-approval-response") {
|
|
172
|
+
resolvedIds.add(part.approvalId);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Find unresolved approvals
|
|
178
|
+
const unresolved: Array<{
|
|
179
|
+
approvalId: string;
|
|
180
|
+
toolCallId: string;
|
|
181
|
+
messageIndex: number;
|
|
182
|
+
}> = [];
|
|
183
|
+
for (const [approvalId, info] of requests) {
|
|
184
|
+
if (!resolvedIds.has(approvalId)) {
|
|
185
|
+
unresolved.push({ approvalId, ...info });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (unresolved.length === 0) {
|
|
190
|
+
return messages;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Group unresolved approvals by the assistant message index they came from
|
|
194
|
+
const byMessageIndex = new Map<
|
|
195
|
+
number,
|
|
196
|
+
Array<{ approvalId: string; toolCallId: string }>
|
|
197
|
+
>();
|
|
198
|
+
for (const entry of unresolved) {
|
|
199
|
+
console.warn(
|
|
200
|
+
`Auto-denying unresolved tool approval ${entry.approvalId} ` +
|
|
201
|
+
`(toolCallId: ${entry.toolCallId}): new generation started`,
|
|
202
|
+
);
|
|
203
|
+
let group = byMessageIndex.get(entry.messageIndex);
|
|
204
|
+
if (!group) {
|
|
205
|
+
group = [];
|
|
206
|
+
byMessageIndex.set(entry.messageIndex, group);
|
|
207
|
+
}
|
|
208
|
+
group.push(entry);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Build result by inserting synthetic denial messages after each relevant
|
|
212
|
+
// assistant message
|
|
152
213
|
const result: ModelMessage[] = [];
|
|
153
|
-
for (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
(cloned.content as any[]).push(...(msg.content as any[]));
|
|
167
|
-
} else {
|
|
168
|
-
result.push(msg);
|
|
214
|
+
for (let i = 0; i < messages.length; i++) {
|
|
215
|
+
result.push(messages[i]);
|
|
216
|
+
const group = byMessageIndex.get(i);
|
|
217
|
+
if (group) {
|
|
218
|
+
result.push({
|
|
219
|
+
role: "tool",
|
|
220
|
+
content: group.map((entry) => ({
|
|
221
|
+
type: "tool-approval-response" as const,
|
|
222
|
+
approvalId: entry.approvalId,
|
|
223
|
+
approved: false,
|
|
224
|
+
reason: "auto-denied: new generation started",
|
|
225
|
+
})),
|
|
226
|
+
});
|
|
169
227
|
}
|
|
170
228
|
}
|
|
171
|
-
return result;
|
|
172
|
-
}
|
|
173
229
|
|
|
174
|
-
|
|
175
|
-
return content.some(
|
|
176
|
-
(p: any) => p.type === "tool-approval-response",
|
|
177
|
-
);
|
|
230
|
+
return result;
|
|
178
231
|
}
|
|
179
232
|
|
|
180
233
|
export function serializeUsage(usage: LanguageModelUsage): Usage {
|
package/dist/UIMessages.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { type UIMessage as AIUIMessage, type UIDataTypes, type UITools } from "ai";
|
|
2
|
-
import type { MessageDoc, MessageStatus, ProviderOptions } from "./validators.js";
|
|
3
|
-
export type UIStatus = "streaming" | MessageStatus;
|
|
4
|
-
export type UIMessage<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools> = AIUIMessage<METADATA, DATA_PARTS, TOOLS> & {
|
|
5
|
-
key: string;
|
|
6
|
-
order: number;
|
|
7
|
-
stepOrder: number;
|
|
8
|
-
status: UIStatus;
|
|
9
|
-
agentName?: string;
|
|
10
|
-
userId?: string;
|
|
11
|
-
text: string;
|
|
12
|
-
_creationTime: number;
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
* Converts a list of UIMessages to MessageDocs, along with extra metadata that
|
|
16
|
-
* may be available to associate with the MessageDocs.
|
|
17
|
-
* @param messages - The UIMessages to convert to MessageDocs.
|
|
18
|
-
* @param meta - The metadata to add to the MessageDocs.
|
|
19
|
-
* @returns
|
|
20
|
-
*/
|
|
21
|
-
export declare function fromUIMessages<METADATA = unknown>(messages: UIMessage<METADATA>[], meta: {
|
|
22
|
-
threadId: string;
|
|
23
|
-
userId?: string;
|
|
24
|
-
model?: string;
|
|
25
|
-
provider?: string;
|
|
26
|
-
providerOptions?: ProviderOptions;
|
|
27
|
-
metadata?: METADATA;
|
|
28
|
-
}): Promise<(MessageDoc & {
|
|
29
|
-
streaming: boolean;
|
|
30
|
-
metadata?: METADATA;
|
|
31
|
-
})[]>;
|
|
32
|
-
type ExtraFields<METADATA = unknown> = {
|
|
33
|
-
streaming?: boolean;
|
|
34
|
-
metadata?: METADATA;
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Converts a list of MessageDocs to UIMessages.
|
|
38
|
-
* This is somewhat lossy, as many fields are not supported by UIMessages, e.g.
|
|
39
|
-
* the model, provider, userId, etc.
|
|
40
|
-
* The UIMessage type is the augmented type that includes more fields such as
|
|
41
|
-
* key, order, stepOrder, status, agentName, text, etc.
|
|
42
|
-
*/
|
|
43
|
-
export declare function toUIMessages<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools>(messages: (MessageDoc & ExtraFields<METADATA>)[]): UIMessage<METADATA, DATA_PARTS, TOOLS>[];
|
|
44
|
-
export declare function combineUIMessages(messages: UIMessage[]): UIMessage[];
|
|
45
|
-
export {};
|
|
46
|
-
//# sourceMappingURL=UIMessages.d.ts.map
|
package/dist/UIMessages.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UIMessages.d.ts","sourceRoot":"","sources":["../src/UIMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,IAAI,WAAW,EAU7B,KAAK,WAAW,EAChB,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAUZ,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,aAAa,CAAC;AAEnD,MAAM,MAAM,SAAS,CACnB,QAAQ,GAAG,OAAO,EAClB,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,KAAK,SAAS,OAAO,GAAG,OAAO,IAC7B,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAG,OAAO,EACrD,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,EAC/B,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,GACA,OAAO,CAAC,CAAC,UAAU,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,EAAE,CAAC,CAiEvE;AA8BD,KAAK,WAAW,CAAC,QAAQ,GAAG,OAAO,IAAI;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,GAAG,OAAO,EAClB,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,KAAK,SAAS,OAAO,GAAG,OAAO,EAE/B,QAAQ,EAAE,CAAC,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,GAC/C,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,CAiB1C;AA+dD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA2CpE"}
|