@assistant-ui/react 0.11.22 → 0.11.23

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 (22) 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 +10 -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/types/MessagePartTypes.d.ts +4 -1
  15. package/dist/types/MessagePartTypes.d.ts.map +1 -1
  16. package/package.json +2 -2
  17. package/src/client/types/Part.ts +2 -2
  18. package/src/legacy-runtime/runtime/MessagePartRuntime.ts +2 -2
  19. package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts +12 -12
  20. package/src/legacy-runtime/runtime-cores/external-store/auto-status.tsx +4 -4
  21. package/src/model-context/frame/AssistantFrameProvider.ts +2 -2
  22. 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;;;yBAgLF,MAAM,WAAW,OAAO;EAehD"}
@@ -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,16 @@ 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]: { type: "interrupt", payload: { type: "human", payload } }
45
45
  }));
46
46
  });
47
47
  }
@@ -143,10 +143,10 @@ function useToolInvocations({
143
143
  }
144
144
  }, [state, controller, onResult]);
145
145
  const abort = () => {
146
- interruptedToolsRef.current.forEach(({ reject }) => {
146
+ humanInputRef.current.forEach(({ reject }) => {
147
147
  reject(new Error("Tool execution aborted"));
148
148
  });
149
- interruptedToolsRef.current.clear();
149
+ humanInputRef.current.clear();
150
150
  setToolStatuses({});
151
151
  acRef.current.abort();
152
152
  acRef.current = new AbortController();
@@ -158,9 +158,9 @@ function useToolInvocations({
158
158
  },
159
159
  abort,
160
160
  resume: (toolCallId, payload) => {
161
- const handlers = interruptedToolsRef.current.get(toolCallId);
161
+ const handlers = humanInputRef.current.get(toolCallId);
162
162
  if (handlers) {
163
- interruptedToolsRef.current.delete(toolCallId);
163
+ humanInputRef.current.delete(toolCallId);
164
164
  setToolStatuses((prev) => {
165
165
  const next = { ...prev };
166
166
  delete next[toolCallId];
@@ -168,7 +168,7 @@ function useToolInvocations({
168
168
  });
169
169
  handlers.resolve(payload);
170
170
  } else {
171
- throw new Error(`Tool call ${toolCallId} is not interrupted`);
171
+ throw new Error(`Tool call ${toolCallId} is not waiting for human input`);
172
172
  }
173
173
  }
174
174
  };
@@ -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]: { type: \"interrupt\", payload: { type: \"human\", 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 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(`Tool call ${toolCallId} is not waiting for human input`);\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":[]}
@@ -44,7 +44,10 @@ export type ToolCallMessagePart<TArgs = ReadonlyJSONObject, TResult = unknown> =
44
44
  readonly isError?: boolean | undefined;
45
45
  readonly argsText: string;
46
46
  readonly artifact?: unknown;
47
- readonly interrupt?: unknown;
47
+ readonly interrupt?: {
48
+ type: "human";
49
+ payload: unknown;
50
+ };
48
51
  readonly parentId?: string;
49
52
  };
50
53
  export type ThreadUserMessagePart = TextMessagePart | ImageMessagePart | FileMessagePart | Unstable_AudioMessagePart;
@@ -1 +1 @@
1
- {"version":3,"file":"MessagePartTypes.d.ts","sourceRoot":"","sources":["../../src/types/MessagePartTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAC7B,KAAK,GAAG,kBAAkB,EAC1B,OAAO,GAAG,OAAO,IACf;IACF,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,yBAAyB,CAAC;AAE9B,MAAM,MAAM,0BAA0B,GAClC,eAAe,GACf,oBAAoB,GACpB,mBAAmB,GACnB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,CAAC"}
1
+ {"version":3,"file":"MessagePartTypes.d.ts","sourceRoot":"","sources":["../../src/types/MessagePartTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAC7B,KAAK,GAAG,kBAAkB,EAC1B,OAAO,GAAG,OAAO,IACf;IACF,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,yBAAyB,CAAC;AAE9B,MAAM,MAAM,0BAA0B,GAClC,eAAe,GACf,oBAAoB,GACpB,mBAAmB,GACnB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "conversational-ui",
29
29
  "conversational-ai"
30
30
  ],
31
- "version": "0.11.22",
31
+ "version": "0.11.23",
32
32
  "license": "MIT",
33
33
  "type": "module",
34
34
  "exports": {
@@ -59,7 +59,7 @@
59
59
  "@radix-ui/react-use-callback-ref": "^1.1.1",
60
60
  "@radix-ui/react-use-escape-keydown": "^1.1.1",
61
61
  "@standard-schema/spec": "^1.0.0",
62
- "assistant-stream": "^0.2.32",
62
+ "assistant-stream": "^0.2.33",
63
63
  "json-schema": "^0.4.0",
64
64
  "nanoid": "5.1.6",
65
65
  "react-textarea-autosize": "^8.5.9",
@@ -27,8 +27,8 @@ export type MessagePartClientApi = {
27
27
  addToolResult(result: any | ToolResponse<any>): void;
28
28
 
29
29
  /**
30
- * Resume an interrupted tool call with a payload.
31
- * This is useful when a tool has interrupted its execution and is waiting for user input.
30
+ * Resume a tool call that is waiting for human input with a payload.
31
+ * This is useful when a tool has requested human input and is waiting for a response.
32
32
  */
33
33
  resumeToolCall(payload: unknown): void;
34
34
 
@@ -31,8 +31,8 @@ export type MessagePartRuntime = {
31
31
  addToolResult(result: any | ToolResponse<any>): void;
32
32
 
33
33
  /**
34
- * Resume an interrupted tool call with a payload.
35
- * This is useful when a tool has interrupted its execution and is waiting for user input.
34
+ * Resume a tool call that is waiting for human input with a payload.
35
+ * This is useful when a tool has requested human input and is waiting for a response.
36
36
  */
37
37
  resumeToolCall(payload: unknown): void;
38
38
 
@@ -39,7 +39,7 @@ type UseToolInvocationsParams = {
39
39
 
40
40
  export type ToolExecutionStatus =
41
41
  | { type: "executing" }
42
- | { type: "interrupt"; payload: unknown };
42
+ | { type: "interrupt"; payload: { type: "human"; payload: unknown } };
43
43
 
44
44
  export function useToolInvocations({
45
45
  state,
@@ -58,7 +58,7 @@ export function useToolInvocations({
58
58
  >
59
59
  >({});
60
60
 
61
- const interruptedToolsRef = useRef<
61
+ const humanInputRef = useRef<
62
62
  Map<
63
63
  string,
64
64
  {
@@ -76,18 +76,18 @@ export function useToolInvocations({
76
76
  () => acRef.current?.signal ?? new AbortController().signal,
77
77
  (toolCallId: string, payload: unknown) => {
78
78
  return new Promise<unknown>((resolve, reject) => {
79
- // Reject previous interrupt if it exists
80
- const previous = interruptedToolsRef.current.get(toolCallId);
79
+ // Reject previous human input request if it exists
80
+ const previous = humanInputRef.current.get(toolCallId);
81
81
  if (previous) {
82
82
  previous.reject(
83
- new Error("Interrupt was superseded by a new interrupt"),
83
+ new Error("Human input request was superseded by a new request"),
84
84
  );
85
85
  }
86
86
 
87
- interruptedToolsRef.current.set(toolCallId, { resolve, reject });
87
+ humanInputRef.current.set(toolCallId, { resolve, reject });
88
88
  setToolStatuses((prev) => ({
89
89
  ...prev,
90
- [toolCallId]: { type: "interrupt", payload },
90
+ [toolCallId]: { type: "interrupt", payload: { type: "human", payload } },
91
91
  }));
92
92
  });
93
93
  },
@@ -206,10 +206,10 @@ export function useToolInvocations({
206
206
  }, [state, controller, onResult]);
207
207
 
208
208
  const abort = () => {
209
- interruptedToolsRef.current.forEach(({ reject }) => {
209
+ humanInputRef.current.forEach(({ reject }) => {
210
210
  reject(new Error("Tool execution aborted"));
211
211
  });
212
- interruptedToolsRef.current.clear();
212
+ humanInputRef.current.clear();
213
213
  setToolStatuses({});
214
214
 
215
215
  acRef.current.abort();
@@ -223,9 +223,9 @@ export function useToolInvocations({
223
223
  },
224
224
  abort,
225
225
  resume: (toolCallId: string, payload: unknown) => {
226
- const handlers = interruptedToolsRef.current.get(toolCallId);
226
+ const handlers = humanInputRef.current.get(toolCallId);
227
227
  if (handlers) {
228
- interruptedToolsRef.current.delete(toolCallId);
228
+ humanInputRef.current.delete(toolCallId);
229
229
  setToolStatuses((prev) => {
230
230
  const next = { ...prev };
231
231
  delete next[toolCallId];
@@ -233,7 +233,7 @@ export function useToolInvocations({
233
233
  });
234
234
  handlers.resolve(payload);
235
235
  } else {
236
- throw new Error(`Tool call ${toolCallId} is not interrupted`);
236
+ throw new Error(`Tool call ${toolCallId} is not waiting for human input`);
237
237
  }
238
238
  },
239
239
  };
@@ -11,7 +11,7 @@ const AUTO_STATUS_PENDING = Object.freeze({
11
11
  reason: "tool-calls",
12
12
  });
13
13
 
14
- const AUTO_STATUS_SUSPENDED = Object.freeze({
14
+ const AUTO_STATUS_INTERRUPT = Object.freeze({
15
15
  type: "requires-action",
16
16
  reason: "interrupt",
17
17
  });
@@ -22,13 +22,13 @@ export const isAutoStatus = (status: MessageStatus) =>
22
22
  export const getAutoStatus = (
23
23
  isLast: boolean,
24
24
  isRunning: boolean,
25
- hasSuspendedToolCalls: boolean,
25
+ hasInterruptedToolCalls: boolean,
26
26
  hasPendingToolCalls: boolean,
27
27
  ) =>
28
28
  isLast && isRunning
29
29
  ? AUTO_STATUS_RUNNING
30
- : hasSuspendedToolCalls
31
- ? AUTO_STATUS_SUSPENDED
30
+ : hasInterruptedToolCalls
31
+ ? AUTO_STATUS_INTERRUPT
32
32
  : hasPendingToolCalls
33
33
  ? AUTO_STATUS_PENDING
34
34
  : AUTO_STATUS_COMPLETE;
@@ -133,9 +133,9 @@ export class AssistantFrameProvider {
133
133
  ? await tool.execute(message.args, {
134
134
  toolCallId: message.id,
135
135
  abortSignal: new AbortController().signal,
136
- interrupt: async () => {
136
+ human: async () => {
137
137
  throw new Error(
138
- "Tool interrupt is not supported in frame context",
138
+ "Tool human input is not supported in frame context",
139
139
  );
140
140
  },
141
141
  })
@@ -54,7 +54,7 @@ export type ToolCallMessagePart<
54
54
  readonly isError?: boolean | undefined;
55
55
  readonly argsText: string;
56
56
  readonly artifact?: unknown;
57
- readonly interrupt?: unknown;
57
+ readonly interrupt?: { type: "human"; payload: unknown };
58
58
  readonly parentId?: string;
59
59
  };
60
60