@assistant-ui/react-ag-ui 0.0.59 → 0.0.60

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.
Files changed (33) hide show
  1. package/dist/agUiExtras.d.ts +1 -2
  2. package/dist/agUiExtras.d.ts.map +1 -1
  3. package/dist/hooks.d.ts +6 -7
  4. package/dist/hooks.d.ts.map +1 -1
  5. package/dist/runtime/AgUiThreadRuntimeCore.d.ts +1 -2
  6. package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
  7. package/dist/runtime/AgUiThreadRuntimeCore.js +5 -3
  8. package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
  9. package/dist/runtime/adapter/conversions.d.ts +11 -11
  10. package/dist/runtime/adapter/conversions.d.ts.map +1 -1
  11. package/dist/runtime/adapter/conversions.js +114 -17
  12. package/dist/runtime/adapter/conversions.js.map +1 -1
  13. package/dist/runtime/adapter/run-aggregator.d.ts +9 -10
  14. package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
  15. package/dist/runtime/adapter/subscriber.d.ts +2 -3
  16. package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
  17. package/dist/runtime/adapter/tool-approval.d.ts +4 -5
  18. package/dist/runtime/adapter/tool-approval.d.ts.map +1 -1
  19. package/dist/runtime/event-parser.d.ts +2 -3
  20. package/dist/runtime/event-parser.d.ts.map +1 -1
  21. package/dist/runtime/interrupt-internals.d.ts +3 -4
  22. package/dist/runtime/interrupt-internals.d.ts.map +1 -1
  23. package/dist/runtime/logger.d.ts +2 -3
  24. package/dist/runtime/logger.d.ts.map +1 -1
  25. package/dist/runtime/mcp-tool-result.d.ts +3 -4
  26. package/dist/runtime/mcp-tool-result.d.ts.map +1 -1
  27. package/dist/runtime/types.d.ts +11 -12
  28. package/dist/runtime/types.d.ts.map +1 -1
  29. package/dist/useAgUiRuntime.d.ts +2 -3
  30. package/dist/useAgUiRuntime.d.ts.map +1 -1
  31. package/package.json +12 -11
  32. package/src/runtime/AgUiThreadRuntimeCore.ts +10 -1
  33. package/src/runtime/adapter/conversions.ts +200 -26
@@ -110,8 +110,7 @@ type SubscriberOptions = {
110
110
  logger?: Logger;
111
111
  onRunFailed?: (error: Error) => void;
112
112
  };
113
- declare const createAgUiSubscriber: (options: SubscriberOptions) => Subscriber;
114
- type AgUiSubscriber = ReturnType<typeof createAgUiSubscriber>;
113
+ export declare const createAgUiSubscriber: (options: SubscriberOptions) => Subscriber;
114
+ export type AgUiSubscriber = ReturnType<typeof createAgUiSubscriber>;
115
115
  //#endregion
116
- export { AgUiSubscriber, createAgUiSubscriber };
117
116
  //# sourceMappingURL=subscriber.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subscriber.d.ts","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"mappings":";;;KAMK,YAAY,OAAO;KAEnB;EACH,WAAW;IAAW;;EACtB,2BAA2B;IAAW;;EACtC,6BAA6B;IAAW;;EACxC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,sBAAsB;IAAW;;EACjC,mCAAmC;IAAW;;EAC9C,qCAAqC;IAAW;;EAChD,iCAAiC;IAAW;;EAC5C,yBAAyB;IAAW;;EACpC,uBAAuB;IAAW;;EAClC,gCAAgC;IAAW;;EAC3C,kCAAkC;IAAW;;EAC7C,8BAA8B;IAAW;;EACzC,kCAAkC;IAAW;;EAC7C,wBAAwB;IAAW;;EACnC,uBAAuB;IAAW;;EAClC,sBAAsB;IAAW;;EACjC,wBAAwB;IAAW;;EACnC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,qBAAqB;IAAW;;EAChC,2BAA2B;IAAW;;EACtC,iBAAiB;IAAW;;EAC5B,cAAc;IAAW;;EACzB,0BAA0B;IAAW;;EACrC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,sBAAsB;IAAW;;EACjC,mBAAmB;IAAW;;EAC9B;EACA,eAAe;IAAW,OAAO;;;KAiC9B;EACH,UAAU;EACV;EACA,SAAS;EACT,eAAe,OAAO;;cAGX,uBACX,SAAS,sBACR;KAsHS,iBAAiB,kBAAkB"}
1
+ {"version":3,"file":"subscriber.d.ts","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"mappings":";;;KAMK,YAAY,OAAO;KAEnB;EACH,WAAW;IAAW;;EACtB,2BAA2B;IAAW;;EACtC,6BAA6B;IAAW;;EACxC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,sBAAsB;IAAW;;EACjC,mCAAmC;IAAW;;EAC9C,qCAAqC;IAAW;;EAChD,iCAAiC;IAAW;;EAC5C,yBAAyB;IAAW;;EACpC,uBAAuB;IAAW;;EAClC,gCAAgC;IAAW;;EAC3C,kCAAkC;IAAW;;EAC7C,8BAA8B;IAAW;;EACzC,kCAAkC;IAAW;;EAC7C,wBAAwB;IAAW;;EACnC,uBAAuB;IAAW;;EAClC,sBAAsB;IAAW;;EACjC,wBAAwB;IAAW;;EACnC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,qBAAqB;IAAW;;EAChC,2BAA2B;IAAW;;EACtC,iBAAiB;IAAW;;EAC5B,cAAc;IAAW;;EACzB,0BAA0B;IAAW;;EACrC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,sBAAsB;IAAW;;EACjC,mBAAmB;IAAW;;EAC9B;EACA,eAAe;IAAW,OAAO;;;KAiC9B;EACH,UAAU;EACV;EACA,SAAS;EACT,eAAe,OAAO;;qBAGX,uBACX,SAAS,sBACR;YAsHS,iBAAiB,kBAAkB"}
@@ -19,7 +19,7 @@ type ToolApproval = NonNullable<ToolCallMessagePart["approval"]>;
19
19
  * nested on ToolCallMessagePart.messages — so only a gate naming a call the
20
20
  * message renders nowhere leaves the batch bespoke.
21
21
  */
22
- declare const projectAgUiToolApprovals: (interrupts: readonly AgUiInterrupt[] | undefined, boundToolCallIds?: ReadonlySet<string>) => ReadonlyMap<string, ToolApproval>;
22
+ export declare const projectAgUiToolApprovals: (interrupts: readonly AgUiInterrupt[] | undefined, boundToolCallIds?: ReadonlySet<string>) => ReadonlyMap<string, ToolApproval>;
23
23
  /**
24
24
  * Records a decision on the gated tool call. The decision is held on the part
25
25
  * until every gate in the batch is answered, because AG-UI resumes a run with
@@ -28,7 +28,7 @@ declare const projectAgUiToolApprovals: (interrupts: readonly AgUiInterrupt[] |
28
28
  * options, and core rejects an `optionId` absent from them, so no option can
29
29
  * reach this seam.
30
30
  */
31
- declare const withToolApprovalDecision: (content: readonly ThreadAssistantMessagePart[], { approvalId, approved, reason }: RespondToToolApprovalOptions) => readonly ThreadAssistantMessagePart[];
31
+ export declare const withToolApprovalDecision: (content: readonly ThreadAssistantMessagePart[], { approvalId, approved, reason }: RespondToToolApprovalOptions) => readonly ThreadAssistantMessagePart[];
32
32
  /**
33
33
  * Maps the recorded decisions onto AG-UI resume entries, or `null` while the
34
34
  * batch is incomplete. A denial is a resolved response carrying
@@ -36,7 +36,7 @@ declare const withToolApprovalDecision: (content: readonly ThreadAssistantMessag
36
36
  * the interrupt without meaningful input and carries no payload, which would
37
37
  * drop the denial reason on the wire.
38
38
  */
39
- declare const buildToolApprovalResume: (content: readonly ThreadAssistantMessagePart[], interrupts: readonly AgUiInterrupt[]) => AgUiResumeEntry[] | null;
39
+ export declare const buildToolApprovalResume: (content: readonly ThreadAssistantMessagePart[], interrupts: readonly AgUiInterrupt[]) => AgUiResumeEntry[] | null;
40
40
  /**
41
41
  * Settles every gate the submitted resume array names, so the displayed outcome
42
42
  * cannot contradict the wire. A decision recorded locally is not exempt: a gate
@@ -52,7 +52,6 @@ declare const buildToolApprovalResume: (content: readonly ThreadAssistantMessage
52
52
  * first settlement instead would mean treating an unsent local decision as
53
53
  * terminal, which is exactly what the cancellation case must override.
54
54
  */
55
- declare const withSettledToolApprovals: (content: readonly ThreadAssistantMessagePart[], resume: readonly AgUiResumeEntry[]) => readonly ThreadAssistantMessagePart[];
55
+ export declare const withSettledToolApprovals: (content: readonly ThreadAssistantMessagePart[], resume: readonly AgUiResumeEntry[]) => readonly ThreadAssistantMessagePart[];
56
56
  //#endregion
57
- export { buildToolApprovalResume, projectAgUiToolApprovals, withSettledToolApprovals, withToolApprovalDecision };
58
57
  //# sourceMappingURL=tool-approval.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-approval.d.ts","names":[],"sources":["../../../src/runtime/adapter/tool-approval.ts"],"mappings":";;;KAgBK,eAAe,YAAY;;;;;;;;;;;;;;;;;;cA2LnB,2BACX,qBAAqB,6BACrB,mBAAmB,wBAClB,oBAAoB;;;;;;;;;cAgCV,2BACX,kBAAkB,gCAClB,YAAA,UAAA,UAAkC,0CACxB;;;;;;;;cAuBC,0BACX,kBAAkB,8BAClB,qBAAqB,oBACpB;;;;;;;;;;;;;;;;cAuFU,2BACX,kBAAkB,8BAClB,iBAAiB,+BACP"}
1
+ {"version":3,"file":"tool-approval.d.ts","names":[],"sources":["../../../src/runtime/adapter/tool-approval.ts"],"mappings":";;;KAgBK,eAAe,YAAY;;;;;;;;;;;;;;;;;;qBA2LnB,2BACX,qBAAqB,6BACrB,mBAAmB,wBAClB,oBAAoB;;;;;;;;;qBAgCV,2BACX,kBAAkB,gCAClB,YAAA,UAAA,UAAkC,0CACxB;;;;;;;;qBAuBC,0BACX,kBAAkB,8BAClB,qBAAqB,oBACpB;;;;;;;;;;;;;;;;qBAuFU,2BACX,kBAAkB,8BAClB,iBAAiB,+BACP"}
@@ -1,10 +1,9 @@
1
1
  import { Logger } from "./logger.js";
2
2
  import { AgUiEvent } from "./types.js";
3
3
  //#region src/runtime/event-parser.d.ts
4
- type ParseAgUiEventOptions = {
4
+ export type ParseAgUiEventOptions = {
5
5
  logger?: Logger;
6
6
  };
7
- declare const parseAgUiEvent: (event: unknown, options?: ParseAgUiEventOptions) => AgUiEvent | null;
7
+ export declare const parseAgUiEvent: (event: unknown, options?: ParseAgUiEventOptions) => AgUiEvent | null;
8
8
  //#endregion
9
- export { ParseAgUiEventOptions, parseAgUiEvent };
10
9
  //# sourceMappingURL=event-parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-parser.d.ts","names":[],"sources":["../../src/runtime/event-parser.ts"],"mappings":";;;KAUY;EACV,SAAS;;cAmHE,iBACX,gBACA,UAAU,0BACT"}
1
+ {"version":3,"file":"event-parser.d.ts","names":[],"sources":["../../src/runtime/event-parser.ts"],"mappings":";;;YAUY;EACV,SAAS;;qBAmHE,iBACX,gBACA,UAAU,0BACT"}
@@ -1,8 +1,7 @@
1
1
  import { AgUiInterrupt } from "./types.js";
2
2
  //#region src/runtime/interrupt-internals.d.ts
3
- declare const withRawResponseSchema: (interrupt: AgUiInterrupt, schema: unknown) => AgUiInterrupt;
4
- declare const readRawResponseSchema: (interrupt: AgUiInterrupt) => unknown;
5
- declare const withoutRawResponseSchema: <T extends AgUiInterrupt>(interrupt: T) => T;
3
+ export declare const withRawResponseSchema: (interrupt: AgUiInterrupt, schema: unknown) => AgUiInterrupt;
4
+ export declare const readRawResponseSchema: (interrupt: AgUiInterrupt) => unknown;
5
+ export declare const withoutRawResponseSchema: <T extends AgUiInterrupt>(interrupt: T) => T;
6
6
  //#endregion
7
- export { readRawResponseSchema, withRawResponseSchema, withoutRawResponseSchema };
8
7
  //# sourceMappingURL=interrupt-internals.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interrupt-internals.d.ts","names":[],"sources":["../../src/runtime/interrupt-internals.ts"],"mappings":";;cAca,wBACX,WAAW,eACX,oBACC;cAQU,wBAAyB,WAAW;cAGpC,2BAA4B,UAAU,eACjD,WAAW,MACV"}
1
+ {"version":3,"file":"interrupt-internals.d.ts","names":[],"sources":["../../src/runtime/interrupt-internals.ts"],"mappings":";;qBAca,wBACX,WAAW,eACX,oBACC;qBAQU,wBAAyB,WAAW;qBAGpC,2BAA4B,UAAU,eACjD,WAAW,MACV"}
@@ -1,9 +1,8 @@
1
1
  //#region src/runtime/logger.d.ts
2
- type Logger = {
2
+ export type Logger = {
3
3
  debug: (...a: any[]) => void;
4
4
  error: (...a: any[]) => void;
5
5
  };
6
- declare const makeLogger: (l?: Partial<Logger>) => Logger;
6
+ export declare const makeLogger: (l?: Partial<Logger>) => Logger;
7
7
  //#endregion
8
- export { Logger, makeLogger };
9
8
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","names":[],"sources":["../../src/runtime/logger.ts"],"mappings":";KAAY;EACV,WAAW;EACX,WAAW;;cAGA,aAAc,IAAI,QAAQ,YAAU"}
1
+ {"version":3,"file":"logger.d.ts","names":[],"sources":["../../src/runtime/logger.ts"],"mappings":";YAAY;EACV,WAAW;EACX,WAAW;;qBAGA,aAAc,IAAI,QAAQ,YAAU"}
@@ -1,12 +1,11 @@
1
1
  //#region src/runtime/mcp-tool-result.d.ts
2
- type McpToolCallResult = Record<string, unknown> & {
2
+ export type McpToolCallResult = Record<string, unknown> & {
3
3
  content: unknown[];
4
4
  structuredContent?: Record<string, unknown>;
5
5
  _meta?: Record<string, unknown>;
6
6
  isError?: boolean;
7
7
  };
8
- declare const parseMcpToolCallResult: (source: Record<string, unknown>, modelContent: string) => McpToolCallResult | undefined;
9
- declare const readMcpAppResourceUri: (meta: unknown) => string | undefined;
8
+ export declare const parseMcpToolCallResult: (source: Record<string, unknown>, modelContent: string) => McpToolCallResult | undefined;
9
+ export declare const readMcpAppResourceUri: (meta: unknown) => string | undefined;
10
10
  //#endregion
11
- export { McpToolCallResult, parseMcpToolCallResult, readMcpAppResourceUri };
12
11
  //# sourceMappingURL=mcp-tool-result.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-tool-result.d.ts","names":[],"sources":["../../src/runtime/mcp-tool-result.ts"],"mappings":";KAGY,oBAAoB;EAC9B;EACA,oBAAoB;EACpB,QAAQ;EACR;;cAGW,yBACX,QAAQ,yBACR,yBACC;cAkBU,wBAAyB"}
1
+ {"version":3,"file":"mcp-tool-result.d.ts","names":[],"sources":["../../src/runtime/mcp-tool-result.ts"],"mappings":";YAGY,oBAAoB;EAC9B;EACA,oBAAoB;EACpB,QAAQ;EACR;;qBAGW,yBACX,QAAQ,yBACR,yBACC;qBAkBU,wBAAyB"}
@@ -20,10 +20,10 @@ type SwitchToThreadResult = {
20
20
  */
21
21
  unstable_resume?: boolean;
22
22
  };
23
- type UseAgUiThreadListAdapter = Omit<ExternalStoreThreadListAdapter, "onSwitchToThread"> & {
23
+ export type UseAgUiThreadListAdapter = Omit<ExternalStoreThreadListAdapter, "onSwitchToThread"> & {
24
24
  onSwitchToThread?: ((threadId: string) => Promise<SwitchToThreadResult> | SwitchToThreadResult) | undefined;
25
25
  };
26
- type UseAgUiRuntimeAdapters = {
26
+ export type UseAgUiRuntimeAdapters = {
27
27
  attachments?: AttachmentAdapter;
28
28
  speech?: SpeechSynthesisAdapter;
29
29
  dictation?: DictationAdapter;
@@ -35,8 +35,8 @@ type UseAgUiRuntimeAdapters = {
35
35
  */
36
36
  threadList?: UseAgUiThreadListAdapter;
37
37
  };
38
- type AgUiResumeTranscript = "full" | "appended";
39
- type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
38
+ export type AgUiResumeTranscript = "full" | "appended";
39
+ export type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
40
40
  agent: AbstractAgent;
41
41
  logger?: Partial<Logger>;
42
42
  showThinking?: boolean;
@@ -86,8 +86,8 @@ type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
86
86
  onCancel?: () => void;
87
87
  adapters?: UseAgUiRuntimeAdapters;
88
88
  };
89
- type AgUiInterruptReason = "tool_call" | "input_required" | "confirmation" | (string & {});
90
- type AgUiInterrupt = {
89
+ export type AgUiInterruptReason = "tool_call" | "input_required" | "confirmation" | (string & {});
90
+ export type AgUiInterrupt = {
91
91
  id: string;
92
92
  reason: AgUiInterruptReason;
93
93
  message?: string;
@@ -96,12 +96,12 @@ type AgUiInterrupt = {
96
96
  expiresAt?: string;
97
97
  metadata?: Record<string, unknown>;
98
98
  };
99
- type AgUiResumeEntry = {
99
+ export type AgUiResumeEntry = {
100
100
  interruptId: string;
101
101
  status: "resolved" | "cancelled";
102
102
  payload?: unknown;
103
103
  };
104
- type AgUiRuntimeExtras = {
104
+ export type AgUiRuntimeExtras = {
105
105
  interrupts: readonly AgUiInterrupt[];
106
106
  sendA2uiAction: (action: Record<string, unknown>) => void;
107
107
  submitInterruptResponses: (responses: readonly AgUiResumeEntry[]) => Promise<void>;
@@ -109,19 +109,19 @@ type AgUiRuntimeExtras = {
109
109
  state: ReadonlyJSONValue | undefined;
110
110
  setState: (next: ReadonlyJSONValue | ((prev: ReadonlyJSONValue | undefined) => ReadonlyJSONValue)) => void;
111
111
  };
112
- type AgUiRunFinishedOutcome = {
112
+ export type AgUiRunFinishedOutcome = {
113
113
  type: "success";
114
114
  } | {
115
115
  type: "interrupt";
116
116
  interrupts: AgUiInterrupt[];
117
117
  };
118
- type AgUiSubagentFinishedOutcome = {
118
+ export type AgUiSubagentFinishedOutcome = {
119
119
  type: "success";
120
120
  } | {
121
121
  type: "suspended";
122
122
  interruptIds?: string[];
123
123
  };
124
- type AgUiEvent = {
124
+ export type AgUiEvent = {
125
125
  type: "RUN_STARTED";
126
126
  runId: string;
127
127
  } | {
@@ -266,5 +266,4 @@ type AgUiEvent = {
266
266
  code?: string;
267
267
  };
268
268
  //#endregion
269
- export { AgUiEvent, AgUiInterrupt, AgUiInterruptReason, AgUiResumeEntry, AgUiResumeTranscript, AgUiRunFinishedOutcome, AgUiRuntimeExtras, AgUiSubagentFinishedOutcome, UseAgUiRuntimeAdapters, UseAgUiRuntimeOptions, UseAgUiThreadListAdapter };
270
269
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/runtime/types.ts"],"mappings":";;;;;;;;;;;;KAuBK;EACH,mBAAmB;EACnB,QAAQ;;;;;;EAMR;;KAGU,2BAA2B,KACrC;EAGA,qBAEM,qBACG,QAAQ,wBAAwB;;KAI/B;EACV,cAAc;EACd,SAAS;EACT,YAAY;EACZ,QAAQ;EACR,WAAW;EACX,UAAU;;;;EAIV,aAAa;;KAGH;KAEA,wBAAwB;EAClC,OAAO;EACP,SAAS,QAAQ;EACjB;;;;;;;;;;;;;;;;;;;;;;;;EAwBA,mBAAmB;;;;;;;;;;;EAWnB;;;;;;;EAOA;EACA,WAAW,GAAG;EACd;EACA,WAAW;;KAGD;KAMA;EACV;EACA,QAAQ;EACR;EACA;EACA,iBAAiB;EACjB;EACA,WAAW;;KAGD;EACV;EACA;EACA;;KAGU;EACV,qBAAqB;EACrB,iBAAiB,QAAQ;EACzB,2BACE,oBAAoB,sBACjB;EACL,YACE,SAAS,qBACT,qBAAqB,sBAClB;EACL,OAAO;EACP,WACE,MACI,sBACE,MAAM,kCAAkC;;KAItC;EACN;;EACA;EAAmB,YAAY;;KAEzB;EACN;;EACA;EAAmB;;KAEb;EACN;EAAqB;;EAErB;EACA;EACA,UAAU;;EAEV;EAAuB;;EACvB;EAAmB;EAAkB;;EACrC;EAA4B;EAAoB;;EAEhD;EACA;EACA;EACA;;EAEA;EAA0B;EAAoB;;EAE9C;EACA;EACA;EACA;;EAEA;EAAwB;;EACxB;;EACA;EAAuC;;EACvC;;EACA;;EACA;EAAyB;EAAoB;;EAE7C;EACA;EACA;;EAGA;EACA;EACA;EACA;;EAGA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;;EAEA;EAAuB;EAAoB;;EAE3C;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;;EAEA;EAAuB;EAAoB;;EAE3C;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;;EAGA;EACA;EACA,SAAS;EACT;EACA;EACA;;EAEA;EAAa;EAAY;;EACzB;EAAgB;EAAc;;EAC9B;EAAwB;;EACxB;EAAqB;;EACrB;EAA2B;;EAE3B;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA,UAAU;;EAGV;EACA;EACA;EACA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/runtime/types.ts"],"mappings":";;;;;;;;;;;;KAuBK;EACH,mBAAmB;EACnB,QAAQ;;;;;;EAMR;;YAGU,2BAA2B,KACrC;EAGA,qBAEM,qBACG,QAAQ,wBAAwB;;YAI/B;EACV,cAAc;EACd,SAAS;EACT,YAAY;EACZ,QAAQ;EACR,WAAW;EACX,UAAU;;;;EAIV,aAAa;;YAGH;YAEA,wBAAwB;EAClC,OAAO;EACP,SAAS,QAAQ;EACjB;;;;;;;;;;;;;;;;;;;;;;;;EAwBA,mBAAmB;;;;;;;;;;;EAWnB;;;;;;;EAOA;EACA,WAAW,GAAG;EACd;EACA,WAAW;;YAGD;YAMA;EACV;EACA,QAAQ;EACR;EACA;EACA,iBAAiB;EACjB;EACA,WAAW;;YAGD;EACV;EACA;EACA;;YAGU;EACV,qBAAqB;EACrB,iBAAiB,QAAQ;EACzB,2BACE,oBAAoB,sBACjB;EACL,YACE,SAAS,qBACT,qBAAqB,sBAClB;EACL,OAAO;EACP,WACE,MACI,sBACE,MAAM,kCAAkC;;YAItC;EACN;;EACA;EAAmB,YAAY;;YAEzB;EACN;;EACA;EAAmB;;YAEb;EACN;EAAqB;;EAErB;EACA;EACA,UAAU;;EAEV;EAAuB;;EACvB;EAAmB;EAAkB;;EACrC;EAA4B;EAAoB;;EAEhD;EACA;EACA;EACA;;EAEA;EAA0B;EAAoB;;EAE9C;EACA;EACA;EACA;;EAEA;EAAwB;;EACxB;;EACA;EAAuC;;EACvC;;EACA;;EACA;EAAyB;EAAoB;;EAE7C;EACA;EACA;;EAGA;EACA;EACA;EACA;;EAGA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;;EAEA;EAAuB;EAAoB;;EAE3C;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;;EAEA;EAAuB;EAAoB;;EAE3C;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;;EAGA;EACA;EACA,SAAS;EACT;EACA;EACA;;EAEA;EAAa;EAAY;;EACzB;EAAgB;EAAc;;EAC9B;EAAwB;;EACxB;EAAqB;;EACrB;EAA2B;;EAE3B;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA,UAAU;;EAGV;EACA;EACA;EACA"}
@@ -1,7 +1,7 @@
1
1
  import { AgUiInterrupt, AgUiResumeEntry, UseAgUiRuntimeOptions } from "./runtime/types.js";
2
2
  import { AssistantRuntime } from "@assistant-ui/core";
3
3
  //#region src/useAgUiRuntime.d.ts
4
- type AgUiAssistantRuntime = AssistantRuntime & {
4
+ export type AgUiAssistantRuntime = AssistantRuntime & {
5
5
  /**
6
6
  * @deprecated Use the `useAgUiInterrupts()` hook instead. This method is kept
7
7
  * for backward compatibility and will be removed in a future major release.
@@ -14,7 +14,6 @@ type AgUiAssistantRuntime = AssistantRuntime & {
14
14
  */
15
15
  unstable_submitInterruptResponses: (responses: readonly AgUiResumeEntry[]) => Promise<void>;
16
16
  };
17
- declare function useAgUiRuntime(options: UseAgUiRuntimeOptions): AgUiAssistantRuntime;
17
+ export declare function useAgUiRuntime(options: UseAgUiRuntimeOptions): AgUiAssistantRuntime;
18
18
  //#endregion
19
- export { AgUiAssistantRuntime, useAgUiRuntime };
20
19
  //# sourceMappingURL=useAgUiRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAgUiRuntime.d.ts","names":[],"sources":["../src/useAgUiRuntime.ts"],"mappings":";;;KA0CY,uBAAuB;;;;;EAKjC,8CAA8C;;;;;;EAM9C,oCACE,oBAAoB,sBACjB;;iBAGS,eACd,SAAS,wBACR"}
1
+ {"version":3,"file":"useAgUiRuntime.d.ts","names":[],"sources":["../src/useAgUiRuntime.ts"],"mappings":";;;YA0CY,uBAAuB;;;;;EAKjC,8CAA8C;;;;;;EAM9C,oCACE,oBAAoB,sBACjB;;wBAGS,eACd,SAAS,wBACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-ag-ui",
3
- "version": "0.0.59",
3
+ "version": "0.0.60",
4
4
  "description": "AG-UI protocol adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "ag-ui",
@@ -30,10 +30,10 @@
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
32
  "@ag-ui/client": "^0.0.59",
33
- "@assistant-ui/core": "^0.3.18",
34
- "@assistant-ui/react-generative-ui": "^0.0.18",
35
- "@assistant-ui/store": "^0.3.13",
36
- "assistant-stream": "^0.3.42",
33
+ "@assistant-ui/core": "^0.3.20",
34
+ "@assistant-ui/react-generative-ui": "^0.0.19",
35
+ "@assistant-ui/store": "^0.3.14",
36
+ "assistant-stream": "^0.3.44",
37
37
  "fast-json-patch": "^3.1.1"
38
38
  },
39
39
  "peerDependencies": {
@@ -46,14 +46,14 @@
46
46
  }
47
47
  },
48
48
  "devDependencies": {
49
- "@assistant-ui/x-buildutils": "0.0.26",
50
- "@testing-library/dom": "^10.4.1",
49
+ "@assistant-ui/x-buildutils": "0.0.28",
50
+ "@testing-library/dom": "^10.4.2",
51
51
  "@testing-library/react": "^16.3.3",
52
- "@types/react": "^19.2.18",
52
+ "@types/react": "^19.3.0",
53
53
  "jsdom": "^30.0.1",
54
- "react": "^19.2.8",
55
- "vitest": "^4.1.11",
56
- "zod": "^4.5.4"
54
+ "react": "^19.3.0",
55
+ "vitest": "^5.0.1",
56
+ "zod": "^4.6.5"
57
57
  },
58
58
  "publishConfig": {
59
59
  "access": "public",
@@ -71,6 +71,7 @@
71
71
  "scripts": {
72
72
  "build": "aui-build",
73
73
  "test": "vitest run",
74
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
74
75
  "test:watch": "vitest"
75
76
  }
76
77
  }
@@ -871,11 +871,17 @@ export class AgUiThreadRuntimeCore {
871
871
  const { content } = mapToolCallPartsDeep(assistant.content, (part) => {
872
872
  if (part.toolCallId !== options.toolCallId) return part;
873
873
  matchedToolCall = true;
874
+ // artifact and modelContent are optional; only override when supplied
875
+ // so a later result that omits them keeps a stored value, and
876
+ // emitToolResult can forward the model-facing content to the agent.
874
877
  return {
875
878
  ...part,
876
879
  result: options.result,
877
- artifact: options.artifact,
878
880
  isError: options.isError,
881
+ ...(options.artifact !== undefined && { artifact: options.artifact }),
882
+ ...(options.modelContent !== undefined && {
883
+ modelContent: options.modelContent,
884
+ }),
879
885
  };
880
886
  });
881
887
  if (!matchedToolCall) return message;
@@ -1602,6 +1608,9 @@ export class AgUiThreadRuntimeCore {
1602
1608
  result: prior.result,
1603
1609
  ...(prior.artifact !== undefined ? { artifact: prior.artifact } : {}),
1604
1610
  ...(prior.isError !== undefined ? { isError: prior.isError } : {}),
1611
+ ...(prior.modelContent !== undefined
1612
+ ? { modelContent: prior.modelContent }
1613
+ : {}),
1605
1614
  };
1606
1615
  });
1607
1616
  return changed ? merged : next;
@@ -5,6 +5,7 @@ import { generateId } from "@assistant-ui/core";
5
5
  import type {
6
6
  ThreadMessageLike as CoreThreadMessageLike,
7
7
  PartProviderMetadata,
8
+ ReasoningMessagePart,
8
9
  ThreadMessage,
9
10
  ToolCallMessagePartMcpMetadata,
10
11
  ToolModelContentPart,
@@ -44,14 +45,14 @@ type AttachmentLike = {
44
45
  };
45
46
 
46
47
  type ThreadMessageLike = {
47
- id?: string;
48
+ id?: string | undefined;
48
49
  role: string;
49
50
  content: unknown;
50
51
  metadata?: unknown;
51
- name?: string;
52
- toolCallId?: string;
53
- error?: string;
54
- attachments?: readonly AttachmentLike[];
52
+ name?: string | undefined;
53
+ toolCallId?: string | undefined;
54
+ error?: string | undefined;
55
+ attachments?: readonly AttachmentLike[] | undefined;
55
56
  };
56
57
 
57
58
  type NormalizedThreadMessageLike = ThreadMessageLike & { id: string };
@@ -733,6 +734,112 @@ function attachA2uiSurfaces(
733
734
  return { ...message, content: [...preserved, ...a2uiParts] };
734
735
  }
735
736
 
737
+ // A tool call that arrives without a `parentMessageId` has no record to join, so
738
+ // the client opens one keyed by the call id. An assistant record whose own id is
739
+ // a call it carries is that container: an id the client invented for the call
740
+ // rather than a boundary an agent drew. The prose the run answers with lands in
741
+ // a record of its own, and nothing on the wire binds the two to the run that
742
+ // produced them.
743
+ function isSyntheticToolCallContainer(message: CoreThreadMessageLike): boolean {
744
+ if (message.role !== "assistant" || !Array.isArray(message.content))
745
+ return false;
746
+ let carriesOwnId = false;
747
+ for (const part of message.content) {
748
+ if (!isObject(part)) continue;
749
+ // The container is opened empty, so text on the record means an agent
750
+ // addressed it and the id is one it chose.
751
+ if (part.type === "text") return false;
752
+ if (
753
+ part.type === "tool-call" &&
754
+ getString(part, "toolCallId") === message.id
755
+ ) {
756
+ carriesOwnId = true;
757
+ }
758
+ }
759
+ return carriesOwnId;
760
+ }
761
+
762
+ function carriesText(message: CoreThreadMessageLike): boolean {
763
+ return (
764
+ Array.isArray(message.content) &&
765
+ message.content.some((part) => isObject(part) && part.type === "text")
766
+ );
767
+ }
768
+
769
+ // What the run put after the container folds onto it: another container for a
770
+ // parallel call, or the parts of the answer. A record carrying a tool call an
771
+ // agent addressed is a boundary of its own and keeps its message.
772
+ function foldsOntoToolCallContainer(message: CoreThreadMessageLike): boolean {
773
+ if (message.role !== "assistant" || !Array.isArray(message.content))
774
+ return false;
775
+ if (message.content.length === 0) return false;
776
+ return (
777
+ isSyntheticToolCallContainer(message) ||
778
+ !message.content.some((part) => isObject(part) && part.type === "tool-call")
779
+ );
780
+ }
781
+
782
+ function readCustomMetadata(metadata: unknown): Record<string, unknown> {
783
+ if (!isObject(metadata) || !isObject(metadata.custom)) return {};
784
+ return metadata.custom;
785
+ }
786
+
787
+ function readNamespacedMetadata(metadata: unknown): Record<string, unknown> {
788
+ const namespaced = readCustomMetadata(metadata)[AG_UI_METADATA_NAMESPACE];
789
+ return isObject(namespaced) ? namespaced : {};
790
+ }
791
+
792
+ function foldOntoToolCallContainer(
793
+ container: CoreThreadMessageLike,
794
+ message: CoreThreadMessageLike,
795
+ ): CoreThreadMessageLike {
796
+ const interrupts = [
797
+ ...(readPersistedInterrupts(container.metadata) ?? []),
798
+ ...(readPersistedInterrupts(message.metadata) ?? []),
799
+ ];
800
+ // An entry that rode the folded record sat ahead of content that now follows
801
+ // the container's calls, so it is replayed after the merged record and its
802
+ // tool results rather than ahead of a message that no longer starts there.
803
+ const opaqueReasoning = [
804
+ ...readOpaqueReasoning(container.metadata),
805
+ ...readOpaqueReasoning(message.metadata).map((entry) => ({
806
+ ...entry,
807
+ after: true,
808
+ })),
809
+ ];
810
+ const namespaced = {
811
+ ...readNamespacedMetadata(container.metadata),
812
+ ...readNamespacedMetadata(message.metadata),
813
+ ...(interrupts.length > 0 ? { interrupts } : {}),
814
+ ...(opaqueReasoning.length > 0 ? { opaqueReasoning } : {}),
815
+ } satisfies AgUiCustomMetadata & Record<string, unknown>;
816
+ const custom = {
817
+ ...readCustomMetadata(container.metadata),
818
+ ...readCustomMetadata(message.metadata),
819
+ ...(Object.keys(namespaced).length > 0
820
+ ? { [AG_UI_METADATA_NAMESPACE]: namespaced }
821
+ : {}),
822
+ };
823
+ const metadata = {
824
+ ...(isObject(container.metadata) ? container.metadata : {}),
825
+ ...(isObject(message.metadata) ? message.metadata : {}),
826
+ ...(Object.keys(custom).length > 0 ? { custom } : {}),
827
+ };
828
+ return {
829
+ ...container,
830
+ ...message,
831
+ // The container's id names a call rather than the turn, so the record the
832
+ // agent addressed its prose to wins: that is the id the next run has to
833
+ // carry for the agent to recognize the message it wrote.
834
+ id: carriesText(message) ? message.id : container.id,
835
+ content: [
836
+ ...(Array.isArray(container.content) ? container.content : []),
837
+ ...(Array.isArray(message.content) ? message.content : []),
838
+ ],
839
+ ...(Object.keys(metadata).length > 0 ? { metadata } : {}),
840
+ } as CoreThreadMessageLike;
841
+ }
842
+
736
843
  export type FromAgUiMessagesOptions = {
737
844
  /**
738
845
  * Whether to convert `reasoning` messages into visible reasoning parts.
@@ -754,6 +861,40 @@ export function fromAgUiMessages(
754
861
  // neighbouring message instead of being dropped. The anchor is the index the
755
862
  // next pushed message will occupy, which is where it sat on the wire.
756
863
  const opaqueReasoning: (AgUiOpaqueReasoning & { anchor: number })[] = [];
864
+ // A reasoning record belongs to the assistant record that follows it, which is
865
+ // the binding the export writes and the one the reference integrations read
866
+ // back. Holding it until that assistant arrives rebuilds the pair as the
867
+ // single message the live run produced.
868
+ const pendingReasoning: {
869
+ id: string | undefined;
870
+ part: ReasoningMessagePart;
871
+ }[] = [];
872
+
873
+ const flushPendingReasoning = () => {
874
+ for (const { id, part } of pendingReasoning) {
875
+ converted.push({
876
+ id: id ?? generateId(),
877
+ role: "assistant",
878
+ content: [part],
879
+ });
880
+ }
881
+ pendingReasoning.length = 0;
882
+ };
883
+
884
+ const withPendingReasoning = (
885
+ message: CoreThreadMessageLike,
886
+ ): CoreThreadMessageLike => {
887
+ if (pendingReasoning.length === 0) return message;
888
+ const parts = pendingReasoning.map(({ part }) => part);
889
+ pendingReasoning.length = 0;
890
+ return {
891
+ ...message,
892
+ content: [
893
+ ...parts,
894
+ ...(Array.isArray(message.content) ? message.content : []),
895
+ ],
896
+ };
897
+ };
757
898
 
758
899
  for (const rawMessage of messages) {
759
900
  if (!isObject(rawMessage)) continue;
@@ -761,6 +902,7 @@ export function fromAgUiMessages(
761
902
  if (!role) continue;
762
903
 
763
904
  if (role === "tool") {
905
+ flushPendingReasoning();
764
906
  const toolCallId = getToolCallId(rawMessage) ?? `tool-${generateId()}`;
765
907
  const toolMessageId = getString(rawMessage, "id");
766
908
  const modelContent = extractText(rawMessage.content);
@@ -872,6 +1014,11 @@ export function fromAgUiMessages(
872
1014
  const operations = activityContent?.["a2ui_operations"];
873
1015
  if (!Array.isArray(operations)) continue;
874
1016
 
1017
+ // A surface belongs to the turn that painted it, and held reasoning is a
1018
+ // nearer antecedent than the previous turn's assistant record, so it is
1019
+ // released here rather than folded past this record.
1020
+ flushPendingReasoning();
1021
+
875
1022
  let ownerIndex = -1;
876
1023
  for (let i = converted.length - 1; i >= 0; i--) {
877
1024
  const candidate = converted[i];
@@ -903,7 +1050,9 @@ export function fromAgUiMessages(
903
1050
  }
904
1051
 
905
1052
  if (role === "assistant") {
906
- converted.push(toAssistantSnapshotMessage(rawMessage));
1053
+ converted.push(
1054
+ withPendingReasoning(toAssistantSnapshotMessage(rawMessage)),
1055
+ );
907
1056
  continue;
908
1057
  }
909
1058
 
@@ -916,6 +1065,9 @@ export function fromAgUiMessages(
916
1065
  // accept the next run.
917
1066
  const opaqueId = getString(rawMessage, "id");
918
1067
  if (opaqueId?.trim() && encryptedValue?.trim()) {
1068
+ // The anchor counts materialized messages, so anything still held
1069
+ // takes its own slot rather than folding past this record.
1070
+ flushPendingReasoning();
919
1071
  opaqueReasoning.push({
920
1072
  id: opaqueId,
921
1073
  encryptedValue,
@@ -939,31 +1091,37 @@ export function fromAgUiMessages(
939
1091
  }
940
1092
  continue;
941
1093
  }
942
- converted.push({
943
- id: getString(rawMessage, "id") ?? generateId(),
944
- role: "assistant",
945
- content: [
946
- {
947
- type: "reasoning",
948
- text,
949
- ...(encryptedValue !== undefined
950
- ? {
951
- providerMetadata: {
952
- [AG_UI_METADATA_NAMESPACE]: { encryptedValue },
953
- },
954
- }
955
- : {}),
956
- },
957
- ],
1094
+ const rawReasoningId = getString(rawMessage, "id");
1095
+ // A blank id still wins over a synthesized one on export, which would put
1096
+ // an unaddressable record on the wire.
1097
+ const reasoningId = rawReasoningId?.trim() ? rawReasoningId : undefined;
1098
+ // The fold costs the record its own message id, so it rides the part
1099
+ // instead: the export re-emits each block under the id it arrived with.
1100
+ const meta = {
1101
+ ...(reasoningId !== undefined ? { reasoningId } : {}),
1102
+ ...(encryptedValue !== undefined ? { encryptedValue } : {}),
1103
+ };
1104
+ pendingReasoning.push({
1105
+ id: reasoningId,
1106
+ part: {
1107
+ type: "reasoning",
1108
+ text,
1109
+ ...(Object.keys(meta).length > 0
1110
+ ? { providerMetadata: { [AG_UI_METADATA_NAMESPACE]: meta } }
1111
+ : {}),
1112
+ },
958
1113
  });
959
1114
  continue;
960
1115
  }
961
1116
 
962
1117
  if (role === "user" || role === "system" || role === "developer") {
1118
+ flushPendingReasoning();
963
1119
  converted.push(toUserOrSystemSnapshotMessage(role, rawMessage));
964
1120
  }
965
1121
  }
966
1122
 
1123
+ flushPendingReasoning();
1124
+
967
1125
  for (const { anchor, ...entry } of opaqueReasoning) {
968
1126
  // Nothing followed it on the wire, so it trails the last message instead.
969
1127
  const trailing = anchor >= converted.length;
@@ -976,8 +1134,24 @@ export function fromAgUiMessages(
976
1134
  ]);
977
1135
  }
978
1136
 
979
- for (let i = 0; i < converted.length; i++) {
980
- const message = converted[i]!;
1137
+ // A turn that called a tool before answering sits on the wire as a container
1138
+ // and the records that follow it, which the live run renders as one message.
1139
+ const folded: CoreThreadMessageLike[] = [];
1140
+ for (const message of converted) {
1141
+ const previous = folded[folded.length - 1];
1142
+ if (
1143
+ previous !== undefined &&
1144
+ isSyntheticToolCallContainer(previous) &&
1145
+ foldsOntoToolCallContainer(message)
1146
+ ) {
1147
+ folded[folded.length - 1] = foldOntoToolCallContainer(previous, message);
1148
+ continue;
1149
+ }
1150
+ folded.push(message);
1151
+ }
1152
+
1153
+ for (let i = 0; i < folded.length; i++) {
1154
+ const message = folded[i]!;
981
1155
  if (message.role !== "assistant") continue;
982
1156
 
983
1157
  const hasInterrupt =
@@ -992,7 +1166,7 @@ export function fromAgUiMessages(
992
1166
  );
993
1167
 
994
1168
  if (hasInterrupt || hasPendingToolCall) {
995
- converted[i] = {
1169
+ folded[i] = {
996
1170
  ...message,
997
1171
  status: getAutoStatus(
998
1172
  false,
@@ -1005,7 +1179,7 @@ export function fromAgUiMessages(
1005
1179
  }
1006
1180
  }
1007
1181
 
1008
- return converted;
1182
+ return folded;
1009
1183
  }
1010
1184
 
1011
1185
  function convertAssistantMessage(