@assistant-ui/react-ag-ui 0.0.44 → 0.0.45
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/dist/agUiExtras.d.ts +0 -1
- package/dist/agUiExtras.d.ts.map +1 -1
- package/dist/hooks.d.ts +15 -9
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +17 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts +26 -4
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +296 -89
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts +0 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +2 -1
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +0 -1
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +36 -7
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/adapter/subscriber.d.ts +0 -1
- package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
- package/dist/runtime/event-parser.d.ts +0 -1
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +18 -9
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/logger.d.ts.map +1 -1
- package/dist/runtime/types.d.ts +13 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/useAgUiRuntime.d.ts +0 -1
- package/dist/useAgUiRuntime.d.ts.map +1 -1
- package/dist/useAgUiRuntime.js +8 -2
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +6 -6
- package/src/hooks.ts +29 -7
- package/src/index.ts +2 -0
- package/src/runtime/AgUiThreadRuntimeCore.ts +390 -108
- package/src/runtime/adapter/conversions.ts +11 -4
- package/src/runtime/adapter/run-aggregator.ts +69 -5
- package/src/runtime/types.ts +17 -0
- package/src/useAgUiRuntime.ts +8 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import type { InputContent } from "@ag-ui/client";
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ThreadMessageLike as CoreThreadMessageLike,
|
|
6
|
+
ToolModelContentPart,
|
|
7
|
+
} from "@assistant-ui/core";
|
|
5
8
|
import { getAutoStatus } from "@assistant-ui/core/internal";
|
|
6
9
|
import { type Tool, toToolsJSONSchema } from "assistant-stream";
|
|
7
10
|
import type { ReadonlyJSONObject } from "assistant-stream/utils";
|
|
@@ -59,6 +62,7 @@ type ToolCallPart = {
|
|
|
59
62
|
args?: ReadonlyJSONObject;
|
|
60
63
|
result?: unknown;
|
|
61
64
|
isError?: boolean;
|
|
65
|
+
modelContent?: readonly ToolModelContentPart[];
|
|
62
66
|
unstable_toolMessageId?: string;
|
|
63
67
|
};
|
|
64
68
|
|
|
@@ -715,10 +719,13 @@ function convertAssistantMessage(
|
|
|
715
719
|
for (const { id: toolCallId, part } of toolCalls) {
|
|
716
720
|
if (part.result === undefined) continue;
|
|
717
721
|
|
|
722
|
+
const modelText = extractText(part.modelContent);
|
|
718
723
|
const resultContent =
|
|
719
|
-
|
|
720
|
-
?
|
|
721
|
-
:
|
|
724
|
+
modelText.length > 0
|
|
725
|
+
? modelText
|
|
726
|
+
: typeof part.result === "string"
|
|
727
|
+
? part.result
|
|
728
|
+
: JSON.stringify(part.result);
|
|
722
729
|
|
|
723
730
|
const toolMessage: AgUiMessage = {
|
|
724
731
|
id: part.unstable_toolMessageId ?? `${toolCallId}:tool`,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type MessageTiming,
|
|
7
7
|
type ThreadAssistantMessagePart,
|
|
8
8
|
type ToolCallMessagePart,
|
|
9
|
+
type ToolModelContentPart,
|
|
9
10
|
} from "@assistant-ui/core";
|
|
10
11
|
import type { AgUiEvent, AgUiInterrupt } from "../types";
|
|
11
12
|
import type { Logger } from "../logger";
|
|
@@ -28,10 +29,16 @@ type ToolCallState = {
|
|
|
28
29
|
parentMessageId?: string;
|
|
29
30
|
toolMessageId?: string;
|
|
30
31
|
mcpAppResourceUri?: string;
|
|
32
|
+
mcpAppServerId?: string;
|
|
33
|
+
modelContent?: ToolModelContentPart[];
|
|
34
|
+
snapshotResultApplied: boolean;
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
const MCP_APPS_ACTIVITY_TYPE = "mcp-apps";
|
|
34
38
|
|
|
39
|
+
const isPlainObject = (value: unknown): value is Record<string, unknown> =>
|
|
40
|
+
!!value && typeof value === "object" && !Array.isArray(value);
|
|
41
|
+
|
|
35
42
|
export type RunAggregatorOptions = {
|
|
36
43
|
showThinking: boolean;
|
|
37
44
|
logger: Logger;
|
|
@@ -236,8 +243,13 @@ export class RunAggregator {
|
|
|
236
243
|
}
|
|
237
244
|
case "ACTIVITY_SNAPSHOT": {
|
|
238
245
|
if (event.activityType !== MCP_APPS_ACTIVITY_TYPE) break;
|
|
239
|
-
const
|
|
240
|
-
const entry =
|
|
246
|
+
const toolCallId = event.content.toolCallId;
|
|
247
|
+
const entry =
|
|
248
|
+
typeof toolCallId === "string"
|
|
249
|
+
? this.toolCalls.get(toolCallId)
|
|
250
|
+
: this.lastResolvedToolCallId
|
|
251
|
+
? this.toolCalls.get(this.lastResolvedToolCallId)
|
|
252
|
+
: undefined;
|
|
241
253
|
const resourceUri = event.content.resourceUri;
|
|
242
254
|
if (
|
|
243
255
|
entry &&
|
|
@@ -245,6 +257,35 @@ export class RunAggregator {
|
|
|
245
257
|
isMcpAppUri(resourceUri)
|
|
246
258
|
) {
|
|
247
259
|
entry.mcpAppResourceUri = resourceUri;
|
|
260
|
+
const id = event.content.serverId;
|
|
261
|
+
const hash = event.content.serverHash;
|
|
262
|
+
if (typeof id === "string" && id.length > 0) {
|
|
263
|
+
entry.mcpAppServerId = id;
|
|
264
|
+
} else if (typeof hash === "string" && hash.length > 0) {
|
|
265
|
+
entry.mcpAppServerId = hash;
|
|
266
|
+
}
|
|
267
|
+
const result = event.content.result;
|
|
268
|
+
if (isPlainObject(result)) {
|
|
269
|
+
if (
|
|
270
|
+
entry.result !== undefined &&
|
|
271
|
+
entry.modelContent === undefined
|
|
272
|
+
) {
|
|
273
|
+
entry.modelContent = [
|
|
274
|
+
{
|
|
275
|
+
type: "text",
|
|
276
|
+
text:
|
|
277
|
+
typeof entry.result === "string"
|
|
278
|
+
? entry.result
|
|
279
|
+
: JSON.stringify(entry.result),
|
|
280
|
+
},
|
|
281
|
+
];
|
|
282
|
+
}
|
|
283
|
+
entry.result = result;
|
|
284
|
+
entry.snapshotResultApplied = true;
|
|
285
|
+
if (typeof result.isError === "boolean") {
|
|
286
|
+
entry.isError = result.isError;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
248
289
|
this.emit();
|
|
249
290
|
}
|
|
250
291
|
break;
|
|
@@ -343,6 +384,7 @@ export class RunAggregator {
|
|
|
343
384
|
parsedArgs: undefined,
|
|
344
385
|
result: undefined,
|
|
345
386
|
isError: undefined,
|
|
387
|
+
snapshotResultApplied: false,
|
|
346
388
|
};
|
|
347
389
|
if (parentMessageId) {
|
|
348
390
|
state.parentMessageId = parentMessageId;
|
|
@@ -411,6 +453,7 @@ export class RunAggregator {
|
|
|
411
453
|
parsedArgs: undefined,
|
|
412
454
|
result: undefined,
|
|
413
455
|
isError: undefined,
|
|
456
|
+
snapshotResultApplied: false,
|
|
414
457
|
};
|
|
415
458
|
this.toolCalls.set(id, entry);
|
|
416
459
|
}
|
|
@@ -421,8 +464,17 @@ export class RunAggregator {
|
|
|
421
464
|
) {
|
|
422
465
|
this.partOrder.push({ kind: "tool-call", toolCallId: id });
|
|
423
466
|
}
|
|
424
|
-
entry.
|
|
425
|
-
|
|
467
|
+
if (entry.snapshotResultApplied) {
|
|
468
|
+
if (entry.modelContent === undefined) {
|
|
469
|
+
entry.modelContent = [{ type: "text", text: content }];
|
|
470
|
+
}
|
|
471
|
+
if (entry.isError === undefined) {
|
|
472
|
+
entry.isError = isError;
|
|
473
|
+
}
|
|
474
|
+
} else {
|
|
475
|
+
entry.result = tryParseJSON(content);
|
|
476
|
+
entry.isError = isError;
|
|
477
|
+
}
|
|
426
478
|
if (toolMessageId) {
|
|
427
479
|
entry.toolMessageId = toolMessageId;
|
|
428
480
|
}
|
|
@@ -460,9 +512,21 @@ export class RunAggregator {
|
|
|
460
512
|
args: (entry.parsedArgs ?? {}) as any,
|
|
461
513
|
argsText: entry.argsText,
|
|
462
514
|
...(entry.result !== undefined ? { result: entry.result } : {}),
|
|
515
|
+
...(entry.modelContent !== undefined
|
|
516
|
+
? { modelContent: entry.modelContent }
|
|
517
|
+
: {}),
|
|
463
518
|
...(entry.isError !== undefined ? { isError: entry.isError } : {}),
|
|
464
519
|
...(entry.mcpAppResourceUri
|
|
465
|
-
? {
|
|
520
|
+
? {
|
|
521
|
+
mcp: {
|
|
522
|
+
app: {
|
|
523
|
+
resourceUri: entry.mcpAppResourceUri,
|
|
524
|
+
...(entry.mcpAppServerId
|
|
525
|
+
? { serverId: entry.mcpAppServerId }
|
|
526
|
+
: {}),
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
}
|
|
466
530
|
: {}),
|
|
467
531
|
...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),
|
|
468
532
|
...(entry.toolMessageId
|
package/src/runtime/types.ts
CHANGED
|
@@ -59,6 +59,17 @@ export type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
|
|
|
59
59
|
agent: AbstractAgent;
|
|
60
60
|
logger?: Partial<Logger>;
|
|
61
61
|
showThinking?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* When the user sends, edits, or reloads a message while client-side tool
|
|
64
|
+
* calls are still pending, automatically cancel the unresolved tool calls
|
|
65
|
+
* with an error result so the agent's tool-call accounting stays
|
|
66
|
+
* consistent. Pending AG-UI interrupts are exempt: they still reject the
|
|
67
|
+
* run and must be answered with `useAgUiSubmitInterruptResponses` or
|
|
68
|
+
* discarded with `useAgUiSteerAway`. When disabled, `useAgUiSteerAway`
|
|
69
|
+
* remains the explicit way to cancel pending tool calls.
|
|
70
|
+
* Defaults to `true`.
|
|
71
|
+
*/
|
|
72
|
+
autoCancelPendingToolCalls?: boolean | undefined;
|
|
62
73
|
onError?: (e: Error) => void;
|
|
63
74
|
onCancel?: () => void;
|
|
64
75
|
adapters?: UseAgUiRuntimeAdapters;
|
|
@@ -95,6 +106,12 @@ export type AgUiRuntimeExtras = {
|
|
|
95
106
|
message: CreateAppendMessage,
|
|
96
107
|
responses?: readonly AgUiResumeEntry[],
|
|
97
108
|
) => Promise<void>;
|
|
109
|
+
state: ReadonlyJSONValue | undefined;
|
|
110
|
+
setState: (
|
|
111
|
+
next:
|
|
112
|
+
| ReadonlyJSONValue
|
|
113
|
+
| ((prev: ReadonlyJSONValue | undefined) => ReadonlyJSONValue),
|
|
114
|
+
) => void;
|
|
98
115
|
};
|
|
99
116
|
|
|
100
117
|
export type AgUiRunFinishedOutcome =
|
package/src/useAgUiRuntime.ts
CHANGED
|
@@ -58,6 +58,7 @@ export function useAgUiRuntime(
|
|
|
58
58
|
agent: options.agent,
|
|
59
59
|
logger,
|
|
60
60
|
showThinking: options.showThinking ?? true,
|
|
61
|
+
autoCancelPendingToolCalls: options.autoCancelPendingToolCalls,
|
|
61
62
|
...(options.onError && { onError: options.onError }),
|
|
62
63
|
...(options.onCancel && { onCancel: options.onCancel }),
|
|
63
64
|
...(historyAdapter && { history: historyAdapter }),
|
|
@@ -70,6 +71,7 @@ export function useAgUiRuntime(
|
|
|
70
71
|
agent: options.agent,
|
|
71
72
|
logger,
|
|
72
73
|
showThinking: options.showThinking ?? true,
|
|
74
|
+
autoCancelPendingToolCalls: options.autoCancelPendingToolCalls,
|
|
73
75
|
...(options.onError && { onError: options.onError }),
|
|
74
76
|
...(options.onCancel && { onCancel: options.onCancel }),
|
|
75
77
|
...(historyAdapter && { history: historyAdapter }),
|
|
@@ -95,6 +97,7 @@ export function useAgUiRuntime(
|
|
|
95
97
|
? async () => {
|
|
96
98
|
await onSwitchToNewThread();
|
|
97
99
|
core.applyExternalMessages([]);
|
|
100
|
+
core.resetState();
|
|
98
101
|
}
|
|
99
102
|
: undefined,
|
|
100
103
|
onSwitchToThread: onSwitchToThread
|
|
@@ -106,6 +109,8 @@ export function useAgUiRuntime(
|
|
|
106
109
|
core.applyExternalMessages(result.messages);
|
|
107
110
|
if (result.state !== undefined) {
|
|
108
111
|
core.loadExternalState(result.state);
|
|
112
|
+
} else {
|
|
113
|
+
core.resetState();
|
|
109
114
|
}
|
|
110
115
|
if (result.unstable_resume) {
|
|
111
116
|
void core.resumeInFlightRun(result.messages);
|
|
@@ -136,7 +141,7 @@ export function useAgUiRuntime(
|
|
|
136
141
|
return {
|
|
137
142
|
...shared,
|
|
138
143
|
isLoading: core.isLoading,
|
|
139
|
-
|
|
144
|
+
messageRepository: core.getMessageRepository(),
|
|
140
145
|
state: core.getState(),
|
|
141
146
|
isRunning: core.isRunning() || hasExecutingTools,
|
|
142
147
|
extras: agUiExtras.provide({
|
|
@@ -145,6 +150,8 @@ export function useAgUiRuntime(
|
|
|
145
150
|
submitInterruptResponses: (responses) =>
|
|
146
151
|
core.submitInterruptResponses(responses),
|
|
147
152
|
steerAway: (message, responses) => core.steerAway(message, responses),
|
|
153
|
+
state: core.getState(),
|
|
154
|
+
setState: (next) => core.setState(next),
|
|
148
155
|
}),
|
|
149
156
|
unstable_enableToolInvocations: true,
|
|
150
157
|
setToolStatuses,
|