@assistant-ui/react 0.11.22 → 0.11.24

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 (29) hide show
  1. package/dist/client/types/Part.d.ts +2 -2
  2. package/dist/legacy-runtime/runtime/MessagePartRuntime.d.ts +2 -2
  3. package/dist/legacy-runtime/runtime/MessagePartRuntime.js.map +1 -1
  4. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.d.ts +4 -1
  5. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.d.ts.map +1 -1
  6. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js +15 -10
  7. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js.map +1 -1
  8. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts +1 -1
  9. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts.map +1 -1
  10. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.js +2 -2
  11. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.js.map +1 -1
  12. package/dist/model-context/frame/AssistantFrameProvider.js +2 -2
  13. package/dist/model-context/frame/AssistantFrameProvider.js.map +1 -1
  14. package/dist/primitives/thread/ThreadSuggestion.d.ts +35 -3
  15. package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
  16. package/dist/primitives/thread/ThreadSuggestion.js +17 -5
  17. package/dist/primitives/thread/ThreadSuggestion.js.map +1 -1
  18. package/dist/tests/setup.js +8 -8
  19. package/dist/tests/setup.js.map +1 -1
  20. package/dist/types/MessagePartTypes.d.ts +4 -1
  21. package/dist/types/MessagePartTypes.d.ts.map +1 -1
  22. package/package.json +2 -2
  23. package/src/client/types/Part.ts +2 -2
  24. package/src/legacy-runtime/runtime/MessagePartRuntime.ts +2 -2
  25. package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts +17 -12
  26. package/src/legacy-runtime/runtime-cores/external-store/auto-status.tsx +4 -4
  27. package/src/model-context/frame/AssistantFrameProvider.ts +2 -2
  28. package/src/primitives/thread/ThreadSuggestion.tsx +43 -5
  29. package/src/types/MessagePartTypes.ts +1 -1
@@ -14,8 +14,8 @@ export type MessagePartClientApi = {
14
14
  */
15
15
  addToolResult(result: any | ToolResponse<any>): void;
16
16
  /**
17
- * Resume an interrupted tool call with a payload.
18
- * This is useful when a tool has interrupted its execution and is waiting for user input.
17
+ * Resume a tool call that is waiting for human input with a payload.
18
+ * This is useful when a tool has requested human input and is waiting for a response.
19
19
  */
20
20
  resumeToolCall(payload: unknown): void;
21
21
  };
@@ -16,8 +16,8 @@ export type MessagePartRuntime = {
16
16
  */
17
17
  addToolResult(result: any | ToolResponse<any>): void;
18
18
  /**
19
- * Resume an interrupted tool call with a payload.
20
- * This is useful when a tool has interrupted its execution and is waiting for user input.
19
+ * Resume a tool call that is waiting for human input with a payload.
20
+ * This is useful when a tool has requested human input and is waiting for a response.
21
21
  */
22
22
  resumeToolCall(payload: unknown): void;
23
23
  readonly path: MessagePartRuntimePath;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/legacy-runtime/runtime/MessagePartRuntime.ts"],"sourcesContent":["import {\n ThreadAssistantMessagePart,\n ThreadUserMessagePart,\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"../../types/AssistantTypes\";\nimport { ThreadRuntimeCoreBinding } from \"./ThreadRuntime\";\nimport type { MessageStateBinding } from \"./RuntimeBindings\";\nimport { SubscribableWithState } from \"./subscribable/Subscribable\";\nimport { Unsubscribe } from \"../../types\";\nimport { MessagePartRuntimePath } from \"./RuntimePathTypes\";\nimport { ToolResponse } from \"assistant-stream\";\n\nexport type MessagePartState = (\n | ThreadUserMessagePart\n | ThreadAssistantMessagePart\n) & {\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n};\n\ntype MessagePartSnapshotBinding = SubscribableWithState<\n MessagePartState,\n MessagePartRuntimePath\n>;\n\nexport type MessagePartRuntime = {\n /**\n * Add tool result to a tool call message part that has no tool result yet.\n * This is useful when you are collecting a tool result via user input (\"human tool calls\").\n */\n addToolResult(result: any | ToolResponse<any>): void;\n\n /**\n * Resume an interrupted tool call with a payload.\n * This is useful when a tool has interrupted its execution and is waiting for user input.\n */\n resumeToolCall(payload: unknown): void;\n\n readonly path: MessagePartRuntimePath;\n getState(): MessagePartState;\n subscribe(callback: () => void): Unsubscribe;\n};\n\nexport class MessagePartRuntimeImpl implements MessagePartRuntime {\n public get path() {\n return this.contentBinding.path;\n }\n\n constructor(\n private contentBinding: MessagePartSnapshotBinding,\n private messageApi?: MessageStateBinding,\n private threadApi?: ThreadRuntimeCoreBinding,\n ) {\n this.__internal_bindMethods();\n }\n\n protected __internal_bindMethods() {\n this.addToolResult = this.addToolResult.bind(this);\n this.resumeToolCall = this.resumeToolCall.bind(this);\n this.getState = this.getState.bind(this);\n this.subscribe = this.subscribe.bind(this);\n }\n\n public getState() {\n return this.contentBinding.getState();\n }\n\n public addToolResult(result: any | ToolResponse<any>) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to add tool result to non-tool message part\");\n\n if (!this.messageApi)\n throw new Error(\n \"Message API is not available. This is likely a bug in assistant-ui.\",\n );\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const message = this.messageApi.getState();\n if (!message) throw new Error(\"Message is not available\");\n\n const toolName = state.toolName;\n const toolCallId = state.toolCallId;\n\n const response = ToolResponse.toResponse(result);\n this.threadApi.getState().addToolResult({\n messageId: message.id,\n toolName,\n toolCallId,\n result: response.result,\n artifact: response.artifact,\n isError: response.isError,\n });\n }\n\n public resumeToolCall(payload: unknown) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to resume tool call on non-tool message part\");\n\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const toolCallId = state.toolCallId;\n this.threadApi.getState().resumeToolCall({\n toolCallId,\n payload,\n });\n }\n\n public subscribe(callback: () => void) {\n return this.contentBinding.subscribe(callback);\n }\n}\n"],"mappings":";AAWA,SAAS,oBAAoB;AAgCtB,IAAM,yBAAN,MAA2D;AAAA,EAKhE,YACU,gBACA,YACA,WACR;AAHQ;AACA;AACA;AAER,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAVA,IAAW,OAAO;AAChB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAUU,yBAAyB;AACjC,SAAK,gBAAgB,KAAK,cAAc,KAAK,IAAI;AACjD,SAAK,iBAAiB,KAAK,eAAe,KAAK,IAAI;AACnD,SAAK,WAAW,KAAK,SAAS,KAAK,IAAI;AACvC,SAAK,YAAY,KAAK,UAAU,KAAK,IAAI;AAAA,EAC3C;AAAA,EAEO,WAAW;AAChB,WAAO,KAAK,eAAe,SAAS;AAAA,EACtC;AAAA,EAEO,cAAc,QAAiC;AACpD,UAAM,QAAQ,KAAK,eAAe,SAAS;AAC3C,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,+BAA+B;AAE3D,QAAI,MAAM,SAAS;AACjB,YAAM,IAAI,MAAM,mDAAmD;AAErE,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AACF,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,6BAA6B;AAElE,UAAM,UAAU,KAAK,WAAW,SAAS;AACzC,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,0BAA0B;AAExD,UAAM,WAAW,MAAM;AACvB,UAAM,aAAa,MAAM;AAEzB,UAAM,WAAW,aAAa,WAAW,MAAM;AAC/C,SAAK,UAAU,SAAS,EAAE,cAAc;AAAA,MACtC,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,UAAU,SAAS;AAAA,MACnB,SAAS,SAAS;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEO,eAAe,SAAkB;AACtC,UAAM,QAAQ,KAAK,eAAe,SAAS;AAC3C,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,+BAA+B;AAE3D,QAAI,MAAM,SAAS;AACjB,YAAM,IAAI,MAAM,oDAAoD;AAEtE,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,6BAA6B;AAElE,UAAM,aAAa,MAAM;AACzB,SAAK,UAAU,SAAS,EAAE,eAAe;AAAA,MACvC;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEO,UAAU,UAAsB;AACrC,WAAO,KAAK,eAAe,UAAU,QAAQ;AAAA,EAC/C;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/legacy-runtime/runtime/MessagePartRuntime.ts"],"sourcesContent":["import {\n ThreadAssistantMessagePart,\n ThreadUserMessagePart,\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"../../types/AssistantTypes\";\nimport { ThreadRuntimeCoreBinding } from \"./ThreadRuntime\";\nimport type { MessageStateBinding } from \"./RuntimeBindings\";\nimport { SubscribableWithState } from \"./subscribable/Subscribable\";\nimport { Unsubscribe } from \"../../types\";\nimport { MessagePartRuntimePath } from \"./RuntimePathTypes\";\nimport { ToolResponse } from \"assistant-stream\";\n\nexport type MessagePartState = (\n | ThreadUserMessagePart\n | ThreadAssistantMessagePart\n) & {\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n};\n\ntype MessagePartSnapshotBinding = SubscribableWithState<\n MessagePartState,\n MessagePartRuntimePath\n>;\n\nexport type MessagePartRuntime = {\n /**\n * Add tool result to a tool call message part that has no tool result yet.\n * This is useful when you are collecting a tool result via user input (\"human tool calls\").\n */\n addToolResult(result: any | ToolResponse<any>): void;\n\n /**\n * Resume a tool call that is waiting for human input with a payload.\n * This is useful when a tool has requested human input and is waiting for a response.\n */\n resumeToolCall(payload: unknown): void;\n\n readonly path: MessagePartRuntimePath;\n getState(): MessagePartState;\n subscribe(callback: () => void): Unsubscribe;\n};\n\nexport class MessagePartRuntimeImpl implements MessagePartRuntime {\n public get path() {\n return this.contentBinding.path;\n }\n\n constructor(\n private contentBinding: MessagePartSnapshotBinding,\n private messageApi?: MessageStateBinding,\n private threadApi?: ThreadRuntimeCoreBinding,\n ) {\n this.__internal_bindMethods();\n }\n\n protected __internal_bindMethods() {\n this.addToolResult = this.addToolResult.bind(this);\n this.resumeToolCall = this.resumeToolCall.bind(this);\n this.getState = this.getState.bind(this);\n this.subscribe = this.subscribe.bind(this);\n }\n\n public getState() {\n return this.contentBinding.getState();\n }\n\n public addToolResult(result: any | ToolResponse<any>) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to add tool result to non-tool message part\");\n\n if (!this.messageApi)\n throw new Error(\n \"Message API is not available. This is likely a bug in assistant-ui.\",\n );\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const message = this.messageApi.getState();\n if (!message) throw new Error(\"Message is not available\");\n\n const toolName = state.toolName;\n const toolCallId = state.toolCallId;\n\n const response = ToolResponse.toResponse(result);\n this.threadApi.getState().addToolResult({\n messageId: message.id,\n toolName,\n toolCallId,\n result: response.result,\n artifact: response.artifact,\n isError: response.isError,\n });\n }\n\n public resumeToolCall(payload: unknown) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to resume tool call on non-tool message part\");\n\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const toolCallId = state.toolCallId;\n this.threadApi.getState().resumeToolCall({\n toolCallId,\n payload,\n });\n }\n\n public subscribe(callback: () => void) {\n return this.contentBinding.subscribe(callback);\n }\n}\n"],"mappings":";AAWA,SAAS,oBAAoB;AAgCtB,IAAM,yBAAN,MAA2D;AAAA,EAKhE,YACU,gBACA,YACA,WACR;AAHQ;AACA;AACA;AAER,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAVA,IAAW,OAAO;AAChB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAUU,yBAAyB;AACjC,SAAK,gBAAgB,KAAK,cAAc,KAAK,IAAI;AACjD,SAAK,iBAAiB,KAAK,eAAe,KAAK,IAAI;AACnD,SAAK,WAAW,KAAK,SAAS,KAAK,IAAI;AACvC,SAAK,YAAY,KAAK,UAAU,KAAK,IAAI;AAAA,EAC3C;AAAA,EAEO,WAAW;AAChB,WAAO,KAAK,eAAe,SAAS;AAAA,EACtC;AAAA,EAEO,cAAc,QAAiC;AACpD,UAAM,QAAQ,KAAK,eAAe,SAAS;AAC3C,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,+BAA+B;AAE3D,QAAI,MAAM,SAAS;AACjB,YAAM,IAAI,MAAM,mDAAmD;AAErE,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AACF,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,6BAA6B;AAElE,UAAM,UAAU,KAAK,WAAW,SAAS;AACzC,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,0BAA0B;AAExD,UAAM,WAAW,MAAM;AACvB,UAAM,aAAa,MAAM;AAEzB,UAAM,WAAW,aAAa,WAAW,MAAM;AAC/C,SAAK,UAAU,SAAS,EAAE,cAAc;AAAA,MACtC,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,UAAU,SAAS;AAAA,MACnB,SAAS,SAAS;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEO,eAAe,SAAkB;AACtC,UAAM,QAAQ,KAAK,eAAe,SAAS;AAC3C,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,+BAA+B;AAE3D,QAAI,MAAM,SAAS;AACjB,YAAM,IAAI,MAAM,oDAAoD;AAEtE,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,6BAA6B;AAElE,UAAM,aAAa,MAAM;AACzB,SAAK,UAAU,SAAS,EAAE,eAAe;AAAA,MACvC;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEO,UAAU,UAAsB;AACrC,WAAO,KAAK,eAAe,UAAU,QAAQ;AAAA,EAC/C;AACF;","names":[]}
@@ -10,7 +10,10 @@ export type ToolExecutionStatus = {
10
10
  type: "executing";
11
11
  } | {
12
12
  type: "interrupt";
13
- payload: unknown;
13
+ payload: {
14
+ type: "human";
15
+ payload: unknown;
16
+ };
14
17
  };
15
18
  export declare function useToolInvocations({ state, getTools, onResult, setToolStatuses, }: UseToolInvocationsParams): {
16
19
  reset: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useToolInvocations.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,IAAI,EACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAejB,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,uBAAuB,CAAC;IAC/B,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACvD,eAAe,EAAE,CACf,OAAO,EACH,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,CAAC,CACC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,KACtC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,KAC1C,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5C,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB;;;yBAgLF,MAAM,WAAW,OAAO;EAehD"}
1
+ {"version":3,"file":"useToolInvocations.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,IAAI,EACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAejB,KAAK,wBAAwB,GAAG;IAC9B,KAAK,EAAE,uBAAuB,CAAC;IAC/B,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACvD,eAAe,EAAE,CACf,OAAO,EACH,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,CAAC,CACC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,KACtC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,KAC1C,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,CAAC;AAExE,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB;;;yBAmLF,MAAM,WAAW,OAAO;EAiBhD"}
@@ -23,7 +23,7 @@ function useToolInvocations({
23
23
  setToolStatuses
24
24
  }) {
25
25
  const lastToolStates = useRef({});
26
- const interruptedToolsRef = useRef(/* @__PURE__ */ new Map());
26
+ const humanInputRef = useRef(/* @__PURE__ */ new Map());
27
27
  const acRef = useRef(new AbortController());
28
28
  const [controller] = useState(() => {
29
29
  const [stream, controller2] = createAssistantStreamController();
@@ -32,16 +32,19 @@ function useToolInvocations({
32
32
  () => acRef.current?.signal ?? new AbortController().signal,
33
33
  (toolCallId, payload) => {
34
34
  return new Promise((resolve, reject) => {
35
- const previous = interruptedToolsRef.current.get(toolCallId);
35
+ const previous = humanInputRef.current.get(toolCallId);
36
36
  if (previous) {
37
37
  previous.reject(
38
- new Error("Interrupt was superseded by a new interrupt")
38
+ new Error("Human input request was superseded by a new request")
39
39
  );
40
40
  }
41
- interruptedToolsRef.current.set(toolCallId, { resolve, reject });
41
+ humanInputRef.current.set(toolCallId, { resolve, reject });
42
42
  setToolStatuses((prev) => ({
43
43
  ...prev,
44
- [toolCallId]: { type: "interrupt", payload }
44
+ [toolCallId]: {
45
+ type: "interrupt",
46
+ payload: { type: "human", payload }
47
+ }
45
48
  }));
46
49
  });
47
50
  }
@@ -143,10 +146,10 @@ function useToolInvocations({
143
146
  }
144
147
  }, [state, controller, onResult]);
145
148
  const abort = () => {
146
- interruptedToolsRef.current.forEach(({ reject }) => {
149
+ humanInputRef.current.forEach(({ reject }) => {
147
150
  reject(new Error("Tool execution aborted"));
148
151
  });
149
- interruptedToolsRef.current.clear();
152
+ humanInputRef.current.clear();
150
153
  setToolStatuses({});
151
154
  acRef.current.abort();
152
155
  acRef.current = new AbortController();
@@ -158,9 +161,9 @@ function useToolInvocations({
158
161
  },
159
162
  abort,
160
163
  resume: (toolCallId, payload) => {
161
- const handlers = interruptedToolsRef.current.get(toolCallId);
164
+ const handlers = humanInputRef.current.get(toolCallId);
162
165
  if (handlers) {
163
- interruptedToolsRef.current.delete(toolCallId);
166
+ humanInputRef.current.delete(toolCallId);
164
167
  setToolStatuses((prev) => {
165
168
  const next = { ...prev };
166
169
  delete next[toolCallId];
@@ -168,7 +171,9 @@ function useToolInvocations({
168
171
  });
169
172
  handlers.resolve(payload);
170
173
  } else {
171
- throw new Error(`Tool call ${toolCallId} is not interrupted`);
174
+ throw new Error(
175
+ `Tool call ${toolCallId} is not waiting for human input`
176
+ );
172
177
  }
173
178
  }
174
179
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n createAssistantStreamController,\n ToolCallStreamController,\n ToolResponse,\n unstable_toolResultStream,\n type Tool,\n} from \"assistant-stream\";\nimport type {\n AssistantTransportCommand,\n AssistantTransportState,\n} from \"./types\";\nimport {\n AssistantMetaTransformStream,\n type ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\nconst isArgsTextComplete = (argsText: string) => {\n try {\n JSON.parse(argsText);\n return true;\n } catch {\n return false;\n }\n};\n\ntype UseToolInvocationsParams = {\n state: AssistantTransportState;\n getTools: () => Record<string, Tool> | undefined;\n onResult: (command: AssistantTransportCommand) => void;\n setToolStatuses: (\n updater:\n | Record<string, ToolExecutionStatus>\n | ((\n prev: Record<string, ToolExecutionStatus>,\n ) => Record<string, ToolExecutionStatus>),\n ) => void;\n};\n\nexport type ToolExecutionStatus =\n | { type: \"executing\" }\n | { type: \"interrupt\"; payload: unknown };\n\nexport function useToolInvocations({\n state,\n getTools,\n onResult,\n setToolStatuses,\n}: UseToolInvocationsParams) {\n const lastToolStates = useRef<\n Record<\n string,\n {\n argsText: string;\n hasResult: boolean;\n controller: ToolCallStreamController;\n }\n >\n >({});\n\n const interruptedToolsRef = useRef<\n Map<\n string,\n {\n resolve: (payload: unknown) => void;\n reject: (reason: unknown) => void;\n }\n >\n >(new Map());\n\n const acRef = useRef<AbortController>(new AbortController());\n const [controller] = useState(() => {\n const [stream, controller] = createAssistantStreamController();\n const transform = unstable_toolResultStream(\n getTools,\n () => acRef.current?.signal ?? new AbortController().signal,\n (toolCallId: string, payload: unknown) => {\n return new Promise<unknown>((resolve, reject) => {\n // Reject previous interrupt if it exists\n const previous = interruptedToolsRef.current.get(toolCallId);\n if (previous) {\n previous.reject(\n new Error(\"Interrupt was superseded by a new interrupt\"),\n );\n }\n\n interruptedToolsRef.current.set(toolCallId, { resolve, reject });\n setToolStatuses((prev) => ({\n ...prev,\n [toolCallId]: { type: \"interrupt\", payload },\n }));\n });\n },\n );\n stream\n .pipeThrough(transform)\n .pipeThrough(new AssistantMetaTransformStream())\n .pipeTo(\n new WritableStream({\n write(chunk) {\n if (chunk.type === \"result\") {\n // the tool call result was already set by the backend\n if (lastToolStates.current[chunk.meta.toolCallId]?.hasResult)\n return;\n\n onResult({\n type: \"add-tool-result\",\n toolCallId: chunk.meta.toolCallId,\n toolName: chunk.meta.toolName,\n result: chunk.result,\n isError: chunk.isError,\n ...(chunk.artifact && { artifact: chunk.artifact }),\n });\n\n // Clear status when result is set\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[chunk.meta.toolCallId];\n return next;\n });\n }\n },\n }),\n );\n\n return controller;\n });\n\n const ignoredToolIds = useRef<Set<string>>(new Set());\n const isInititialState = useRef(true);\n\n useEffect(() => {\n if (isInititialState.current) {\n state.messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n ignoredToolIds.current.add(content.toolCallId);\n }\n });\n });\n isInititialState.current = false;\n } else {\n state.messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n if (ignoredToolIds.current.has(content.toolCallId)) {\n return;\n }\n let lastState = lastToolStates.current[content.toolCallId];\n if (!lastState) {\n const toolCallController = controller.addToolCallPart({\n toolName: content.toolName,\n toolCallId: content.toolCallId,\n });\n lastState = {\n argsText: \"\",\n hasResult: false,\n controller: toolCallController,\n };\n lastToolStates.current[content.toolCallId] = lastState;\n }\n\n if (content.argsText !== lastState.argsText) {\n if (!content.argsText.startsWith(lastState.argsText)) {\n throw new Error(\n `Tool call argsText can only be appended, not updated: ${content.argsText} does not start with ${lastState.argsText}`,\n );\n }\n\n const argsTextDelta = content.argsText.slice(\n lastState.argsText.length,\n );\n lastState.controller.argsText.append(argsTextDelta);\n\n if (isArgsTextComplete(content.argsText)) {\n lastState.controller.argsText.close();\n }\n\n lastToolStates.current[content.toolCallId] = {\n argsText: content.argsText,\n hasResult: lastState.hasResult,\n controller: lastState.controller,\n };\n }\n\n if (content.result !== undefined && !lastState.hasResult) {\n lastState.controller.setResponse(\n new ToolResponse({\n result: content.result as ReadonlyJSONValue,\n artifact: content.artifact as ReadonlyJSONValue | undefined,\n isError: content.isError,\n }),\n );\n lastState.controller.close();\n\n lastToolStates.current[content.toolCallId] = {\n hasResult: true,\n argsText: lastState.argsText,\n controller: lastState.controller,\n };\n }\n }\n });\n });\n }\n }, [state, controller, onResult]);\n\n const abort = () => {\n interruptedToolsRef.current.forEach(({ reject }) => {\n reject(new Error(\"Tool execution aborted\"));\n });\n interruptedToolsRef.current.clear();\n setToolStatuses({});\n\n acRef.current.abort();\n acRef.current = new AbortController();\n };\n\n return {\n reset: () => {\n abort();\n isInititialState.current = true;\n },\n abort,\n resume: (toolCallId: string, payload: unknown) => {\n const handlers = interruptedToolsRef.current.get(toolCallId);\n if (handlers) {\n interruptedToolsRef.current.delete(toolCallId);\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[toolCallId];\n return next;\n });\n handlers.resolve(payload);\n } else {\n throw new Error(`Tool call ${toolCallId} is not interrupted`);\n }\n },\n };\n}\n"],"mappings":"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","names":["controller"]}
1
+ {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n createAssistantStreamController,\n ToolCallStreamController,\n ToolResponse,\n unstable_toolResultStream,\n type Tool,\n} from \"assistant-stream\";\nimport type {\n AssistantTransportCommand,\n AssistantTransportState,\n} from \"./types\";\nimport {\n AssistantMetaTransformStream,\n type ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\nconst isArgsTextComplete = (argsText: string) => {\n try {\n JSON.parse(argsText);\n return true;\n } catch {\n return false;\n }\n};\n\ntype UseToolInvocationsParams = {\n state: AssistantTransportState;\n getTools: () => Record<string, Tool> | undefined;\n onResult: (command: AssistantTransportCommand) => void;\n setToolStatuses: (\n updater:\n | Record<string, ToolExecutionStatus>\n | ((\n prev: Record<string, ToolExecutionStatus>,\n ) => Record<string, ToolExecutionStatus>),\n ) => void;\n};\n\nexport type ToolExecutionStatus =\n | { type: \"executing\" }\n | { type: \"interrupt\"; payload: { type: \"human\"; payload: unknown } };\n\nexport function useToolInvocations({\n state,\n getTools,\n onResult,\n setToolStatuses,\n}: UseToolInvocationsParams) {\n const lastToolStates = useRef<\n Record<\n string,\n {\n argsText: string;\n hasResult: boolean;\n controller: ToolCallStreamController;\n }\n >\n >({});\n\n const humanInputRef = useRef<\n Map<\n string,\n {\n resolve: (payload: unknown) => void;\n reject: (reason: unknown) => void;\n }\n >\n >(new Map());\n\n const acRef = useRef<AbortController>(new AbortController());\n const [controller] = useState(() => {\n const [stream, controller] = createAssistantStreamController();\n const transform = unstable_toolResultStream(\n getTools,\n () => acRef.current?.signal ?? new AbortController().signal,\n (toolCallId: string, payload: unknown) => {\n return new Promise<unknown>((resolve, reject) => {\n // Reject previous human input request if it exists\n const previous = humanInputRef.current.get(toolCallId);\n if (previous) {\n previous.reject(\n new Error(\"Human input request was superseded by a new request\"),\n );\n }\n\n humanInputRef.current.set(toolCallId, { resolve, reject });\n setToolStatuses((prev) => ({\n ...prev,\n [toolCallId]: {\n type: \"interrupt\",\n payload: { type: \"human\", payload },\n },\n }));\n });\n },\n );\n stream\n .pipeThrough(transform)\n .pipeThrough(new AssistantMetaTransformStream())\n .pipeTo(\n new WritableStream({\n write(chunk) {\n if (chunk.type === \"result\") {\n // the tool call result was already set by the backend\n if (lastToolStates.current[chunk.meta.toolCallId]?.hasResult)\n return;\n\n onResult({\n type: \"add-tool-result\",\n toolCallId: chunk.meta.toolCallId,\n toolName: chunk.meta.toolName,\n result: chunk.result,\n isError: chunk.isError,\n ...(chunk.artifact && { artifact: chunk.artifact }),\n });\n\n // Clear status when result is set\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[chunk.meta.toolCallId];\n return next;\n });\n }\n },\n }),\n );\n\n return controller;\n });\n\n const ignoredToolIds = useRef<Set<string>>(new Set());\n const isInititialState = useRef(true);\n\n useEffect(() => {\n if (isInititialState.current) {\n state.messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n ignoredToolIds.current.add(content.toolCallId);\n }\n });\n });\n isInititialState.current = false;\n } else {\n state.messages.forEach((message) => {\n message.content.forEach((content) => {\n if (content.type === \"tool-call\") {\n if (ignoredToolIds.current.has(content.toolCallId)) {\n return;\n }\n let lastState = lastToolStates.current[content.toolCallId];\n if (!lastState) {\n const toolCallController = controller.addToolCallPart({\n toolName: content.toolName,\n toolCallId: content.toolCallId,\n });\n lastState = {\n argsText: \"\",\n hasResult: false,\n controller: toolCallController,\n };\n lastToolStates.current[content.toolCallId] = lastState;\n }\n\n if (content.argsText !== lastState.argsText) {\n if (!content.argsText.startsWith(lastState.argsText)) {\n throw new Error(\n `Tool call argsText can only be appended, not updated: ${content.argsText} does not start with ${lastState.argsText}`,\n );\n }\n\n const argsTextDelta = content.argsText.slice(\n lastState.argsText.length,\n );\n lastState.controller.argsText.append(argsTextDelta);\n\n if (isArgsTextComplete(content.argsText)) {\n lastState.controller.argsText.close();\n }\n\n lastToolStates.current[content.toolCallId] = {\n argsText: content.argsText,\n hasResult: lastState.hasResult,\n controller: lastState.controller,\n };\n }\n\n if (content.result !== undefined && !lastState.hasResult) {\n lastState.controller.setResponse(\n new ToolResponse({\n result: content.result as ReadonlyJSONValue,\n artifact: content.artifact as ReadonlyJSONValue | undefined,\n isError: content.isError,\n }),\n );\n lastState.controller.close();\n\n lastToolStates.current[content.toolCallId] = {\n hasResult: true,\n argsText: lastState.argsText,\n controller: lastState.controller,\n };\n }\n }\n });\n });\n }\n }, [state, controller, onResult]);\n\n const abort = () => {\n humanInputRef.current.forEach(({ reject }) => {\n reject(new Error(\"Tool execution aborted\"));\n });\n humanInputRef.current.clear();\n setToolStatuses({});\n\n acRef.current.abort();\n acRef.current = new AbortController();\n };\n\n return {\n reset: () => {\n abort();\n isInititialState.current = true;\n },\n abort,\n resume: (toolCallId: string, payload: unknown) => {\n const handlers = humanInputRef.current.get(toolCallId);\n if (handlers) {\n humanInputRef.current.delete(toolCallId);\n setToolStatuses((prev) => {\n const next = { ...prev };\n delete next[toolCallId];\n return next;\n });\n handlers.resolve(payload);\n } else {\n throw new Error(\n `Tool call ${toolCallId} is not waiting for human input`,\n );\n }\n },\n };\n}\n"],"mappings":"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","names":["controller"]}
@@ -1,6 +1,6 @@
1
1
  import { MessageStatus } from "../../../types";
2
2
  export declare const isAutoStatus: (status: MessageStatus) => boolean;
3
- export declare const getAutoStatus: (isLast: boolean, isRunning: boolean, hasSuspendedToolCalls: boolean, hasPendingToolCalls: boolean) => Readonly<{
3
+ export declare const getAutoStatus: (isLast: boolean, isRunning: boolean, hasInterruptedToolCalls: boolean, hasPendingToolCalls: boolean) => Readonly<{
4
4
  type: "running";
5
5
  }> | Readonly<{
6
6
  type: "complete";
@@ -1 +1 @@
1
- {"version":3,"file":"auto-status.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/external-store/auto-status.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAkB/C,eAAO,MAAM,YAAY,GAAI,QAAQ,aAAa,YACiB,CAAC;AAEpE,eAAO,MAAM,aAAa,GACxB,QAAQ,OAAO,EACf,WAAW,OAAO,EAClB,uBAAuB,OAAO,EAC9B,qBAAqB,OAAO;;;;;;;;;;;EAQA,CAAC"}
1
+ {"version":3,"file":"auto-status.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/external-store/auto-status.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAkB/C,eAAO,MAAM,YAAY,GAAI,QAAQ,aAAa,YACiB,CAAC;AAEpE,eAAO,MAAM,aAAa,GACxB,QAAQ,OAAO,EACf,WAAW,OAAO,EAClB,yBAAyB,OAAO,EAChC,qBAAqB,OAAO;;;;;;;;;;;EAQA,CAAC"}
@@ -8,12 +8,12 @@ var AUTO_STATUS_PENDING = Object.freeze({
8
8
  type: "requires-action",
9
9
  reason: "tool-calls"
10
10
  });
11
- var AUTO_STATUS_SUSPENDED = Object.freeze({
11
+ var AUTO_STATUS_INTERRUPT = Object.freeze({
12
12
  type: "requires-action",
13
13
  reason: "interrupt"
14
14
  });
15
15
  var isAutoStatus = (status) => status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;
16
- var getAutoStatus = (isLast, isRunning, hasSuspendedToolCalls, hasPendingToolCalls) => isLast && isRunning ? AUTO_STATUS_RUNNING : hasSuspendedToolCalls ? AUTO_STATUS_SUSPENDED : hasPendingToolCalls ? AUTO_STATUS_PENDING : AUTO_STATUS_COMPLETE;
16
+ var getAutoStatus = (isLast, isRunning, hasInterruptedToolCalls, hasPendingToolCalls) => isLast && isRunning ? AUTO_STATUS_RUNNING : hasInterruptedToolCalls ? AUTO_STATUS_INTERRUPT : hasPendingToolCalls ? AUTO_STATUS_PENDING : AUTO_STATUS_COMPLETE;
17
17
  export {
18
18
  getAutoStatus,
19
19
  isAutoStatus
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/external-store/auto-status.tsx"],"sourcesContent":["import { MessageStatus } from \"../../../types\";\n\nconst AUTO_STATUS_RUNNING = Object.freeze({ type: \"running\" });\nconst AUTO_STATUS_COMPLETE = Object.freeze({\n type: \"complete\",\n reason: \"unknown\",\n});\n\nconst AUTO_STATUS_PENDING = Object.freeze({\n type: \"requires-action\",\n reason: \"tool-calls\",\n});\n\nconst AUTO_STATUS_SUSPENDED = Object.freeze({\n type: \"requires-action\",\n reason: \"interrupt\",\n});\n\nexport const isAutoStatus = (status: MessageStatus) =>\n status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;\n\nexport const getAutoStatus = (\n isLast: boolean,\n isRunning: boolean,\n hasSuspendedToolCalls: boolean,\n hasPendingToolCalls: boolean,\n) =>\n isLast && isRunning\n ? AUTO_STATUS_RUNNING\n : hasSuspendedToolCalls\n ? AUTO_STATUS_SUSPENDED\n : hasPendingToolCalls\n ? AUTO_STATUS_PENDING\n : AUTO_STATUS_COMPLETE;\n"],"mappings":";AAEA,IAAM,sBAAsB,OAAO,OAAO,EAAE,MAAM,UAAU,CAAC;AAC7D,IAAM,uBAAuB,OAAO,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAED,IAAM,sBAAsB,OAAO,OAAO;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAED,IAAM,wBAAwB,OAAO,OAAO;AAAA,EAC1C,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAEM,IAAM,eAAe,CAAC,WAC3B,WAAW,uBAAuB,WAAW;AAExC,IAAM,gBAAgB,CAC3B,QACA,WACA,uBACA,wBAEA,UAAU,YACN,sBACA,wBACE,wBACA,sBACE,sBACA;","names":[]}
1
+ {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/external-store/auto-status.tsx"],"sourcesContent":["import { MessageStatus } from \"../../../types\";\n\nconst AUTO_STATUS_RUNNING = Object.freeze({ type: \"running\" });\nconst AUTO_STATUS_COMPLETE = Object.freeze({\n type: \"complete\",\n reason: \"unknown\",\n});\n\nconst AUTO_STATUS_PENDING = Object.freeze({\n type: \"requires-action\",\n reason: \"tool-calls\",\n});\n\nconst AUTO_STATUS_INTERRUPT = Object.freeze({\n type: \"requires-action\",\n reason: \"interrupt\",\n});\n\nexport const isAutoStatus = (status: MessageStatus) =>\n status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;\n\nexport const getAutoStatus = (\n isLast: boolean,\n isRunning: boolean,\n hasInterruptedToolCalls: boolean,\n hasPendingToolCalls: boolean,\n) =>\n isLast && isRunning\n ? AUTO_STATUS_RUNNING\n : hasInterruptedToolCalls\n ? AUTO_STATUS_INTERRUPT\n : hasPendingToolCalls\n ? AUTO_STATUS_PENDING\n : AUTO_STATUS_COMPLETE;\n"],"mappings":";AAEA,IAAM,sBAAsB,OAAO,OAAO,EAAE,MAAM,UAAU,CAAC;AAC7D,IAAM,uBAAuB,OAAO,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAED,IAAM,sBAAsB,OAAO,OAAO;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAED,IAAM,wBAAwB,OAAO,OAAO;AAAA,EAC1C,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAEM,IAAM,eAAe,CAAC,WAC3B,WAAW,uBAAuB,WAAW;AAExC,IAAM,gBAAgB,CAC3B,QACA,WACA,yBACA,wBAEA,UAAU,YACN,sBACA,0BACE,wBACA,sBACE,sBACA;","names":[]}
@@ -67,9 +67,9 @@ var AssistantFrameProvider = class _AssistantFrameProvider {
67
67
  result = tool.execute ? await tool.execute(message.args, {
68
68
  toolCallId: message.id,
69
69
  abortSignal: new AbortController().signal,
70
- interrupt: async () => {
70
+ human: async () => {
71
71
  throw new Error(
72
- "Tool interrupt is not supported in frame context"
72
+ "Tool human input is not supported in frame context"
73
73
  );
74
74
  }
75
75
  }) : void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/model-context/frame/AssistantFrameProvider.ts"],"sourcesContent":["import {\n ModelContextProvider,\n ModelContext,\n} from \"../../model-context/ModelContextTypes\";\nimport { Unsubscribe } from \"../../types/Unsubscribe\";\nimport { Tool } from \"assistant-stream\";\nimport { z } from \"zod\";\nimport {\n FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n SerializedModelContext,\n SerializedTool,\n} from \"./AssistantFrameTypes\";\n\n/**\n * Converts tools to JSON Schema format for serialization\n */\nconst serializeTool = (tool: Tool<any, any>): SerializedTool => ({\n ...(tool.description && { description: tool.description }),\n parameters:\n tool.parameters instanceof z.ZodType\n ? ((z as any).toJSONSchema?.(tool.parameters) ?? tool.parameters)\n : tool.parameters,\n ...(tool.disabled !== undefined && { disabled: tool.disabled }),\n ...(tool.type && { type: tool.type }),\n});\n\n/**\n * Serializes a ModelContext for transmission across iframe boundary\n */\nconst serializeModelContext = (\n context: ModelContext,\n): SerializedModelContext => ({\n ...(context.system !== undefined && { system: context.system }),\n ...(context.tools && {\n tools: Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n serializeTool(tool),\n ]),\n ),\n }),\n});\n\n/**\n * AssistantFrameProvider - Runs inside an iframe and provides ModelContextProviders\n * to the parent window's AssistantFrameHost.\n *\n * Usage example:\n * ```typescript\n * // Inside the iframe\n * // Add model context providers\n * const registry = new ModelContextRegistry();\n * AssistantFrameProvider.addModelContextProvider(registry);\n *\n * // Add tools to registry\n * registry.addTool({\n * toolName: \"search\",\n * description: \"Search the web\",\n * parameters: z.object({ query: z.string() }),\n * execute: async (args) => {\n * // Tool implementation runs in iframe\n * return { results: [\"...\"] };\n * }\n * });\n * ```\n */\nexport class AssistantFrameProvider {\n private static _instance: AssistantFrameProvider | null = null;\n\n private _providers = new Set<ModelContextProvider>();\n private _providerUnsubscribes = new Map<\n ModelContextProvider,\n Unsubscribe | undefined\n >();\n private _targetOrigin: string;\n\n private constructor(targetOrigin: string = \"*\") {\n this._targetOrigin = targetOrigin;\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n // Send initial update on initialization\n setTimeout(() => this.broadcastUpdate(), 0);\n }\n\n private static getInstance(targetOrigin?: string): AssistantFrameProvider {\n if (!AssistantFrameProvider._instance) {\n AssistantFrameProvider._instance = new AssistantFrameProvider(\n targetOrigin,\n );\n }\n return AssistantFrameProvider._instance;\n }\n\n private handleMessage(event: MessageEvent) {\n // Security: Validate origin if specified\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-request\":\n // Respond with current context\n this.sendMessage(event, {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n });\n break;\n\n case \"tool-call\":\n this.handleToolCall(message, event);\n break;\n }\n }\n\n private async handleToolCall(\n message: Extract<FrameMessage, { type: \"tool-call\" }>,\n event: MessageEvent,\n ) {\n const tool = this.getModelContext().tools?.[message.toolName];\n\n let result: any;\n let error: string | undefined;\n\n if (!tool) {\n error = `Tool \"${message.toolName}\" not found`;\n } else {\n try {\n result = tool.execute\n ? await tool.execute(message.args, {\n toolCallId: message.id,\n abortSignal: new AbortController().signal,\n interrupt: async () => {\n throw new Error(\n \"Tool interrupt is not supported in frame context\",\n );\n },\n })\n : undefined;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n ...(error ? { error } : { result }),\n });\n }\n\n private sendMessage(event: MessageEvent, message: FrameMessage) {\n event.source?.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n { targetOrigin: event.origin },\n );\n }\n\n private getModelContext(): ModelContext {\n const contexts = Array.from(this._providers).map((p) =>\n p.getModelContext(),\n );\n\n return contexts.reduce(\n (merged, context) => ({\n system: context.system\n ? merged.system\n ? `${merged.system}\\n\\n${context.system}`\n : context.system\n : merged.system,\n tools: { ...(merged.tools || {}), ...(context.tools || {}) },\n }),\n {} as ModelContext,\n );\n }\n\n private broadcastUpdate() {\n // Always broadcast to parent window\n if (window.parent && window.parent !== window) {\n const updateMessage: FrameMessage = {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n };\n\n window.parent.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message: updateMessage },\n this._targetOrigin,\n );\n }\n }\n\n static addModelContextProvider(\n provider: ModelContextProvider,\n targetOrigin?: string,\n ): Unsubscribe {\n const instance = AssistantFrameProvider.getInstance(targetOrigin);\n instance._providers.add(provider);\n\n const unsubscribe = provider.subscribe?.(() => instance.broadcastUpdate());\n if (unsubscribe) {\n instance._providerUnsubscribes.set(provider, unsubscribe);\n }\n\n instance.broadcastUpdate();\n\n return () => {\n instance._providers.delete(provider);\n instance._providerUnsubscribes.get(provider)?.();\n instance._providerUnsubscribes.delete(provider);\n instance.broadcastUpdate();\n };\n }\n\n static dispose() {\n if (AssistantFrameProvider._instance) {\n const instance = AssistantFrameProvider._instance;\n window.removeEventListener(\"message\", instance.handleMessage);\n\n // Unsubscribe from all providers\n instance._providerUnsubscribes.forEach((unsubscribe) => unsubscribe?.());\n instance._providerUnsubscribes.clear();\n instance._providers.clear();\n\n AssistantFrameProvider._instance = null;\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/model-context/frame/AssistantFrameProvider.ts"],"sourcesContent":["import {\n ModelContextProvider,\n ModelContext,\n} from \"../../model-context/ModelContextTypes\";\nimport { Unsubscribe } from \"../../types/Unsubscribe\";\nimport { Tool } from \"assistant-stream\";\nimport { z } from \"zod\";\nimport {\n FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n SerializedModelContext,\n SerializedTool,\n} from \"./AssistantFrameTypes\";\n\n/**\n * Converts tools to JSON Schema format for serialization\n */\nconst serializeTool = (tool: Tool<any, any>): SerializedTool => ({\n ...(tool.description && { description: tool.description }),\n parameters:\n tool.parameters instanceof z.ZodType\n ? ((z as any).toJSONSchema?.(tool.parameters) ?? tool.parameters)\n : tool.parameters,\n ...(tool.disabled !== undefined && { disabled: tool.disabled }),\n ...(tool.type && { type: tool.type }),\n});\n\n/**\n * Serializes a ModelContext for transmission across iframe boundary\n */\nconst serializeModelContext = (\n context: ModelContext,\n): SerializedModelContext => ({\n ...(context.system !== undefined && { system: context.system }),\n ...(context.tools && {\n tools: Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n serializeTool(tool),\n ]),\n ),\n }),\n});\n\n/**\n * AssistantFrameProvider - Runs inside an iframe and provides ModelContextProviders\n * to the parent window's AssistantFrameHost.\n *\n * Usage example:\n * ```typescript\n * // Inside the iframe\n * // Add model context providers\n * const registry = new ModelContextRegistry();\n * AssistantFrameProvider.addModelContextProvider(registry);\n *\n * // Add tools to registry\n * registry.addTool({\n * toolName: \"search\",\n * description: \"Search the web\",\n * parameters: z.object({ query: z.string() }),\n * execute: async (args) => {\n * // Tool implementation runs in iframe\n * return { results: [\"...\"] };\n * }\n * });\n * ```\n */\nexport class AssistantFrameProvider {\n private static _instance: AssistantFrameProvider | null = null;\n\n private _providers = new Set<ModelContextProvider>();\n private _providerUnsubscribes = new Map<\n ModelContextProvider,\n Unsubscribe | undefined\n >();\n private _targetOrigin: string;\n\n private constructor(targetOrigin: string = \"*\") {\n this._targetOrigin = targetOrigin;\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n // Send initial update on initialization\n setTimeout(() => this.broadcastUpdate(), 0);\n }\n\n private static getInstance(targetOrigin?: string): AssistantFrameProvider {\n if (!AssistantFrameProvider._instance) {\n AssistantFrameProvider._instance = new AssistantFrameProvider(\n targetOrigin,\n );\n }\n return AssistantFrameProvider._instance;\n }\n\n private handleMessage(event: MessageEvent) {\n // Security: Validate origin if specified\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-request\":\n // Respond with current context\n this.sendMessage(event, {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n });\n break;\n\n case \"tool-call\":\n this.handleToolCall(message, event);\n break;\n }\n }\n\n private async handleToolCall(\n message: Extract<FrameMessage, { type: \"tool-call\" }>,\n event: MessageEvent,\n ) {\n const tool = this.getModelContext().tools?.[message.toolName];\n\n let result: any;\n let error: string | undefined;\n\n if (!tool) {\n error = `Tool \"${message.toolName}\" not found`;\n } else {\n try {\n result = tool.execute\n ? await tool.execute(message.args, {\n toolCallId: message.id,\n abortSignal: new AbortController().signal,\n human: async () => {\n throw new Error(\n \"Tool human input is not supported in frame context\",\n );\n },\n })\n : undefined;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n ...(error ? { error } : { result }),\n });\n }\n\n private sendMessage(event: MessageEvent, message: FrameMessage) {\n event.source?.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n { targetOrigin: event.origin },\n );\n }\n\n private getModelContext(): ModelContext {\n const contexts = Array.from(this._providers).map((p) =>\n p.getModelContext(),\n );\n\n return contexts.reduce(\n (merged, context) => ({\n system: context.system\n ? merged.system\n ? `${merged.system}\\n\\n${context.system}`\n : context.system\n : merged.system,\n tools: { ...(merged.tools || {}), ...(context.tools || {}) },\n }),\n {} as ModelContext,\n );\n }\n\n private broadcastUpdate() {\n // Always broadcast to parent window\n if (window.parent && window.parent !== window) {\n const updateMessage: FrameMessage = {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n };\n\n window.parent.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message: updateMessage },\n this._targetOrigin,\n );\n }\n }\n\n static addModelContextProvider(\n provider: ModelContextProvider,\n targetOrigin?: string,\n ): Unsubscribe {\n const instance = AssistantFrameProvider.getInstance(targetOrigin);\n instance._providers.add(provider);\n\n const unsubscribe = provider.subscribe?.(() => instance.broadcastUpdate());\n if (unsubscribe) {\n instance._providerUnsubscribes.set(provider, unsubscribe);\n }\n\n instance.broadcastUpdate();\n\n return () => {\n instance._providers.delete(provider);\n instance._providerUnsubscribes.get(provider)?.();\n instance._providerUnsubscribes.delete(provider);\n instance.broadcastUpdate();\n };\n }\n\n static dispose() {\n if (AssistantFrameProvider._instance) {\n const instance = AssistantFrameProvider._instance;\n window.removeEventListener(\"message\", instance.handleMessage);\n\n // Unsubscribe from all providers\n instance._providerUnsubscribes.forEach((unsubscribe) => unsubscribe?.());\n instance._providerUnsubscribes.clear();\n instance._providers.clear();\n\n AssistantFrameProvider._instance = null;\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,8 +1,24 @@
1
1
  import { ActionButtonElement, ActionButtonProps } from "../../utils/createActionButton";
2
- declare const useThreadSuggestion: ({ prompt, autoSend, }: {
2
+ declare const useThreadSuggestion: ({ prompt, send, clearComposer, autoSend, method: _method, }: {
3
+ /** The suggestion prompt. */
3
4
  prompt: string;
4
- method?: "replace";
5
+ /**
6
+ * When true, automatically sends the message.
7
+ * When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`.
8
+ */
9
+ send?: boolean | undefined;
10
+ /**
11
+ * Whether to clear the composer after sending.
12
+ * When send is set to false, determines if composer text is replaced with suggestion (true, default),
13
+ * or if it's appended to the composer text (false).
14
+ *
15
+ * @default true
16
+ */
17
+ clearComposer?: boolean | undefined;
18
+ /** @deprecated Use `send` instead. */
5
19
  autoSend?: boolean | undefined;
20
+ /** @deprecated Use `clearComposer` instead. */
21
+ method?: "replace";
6
22
  }) => (() => void) | null;
7
23
  export declare namespace ThreadPrimitiveSuggestion {
8
24
  type Element = ActionButtonElement;
@@ -11,9 +27,25 @@ export declare namespace ThreadPrimitiveSuggestion {
11
27
  export declare const ThreadPrimitiveSuggestion: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement> & {
12
28
  asChild?: boolean;
13
29
  }, "ref"> & {
30
+ /** The suggestion prompt. */
14
31
  prompt: string;
15
- method?: "replace";
32
+ /**
33
+ * When true, automatically sends the message.
34
+ * When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`.
35
+ */
36
+ send?: boolean | undefined;
37
+ /**
38
+ * Whether to clear the composer after sending.
39
+ * When send is set to false, determines if composer text is replaced with suggestion (true, default),
40
+ * or if it's appended to the composer text (false).
41
+ *
42
+ * @default true
43
+ */
44
+ clearComposer?: boolean | undefined;
45
+ /** @deprecated Use `send` instead. */
16
46
  autoSend?: boolean | undefined;
47
+ /** @deprecated Use `clearComposer` instead. */
48
+ method?: "replace";
17
49
  } & import("react").RefAttributes<HTMLButtonElement>>;
18
50
  export {};
19
51
  //# sourceMappingURL=ThreadSuggestion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadSuggestion.d.ts","sourceRoot":"","sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AAIxC,QAAA,MAAM,mBAAmB,GAAI,uBAG1B;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,wBAeA,CAAC;AAEF,yBAAiB,yBAAyB,CAAC;IACzC,KAAY,OAAO,GAAG,mBAAmB,CAAC;IAC1C,KAAY,KAAK,GAAG,iBAAiB,CAAC,OAAO,mBAAmB,CAAC,CAAC;CACnE;AAED,eAAO,MAAM,yBAAyB;;;YAzB5B,MAAM;aACL,SAAS;eACP,OAAO,GAAG,SAAS;qDA2B/B,CAAC"}
1
+ {"version":3,"file":"ThreadSuggestion.d.ts","sourceRoot":"","sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AAIxC,QAAA,MAAM,mBAAmB,GAAI,6DAM1B;IACD,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE3B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAEpC,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE/B,+CAA+C;IAC/C,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,wBA8BA,CAAC;AAEF,yBAAiB,yBAAyB,CAAC;IACzC,KAAY,OAAO,GAAG,mBAAmB,CAAC;IAC1C,KAAY,KAAK,GAAG,iBAAiB,CAAC,OAAO,mBAAmB,CAAC,CAAC;CACnE;AAED,eAAO,MAAM,yBAAyB;;;IA5DpC,6BAA6B;YACrB,MAAM;IAEd;;;OAGG;WACI,OAAO,GAAG,SAAS;IAE1B;;;;;;OAMG;oBACa,OAAO,GAAG,SAAS;IAEnC,sCAAsC;eAC3B,OAAO,GAAG,SAAS;IAE9B,+CAA+C;aACtC,SAAS;qDA0CnB,CAAC"}
@@ -8,25 +8,37 @@ import { useCallback } from "react";
8
8
  import { useAssistantState, useAssistantApi } from "../../context/index.js";
9
9
  var useThreadSuggestion = ({
10
10
  prompt,
11
- autoSend
11
+ send,
12
+ clearComposer = true,
13
+ autoSend,
14
+ method: _method
12
15
  }) => {
13
16
  const api = useAssistantApi();
14
17
  const disabled = useAssistantState(({ thread }) => thread.isDisabled);
18
+ const resolvedSend = send ?? autoSend ?? false;
15
19
  const callback = useCallback(() => {
16
20
  const isRunning = api.thread().getState().isRunning;
17
- if (autoSend && !isRunning) {
21
+ if (resolvedSend && !isRunning) {
18
22
  api.thread().append(prompt);
23
+ if (clearComposer) {
24
+ api.composer().setText("");
25
+ }
19
26
  } else {
20
- api.composer().setText(prompt);
27
+ if (clearComposer) {
28
+ api.composer().setText(prompt);
29
+ } else {
30
+ const currentText = api.composer().getState().text;
31
+ api.composer().setText(currentText.trim() ? `${currentText} ${prompt}` : prompt);
32
+ }
21
33
  }
22
- }, [api, autoSend, prompt]);
34
+ }, [api, resolvedSend, clearComposer, prompt]);
23
35
  if (disabled) return null;
24
36
  return callback;
25
37
  };
26
38
  var ThreadPrimitiveSuggestion = createActionButton(
27
39
  "ThreadPrimitive.Suggestion",
28
40
  useThreadSuggestion,
29
- ["prompt", "autoSend", "method"]
41
+ ["prompt", "send", "clearComposer", "autoSend", "method"]
30
42
  );
31
43
  export {
32
44
  ThreadPrimitiveSuggestion
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ActionButtonElement,\n ActionButtonProps,\n createActionButton,\n} from \"../../utils/createActionButton\";\nimport { useCallback } from \"react\";\nimport { useAssistantState, useAssistantApi } from \"../../context\";\n\nconst useThreadSuggestion = ({\n prompt,\n autoSend,\n}: {\n prompt: string;\n method?: \"replace\";\n autoSend?: boolean | undefined;\n}) => {\n const api = useAssistantApi();\n const disabled = useAssistantState(({ thread }) => thread.isDisabled);\n\n const callback = useCallback(() => {\n const isRunning = api.thread().getState().isRunning;\n if (autoSend && !isRunning) {\n api.thread().append(prompt);\n } else {\n api.composer().setText(prompt);\n }\n }, [api, autoSend, prompt]);\n\n if (disabled) return null;\n return callback;\n};\n\nexport namespace ThreadPrimitiveSuggestion {\n export type Element = ActionButtonElement;\n export type Props = ActionButtonProps<typeof useThreadSuggestion>;\n}\n\nexport const ThreadPrimitiveSuggestion = createActionButton(\n \"ThreadPrimitive.Suggestion\",\n useThreadSuggestion,\n [\"prompt\", \"autoSend\", \"method\"],\n);\n"],"mappings":";;;AAEA;AAAA,EAGE;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB,uBAAuB;AAEnD,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AACF,MAIM;AACJ,QAAM,MAAM,gBAAgB;AAC5B,QAAM,WAAW,kBAAkB,CAAC,EAAE,OAAO,MAAM,OAAO,UAAU;AAEpE,QAAM,WAAW,YAAY,MAAM;AACjC,UAAM,YAAY,IAAI,OAAO,EAAE,SAAS,EAAE;AAC1C,QAAI,YAAY,CAAC,WAAW;AAC1B,UAAI,OAAO,EAAE,OAAO,MAAM;AAAA,IAC5B,OAAO;AACL,UAAI,SAAS,EAAE,QAAQ,MAAM;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,KAAK,UAAU,MAAM,CAAC;AAE1B,MAAI,SAAU,QAAO;AACrB,SAAO;AACT;AAOO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA,CAAC,UAAU,YAAY,QAAQ;AACjC;","names":[]}
1
+ {"version":3,"sources":["../../../src/primitives/thread/ThreadSuggestion.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ActionButtonElement,\n ActionButtonProps,\n createActionButton,\n} from \"../../utils/createActionButton\";\nimport { useCallback } from \"react\";\nimport { useAssistantState, useAssistantApi } from \"../../context\";\n\nconst useThreadSuggestion = ({\n prompt,\n send,\n clearComposer = true,\n autoSend,\n method: _method,\n}: {\n /** The suggestion prompt. */\n prompt: string;\n\n /**\n * When true, automatically sends the message.\n * When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`.\n */\n send?: boolean | undefined;\n\n /**\n * Whether to clear the composer after sending.\n * When send is set to false, determines if composer text is replaced with suggestion (true, default),\n * or if it's appended to the composer text (false).\n *\n * @default true\n */\n clearComposer?: boolean | undefined;\n\n /** @deprecated Use `send` instead. */\n autoSend?: boolean | undefined;\n\n /** @deprecated Use `clearComposer` instead. */\n method?: \"replace\";\n}) => {\n const api = useAssistantApi();\n const disabled = useAssistantState(({ thread }) => thread.isDisabled);\n\n // ========== Deprecation Mapping ==========\n const resolvedSend = send ?? autoSend ?? false;\n // ==========================================\n\n const callback = useCallback(() => {\n const isRunning = api.thread().getState().isRunning;\n\n if (resolvedSend && !isRunning) {\n api.thread().append(prompt);\n if (clearComposer) {\n api.composer().setText(\"\");\n }\n } else {\n if (clearComposer) {\n api.composer().setText(prompt);\n } else {\n const currentText = api.composer().getState().text;\n api\n .composer()\n .setText(currentText.trim() ? `${currentText} ${prompt}` : prompt);\n }\n }\n }, [api, resolvedSend, clearComposer, prompt]);\n\n if (disabled) return null;\n return callback;\n};\n\nexport namespace ThreadPrimitiveSuggestion {\n export type Element = ActionButtonElement;\n export type Props = ActionButtonProps<typeof useThreadSuggestion>;\n}\n\nexport const ThreadPrimitiveSuggestion = createActionButton(\n \"ThreadPrimitive.Suggestion\",\n useThreadSuggestion,\n [\"prompt\", \"send\", \"clearComposer\", \"autoSend\", \"method\"],\n);\n"],"mappings":";;;AAEA;AAAA,EAGE;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB,uBAAuB;AAEnD,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA,QAAQ;AACV,MAwBM;AACJ,QAAM,MAAM,gBAAgB;AAC5B,QAAM,WAAW,kBAAkB,CAAC,EAAE,OAAO,MAAM,OAAO,UAAU;AAGpE,QAAM,eAAe,QAAQ,YAAY;AAGzC,QAAM,WAAW,YAAY,MAAM;AACjC,UAAM,YAAY,IAAI,OAAO,EAAE,SAAS,EAAE;AAE1C,QAAI,gBAAgB,CAAC,WAAW;AAC9B,UAAI,OAAO,EAAE,OAAO,MAAM;AAC1B,UAAI,eAAe;AACjB,YAAI,SAAS,EAAE,QAAQ,EAAE;AAAA,MAC3B;AAAA,IACF,OAAO;AACL,UAAI,eAAe;AACjB,YAAI,SAAS,EAAE,QAAQ,MAAM;AAAA,MAC/B,OAAO;AACL,cAAM,cAAc,IAAI,SAAS,EAAE,SAAS,EAAE;AAC9C,YACG,SAAS,EACT,QAAQ,YAAY,KAAK,IAAI,GAAG,WAAW,IAAI,MAAM,KAAK,MAAM;AAAA,MACrE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,cAAc,eAAe,MAAM,CAAC;AAE7C,MAAI,SAAU,QAAO;AACrB,SAAO;AACT;AAOO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA,CAAC,UAAU,QAAQ,iBAAiB,YAAY,QAAQ;AAC1D;","names":[]}
@@ -1,10 +1,10 @@
1
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
1
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
2
2
  import { equals, iterableEquality, subsetEquality, JestExtend, JestChaiExpect, JestAsymmetricMatchers, GLOBAL_EXPECT, ASYMMETRIC_MATCHERS_OBJECT, getState, setState, addCustomEqualityTesters, customMatchers } from "@vitest/expect.js";
3
3
  import { getCurrentTest } from "@vitest/runner.js";
4
4
  import { getNames, getTestName } from "@vitest/runner/utils.js";
5
5
  import * as chai$1 from "chai.js";
6
6
 
7
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/utils.XdZDrNZV.js
7
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/utils.XdZDrNZV.js
8
8
  import { getSafeTimers } from "@vitest/utils.js";
9
9
  var NAME_WORKER_STATE = "__vitest_worker__";
10
10
  function getWorkerState() {
@@ -53,22 +53,22 @@ async function waitForImportsToResolve() {
53
53
  await waitForImportsToResolve();
54
54
  }
55
55
 
56
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
56
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
57
57
  import { getSafeTimers as getSafeTimers2, assertTypes, createSimpleStackTrace } from "@vitest/utils.js";
58
58
 
59
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js
59
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js
60
60
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
61
61
  function getDefaultExportFromCjs(x) {
62
62
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
63
63
  }
64
64
 
65
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
65
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
66
66
  import { stripSnapshotIndentation, addSerializer, SnapshotClient } from "@vitest/snapshot.js";
67
67
  import "@vitest/utils/error.js";
68
68
  import { fn, spyOn, mocks, isMockFunction } from "@vitest/spy.js";
69
69
  import { parseSingleStack } from "@vitest/utils/source-map.js";
70
70
 
71
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/date.Bq6ZW5rf.js
71
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/date.Bq6ZW5rf.js
72
72
  var RealDate = Date;
73
73
  var now = null;
74
74
  var MockDate = class _MockDate extends RealDate {
@@ -116,7 +116,7 @@ function resetDate() {
116
116
  globalThis.Date = RealDate;
117
117
  }
118
118
 
119
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
119
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js
120
120
  var unsupported = [
121
121
  "matchSnapshot",
122
122
  "toMatchSnapshot",
@@ -2800,7 +2800,7 @@ function getImporter(name) {
2800
2800
  return stack?.file || "";
2801
2801
  }
2802
2802
 
2803
- // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.5.2_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_688234ac2804d6d71aa9eebd3ba7952f/node_modules/vitest/dist/index.js
2803
+ // ../../node_modules/.pnpm/vitest@3.2.4_@types+debug@4.1.12_@types+node@24.6.0_@vitest+ui@3.2.4_jiti@2.6.0_jsdom@2_0944c02044ecb45772bbd20c7867378e/node_modules/vitest/dist/index.js
2804
2804
  import { expectTypeOf } from "expect-type.js";
2805
2805
  import { afterAll, afterEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, suite, test } from "@vitest/runner.js";
2806
2806
  import * as chai2 from "chai.js";