@assistant-ui/core 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -0
- package/dist/internal/duplicate-detection.d.ts +5 -0
- package/dist/internal/duplicate-detection.d.ts.map +1 -0
- package/dist/internal/duplicate-detection.js +11 -0
- package/dist/internal/duplicate-detection.js.map +1 -0
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +2 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/tool.d.ts.map +1 -1
- package/dist/react/AssistantProvider.d.ts.map +1 -1
- package/dist/react/AssistantProvider.js.map +1 -1
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +26 -15
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +5 -4
- package/dist/react/index.js +2 -2
- package/dist/react/model-context/toolbox.d.ts +29 -2
- package/dist/react/model-context/toolbox.d.ts.map +1 -1
- package/dist/react/model-context/toolbox.js +18 -0
- package/dist/react/model-context/toolbox.js.map +1 -0
- package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantTool.js +6 -3
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.d.ts +6 -0
- package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.js +4 -2
- package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
- package/dist/react/model-context/useInlineRender.js.map +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.d.ts +49 -7
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +28 -3
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +2 -7
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.js +6 -5
- package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/external-message-converter.d.ts +1 -1
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +1 -0
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts +7 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts.map +1 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js +21 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -0
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +19 -2
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/react/utils/groupParts.d.ts +32 -11
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +13 -6
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
- package/dist/runtime/api/attachment-runtime.js.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/base/base-assistant-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +8 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts +9 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +34 -14
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.d.ts +1 -0
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +2 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts +31 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-shared-options.d.ts +8 -0
- package/dist/runtimes/external-store/external-store-shared-options.d.ts.map +1 -0
- package/dist/runtimes/external-store/external-store-shared-options.js +11 -0
- package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -0
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +25 -2
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +106 -26
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/thread-message-converter.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +168 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +449 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -0
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js.map +1 -1
- package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
- package/dist/types/message.d.ts +6 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/id.d.ts +1 -3
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +1 -4
- package/dist/utils/id.js.map +1 -1
- package/package.json +10 -10
- package/src/adapters/index.ts +1 -4
- package/src/adapters/speech.ts +0 -1
- package/src/index.ts +12 -0
- package/src/internal/duplicate-detection.ts +26 -0
- package/src/internal.ts +0 -2
- package/src/model-context/frame/host.ts +0 -1
- package/src/model-context/frame/provider.ts +0 -1
- package/src/react/AssistantProvider.tsx +2 -3
- package/src/react/client/Interactables.ts +0 -1
- package/src/react/client/Tools.ts +50 -25
- package/src/react/index.ts +9 -8
- package/src/react/model-context/toolbox.ts +46 -1
- package/src/react/model-context/useAssistantTool.ts +8 -3
- package/src/react/model-context/useAssistantToolUI.ts +9 -2
- package/src/react/model-context/useInlineRender.ts +0 -1
- package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -2
- package/src/react/primitives/message/MessageAttachments.test.tsx +1 -1
- package/src/react/primitives/message/MessageGroupedParts.tsx +102 -13
- package/src/react/primitives/message/MessageParts.tsx +4 -7
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
- package/src/react/runtimes/RuntimeAdapterProvider.tsx +12 -7
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +0 -3
- package/src/react/runtimes/external-message-converter.ts +5 -1
- package/src/react/runtimes/useExternalStoreSharedOptions.ts +23 -0
- package/src/react/runtimes/useLocalRuntime.ts +0 -10
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +0 -6
- package/src/react/types/scopes/tools.ts +20 -1
- package/src/react/utils/groupParts.ts +49 -18
- package/src/runtime/api/attachment-runtime.ts +1 -2
- package/src/runtime/interfaces/thread-runtime-core.ts +8 -0
- package/src/runtime/internal.ts +1 -4
- package/src/runtime/utils/message-repository.ts +57 -16
- package/src/runtime/utils/thread-message-like.ts +2 -0
- package/src/runtimes/external-store/external-store-adapter.ts +33 -0
- package/src/runtimes/external-store/external-store-shared-options.ts +18 -0
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +1 -3
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +179 -37
- package/src/runtimes/tool-invocations/EDGE_CASES.md +194 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +1054 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +782 -0
- package/src/subscribable/subscribable.ts +3 -3
- package/src/tests/MessageRepository.test.ts +83 -52
- package/src/tests/OptimisticState-delete-crash.test.ts +2 -0
- package/src/tests/OptimisticState-list-race.test.ts +2 -4
- package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +5 -5
- package/src/tests/auiV0Encode.test.ts +1 -1
- package/src/tests/composer-can-send.test.ts +8 -4
- package/src/tests/duplicate-detection.test.ts +34 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +1 -1
- package/src/tests/external-store-thread-runtime-core.test.ts +112 -79
- package/src/tests/groupParts.test.ts +70 -0
- package/src/tests/no-unsafe-process-env.test.ts +1 -0
- package/src/tests/remote-thread-list-isLoading.test.ts +2 -5
- package/src/tests/thread-message-like.test.ts +4 -1
- package/src/types/index.ts +1 -4
- package/src/types/message.ts +6 -0
- package/src/utils/id.ts +0 -4
- package/dist/react/runtimes/useToolInvocations.d.ts +0 -53
- package/dist/react/runtimes/useToolInvocations.d.ts.map +0 -1
- package/dist/react/runtimes/useToolInvocations.js +0 -380
- package/dist/react/runtimes/useToolInvocations.js.map +0 -1
- package/src/react/runtimes/useToolInvocations.ts +0 -694
|
@@ -160,6 +160,76 @@ describe("groupPartByType", () => {
|
|
|
160
160
|
expect(fn(notMcp)).toEqual(["group-tool"]);
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
+
const standaloneContext = (...names: string[]) => ({
|
|
164
|
+
toolUIs: Object.fromEntries(
|
|
165
|
+
names.map((name) => [name, [{ render: () => null, standalone: true }]]),
|
|
166
|
+
),
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("routes context-standalone tool calls through the 'standalone-tool-call' entry", () => {
|
|
170
|
+
const fn = groupPartByType({
|
|
171
|
+
"tool-call": ["group-tool"],
|
|
172
|
+
"standalone-tool-call": [],
|
|
173
|
+
});
|
|
174
|
+
const standalone = part({
|
|
175
|
+
type: "tool-call",
|
|
176
|
+
toolName: "ask_user",
|
|
177
|
+
} as Partial<PartState>);
|
|
178
|
+
const regular = part({
|
|
179
|
+
type: "tool-call",
|
|
180
|
+
toolName: "search",
|
|
181
|
+
} as Partial<PartState>);
|
|
182
|
+
expect(fn(standalone, standaloneContext("ask_user"))).toEqual([]);
|
|
183
|
+
expect(fn(regular, standaloneContext("ask_user"))).toEqual(["group-tool"]);
|
|
184
|
+
// No context → not standalone, falls through to "tool-call".
|
|
185
|
+
expect(fn(standalone)).toEqual(["group-tool"]);
|
|
186
|
+
// Registered but not standalone → also falls through to "tool-call".
|
|
187
|
+
const inlineCtx = {
|
|
188
|
+
toolUIs: { ask_user: [{ render: () => null, standalone: false }] },
|
|
189
|
+
};
|
|
190
|
+
expect(fn(standalone, inlineCtx)).toEqual(["group-tool"]);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("routes MCP-app parts through 'standalone-tool-call' from the part alone", () => {
|
|
194
|
+
const fn = groupPartByType({
|
|
195
|
+
"tool-call": ["group-tool"],
|
|
196
|
+
"standalone-tool-call": [],
|
|
197
|
+
});
|
|
198
|
+
const mcpApp = part({
|
|
199
|
+
type: "tool-call",
|
|
200
|
+
toolName: "render",
|
|
201
|
+
mcp: { app: { resourceUri: "ui://my-app" } },
|
|
202
|
+
} as Partial<PartState>);
|
|
203
|
+
expect(fn(mcpApp)).toEqual([]);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("routes MCP-app parts through the deprecated 'mcp-app' entry", () => {
|
|
207
|
+
const fn = groupPartByType({
|
|
208
|
+
"tool-call": ["group-tool"],
|
|
209
|
+
"mcp-app": ["group-mcp"],
|
|
210
|
+
});
|
|
211
|
+
const mcpApp = part({
|
|
212
|
+
type: "tool-call",
|
|
213
|
+
toolName: "render",
|
|
214
|
+
mcp: { app: { resourceUri: "ui://my-app" } },
|
|
215
|
+
} as Partial<PartState>);
|
|
216
|
+
expect(fn(mcpApp)).toEqual(["group-mcp"]);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("prefers 'standalone-tool-call' over the deprecated 'mcp-app' entry", () => {
|
|
220
|
+
const fn = groupPartByType({
|
|
221
|
+
"tool-call": ["group-tool"],
|
|
222
|
+
"standalone-tool-call": ["group-standalone"],
|
|
223
|
+
"mcp-app": ["group-mcp"],
|
|
224
|
+
});
|
|
225
|
+
const mcpApp = part({
|
|
226
|
+
type: "tool-call",
|
|
227
|
+
toolName: "render",
|
|
228
|
+
mcp: { app: { resourceUri: "ui://x" } },
|
|
229
|
+
} as Partial<PartState>);
|
|
230
|
+
expect(fn(mcpApp)).toEqual(["group-standalone"]);
|
|
231
|
+
});
|
|
232
|
+
|
|
163
233
|
it("tags the function with a GROUPBY_MEMO_KEY fingerprint", () => {
|
|
164
234
|
const fn = groupPartByType({ reasoning: ["group-r"] });
|
|
165
235
|
const memoKey = (fn as unknown as { [GROUPBY_MEMO_KEY]: string })[
|
|
@@ -26,6 +26,8 @@ type ListResult = {
|
|
|
26
26
|
|
|
27
27
|
const INITIAL_STATE: RemoteThreadState = {
|
|
28
28
|
isLoading: true,
|
|
29
|
+
isLoadingMore: false,
|
|
30
|
+
cursor: undefined,
|
|
29
31
|
newThreadId: undefined,
|
|
30
32
|
threadIds: [],
|
|
31
33
|
archivedThreadIds: [],
|
|
@@ -84,7 +86,6 @@ describe("RemoteThreadList isLoading lifecycle", () => {
|
|
|
84
86
|
state.optimisticUpdate({
|
|
85
87
|
execute: () => d.promise,
|
|
86
88
|
loading: (s) => ({ ...s, isLoading: true }),
|
|
87
|
-
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
88
89
|
then: applyListResult,
|
|
89
90
|
});
|
|
90
91
|
|
|
@@ -98,7 +99,6 @@ describe("RemoteThreadList isLoading lifecycle", () => {
|
|
|
98
99
|
const promise = state.optimisticUpdate({
|
|
99
100
|
execute: () => d.promise,
|
|
100
101
|
loading: (s) => ({ ...s, isLoading: true }),
|
|
101
|
-
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
102
102
|
then: applyListResult,
|
|
103
103
|
});
|
|
104
104
|
|
|
@@ -115,7 +115,6 @@ describe("RemoteThreadList isLoading lifecycle", () => {
|
|
|
115
115
|
const promise = state.optimisticUpdate({
|
|
116
116
|
execute: () => d.promise,
|
|
117
117
|
loading: (s) => ({ ...s, isLoading: true }),
|
|
118
|
-
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
119
118
|
then: applyListResult,
|
|
120
119
|
});
|
|
121
120
|
|
|
@@ -140,7 +139,6 @@ describe("RemoteThreadList isLoading lifecycle", () => {
|
|
|
140
139
|
const promise = state.optimisticUpdate({
|
|
141
140
|
execute: () => d.promise,
|
|
142
141
|
loading: (s) => ({ ...s, isLoading: true }),
|
|
143
|
-
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
144
142
|
then: applyListResult,
|
|
145
143
|
});
|
|
146
144
|
|
|
@@ -164,7 +162,6 @@ describe("RemoteThreadList isLoading error path", () => {
|
|
|
164
162
|
.optimisticUpdate({
|
|
165
163
|
execute: () => d.promise,
|
|
166
164
|
loading: (s) => ({ ...s, isLoading: true }),
|
|
167
|
-
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
168
165
|
then: applyListResult,
|
|
169
166
|
})
|
|
170
167
|
.catch(() => {
|
|
@@ -2,7 +2,10 @@ import { describe, expect, it } from "vitest";
|
|
|
2
2
|
import { fromThreadMessageLike } from "../runtime/utils/thread-message-like";
|
|
3
3
|
|
|
4
4
|
const fallbackId = "test-id";
|
|
5
|
-
const fallbackStatus = {
|
|
5
|
+
const fallbackStatus = {
|
|
6
|
+
type: "complete" as const,
|
|
7
|
+
reason: "stop" as const,
|
|
8
|
+
};
|
|
6
9
|
|
|
7
10
|
describe("fromThreadMessageLike", () => {
|
|
8
11
|
describe("data-* prefixed types", () => {
|
package/src/types/index.ts
CHANGED
package/src/types/message.ts
CHANGED
|
@@ -314,6 +314,11 @@ export type ThreadAssistantMessage = MessageCommonProps & {
|
|
|
314
314
|
readonly steps: readonly ThreadStep[];
|
|
315
315
|
readonly submittedFeedback?: { readonly type: "positive" | "negative" };
|
|
316
316
|
readonly timing?: MessageTiming;
|
|
317
|
+
/**
|
|
318
|
+
* Marks a client-side optimistic placeholder. Such messages are evicted
|
|
319
|
+
* once off the head branch and are never persisted.
|
|
320
|
+
*/
|
|
321
|
+
readonly isOptimistic?: boolean;
|
|
317
322
|
readonly custom: Record<string, unknown>;
|
|
318
323
|
};
|
|
319
324
|
};
|
|
@@ -327,6 +332,7 @@ type BaseThreadMessage = {
|
|
|
327
332
|
readonly steps?: readonly ThreadStep[];
|
|
328
333
|
readonly submittedFeedback?: { readonly type: "positive" | "negative" };
|
|
329
334
|
readonly timing?: MessageTiming;
|
|
335
|
+
readonly isOptimistic?: boolean;
|
|
330
336
|
readonly custom: Record<string, unknown>;
|
|
331
337
|
};
|
|
332
338
|
readonly attachments?: ThreadUserMessage["attachments"];
|
package/src/utils/id.ts
CHANGED
|
@@ -5,10 +5,6 @@ export const generateId = customAlphabet(
|
|
|
5
5
|
7,
|
|
6
6
|
);
|
|
7
7
|
|
|
8
|
-
const optimisticPrefix = "__optimistic__";
|
|
9
|
-
export const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
|
10
|
-
export const isOptimisticId = (id: string) => id.startsWith(optimisticPrefix);
|
|
11
|
-
|
|
12
8
|
const errorPrefix = "__error__";
|
|
13
9
|
export const generateErrorMessageId = () => `${errorPrefix}${generateId()}`;
|
|
14
10
|
export const isErrorMessageId = (id: string) => id.startsWith(errorPrefix);
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { ThreadMessage } from "../../types/message.js";
|
|
2
|
-
import { Tool, ToolModelContentPart } from "assistant-stream";
|
|
3
|
-
import { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
4
|
-
|
|
5
|
-
//#region src/react/runtimes/useToolInvocations.d.ts
|
|
6
|
-
type AssistantTransportState = {
|
|
7
|
-
readonly messages: readonly ThreadMessage[];
|
|
8
|
-
readonly state?: ReadonlyJSONValue;
|
|
9
|
-
readonly isRunning: boolean;
|
|
10
|
-
};
|
|
11
|
-
type AddToolResultCommand = {
|
|
12
|
-
readonly type: "add-tool-result";
|
|
13
|
-
readonly toolCallId: string;
|
|
14
|
-
readonly toolName: string;
|
|
15
|
-
readonly result: ReadonlyJSONValue;
|
|
16
|
-
readonly isError: boolean;
|
|
17
|
-
readonly artifact?: ReadonlyJSONValue;
|
|
18
|
-
readonly modelContent?: readonly ToolModelContentPart[];
|
|
19
|
-
};
|
|
20
|
-
type UseToolInvocationsParams = {
|
|
21
|
-
state: AssistantTransportState;
|
|
22
|
-
getTools: () => Record<string, Tool> | undefined;
|
|
23
|
-
onResult: (command: AddToolResultCommand) => void;
|
|
24
|
-
setToolStatuses: (updater: Record<string, ToolExecutionStatus> | ((prev: Record<string, ToolExecutionStatus>) => Record<string, ToolExecutionStatus>)) => void;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Streaming execution state for a frontend tool.
|
|
28
|
-
*
|
|
29
|
-
* Custom runtime integrations use this to mirror in-flight tool calls while
|
|
30
|
-
* `useToolInvocations` executes tools in the browser.
|
|
31
|
-
*/
|
|
32
|
-
type ToolExecutionStatus = {
|
|
33
|
-
/** The tool's execute function is currently running. */type: "executing";
|
|
34
|
-
} | {
|
|
35
|
-
/** The tool is waiting for a human input payload before continuing. */type: "interrupt"; /** Human input request emitted by the tool execution context. */
|
|
36
|
-
payload: {
|
|
37
|
-
type: "human";
|
|
38
|
-
payload: unknown;
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
declare function useToolInvocations({
|
|
42
|
-
state,
|
|
43
|
-
getTools,
|
|
44
|
-
onResult,
|
|
45
|
-
setToolStatuses
|
|
46
|
-
}: UseToolInvocationsParams): {
|
|
47
|
-
reset: () => void;
|
|
48
|
-
abort: () => Promise<void>;
|
|
49
|
-
resume: (toolCallId: string, payload: unknown) => void;
|
|
50
|
-
};
|
|
51
|
-
//#endregion
|
|
52
|
-
export { AddToolResultCommand, AssistantTransportState, ToolExecutionStatus, useToolInvocations };
|
|
53
|
-
//# sourceMappingURL=useToolInvocations.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useToolInvocations.d.ts","names":[],"sources":["../../../src/react/runtimes/useToolInvocations.ts"],"mappings":";;;;;KAkBY,uBAAA;EAAA,SACD,QAAA,WAAmB,aAAA;EAAA,SACnB,KAAA,GAAQ,iBAAiB;EAAA,SACzB,SAAA;AAAA;AAAA,KAGC,oBAAA;EAAA,SACD,IAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,EAAQ,iBAAA;EAAA,SACR,OAAA;EAAA,SACA,QAAA,GAAW,iBAAA;EAAA,SACX,YAAA,YAAwB,oBAAA;AAAA;AAAA,KA2B9B,wBAAA;EACH,KAAA,EAAO,uBAAA;EACP,QAAA,QAAgB,MAAA,SAAe,IAAA;EAC/B,QAAA,GAAW,OAAA,EAAS,oBAAA;EACpB,eAAA,GACE,OAAA,EACI,MAAA,SAAe,mBAAA,MAEb,IAAA,EAAM,MAAA,SAAe,mBAAA,MAClB,MAAA,SAAe,mBAAA;AAAA;;;;;;;KAUhB,mBAAA;EA/CD,wDAkDL,IAAA;AAAA;EAjD6B,uEAqD7B,IAAA,eArDiD;EAuDjD,OAAA;IAAW,IAAA;IAAe,OAAA;EAAA;AAAA;AAAA,iBAyChB,kBAAA,CAAA;EACd,KAAA;EACA,QAAA;EACA,QAAA;EACA;AAAA,GACC,wBAAA;;eA+fiB,OAAA;+BAkCW,OAAA;AAAA"}
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { isJSONValueEqual } from "../../utils/json/is-json-equal.js";
|
|
2
|
-
import { ToolResponse, createAssistantStreamController, unstable_toolResultStream } from "assistant-stream";
|
|
3
|
-
import { AssistantMetaTransformStream } from "assistant-stream/utils";
|
|
4
|
-
import { useEffect, useRef, useState } from "react";
|
|
5
|
-
//#region src/react/runtimes/useToolInvocations.ts
|
|
6
|
-
const isArgsTextComplete = (argsText) => {
|
|
7
|
-
try {
|
|
8
|
-
JSON.parse(argsText);
|
|
9
|
-
return true;
|
|
10
|
-
} catch {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
const parseArgsText = (argsText) => {
|
|
15
|
-
try {
|
|
16
|
-
return JSON.parse(argsText);
|
|
17
|
-
} catch {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
const isEquivalentCompleteArgsText = (previous, next) => {
|
|
22
|
-
const previousValue = parseArgsText(previous);
|
|
23
|
-
const nextValue = parseArgsText(next);
|
|
24
|
-
if (previousValue === void 0 || nextValue === void 0) return false;
|
|
25
|
-
return isJSONValueEqual(previousValue, nextValue);
|
|
26
|
-
};
|
|
27
|
-
function useToolInvocations({ state, getTools, onResult, setToolStatuses }) {
|
|
28
|
-
/**
|
|
29
|
-
* Single source of truth for per-tool-call lifecycle. Keyed by *logical*
|
|
30
|
-
* toolCallId (the id the host knows). Restored entries have no controller;
|
|
31
|
-
* active entries carry their stream id and rewrite/execution bookkeeping.
|
|
32
|
-
*/
|
|
33
|
-
const entriesRef = useRef(/* @__PURE__ */ new Map());
|
|
34
|
-
/**
|
|
35
|
-
* Reverse alias map populated only when a rewrite assigns a synthetic stream
|
|
36
|
-
* id to an entry. Identity mappings are implicit via the fallback in
|
|
37
|
-
* `getLogicalToolCallId`.
|
|
38
|
-
*/
|
|
39
|
-
const streamToLogicalRef = useRef(/* @__PURE__ */ new Map());
|
|
40
|
-
/**
|
|
41
|
-
* Stream ids whose `result` chunks must be dropped before reaching `onResult`.
|
|
42
|
-
* Populated when:
|
|
43
|
-
* - an argsText rewrite supersedes a stream (the old stream's result, if
|
|
44
|
-
* any, is no longer authoritative)
|
|
45
|
-
* - `reset()` is called while a pre-resolved tool call has a never-settling
|
|
46
|
-
* Promise pending in the executor — the eventual cancellation chunk
|
|
47
|
-
* would otherwise be forwarded to a host that has already moved on.
|
|
48
|
-
*/
|
|
49
|
-
const abandonedStreamIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
50
|
-
/**
|
|
51
|
-
* Stream ids whose `execute` should be short-circuited in the tool wrapper.
|
|
52
|
-
* Tracked by physical stream id (not logical id) so cleanup is keyed off
|
|
53
|
-
* the same id the wrapper sees in its context.
|
|
54
|
-
*/
|
|
55
|
-
const skipExecuteStreamIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
56
|
-
const humanInputRef = useRef(/* @__PURE__ */ new Map());
|
|
57
|
-
/**
|
|
58
|
-
* In-flight `execute` invocations keyed by physical stream id. Lives outside
|
|
59
|
-
* `entriesRef` so `reset()` can drop tool-call state without orphaning the
|
|
60
|
-
* cleanup the cancellation `onExecutionEnd` still needs.
|
|
61
|
-
*/
|
|
62
|
-
const executingRef = useRef(/* @__PURE__ */ new Map());
|
|
63
|
-
const acRef = useRef(new AbortController());
|
|
64
|
-
const executingCountRef = useRef(0);
|
|
65
|
-
const settledResolversRef = useRef([]);
|
|
66
|
-
const rewriteCounterRef = useRef(0);
|
|
67
|
-
/**
|
|
68
|
-
* `true` until the first snapshot has been processed; `reset()` flips it
|
|
69
|
-
* back to `true`. Snapshots observed while this is `true` are treated as
|
|
70
|
-
* historical: their tool calls are recorded in `entriesRef` as restored
|
|
71
|
-
* but no streamCall/execute fires. The next snapshot is processed as live.
|
|
72
|
-
*/
|
|
73
|
-
const pendingRestoreRef = useRef(true);
|
|
74
|
-
const getLogicalToolCallId = (streamId) => streamToLogicalRef.current.get(streamId) ?? streamId;
|
|
75
|
-
const getWrappedTools = () => {
|
|
76
|
-
const tools = getTools();
|
|
77
|
-
if (!tools) return void 0;
|
|
78
|
-
return Object.fromEntries(Object.entries(tools).map(([name, tool]) => {
|
|
79
|
-
const execute = tool.execute;
|
|
80
|
-
const streamCall = tool.streamCall;
|
|
81
|
-
const toModelOutput = tool.toModelOutput;
|
|
82
|
-
return [name, {
|
|
83
|
-
...tool,
|
|
84
|
-
...execute !== void 0 && { execute: (...[args, context]) => {
|
|
85
|
-
if (skipExecuteStreamIdsRef.current.has(context.toolCallId)) return new Promise(() => {});
|
|
86
|
-
return execute(args, {
|
|
87
|
-
...context,
|
|
88
|
-
toolCallId: getLogicalToolCallId(context.toolCallId)
|
|
89
|
-
});
|
|
90
|
-
} },
|
|
91
|
-
...streamCall !== void 0 && { streamCall: (...[reader, context]) => streamCall(reader, {
|
|
92
|
-
...context,
|
|
93
|
-
toolCallId: getLogicalToolCallId(context.toolCallId)
|
|
94
|
-
}) },
|
|
95
|
-
...toModelOutput !== void 0 && { toModelOutput: (options) => toModelOutput({
|
|
96
|
-
...options,
|
|
97
|
-
toolCallId: getLogicalToolCallId(options.toolCallId)
|
|
98
|
-
}) }
|
|
99
|
-
}];
|
|
100
|
-
}));
|
|
101
|
-
};
|
|
102
|
-
const resolveAllSettledResolvers = () => {
|
|
103
|
-
const resolvers = settledResolversRef.current;
|
|
104
|
-
settledResolversRef.current = [];
|
|
105
|
-
resolvers.forEach((resolve) => resolve());
|
|
106
|
-
};
|
|
107
|
-
const [controller] = useState(() => {
|
|
108
|
-
const [stream, controller] = createAssistantStreamController();
|
|
109
|
-
const transform = unstable_toolResultStream(getWrappedTools, () => acRef.current?.signal ?? new AbortController().signal, (toolCallId, payload) => {
|
|
110
|
-
const logicalToolCallId = getLogicalToolCallId(toolCallId);
|
|
111
|
-
return new Promise((resolve, reject) => {
|
|
112
|
-
const previous = humanInputRef.current.get(logicalToolCallId);
|
|
113
|
-
if (previous) previous.reject(/* @__PURE__ */ new Error("Human input request was superseded by a new request"));
|
|
114
|
-
humanInputRef.current.set(logicalToolCallId, {
|
|
115
|
-
resolve,
|
|
116
|
-
reject
|
|
117
|
-
});
|
|
118
|
-
setToolStatuses((prev) => ({
|
|
119
|
-
...prev,
|
|
120
|
-
[logicalToolCallId]: {
|
|
121
|
-
type: "interrupt",
|
|
122
|
-
payload: {
|
|
123
|
-
type: "human",
|
|
124
|
-
payload
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}));
|
|
128
|
-
});
|
|
129
|
-
}, {
|
|
130
|
-
onExecutionStart: (streamId) => {
|
|
131
|
-
if (skipExecuteStreamIdsRef.current.has(streamId)) return;
|
|
132
|
-
const logicalToolCallId = getLogicalToolCallId(streamId);
|
|
133
|
-
const abandoned = abandonedStreamIdsRef.current.has(streamId);
|
|
134
|
-
executingRef.current.set(streamId, {
|
|
135
|
-
logicalToolCallId,
|
|
136
|
-
abandoned
|
|
137
|
-
});
|
|
138
|
-
executingCountRef.current++;
|
|
139
|
-
if (!abandoned) setToolStatuses((prev) => ({
|
|
140
|
-
...prev,
|
|
141
|
-
[logicalToolCallId]: { type: "executing" }
|
|
142
|
-
}));
|
|
143
|
-
},
|
|
144
|
-
onExecutionEnd: (streamId) => {
|
|
145
|
-
const info = executingRef.current.get(streamId);
|
|
146
|
-
if (!info) return;
|
|
147
|
-
executingRef.current.delete(streamId);
|
|
148
|
-
executingCountRef.current--;
|
|
149
|
-
if (!info.abandoned) setToolStatuses((prev) => {
|
|
150
|
-
const next = { ...prev };
|
|
151
|
-
delete next[info.logicalToolCallId];
|
|
152
|
-
return next;
|
|
153
|
-
});
|
|
154
|
-
if (executingCountRef.current === 0) resolveAllSettledResolvers();
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
stream.pipeThrough(transform).pipeThrough(new AssistantMetaTransformStream()).pipeTo(new WritableStream({ write(chunk) {
|
|
158
|
-
if (chunk.type !== "result") return;
|
|
159
|
-
const streamId = chunk.meta.toolCallId;
|
|
160
|
-
const logicalToolCallId = getLogicalToolCallId(streamId);
|
|
161
|
-
const entry = entriesRef.current.get(logicalToolCallId);
|
|
162
|
-
if (abandonedStreamIdsRef.current.delete(streamId)) {
|
|
163
|
-
streamToLogicalRef.current.delete(streamId);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (!entry && skipExecuteStreamIdsRef.current.has(streamId)) return;
|
|
167
|
-
if (entry?.hasResult) return;
|
|
168
|
-
if (streamId !== logicalToolCallId) streamToLogicalRef.current.delete(streamId);
|
|
169
|
-
onResult({
|
|
170
|
-
type: "add-tool-result",
|
|
171
|
-
toolCallId: logicalToolCallId,
|
|
172
|
-
toolName: chunk.meta.toolName,
|
|
173
|
-
result: chunk.result,
|
|
174
|
-
isError: chunk.isError,
|
|
175
|
-
...chunk.artifact !== void 0 && { artifact: chunk.artifact },
|
|
176
|
-
...chunk.modelContent !== void 0 && { modelContent: chunk.modelContent }
|
|
177
|
-
});
|
|
178
|
-
} }));
|
|
179
|
-
return controller;
|
|
180
|
-
});
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
const hasExecutableTool = (toolName) => {
|
|
183
|
-
const tool = getTools()?.[toolName];
|
|
184
|
-
return tool?.execute !== void 0 || tool?.streamCall !== void 0;
|
|
185
|
-
};
|
|
186
|
-
const shouldCloseArgsStream = ({ toolName, argsText, hasResult }) => {
|
|
187
|
-
if (hasResult) return true;
|
|
188
|
-
if (!hasExecutableTool(toolName)) return !state.isRunning && isArgsTextComplete(argsText);
|
|
189
|
-
return isArgsTextComplete(argsText);
|
|
190
|
-
};
|
|
191
|
-
const startActiveEntry = (toolCallId, toolName, skipExecute) => {
|
|
192
|
-
const toolCallController = controller.addToolCallPart({
|
|
193
|
-
toolName,
|
|
194
|
-
toolCallId
|
|
195
|
-
});
|
|
196
|
-
if (skipExecute) skipExecuteStreamIdsRef.current.add(toolCallId);
|
|
197
|
-
const entry = {
|
|
198
|
-
toolName,
|
|
199
|
-
controller: toolCallController,
|
|
200
|
-
streamId: toolCallId,
|
|
201
|
-
argsText: "",
|
|
202
|
-
hasResult: false,
|
|
203
|
-
argsComplete: false
|
|
204
|
-
};
|
|
205
|
-
entriesRef.current.set(toolCallId, entry);
|
|
206
|
-
return entry;
|
|
207
|
-
};
|
|
208
|
-
const restartArgsStream = (entry, toolCallId) => {
|
|
209
|
-
if (!entry.controller) return;
|
|
210
|
-
abandonedStreamIdsRef.current.add(entry.streamId);
|
|
211
|
-
const wasSkipExecute = skipExecuteStreamIdsRef.current.has(entry.streamId);
|
|
212
|
-
entry.controller.argsText.close();
|
|
213
|
-
const newStreamId = `${toolCallId}:rewrite:${rewriteCounterRef.current++}`;
|
|
214
|
-
streamToLogicalRef.current.set(newStreamId, toolCallId);
|
|
215
|
-
const newController = controller.addToolCallPart({
|
|
216
|
-
toolName: entry.toolName,
|
|
217
|
-
toolCallId: newStreamId
|
|
218
|
-
});
|
|
219
|
-
if (wasSkipExecute) skipExecuteStreamIdsRef.current.add(newStreamId);
|
|
220
|
-
if (process.env.NODE_ENV !== "production") console.warn("started replacement stream tool call", {
|
|
221
|
-
toolCallId,
|
|
222
|
-
streamToolCallId: newStreamId
|
|
223
|
-
});
|
|
224
|
-
entry.controller = newController;
|
|
225
|
-
entry.streamId = newStreamId;
|
|
226
|
-
entry.argsText = "";
|
|
227
|
-
entry.argsComplete = false;
|
|
228
|
-
};
|
|
229
|
-
const processArgsText = (entry, content) => {
|
|
230
|
-
if (!entry.controller) return;
|
|
231
|
-
const hasResult = content.result !== void 0;
|
|
232
|
-
if (content.argsText !== entry.argsText) {
|
|
233
|
-
let shouldWriteArgsText = true;
|
|
234
|
-
if (entry.argsComplete) if (isEquivalentCompleteArgsText(entry.argsText, content.argsText)) {
|
|
235
|
-
entry.argsText = content.argsText;
|
|
236
|
-
shouldWriteArgsText = false;
|
|
237
|
-
} else {
|
|
238
|
-
const canRestart = !entry.hasResult && !executingRef.current.has(entry.streamId);
|
|
239
|
-
if (process.env.NODE_ENV !== "production") console.warn(canRestart ? "argsText updated after controller was closed, restarting tool args stream:" : "argsText updated after controller was closed:", {
|
|
240
|
-
previous: entry.argsText,
|
|
241
|
-
next: content.argsText
|
|
242
|
-
});
|
|
243
|
-
if (!canRestart) {
|
|
244
|
-
entry.argsText = content.argsText;
|
|
245
|
-
shouldWriteArgsText = false;
|
|
246
|
-
} else restartArgsStream(entry, content.toolCallId);
|
|
247
|
-
}
|
|
248
|
-
else if (!content.argsText.startsWith(entry.argsText)) if (isArgsTextComplete(entry.argsText) && isArgsTextComplete(content.argsText) && isEquivalentCompleteArgsText(entry.argsText, content.argsText)) {
|
|
249
|
-
const shouldClose = shouldCloseArgsStream({
|
|
250
|
-
toolName: content.toolName,
|
|
251
|
-
argsText: content.argsText,
|
|
252
|
-
hasResult
|
|
253
|
-
});
|
|
254
|
-
if (shouldClose) entry.controller.argsText.close();
|
|
255
|
-
entry.argsText = content.argsText;
|
|
256
|
-
entry.argsComplete = shouldClose;
|
|
257
|
-
shouldWriteArgsText = false;
|
|
258
|
-
} else {
|
|
259
|
-
if (process.env.NODE_ENV !== "production") console.warn("argsText rewrote previous snapshot, restarting tool args stream:", {
|
|
260
|
-
previous: entry.argsText,
|
|
261
|
-
next: content.argsText,
|
|
262
|
-
toolCallId: content.toolCallId
|
|
263
|
-
});
|
|
264
|
-
restartArgsStream(entry, content.toolCallId);
|
|
265
|
-
}
|
|
266
|
-
if (shouldWriteArgsText) {
|
|
267
|
-
const delta = content.argsText.slice(entry.argsText.length);
|
|
268
|
-
entry.controller.argsText.append(delta);
|
|
269
|
-
const shouldClose = shouldCloseArgsStream({
|
|
270
|
-
toolName: content.toolName,
|
|
271
|
-
argsText: content.argsText,
|
|
272
|
-
hasResult
|
|
273
|
-
});
|
|
274
|
-
if (shouldClose) entry.controller.argsText.close();
|
|
275
|
-
entry.argsText = content.argsText;
|
|
276
|
-
entry.argsComplete = shouldClose;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
if (!entry.argsComplete) {
|
|
280
|
-
if (shouldCloseArgsStream({
|
|
281
|
-
toolName: content.toolName,
|
|
282
|
-
argsText: content.argsText,
|
|
283
|
-
hasResult
|
|
284
|
-
})) {
|
|
285
|
-
entry.controller.argsText.close();
|
|
286
|
-
entry.argsText = content.argsText;
|
|
287
|
-
entry.argsComplete = true;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
const processMessages = (messages) => {
|
|
292
|
-
const isRestore = pendingRestoreRef.current;
|
|
293
|
-
messages.forEach((message) => {
|
|
294
|
-
message.content.forEach((content) => {
|
|
295
|
-
if (content.type !== "tool-call") return;
|
|
296
|
-
const existing = entriesRef.current.get(content.toolCallId);
|
|
297
|
-
if (isRestore) {
|
|
298
|
-
if (!existing?.controller) entriesRef.current.set(content.toolCallId, {
|
|
299
|
-
toolName: content.toolName,
|
|
300
|
-
argsText: content.argsText,
|
|
301
|
-
hasResult: content.result !== void 0
|
|
302
|
-
});
|
|
303
|
-
if (content.messages) processMessages(content.messages);
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
let entry = existing;
|
|
307
|
-
if (entry && !entry.controller) {
|
|
308
|
-
if (!(content.argsText !== entry.argsText || content.result !== void 0 !== entry.hasResult)) {
|
|
309
|
-
if (content.messages) processMessages(content.messages);
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
entriesRef.current.delete(content.toolCallId);
|
|
313
|
-
entry = void 0;
|
|
314
|
-
}
|
|
315
|
-
if (!entry) entry = startActiveEntry(content.toolCallId, content.toolName, content.result !== void 0);
|
|
316
|
-
processArgsText(entry, content);
|
|
317
|
-
if (content.result !== void 0 && !entry.hasResult) {
|
|
318
|
-
const { controller: activeController } = entry;
|
|
319
|
-
if (!activeController) return;
|
|
320
|
-
entry.hasResult = true;
|
|
321
|
-
entry.argsComplete = true;
|
|
322
|
-
activeController.setResponse(new ToolResponse({
|
|
323
|
-
result: content.result,
|
|
324
|
-
artifact: content.artifact,
|
|
325
|
-
isError: content.isError,
|
|
326
|
-
...content.modelContent !== void 0 ? { modelContent: content.modelContent } : {}
|
|
327
|
-
}));
|
|
328
|
-
activeController.close();
|
|
329
|
-
}
|
|
330
|
-
if (content.messages) processMessages(content.messages);
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
};
|
|
334
|
-
processMessages(state.messages);
|
|
335
|
-
pendingRestoreRef.current = false;
|
|
336
|
-
}, [
|
|
337
|
-
state,
|
|
338
|
-
controller,
|
|
339
|
-
getTools
|
|
340
|
-
]);
|
|
341
|
-
const abort = () => {
|
|
342
|
-
humanInputRef.current.forEach(({ reject }) => {
|
|
343
|
-
reject(/* @__PURE__ */ new Error("Tool execution aborted"));
|
|
344
|
-
});
|
|
345
|
-
humanInputRef.current.clear();
|
|
346
|
-
acRef.current.abort();
|
|
347
|
-
acRef.current = new AbortController();
|
|
348
|
-
if (executingCountRef.current === 0) return Promise.resolve();
|
|
349
|
-
return new Promise((resolve) => {
|
|
350
|
-
settledResolversRef.current.push(resolve);
|
|
351
|
-
});
|
|
352
|
-
};
|
|
353
|
-
return {
|
|
354
|
-
reset: () => {
|
|
355
|
-
pendingRestoreRef.current = true;
|
|
356
|
-
entriesRef.current.clear();
|
|
357
|
-
abort().finally(() => {
|
|
358
|
-
executingRef.current.clear();
|
|
359
|
-
streamToLogicalRef.current.clear();
|
|
360
|
-
rewriteCounterRef.current = 0;
|
|
361
|
-
});
|
|
362
|
-
},
|
|
363
|
-
abort,
|
|
364
|
-
resume: (toolCallId, payload) => {
|
|
365
|
-
const handlers = humanInputRef.current.get(toolCallId);
|
|
366
|
-
if (handlers) {
|
|
367
|
-
humanInputRef.current.delete(toolCallId);
|
|
368
|
-
setToolStatuses((prev) => ({
|
|
369
|
-
...prev,
|
|
370
|
-
[toolCallId]: { type: "executing" }
|
|
371
|
-
}));
|
|
372
|
-
handlers.resolve(payload);
|
|
373
|
-
} else throw new Error(`Tool call ${toolCallId} is not waiting for human input`);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
//#endregion
|
|
378
|
-
export { useToolInvocations };
|
|
379
|
-
|
|
380
|
-
//# sourceMappingURL=useToolInvocations.js.map
|