@agent-native/core 0.196.0 → 0.196.1-nightly-20260928200103
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/corpus/README.md +1 -1
- package/corpus/templates/clips/actions/create-recording.ts +1 -1
- package/corpus/templates/clips/actions/lib/auto-title-candidates.ts +42 -0
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +1 -1
- package/corpus/templates/clips/actions/lib/transcript-text.ts +16 -0
- package/corpus/templates/clips/actions/list-ai-requests.ts +49 -31
- package/corpus/templates/clips/actions/list-recordings.ts +2 -4
- package/corpus/templates/clips/actions/list-transactional-email-ai-requests.ts +12 -6
- package/corpus/templates/clips/actions/regenerate-title.ts +4 -1
- package/corpus/templates/clips/actions/request-transcript.ts +1 -1
- package/corpus/templates/clips/actions/save-browser-transcript.ts +1 -1
- package/corpus/templates/clips/app/components/editable-recording-title.tsx +1 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +1 -1
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +194 -219
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +2 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +1 -1
- package/corpus/templates/clips/server/lib/transactional-email-store.ts +42 -2
- package/corpus/templates/clips/shared/ai-request-status.ts +6 -0
- package/corpus/templates/clips/{actions/lib → shared}/title-source.ts +9 -2
- package/dist/agent/production-agent.js +2 -0
- package/dist/agent/run-manager.d.ts +2 -0
- package/dist/agent/run-manager.js +9 -2
- package/dist/agent/thread-data-builder.d.ts +1 -0
- package/dist/agent/thread-data-builder.js +148 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/chat-threads/store.d.ts +1 -0
- package/dist/chat-threads/store.js +244 -21
- package/dist/client/AgentKitAssistantChat.js +23 -12
- package/dist/client/chat/agentkit-agent-native.js +409 -8
- package/dist/client/chat/agentkit-protocol.js +3 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-chat-plugin.d.ts +2 -0
- package/dist/server/agent-chat-plugin.js +12 -7
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { hasActiveAgentRuns, } from "@agent-native/agentkit";
|
|
2
3
|
import { AgentKitChat, AgentKitComposer, AgentApprovalPrompt, AgentMessageView, useAgentKit, useAgentKitControl, useAgentThread, } from "@agent-native/agentkit/react";
|
|
3
4
|
import { AgentKitRoot } from "@agent-native/agentkit/react/root";
|
|
4
5
|
import { AgentSuggestionBar, agentSuggestionPrompt, } from "@agent-native/toolkit/composer";
|
|
@@ -577,7 +578,7 @@ export const AgentKitAssistantChat = forwardRef(function AgentKitAssistantChat(p
|
|
|
577
578
|
}, children: history ? (_jsx(AgentKitHistoryProvider, { history: history, children: _jsx(AgentKitDevCheckpointProvider, { apiUrl: props.apiUrl ?? agentNativePath("/_agent-native/agent-chat"), children: _jsx(AgentKitAssistantChatBody, { ...props, threadId: threadId, handoffSnapshot: handoffSnapshot, getThreadSnapshot: getThreadSnapshot, threadRestore: threadRestore, retryThreadRestore: retryThreadRestore, onThreadRestoreLoaded: onThreadRestoreLoaded, ref: ref }) }) })) : (_jsx(AgentKitDevCheckpointProvider, { apiUrl: props.apiUrl ?? agentNativePath("/_agent-native/agent-chat"), children: _jsx(AgentKitAssistantChatBody, { ...props, threadId: threadId, handoffSnapshot: handoffSnapshot, getThreadSnapshot: getThreadSnapshot, threadRestore: threadRestore, retryThreadRestore: retryThreadRestore, onThreadRestoreLoaded: onThreadRestoreLoaded, ref: ref }) })) }) }) }));
|
|
578
579
|
});
|
|
579
580
|
const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(props, ref) {
|
|
580
|
-
const { threadId, requestComposerFocus } = useAgentKit();
|
|
581
|
+
const { controller, threadId, requestComposerFocus } = useAgentKit();
|
|
581
582
|
const control = useAgentKitControl(threadId);
|
|
582
583
|
const thread = useAgentThread(threadId);
|
|
583
584
|
const history = useOptionalAgentKitHistory();
|
|
@@ -701,7 +702,8 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
|
|
|
701
702
|
const latestAssistant = useMemo(() => [...thread.messages]
|
|
702
703
|
.reverse()
|
|
703
704
|
.find((message) => message.role === "assistant"), [thread.messages]);
|
|
704
|
-
const isRunning = thread
|
|
705
|
+
const isRunning = hasActiveAgentRuns(thread);
|
|
706
|
+
const isThreadRunning = useCallback(() => hasActiveAgentRuns(controller.getThread(threadId)), [controller, threadId]);
|
|
705
707
|
useEffect(() => {
|
|
706
708
|
if (previousPrefillRevisionRef.current === prefillRevision)
|
|
707
709
|
return;
|
|
@@ -1541,7 +1543,7 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
|
|
|
1541
1543
|
thread.queuedMessages,
|
|
1542
1544
|
threadId,
|
|
1543
1545
|
]);
|
|
1544
|
-
const send = useCallback(async (text, images, options) => submit(text, [], [], { intent:
|
|
1546
|
+
const send = useCallback(async (text, images, options) => submit(text, [], [], { intent: isThreadRunning() ? "queued" : "immediate" }, {
|
|
1545
1547
|
...options,
|
|
1546
1548
|
attachments: [
|
|
1547
1549
|
...(options?.attachments ?? []),
|
|
@@ -1551,9 +1553,9 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
|
|
|
1551
1553
|
url,
|
|
1552
1554
|
})),
|
|
1553
1555
|
],
|
|
1554
|
-
}), [
|
|
1556
|
+
}), [isThreadRunning, submit]);
|
|
1555
1557
|
const sendRecoveryMessage = useCallback(async (text, recoveryAction, images, attachments, references, recoveryOptions) => {
|
|
1556
|
-
return submit(text, [], [], { intent:
|
|
1558
|
+
return submit(text, [], [], { intent: isThreadRunning() ? "queued" : "immediate" }, {
|
|
1557
1559
|
hideUserMessage: true,
|
|
1558
1560
|
recoveryAction,
|
|
1559
1561
|
recoveryReferences: references,
|
|
@@ -1567,7 +1569,7 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
|
|
|
1567
1569
|
})),
|
|
1568
1570
|
],
|
|
1569
1571
|
});
|
|
1570
|
-
}, [
|
|
1572
|
+
}, [isThreadRunning, submit]);
|
|
1571
1573
|
const resumeIntegrationPrompt = useCallback((message) => {
|
|
1572
1574
|
if (props.isActiveComposer === false)
|
|
1573
1575
|
return;
|
|
@@ -1576,10 +1578,10 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
|
|
|
1576
1578
|
});
|
|
1577
1579
|
}, [props.isActiveComposer, props.tabId, send, threadId]);
|
|
1578
1580
|
const submitSuggestion = useCallback((prompt) => void submit(prompt, [], [], {
|
|
1579
|
-
intent:
|
|
1581
|
+
intent: isThreadRunning() ? "queued" : "immediate",
|
|
1580
1582
|
}).catch((error) => {
|
|
1581
1583
|
dispatchSetupRequiredEvent(error, props.tabId, threadId);
|
|
1582
|
-
}), [
|
|
1584
|
+
}), [isThreadRunning, props.tabId, submit, threadId]);
|
|
1583
1585
|
const retryDeferredSubmission = useCallback(async () => {
|
|
1584
1586
|
if (!deferredProviderSubmissionFailureId)
|
|
1585
1587
|
return;
|
|
@@ -1659,7 +1661,7 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
|
|
|
1659
1661
|
url,
|
|
1660
1662
|
})),
|
|
1661
1663
|
}),
|
|
1662
|
-
isRunning:
|
|
1664
|
+
isRunning: isThreadRunning,
|
|
1663
1665
|
hasInFlightWork: () => Object.values(thread.tools).some((tool) => tool.status === "running") ||
|
|
1664
1666
|
Object.values(thread.activities).some((activity) => activity.status === "running"),
|
|
1665
1667
|
focusComposer: () => requestComposerFocus(threadId),
|
|
@@ -1787,6 +1789,7 @@ function AgentKitSelectionPill({ length, onClear, }) {
|
|
|
1787
1789
|
}) }), _jsx("button", { type: "button", "aria-label": t("agentChat.selection.clear"), onClick: onClear, className: "flex h-4 w-4 items-center justify-center rounded text-muted-foreground hover:bg-accent/60 hover:text-foreground", children: _jsx(IconX, { size: 11, "aria-hidden": "true" }) })] }) }));
|
|
1788
1790
|
}
|
|
1789
1791
|
function AgentKitTranscript({ children, threadId }) {
|
|
1792
|
+
const { controller } = useAgentKit();
|
|
1790
1793
|
const surface = useAgentKitSurface();
|
|
1791
1794
|
const t = useT();
|
|
1792
1795
|
const thread = useAgentThread(threadId);
|
|
@@ -1800,11 +1803,19 @@ function AgentKitTranscript({ children, threadId }) {
|
|
|
1800
1803
|
browserTabId: surface.props.browserTabId,
|
|
1801
1804
|
threadId,
|
|
1802
1805
|
onSubmitMessage: async ({ message, context }) => {
|
|
1803
|
-
await surface.onSubmit(appendAgentChatContextToMessage(message, context), [], [], {
|
|
1806
|
+
await surface.onSubmit(appendAgentChatContextToMessage(message, context), [], [], {
|
|
1807
|
+
intent: hasActiveAgentRuns(controller.getThread(threadId))
|
|
1808
|
+
? "queued"
|
|
1809
|
+
: "immediate",
|
|
1810
|
+
});
|
|
1804
1811
|
return { delivered: true };
|
|
1805
1812
|
},
|
|
1806
1813
|
onSkipMessage: async ({ message, context }) => {
|
|
1807
|
-
await surface.onSubmit(appendAgentChatContextToMessage(message, context), [], [], {
|
|
1814
|
+
await surface.onSubmit(appendAgentChatContextToMessage(message, context), [], [], {
|
|
1815
|
+
intent: hasActiveAgentRuns(controller.getThread(threadId))
|
|
1816
|
+
? "queued"
|
|
1817
|
+
: "immediate",
|
|
1818
|
+
});
|
|
1808
1819
|
return { delivered: true };
|
|
1809
1820
|
},
|
|
1810
1821
|
});
|
|
@@ -2035,7 +2046,7 @@ function AgentKitMessageSupplement(props) {
|
|
|
2035
2046
|
.join("\n");
|
|
2036
2047
|
const integration = value.role === "assistant" &&
|
|
2037
2048
|
value.status === "complete" &&
|
|
2038
|
-
thread
|
|
2049
|
+
!hasActiveAgentRuns(thread)
|
|
2039
2050
|
? findMcpConnectionSuggestionIntegration({
|
|
2040
2051
|
text,
|
|
2041
2052
|
contextText,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseAgentThreadSnapshot } from "@agent-native/agentkit/protocol";
|
|
1
|
+
import { isAgentKitProtocolVersion, parseAgentThreadSnapshot, } from "@agent-native/agentkit/protocol";
|
|
2
2
|
import { agentNativePath } from "../api-path.js";
|
|
3
3
|
import { dispatchAgentChatRunning } from "../use-agent-chat-running-threads.js";
|
|
4
4
|
import { appendChatThreadScopeParams, } from "../use-chat-threads.js";
|
|
@@ -285,6 +285,249 @@ function storedRepository(stored) {
|
|
|
285
285
|
}
|
|
286
286
|
return repository;
|
|
287
287
|
}
|
|
288
|
+
function persistedError(value) {
|
|
289
|
+
const error = asRecord(value);
|
|
290
|
+
if (typeof error?.code !== "string" || typeof error.message !== "string") {
|
|
291
|
+
throw new TypeError("Agent chat run errors must include a code and message.");
|
|
292
|
+
}
|
|
293
|
+
const persisted = {
|
|
294
|
+
code: error.code.slice(0, 128),
|
|
295
|
+
message: error.message.slice(0, 2_048),
|
|
296
|
+
};
|
|
297
|
+
if (typeof error.retryable === "boolean") {
|
|
298
|
+
persisted.retryable = error.retryable;
|
|
299
|
+
}
|
|
300
|
+
if (typeof error.correlationId === "string") {
|
|
301
|
+
persisted.correlationId = error.correlationId.slice(0, 128);
|
|
302
|
+
}
|
|
303
|
+
if (error.code === "capability_unsupported" ||
|
|
304
|
+
error.code === "capability_unavailable") {
|
|
305
|
+
persisted.capability =
|
|
306
|
+
typeof error.capability === "string"
|
|
307
|
+
? error.capability.slice(0, 128)
|
|
308
|
+
: "x-unknown";
|
|
309
|
+
persisted.retryable =
|
|
310
|
+
error.code === "capability_unsupported"
|
|
311
|
+
? false
|
|
312
|
+
: typeof error.retryable === "boolean"
|
|
313
|
+
? error.retryable
|
|
314
|
+
: false;
|
|
315
|
+
}
|
|
316
|
+
else if (error.code === "operation_unsupported") {
|
|
317
|
+
persisted.operation =
|
|
318
|
+
typeof error.operation === "string"
|
|
319
|
+
? error.operation.slice(0, 128)
|
|
320
|
+
: "unknown";
|
|
321
|
+
persisted.retryable = false;
|
|
322
|
+
}
|
|
323
|
+
else if (error.code === "protocol_version_unsupported") {
|
|
324
|
+
persisted.supportedVersions = Array.isArray(error.supportedVersions)
|
|
325
|
+
? error.supportedVersions.filter(isAgentKitProtocolVersion).slice(0, 32)
|
|
326
|
+
: [];
|
|
327
|
+
persisted.receivedVersions = Array.isArray(error.receivedVersions)
|
|
328
|
+
? error.receivedVersions
|
|
329
|
+
.filter((version) => Number.isSafeInteger(version) && Number(version) > 0)
|
|
330
|
+
.slice(0, 32)
|
|
331
|
+
: [];
|
|
332
|
+
persisted.retryable = false;
|
|
333
|
+
}
|
|
334
|
+
return persisted;
|
|
335
|
+
}
|
|
336
|
+
function persistedAnnotation(annotation) {
|
|
337
|
+
return {
|
|
338
|
+
id: annotation.id,
|
|
339
|
+
kind: annotation.kind,
|
|
340
|
+
label: annotation.label,
|
|
341
|
+
...(annotation.url ? { url: annotation.url } : {}),
|
|
342
|
+
...(annotation.start !== undefined ? { start: annotation.start } : {}),
|
|
343
|
+
...(annotation.end !== undefined ? { end: annotation.end } : {}),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function persistedAnnotations(annotations = [], messageIds) {
|
|
347
|
+
return annotations.flatMap(({ messageId, annotation }) => messageIds.has(messageId)
|
|
348
|
+
? [{ messageId, annotation: persistedAnnotation(annotation) }]
|
|
349
|
+
: []);
|
|
350
|
+
}
|
|
351
|
+
function persistedFileUrl(url) {
|
|
352
|
+
return url && !/^\s*data:/i.test(url) ? url : undefined;
|
|
353
|
+
}
|
|
354
|
+
function persistedHistoryEvents(events = []) {
|
|
355
|
+
const sequenceByRun = new Map();
|
|
356
|
+
return events.flatMap((event) => {
|
|
357
|
+
const base = () => {
|
|
358
|
+
const sequence = (sequenceByRun.get(event.runId) ?? 0) + 1;
|
|
359
|
+
sequenceByRun.set(event.runId, sequence);
|
|
360
|
+
return {
|
|
361
|
+
id: event.id,
|
|
362
|
+
threadId: event.threadId,
|
|
363
|
+
runId: event.runId,
|
|
364
|
+
sequence,
|
|
365
|
+
occurredAt: event.occurredAt,
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
if (event.type === "run.started") {
|
|
369
|
+
return [{ ...base(), type: event.type }];
|
|
370
|
+
}
|
|
371
|
+
if (event.type === "run.completed" || event.type === "run.cancelled") {
|
|
372
|
+
return [{ ...base(), type: event.type }];
|
|
373
|
+
}
|
|
374
|
+
if (event.type === "run.failed") {
|
|
375
|
+
return [
|
|
376
|
+
{ ...base(), type: event.type, error: persistedError(event.error) },
|
|
377
|
+
];
|
|
378
|
+
}
|
|
379
|
+
if (event.type === "run.status") {
|
|
380
|
+
return [{ ...base(), type: event.type, status: event.status }];
|
|
381
|
+
}
|
|
382
|
+
if (event.type === "activity.started" ||
|
|
383
|
+
event.type === "activity.updated" ||
|
|
384
|
+
event.type === "activity.completed") {
|
|
385
|
+
const activity = event.activity;
|
|
386
|
+
return [
|
|
387
|
+
{
|
|
388
|
+
...base(),
|
|
389
|
+
type: event.type,
|
|
390
|
+
activity: {
|
|
391
|
+
id: activity.id,
|
|
392
|
+
kind: activity.kind,
|
|
393
|
+
label: activity.label,
|
|
394
|
+
status: activity.status,
|
|
395
|
+
...(activity.runId ? { runId: activity.runId } : {}),
|
|
396
|
+
...(activity.agentId ? { agentId: activity.agentId } : {}),
|
|
397
|
+
...(activity.startedAt ? { startedAt: activity.startedAt } : {}),
|
|
398
|
+
...(activity.completedAt
|
|
399
|
+
? { completedAt: activity.completedAt }
|
|
400
|
+
: {}),
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
if (event.type === "message.completed" &&
|
|
406
|
+
event.message.role === "assistant") {
|
|
407
|
+
return [
|
|
408
|
+
{
|
|
409
|
+
...base(),
|
|
410
|
+
type: event.type,
|
|
411
|
+
message: {
|
|
412
|
+
id: event.message.id,
|
|
413
|
+
role: event.message.role,
|
|
414
|
+
parts: event.message.parts.filter((part) => part.type === "text"),
|
|
415
|
+
...(event.message.createdAt
|
|
416
|
+
? { createdAt: event.message.createdAt }
|
|
417
|
+
: {}),
|
|
418
|
+
...(event.message.status ? { status: event.message.status } : {}),
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
];
|
|
422
|
+
}
|
|
423
|
+
return [];
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
function persistedMessages(messages) {
|
|
427
|
+
return messages.map((message) => ({
|
|
428
|
+
id: message.id,
|
|
429
|
+
role: message.role,
|
|
430
|
+
parts: message.parts.flatMap((part) => {
|
|
431
|
+
if (part.type === "text") {
|
|
432
|
+
return [
|
|
433
|
+
{
|
|
434
|
+
type: "text",
|
|
435
|
+
text: part.text,
|
|
436
|
+
...(part.format ? { format: part.format } : {}),
|
|
437
|
+
},
|
|
438
|
+
];
|
|
439
|
+
}
|
|
440
|
+
if (part.type === "citation") {
|
|
441
|
+
return [
|
|
442
|
+
{
|
|
443
|
+
type: "citation",
|
|
444
|
+
title: part.title,
|
|
445
|
+
...(part.url ? { url: part.url } : {}),
|
|
446
|
+
...(part.sourceId ? { sourceId: part.sourceId } : {}),
|
|
447
|
+
},
|
|
448
|
+
];
|
|
449
|
+
}
|
|
450
|
+
if (part.type === "annotation") {
|
|
451
|
+
return [
|
|
452
|
+
{
|
|
453
|
+
type: "annotation",
|
|
454
|
+
annotation: persistedAnnotation(part.annotation),
|
|
455
|
+
},
|
|
456
|
+
];
|
|
457
|
+
}
|
|
458
|
+
if (part.type === "file") {
|
|
459
|
+
const url = persistedFileUrl(part.url);
|
|
460
|
+
if (!url && !part.fileId)
|
|
461
|
+
return [];
|
|
462
|
+
return [
|
|
463
|
+
{
|
|
464
|
+
type: "file",
|
|
465
|
+
name: part.name,
|
|
466
|
+
...(part.mediaType ? { mediaType: part.mediaType } : {}),
|
|
467
|
+
...(url ? { url } : {}),
|
|
468
|
+
...(part.fileId ? { fileId: part.fileId } : {}),
|
|
469
|
+
},
|
|
470
|
+
];
|
|
471
|
+
}
|
|
472
|
+
return [];
|
|
473
|
+
}),
|
|
474
|
+
...(message.createdAt ? { createdAt: message.createdAt } : {}),
|
|
475
|
+
...(message.status ? { status: message.status } : {}),
|
|
476
|
+
...(asRecord(message.metadata)?.hideUserMessage === true
|
|
477
|
+
? { metadata: { hideUserMessage: true } }
|
|
478
|
+
: {}),
|
|
479
|
+
}));
|
|
480
|
+
}
|
|
481
|
+
function persistedActionWidgets(widgets = [], messageIds) {
|
|
482
|
+
return widgets.flatMap(({ messageId, widget }) => {
|
|
483
|
+
if (!messageIds.has(messageId))
|
|
484
|
+
return [];
|
|
485
|
+
const data = asRecord(widget.data);
|
|
486
|
+
if (typeof data?.toolCallId !== "string" ||
|
|
487
|
+
typeof data.toolName !== "string") {
|
|
488
|
+
return [];
|
|
489
|
+
}
|
|
490
|
+
const description = asRecord(widget.metadata)?.description;
|
|
491
|
+
return [
|
|
492
|
+
{
|
|
493
|
+
messageId,
|
|
494
|
+
widget: {
|
|
495
|
+
id: widget.id,
|
|
496
|
+
kind: widget.kind,
|
|
497
|
+
data: { toolCallId: data.toolCallId, toolName: data.toolName },
|
|
498
|
+
...(widget.title ? { title: widget.title } : {}),
|
|
499
|
+
...(typeof description === "string"
|
|
500
|
+
? { metadata: { description } }
|
|
501
|
+
: {}),
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
];
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
function persistedToolCalls(toolCalls = []) {
|
|
508
|
+
return toolCalls.flatMap((toolCall) => {
|
|
509
|
+
const serialized = JSON.stringify(toolCall);
|
|
510
|
+
if (serialized &&
|
|
511
|
+
new TextEncoder().encode(serialized).byteLength <= 64 * 1024) {
|
|
512
|
+
return [JSON.parse(serialized)];
|
|
513
|
+
}
|
|
514
|
+
return [
|
|
515
|
+
{
|
|
516
|
+
id: toolCall.id,
|
|
517
|
+
name: toolCall.name,
|
|
518
|
+
status: toolCall.status,
|
|
519
|
+
...(toolCall.runId ? { runId: toolCall.runId } : {}),
|
|
520
|
+
...(toolCall.messageId ? { messageId: toolCall.messageId } : {}),
|
|
521
|
+
metadata: {
|
|
522
|
+
agentKitSnapshot: {
|
|
523
|
+
toolCallResult: "omitted",
|
|
524
|
+
reason: serialized ? "size_limit" : "not_json",
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
];
|
|
529
|
+
});
|
|
530
|
+
}
|
|
288
531
|
function storedMessageId(value) {
|
|
289
532
|
const outer = asRecord(value);
|
|
290
533
|
const message = asRecord(outer?.message ?? outer);
|
|
@@ -452,6 +695,7 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
452
695
|
const createdAt = timestamp(stored.createdAt, projectedAt);
|
|
453
696
|
const updatedAt = timestamp(stored.updatedAt, createdAt);
|
|
454
697
|
const repository = storedRepository(stored);
|
|
698
|
+
const storedMessageProjection = storedMessages(repository.messages, now, options.adapter?.textFormat);
|
|
455
699
|
const queuedMessages = storedQueue(repository.queuedMessages, threadId, updatedAt);
|
|
456
700
|
const agentKit = asRecord(repository.agentKit);
|
|
457
701
|
const protocolSnapshot = agentKit
|
|
@@ -461,13 +705,17 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
461
705
|
createdAt,
|
|
462
706
|
updatedAt,
|
|
463
707
|
metadata: asRecord(stored.metadata) ?? undefined,
|
|
464
|
-
messages: agentKit.messages
|
|
708
|
+
messages: Array.isArray(agentKit.messages)
|
|
709
|
+
? agentKit.messages
|
|
710
|
+
: storedMessageProjection,
|
|
465
711
|
events: agentKit.events,
|
|
466
712
|
runs: agentKit.runs,
|
|
467
713
|
activeRunIds: agentKit.activeRunIds,
|
|
714
|
+
suggestions: agentKit.suggestions,
|
|
468
715
|
toolCalls: agentKit.toolCalls,
|
|
469
716
|
activities: agentKit.activities,
|
|
470
717
|
widgets: agentKit.widgets,
|
|
718
|
+
annotations: agentKit.annotations,
|
|
471
719
|
})
|
|
472
720
|
: undefined;
|
|
473
721
|
const durableMessages = storedMessages(repository.messages, now, options.adapter?.textFormat);
|
|
@@ -475,14 +723,52 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
475
723
|
? reconcileDurableAssistantText(protocolSnapshot.messages, durableMessages, protocolSnapshot.events)
|
|
476
724
|
: durableMessages;
|
|
477
725
|
const actionWidgets = storedActionWidgets(repository.messages);
|
|
726
|
+
const canonicalToolCallMessageIds = new Map((protocolSnapshot?.toolCalls ?? []).flatMap((toolCall) => toolCall.messageId ? [[toolCall.id, toolCall.messageId]] : []));
|
|
727
|
+
const embeddedWidgetIds = new Set(messages.flatMap((message) => message.parts.flatMap((part) => part.type === "widget" ? [part.widget.id] : [])));
|
|
728
|
+
const persistedWidgetIds = new Set([
|
|
729
|
+
...(protocolSnapshot?.widgets ?? []).map(({ widget }) => widget.id),
|
|
730
|
+
...embeddedWidgetIds,
|
|
731
|
+
]);
|
|
732
|
+
const messageIds = new Set(messages.map((message) => message.id));
|
|
733
|
+
const reconciledActionWidgets = actionWidgets.widgets.map(({ messageId, widget }) => {
|
|
734
|
+
const toolCallId = asRecord(widget.data)?.toolCallId;
|
|
735
|
+
const canonicalMessageId = typeof toolCallId === "string"
|
|
736
|
+
? canonicalToolCallMessageIds.get(toolCallId)
|
|
737
|
+
: undefined;
|
|
738
|
+
return {
|
|
739
|
+
messageId: canonicalMessageId && messageIds.has(canonicalMessageId)
|
|
740
|
+
? canonicalMessageId
|
|
741
|
+
: messageId,
|
|
742
|
+
widget,
|
|
743
|
+
};
|
|
744
|
+
});
|
|
745
|
+
const widgetMessageIds = new Set(reconciledActionWidgets
|
|
746
|
+
.filter(({ widget }) => !persistedWidgetIds.has(widget.id))
|
|
747
|
+
.map(({ messageId }) => messageId));
|
|
748
|
+
for (const message of storedMessageProjection) {
|
|
749
|
+
if (!widgetMessageIds.has(message.id) || messageIds.has(message.id)) {
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
messages.push({
|
|
753
|
+
...message,
|
|
754
|
+
parts: message.parts.filter((part) => part.type !== "data"),
|
|
755
|
+
});
|
|
756
|
+
messageIds.add(message.id);
|
|
757
|
+
}
|
|
758
|
+
for (const { messageId, widget } of reconciledActionWidgets) {
|
|
759
|
+
if (!persistedWidgetIds.has(widget.id) && !messageIds.has(messageId)) {
|
|
760
|
+
throw new TypeError(`Action widget ${widget.id} references missing message ${messageId}.`);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
478
763
|
const toolCalls = new Map((protocolSnapshot?.toolCalls ?? []).map((toolCall) => [toolCall.id, toolCall]));
|
|
479
764
|
for (const toolCall of actionWidgets.toolCalls) {
|
|
480
765
|
if (!toolCalls.has(toolCall.id))
|
|
481
766
|
toolCalls.set(toolCall.id, toolCall);
|
|
482
767
|
}
|
|
483
768
|
const widgets = new Map((protocolSnapshot?.widgets ?? []).map((widget) => [widget.widget.id, widget]));
|
|
484
|
-
for (const widget of
|
|
485
|
-
if (!widgets.has(widget.widget.id)
|
|
769
|
+
for (const widget of reconciledActionWidgets) {
|
|
770
|
+
if (!widgets.has(widget.widget.id) &&
|
|
771
|
+
!embeddedWidgetIds.has(widget.widget.id)) {
|
|
486
772
|
widgets.set(widget.widget.id, widget);
|
|
487
773
|
}
|
|
488
774
|
}
|
|
@@ -499,9 +785,15 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
499
785
|
...(protocolSnapshot?.activeRunIds
|
|
500
786
|
? { activeRunIds: protocolSnapshot.activeRunIds }
|
|
501
787
|
: {}),
|
|
788
|
+
...(protocolSnapshot?.suggestions
|
|
789
|
+
? { suggestions: protocolSnapshot.suggestions }
|
|
790
|
+
: {}),
|
|
502
791
|
...(protocolSnapshot?.activities
|
|
503
792
|
? { activities: protocolSnapshot.activities }
|
|
504
793
|
: {}),
|
|
794
|
+
...(protocolSnapshot?.annotations
|
|
795
|
+
? { annotations: protocolSnapshot.annotations }
|
|
796
|
+
: {}),
|
|
505
797
|
toolCalls: [...toolCalls.values()],
|
|
506
798
|
widgets: [...widgets.values()],
|
|
507
799
|
};
|
|
@@ -562,6 +854,78 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
562
854
|
],
|
|
563
855
|
};
|
|
564
856
|
}
|
|
857
|
+
async function persistThreadSnapshot(input) {
|
|
858
|
+
const stored = await fetchThread(input.threadId);
|
|
859
|
+
if (!stored) {
|
|
860
|
+
throw new Error(`Agent chat thread ${input.threadId} does not exist.`);
|
|
861
|
+
}
|
|
862
|
+
const repository = storedRepository(stored);
|
|
863
|
+
const previousAgentKit = asRecord(repository.agentKit) ?? {};
|
|
864
|
+
const compactEvents = persistedHistoryEvents(input.snapshot.events);
|
|
865
|
+
const compactRunIds = new Set(compactEvents.map((event) => event.runId));
|
|
866
|
+
const eventsById = new Map();
|
|
867
|
+
const previousEvents = Array.isArray(previousAgentKit.events)
|
|
868
|
+
? previousAgentKit.events
|
|
869
|
+
: [];
|
|
870
|
+
for (const event of previousEvents) {
|
|
871
|
+
const record = asRecord(event);
|
|
872
|
+
if (typeof record?.id === "string" &&
|
|
873
|
+
typeof record.runId === "string" &&
|
|
874
|
+
!compactRunIds.has(record.runId)) {
|
|
875
|
+
eventsById.set(record.id, event);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
for (const event of compactEvents) {
|
|
879
|
+
eventsById.set(event.id, event);
|
|
880
|
+
}
|
|
881
|
+
const runsById = new Map();
|
|
882
|
+
const previousRuns = Array.isArray(previousAgentKit.runs)
|
|
883
|
+
? previousAgentKit.runs
|
|
884
|
+
: [];
|
|
885
|
+
for (const run of [...previousRuns, ...(input.snapshot.runs ?? [])]) {
|
|
886
|
+
const record = asRecord(run);
|
|
887
|
+
if (typeof record?.id === "string")
|
|
888
|
+
runsById.set(record.id, run);
|
|
889
|
+
}
|
|
890
|
+
const snapshotMessageIds = new Set(input.snapshot.messages.map((message) => message.id));
|
|
891
|
+
const annotations = input.snapshot.annotations ??
|
|
892
|
+
(Array.isArray(previousAgentKit.annotations)
|
|
893
|
+
? previousAgentKit.annotations
|
|
894
|
+
: []);
|
|
895
|
+
const agentKit = {
|
|
896
|
+
...previousAgentKit,
|
|
897
|
+
messages: persistedMessages(input.snapshot.messages),
|
|
898
|
+
widgets: persistedActionWidgets(input.snapshot.widgets, new Set(input.snapshot.messages.map((message) => message.id))),
|
|
899
|
+
toolCalls: persistedToolCalls(input.snapshot.toolCalls),
|
|
900
|
+
events: [...eventsById.values()],
|
|
901
|
+
runs: [...runsById.values()].map((run) => {
|
|
902
|
+
const record = asRecord(run);
|
|
903
|
+
return record && record.error !== undefined
|
|
904
|
+
? { ...record, error: persistedError(record.error) }
|
|
905
|
+
: run;
|
|
906
|
+
}),
|
|
907
|
+
activeRunIds: input.snapshot.activeRunIds ?? [],
|
|
908
|
+
suggestions: input.snapshot.suggestions ?? previousAgentKit.suggestions,
|
|
909
|
+
annotations: persistedAnnotations(annotations, snapshotMessageIds),
|
|
910
|
+
};
|
|
911
|
+
const requestHeaders = await headers({ sessionId: input.threadId });
|
|
912
|
+
requestHeaders.set("content-type", "application/json");
|
|
913
|
+
const snapshotRepository = { ...repository };
|
|
914
|
+
delete snapshotRepository.queuedMessages;
|
|
915
|
+
const response = await fetcher(scopedThreadEndpoint(`${apiUrl}/threads/${encodeURIComponent(input.threadId)}`, options), {
|
|
916
|
+
method: "PUT",
|
|
917
|
+
headers: requestHeaders,
|
|
918
|
+
body: JSON.stringify({
|
|
919
|
+
threadData: JSON.stringify({ ...snapshotRepository, agentKit }),
|
|
920
|
+
title: input.snapshot.title ??
|
|
921
|
+
(typeof stored.title === "string" ? stored.title : ""),
|
|
922
|
+
preview: typeof stored.preview === "string" ? stored.preview : "",
|
|
923
|
+
messageCount: input.snapshot.messages.length,
|
|
924
|
+
}),
|
|
925
|
+
});
|
|
926
|
+
if (!response.ok)
|
|
927
|
+
throw await responseError(response);
|
|
928
|
+
}
|
|
565
929
|
async function persistQueueMutation(threadId, mutation) {
|
|
566
930
|
const requestHeaders = await headers({ sessionId: threadId });
|
|
567
931
|
requestHeaders.set("content-type", "application/json");
|
|
@@ -641,6 +1005,7 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
641
1005
|
},
|
|
642
1006
|
operations: {
|
|
643
1007
|
...options.operations,
|
|
1008
|
+
persistThreadSnapshot: options.operations?.persistThreadSnapshot ?? persistThreadSnapshot,
|
|
644
1009
|
getThread: async ({ threadId }) => {
|
|
645
1010
|
const thread = await snapshot(threadId);
|
|
646
1011
|
if (!thread)
|
|
@@ -741,23 +1106,59 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
741
1106
|
let forkSource;
|
|
742
1107
|
if (fromMessageId) {
|
|
743
1108
|
const repository = storedRepository(source);
|
|
744
|
-
|
|
1109
|
+
const agentKit = asRecord(repository.agentKit);
|
|
1110
|
+
const sourceMessages = Array.isArray(agentKit?.messages)
|
|
1111
|
+
? agentKit.messages
|
|
1112
|
+
: repository.messages;
|
|
1113
|
+
if (!Array.isArray(sourceMessages)) {
|
|
745
1114
|
throw new Error("The Agent-Native thread cannot be forked from a message without durable history.");
|
|
746
1115
|
}
|
|
747
|
-
const throughIndex =
|
|
1116
|
+
const throughIndex = sourceMessages.findIndex((message) => storedMessageId(message) === fromMessageId);
|
|
748
1117
|
if (throughIndex < 0) {
|
|
749
1118
|
throw new Error("Unknown message for fork: " + fromMessageId);
|
|
750
1119
|
}
|
|
751
|
-
const messages =
|
|
1120
|
+
const messages = sourceMessages.slice(0, throughIndex + 1);
|
|
1121
|
+
const retainedMessageIds = new Set(messages
|
|
1122
|
+
.map(storedMessageId)
|
|
1123
|
+
.filter((id) => Boolean(id)));
|
|
1124
|
+
const legacyMessages = Array.isArray(repository.messages)
|
|
1125
|
+
? repository.messages.filter((message) => retainedMessageIds.has(storedMessageId(message) ?? ""))
|
|
1126
|
+
: undefined;
|
|
1127
|
+
const retainedAgentKit = agentKit && Array.isArray(agentKit.messages)
|
|
1128
|
+
? {
|
|
1129
|
+
...agentKit,
|
|
1130
|
+
messages,
|
|
1131
|
+
...(Array.isArray(agentKit.widgets)
|
|
1132
|
+
? {
|
|
1133
|
+
widgets: agentKit.widgets.filter((entry) => {
|
|
1134
|
+
const widget = asRecord(entry);
|
|
1135
|
+
return (typeof widget?.messageId === "string" &&
|
|
1136
|
+
retainedMessageIds.has(widget.messageId));
|
|
1137
|
+
}),
|
|
1138
|
+
}
|
|
1139
|
+
: {}),
|
|
1140
|
+
...(Array.isArray(agentKit.toolCalls)
|
|
1141
|
+
? {
|
|
1142
|
+
toolCalls: agentKit.toolCalls.filter((entry) => {
|
|
1143
|
+
const toolCall = asRecord(entry);
|
|
1144
|
+
return (typeof toolCall?.messageId !== "string" ||
|
|
1145
|
+
retainedMessageIds.has(toolCall.messageId));
|
|
1146
|
+
}),
|
|
1147
|
+
}
|
|
1148
|
+
: {}),
|
|
1149
|
+
}
|
|
1150
|
+
: undefined;
|
|
752
1151
|
forkSource = {
|
|
753
1152
|
threadData: JSON.stringify({
|
|
754
1153
|
...repository,
|
|
755
|
-
messages,
|
|
1154
|
+
...(legacyMessages ? { messages: legacyMessages } : {}),
|
|
1155
|
+
...(retainedAgentKit ? { agentKit: retainedAgentKit } : {}),
|
|
756
1156
|
queuedMessages: [],
|
|
757
1157
|
}),
|
|
758
1158
|
title: title ?? (typeof source.title === "string" ? source.title : ""),
|
|
759
1159
|
preview: "",
|
|
760
1160
|
messageCount: messages.length,
|
|
1161
|
+
fromMessageId,
|
|
761
1162
|
};
|
|
762
1163
|
}
|
|
763
1164
|
const requestHeaders = await headers({ sessionId: threadId });
|
|
@@ -2610,6 +2610,9 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
2610
2610
|
};
|
|
2611
2611
|
}
|
|
2612
2612
|
const hostOperations = options.operations;
|
|
2613
|
+
if (hostOperations?.persistThreadSnapshot) {
|
|
2614
|
+
transport.persistThreadSnapshot = hostOperations.persistThreadSnapshot;
|
|
2615
|
+
}
|
|
2613
2616
|
if (hostOperations?.createThread) {
|
|
2614
2617
|
transport.createThread = (input = {}, context) => {
|
|
2615
2618
|
const metadata = mergeTrustedProtocolMetadata(options.metadata, input.metadata);
|
|
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
38
38
|
error: string;
|
|
39
39
|
states?: undefined;
|
|
40
40
|
} | {
|
|
41
|
-
error?: undefined;
|
|
42
41
|
states: {
|
|
43
42
|
clientId: number;
|
|
44
43
|
state: string;
|
|
45
44
|
}[];
|
|
45
|
+
error?: undefined;
|
|
46
46
|
}>>;
|
|
47
47
|
export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
48
48
|
error: string;
|
|
49
49
|
users?: undefined;
|
|
50
50
|
} | {
|
|
51
|
-
error?: undefined;
|
|
52
51
|
users: {
|
|
53
52
|
clientId: number;
|
|
54
53
|
lastSeen: number;
|
|
55
54
|
}[];
|
|
55
|
+
error?: undefined;
|
|
56
56
|
}>>;
|