@assistant-ui/core 0.2.18 → 0.2.20
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/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +2 -1
- package/dist/internal.js +2 -1
- package/dist/model-context/interactable-composer-metadata.d.ts +105 -0
- package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -0
- package/dist/model-context/interactable-composer-metadata.js +259 -0
- package/dist/model-context/interactable-composer-metadata.js.map +1 -0
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +1 -0
- package/dist/model-context/registry.js.map +1 -1
- package/dist/model-context/types.d.ts +6 -0
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +4 -0
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/AssistantProvider.d.ts +1 -1
- package/dist/react/AssistantProvider.js +1 -1
- package/dist/react/AssistantRuntimeProvider.d.ts +1 -1
- package/dist/react/RuntimeAdapter.js +1 -1
- package/dist/react/client/Interactables.d.ts +8 -2
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +190 -94
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.js +1 -1
- package/dist/react/client/interactable-model-context.d.ts +9 -6
- package/dist/react/client/interactable-model-context.d.ts.map +1 -1
- package/dist/react/client/interactable-model-context.js +154 -32
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/index.d.ts +15 -6
- package/dist/react/index.js +12 -5
- package/dist/react/interactables-legacy/Interactables.d.ts +12 -0
- package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -0
- package/dist/react/interactables-legacy/Interactables.js +264 -0
- package/dist/react/interactables-legacy/Interactables.js.map +1 -0
- package/dist/react/interactables-legacy/interactable-model-context.d.ts +12 -0
- package/dist/react/interactables-legacy/interactable-model-context.d.ts.map +1 -0
- package/dist/react/interactables-legacy/interactable-model-context.js +54 -0
- package/dist/react/interactables-legacy/interactable-model-context.js.map +1 -0
- package/dist/react/interactables-legacy/scopes.d.ts +58 -0
- package/dist/react/interactables-legacy/scopes.d.ts.map +1 -0
- package/dist/react/interactables-legacy/scopes.js +0 -0
- package/dist/react/interactables-legacy/useAssistantInteractable.d.ts +31 -0
- package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -0
- package/dist/react/{model-context → interactables-legacy}/useAssistantInteractable.js +6 -2
- package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -0
- package/dist/react/interactables-legacy/useInteractableState.d.ts +21 -0
- package/dist/react/interactables-legacy/useInteractableState.d.ts.map +1 -0
- package/dist/react/interactables-legacy/useInteractableState.js +84 -0
- package/dist/react/interactables-legacy/useInteractableState.js.map +1 -0
- package/dist/react/model-context/interactableTool.d.ts +53 -0
- package/dist/react/model-context/interactableTool.d.ts.map +1 -0
- package/dist/react/model-context/interactableTool.js +188 -0
- package/dist/react/model-context/interactableTool.js.map +1 -0
- package/dist/react/model-context/useAssistantContext.js +1 -1
- package/dist/react/model-context/useAssistantDataUI.js +1 -1
- package/dist/react/model-context/useAssistantInstructions.js +1 -1
- package/dist/react/model-context/useAssistantTool.js +1 -1
- package/dist/react/model-context/useAssistantToolUI.js +1 -1
- package/dist/react/model-context/useAuiToolOverrides.js +1 -1
- package/dist/react/model-context/useInteractable.d.ts +73 -0
- package/dist/react/model-context/useInteractable.d.ts.map +1 -0
- package/dist/react/model-context/useInteractable.js +100 -0
- package/dist/react/model-context/useInteractable.js.map +1 -0
- package/dist/react/model-context/useInteractableState.d.ts +8 -5
- package/dist/react/model-context/useInteractableState.d.ts.map +1 -1
- package/dist/react/model-context/useInteractableState.js +48 -48
- package/dist/react/model-context/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useInteractableVersions.d.ts +19 -0
- package/dist/react/model-context/useInteractableVersions.d.ts.map +1 -0
- package/dist/react/model-context/useInteractableVersions.js +51 -0
- package/dist/react/model-context/useInteractableVersions.js.map +1 -0
- package/dist/react/primitive-hooks/useThreadMessageIds.d.ts +15 -0
- package/dist/react/primitive-hooks/useThreadMessageIds.d.ts.map +1 -0
- package/dist/react/primitive-hooks/useThreadMessageIds.js +26 -0
- package/dist/react/primitive-hooks/useThreadMessageIds.js.map +1 -0
- package/dist/react/primitive-hooks/useVoice.js +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js +1 -1
- package/dist/react/primitives/generativeUI/GenerativeUI.d.ts.map +1 -1
- package/dist/react/primitives/generativeUI/GenerativeUI.js +2 -2
- package/dist/react/primitives/generativeUI/GenerativeUI.js.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.js +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +1 -1
- package/dist/react/primitives/message/MessageParts.js +1 -1
- package/dist/react/primitives/message/MessageQuote.js +1 -1
- package/dist/react/primitives/part/PartMessages.d.ts +5 -2
- package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
- package/dist/react/primitives/part/PartMessages.js +8 -8
- package/dist/react/primitives/part/PartMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts +31 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +64 -2
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
- package/dist/react/providers/MessageByIdProvider.d.ts +9 -0
- package/dist/react/providers/MessageByIdProvider.d.ts.map +1 -0
- package/dist/react/providers/MessageByIdProvider.js +57 -0
- package/dist/react/providers/MessageByIdProvider.js.map +1 -0
- package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +3 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +16 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +1 -1
- package/dist/react/runtimes/createRuntimeExtras.d.ts +20 -0
- package/dist/react/runtimes/createRuntimeExtras.d.ts.map +1 -0
- package/dist/react/runtimes/createRuntimeExtras.js +43 -0
- package/dist/react/runtimes/createRuntimeExtras.js.map +1 -0
- package/dist/react/runtimes/useLocalRuntime.js +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js +6 -2
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/runtimes/useStreamingTiming.d.ts +26 -0
- package/dist/react/runtimes/useStreamingTiming.d.ts.map +1 -0
- package/dist/react/runtimes/useStreamingTiming.js +43 -0
- package/dist/react/runtimes/useStreamingTiming.js.map +1 -0
- package/dist/react/types/scopes/interactables.d.ts +40 -24
- package/dist/react/types/scopes/interactables.d.ts.map +1 -1
- package/dist/react/types/store-augmentation.d.ts +3 -1
- package/dist/react/types/store-augmentation.d.ts.map +1 -1
- package/dist/react/utils/useJSONEqual.d.ts +11 -0
- package/dist/react/utils/useJSONEqual.d.ts.map +1 -0
- package/dist/react/utils/useJSONEqual.js +30 -0
- package/dist/react/utils/useJSONEqual.js.map +1 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts +5 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +13 -0
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +6 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +4 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts +1 -0
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +6 -3
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/streaming-timing.d.ts +59 -0
- package/dist/runtime/utils/streaming-timing.d.ts.map +1 -0
- package/dist/runtime/utils/streaming-timing.js +76 -0
- package/dist/runtime/utils/streaming-timing.js.map +1 -0
- 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 +26 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +9 -0
- 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 +19 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +12 -0
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +1 -1
- package/dist/store/clients/thread-message-client.js +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +1 -1
- package/dist/tests/remote-thread-list-test-helpers.d.ts +1 -1
- package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
- package/dist/tests/remote-thread-list-test-helpers.js +3 -2
- package/dist/tests/remote-thread-list-test-helpers.js.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +17 -0
- package/src/internal.ts +7 -0
- package/src/model-context/interactable-composer-metadata.test.ts +550 -0
- package/src/model-context/interactable-composer-metadata.ts +395 -0
- package/src/model-context/registry.ts +5 -0
- package/src/model-context/types.ts +12 -0
- package/src/react/client/Interactables.test.ts +358 -0
- package/src/react/client/Interactables.ts +339 -86
- package/src/react/client/interactable-model-context.test.ts +418 -0
- package/src/react/client/interactable-model-context.ts +252 -58
- package/src/react/index.ts +72 -3
- package/src/react/interactables-legacy/Interactables.ts +332 -0
- package/src/react/interactables-legacy/interactable-model-context.test.ts +54 -0
- package/src/react/interactables-legacy/interactable-model-context.ts +80 -0
- package/src/react/interactables-legacy/scopes.ts +66 -0
- package/src/react/{model-context → interactables-legacy}/useAssistantInteractable.ts +10 -1
- package/src/react/interactables-legacy/useInteractableState.ts +67 -0
- package/src/react/model-context/interactableTool.tsx +175 -0
- package/src/react/model-context/useInteractable.ts +233 -0
- package/src/react/model-context/useInteractableState.ts +31 -23
- package/src/react/model-context/useInteractableVersions.ts +48 -0
- package/src/react/primitive-hooks/useThreadMessageIds.ts +27 -0
- package/src/react/primitives/generativeUI/GenerativeUI.tsx +5 -1
- package/src/react/primitives/part/PartMessages.test.tsx +17 -0
- package/src/react/primitives/part/PartMessages.tsx +13 -8
- package/src/react/primitives/thread/ThreadMessages.tsx +67 -0
- package/src/react/providers/MessageByIdProvider.tsx +23 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +21 -1
- package/src/react/runtimes/createRuntimeExtras.test.ts +58 -0
- package/src/react/runtimes/createRuntimeExtras.ts +68 -0
- package/src/react/runtimes/createRuntimeExtras.use.test.ts +50 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +13 -1
- package/src/react/runtimes/useStreamingTiming.ts +68 -0
- package/src/react/types/scopes/interactables.ts +45 -23
- package/src/react/types/store-augmentation.ts +4 -2
- package/src/react/utils/useJSONEqual.ts +20 -0
- package/src/runtime/base/base-composer-runtime-core.ts +13 -0
- package/src/runtime/base/default-edit-composer-runtime-core.ts +18 -1
- package/src/runtime/base/default-thread-composer-runtime-core.ts +11 -1
- package/src/runtime/utils/message-repository.ts +11 -7
- package/src/runtime/utils/streaming-timing.test.ts +301 -0
- package/src/runtime/utils/streaming-timing.ts +161 -0
- package/src/runtime/utils/thread-message-like.ts +2 -1
- package/src/runtimes/external-store/external-store-adapter.ts +28 -0
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +33 -1
- package/src/runtimes/local/local-thread-runtime-core.ts +4 -1
- package/src/runtimes/remote-thread-list/types.ts +13 -0
- package/src/tests/MessageRepository.test.ts +2 -0
- package/src/tests/composer-can-send.test.ts +1 -0
- package/src/tests/default-edit-composer-runtime-core.test.ts +78 -1
- package/src/tests/default-thread-composer-runtime-core.test.ts +82 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +337 -0
- package/src/tests/groupParts.test.ts +32 -0
- package/src/tests/remote-thread-list-reactive-threadId.test.ts +90 -0
- package/src/tests/remote-thread-list-test-helpers.ts +2 -1
- package/src/tests/thread-message-like.test.ts +50 -0
- package/dist/react/model-context/useAssistantInteractable.d.ts +0 -22
- package/dist/react/model-context/useAssistantInteractable.d.ts.map +0 -1
- package/dist/react/model-context/useAssistantInteractable.js.map +0 -1
|
@@ -1,83 +1,277 @@
|
|
|
1
1
|
import type { Tool } from "assistant-stream";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
import { toJSONSchema } from "assistant-stream";
|
|
3
|
+
import type { Unstable_InteractableDefinition } from "../types/scopes/interactables";
|
|
4
|
+
import {
|
|
5
|
+
interactableToolName,
|
|
6
|
+
shallowMergeInteractableState,
|
|
7
|
+
type Unstable_InteractableSnapshotEntry,
|
|
8
|
+
} from "../../model-context/interactable-composer-metadata";
|
|
9
|
+
import { generateId } from "../../utils/id";
|
|
10
|
+
import { isRecord } from "../../utils/json/is-json";
|
|
11
|
+
|
|
12
|
+
export type PartialJSONSchema = ReturnType<typeof toJSONSchema>;
|
|
13
|
+
|
|
14
|
+
const ID_PROPERTY = {
|
|
15
|
+
type: "string" as const,
|
|
16
|
+
description:
|
|
17
|
+
"The id of the instance to update, as shown in its state snapshot in the conversation.",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const hasIdProperty = (schema: Record<string, unknown>) => {
|
|
21
|
+
const properties = schema.properties;
|
|
22
|
+
return isRecord(properties) && properties.id !== undefined;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const withRequiredItemId = (schema: Record<string, unknown>) => ({
|
|
26
|
+
...schema,
|
|
27
|
+
required: ["id"],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// The framework assigns ids to new items, so the model never sees the `id`
|
|
31
|
+
// field when adding (it can't address an item that doesn't exist yet).
|
|
32
|
+
const withoutItemId = (schema: Record<string, unknown>) => {
|
|
33
|
+
const { id: _omitted, ...properties } = isRecord(schema.properties)
|
|
34
|
+
? schema.properties
|
|
35
|
+
: {};
|
|
36
|
+
const required = Array.isArray(schema.required)
|
|
37
|
+
? schema.required.filter((key) => key !== "id")
|
|
38
|
+
: schema.required;
|
|
39
|
+
return { ...schema, properties, required };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const toArrayUpdateSchema = (schema: unknown, field: string) => {
|
|
43
|
+
if (!isRecord(schema) || schema.type !== "array") return schema;
|
|
44
|
+
const itemSchema = schema.items;
|
|
45
|
+
if (Array.isArray(itemSchema) || !isRecord(itemSchema)) return schema;
|
|
46
|
+
|
|
47
|
+
const idKeyed = hasIdProperty(itemSchema);
|
|
48
|
+
const properties: Record<string, unknown> = {
|
|
49
|
+
add: {
|
|
50
|
+
type: "array",
|
|
51
|
+
items: idKeyed ? withoutItemId(itemSchema) : itemSchema,
|
|
52
|
+
},
|
|
53
|
+
remove: {
|
|
54
|
+
type: "array",
|
|
55
|
+
items: idKeyed ? ID_PROPERTY : itemSchema,
|
|
56
|
+
},
|
|
57
|
+
clear: { type: "boolean" },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (idKeyed) {
|
|
61
|
+
properties.update = {
|
|
62
|
+
type: "array",
|
|
63
|
+
items: withRequiredItemId(itemSchema),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
type: "object" as const,
|
|
69
|
+
description:
|
|
70
|
+
`Operations for array field "${field}". To change one item use update ` +
|
|
71
|
+
`with its id; add new items (their ids are assigned for you), remove items ` +
|
|
72
|
+
`by id, or clear to empty. Change only the items you mean to — never resend ` +
|
|
73
|
+
`the whole array to edit one item.`,
|
|
74
|
+
properties,
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Top-level array fields whose items carry an `id` — the fields the framework
|
|
80
|
+
// mints ids for on add.
|
|
81
|
+
const idKeyedArrayFieldNames = (
|
|
82
|
+
properties: Record<string, unknown>,
|
|
83
|
+
): Set<string> => {
|
|
84
|
+
const names = new Set<string>();
|
|
85
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
86
|
+
if (
|
|
87
|
+
isRecord(value) &&
|
|
88
|
+
value.type === "array" &&
|
|
89
|
+
isRecord(value.items) &&
|
|
90
|
+
hasIdProperty(value.items)
|
|
91
|
+
) {
|
|
92
|
+
names.add(key);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return names;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const withArrayUpdateSchemas = (properties: Record<string, unknown>) =>
|
|
99
|
+
Object.fromEntries(
|
|
100
|
+
Object.entries(properties).map(([key, value]) => [
|
|
101
|
+
key,
|
|
102
|
+
toArrayUpdateSchema(value, key),
|
|
103
|
+
]),
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Wraps an interactable's partial state schema with the required `id`
|
|
108
|
+
* parameter. Falls back to a permissive schema when the partial conversion
|
|
109
|
+
* failed at registration time.
|
|
110
|
+
*/
|
|
111
|
+
function withRequiredId(partial: PartialJSONSchema | undefined) {
|
|
112
|
+
if (!partial || typeof partial !== "object" || partial.type !== "object") {
|
|
113
|
+
return {
|
|
114
|
+
type: "object" as const,
|
|
115
|
+
properties: { id: ID_PROPERTY },
|
|
116
|
+
required: ["id"],
|
|
117
|
+
additionalProperties: true,
|
|
118
|
+
};
|
|
17
119
|
}
|
|
120
|
+
if (process.env.NODE_ENV !== "production" && partial.properties?.id) {
|
|
121
|
+
console.warn(
|
|
122
|
+
`[Interactables] a top-level "id" field in an interactable's stateSchema is ` +
|
|
123
|
+
`reserved for instance addressing by the update tool and cannot be updated ` +
|
|
124
|
+
`by the model. Rename the field to make it model-writable.`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const { id: _reserved, ...properties } = partial.properties ?? {};
|
|
18
128
|
return {
|
|
19
|
-
...
|
|
20
|
-
|
|
129
|
+
...partial,
|
|
130
|
+
properties: { id: ID_PROPERTY, ...withArrayUpdateSchemas(properties) },
|
|
131
|
+
required: ["id"],
|
|
21
132
|
};
|
|
22
133
|
}
|
|
23
134
|
|
|
24
135
|
export function buildInteractableModelContext(
|
|
25
|
-
definitions: Record<string,
|
|
26
|
-
partialSchemaCache: Map<string,
|
|
136
|
+
definitions: Record<string, Unstable_InteractableDefinition>,
|
|
137
|
+
partialSchemaCache: Map<string, PartialJSONSchema>,
|
|
27
138
|
setDefState: (id: string, updater: (prev: unknown) => unknown) => void,
|
|
28
|
-
|
|
139
|
+
streamBaselines = new Map<string, { targetId: string; state: unknown }>(),
|
|
140
|
+
):
|
|
141
|
+
| {
|
|
142
|
+
tools: Record<string, Tool<any, any>>;
|
|
143
|
+
unstable_composerMetadata?: Record<string, unknown>;
|
|
144
|
+
}
|
|
145
|
+
| undefined {
|
|
29
146
|
const entries = Object.values(definitions);
|
|
30
147
|
if (entries.length === 0) return undefined;
|
|
31
148
|
|
|
32
|
-
const byName = new Map<string,
|
|
149
|
+
const byName = new Map<string, Unstable_InteractableDefinition[]>();
|
|
33
150
|
for (const def of entries) {
|
|
34
151
|
const list = byName.get(def.name) ?? [];
|
|
35
152
|
list.push(def);
|
|
36
153
|
byName.set(def.name, list);
|
|
37
154
|
}
|
|
38
155
|
|
|
39
|
-
const systemParts: string[] = [];
|
|
40
156
|
const tools: Record<string, Tool<any, any>> = {};
|
|
41
157
|
|
|
42
158
|
for (const [name, instances] of byName) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
159
|
+
const toolName = interactableToolName(name);
|
|
160
|
+
if (tools[toolName]) {
|
|
161
|
+
if (process.env.NODE_ENV !== "production") {
|
|
162
|
+
console.warn(
|
|
163
|
+
`[Interactables] interactable names "${name}" and another registered name ` +
|
|
164
|
+
`both sanitize to the tool name "${toolName}". Rename one of them.`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const first = instances[0]!;
|
|
171
|
+
const partialSchema = partialSchemaCache.get(first.id);
|
|
172
|
+
const idKeyedFields =
|
|
173
|
+
partialSchema && isRecord(partialSchema.properties)
|
|
174
|
+
? idKeyedArrayFieldNames(partialSchema.properties)
|
|
175
|
+
: new Set<string>();
|
|
176
|
+
|
|
177
|
+
// `id` resolves to a definition of this name; an id-less call is accepted
|
|
178
|
+
// only while exactly one instance exists.
|
|
179
|
+
const resolveTarget = (
|
|
180
|
+
id: unknown,
|
|
181
|
+
): Unstable_InteractableDefinition | undefined => {
|
|
182
|
+
if (typeof id === "string") {
|
|
183
|
+
const def = definitions[id];
|
|
184
|
+
return def?.name === name ? def : undefined;
|
|
185
|
+
}
|
|
186
|
+
return instances.length === 1 ? first : undefined;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
tools[toolName] = {
|
|
190
|
+
type: "frontend",
|
|
191
|
+
description:
|
|
192
|
+
`Update the state of interactable component "${name}". ${first.description} ` +
|
|
193
|
+
`Pass the id of the instance to update — instance ids and current state ` +
|
|
194
|
+
`appear in the conversation as state snapshots. Only include the fields ` +
|
|
195
|
+
`you want to change; omitted fields keep their current values.`,
|
|
196
|
+
parameters: withRequiredId(partialSchema),
|
|
197
|
+
streamCall: async (reader, { toolCallId }) => {
|
|
198
|
+
try {
|
|
199
|
+
for await (const partialArgs of reader.args.streamValues()) {
|
|
200
|
+
if (!partialArgs || typeof partialArgs !== "object") continue;
|
|
201
|
+
const args = partialArgs as Record<string, unknown>;
|
|
202
|
+
const keys = Object.keys(args);
|
|
203
|
+
const idIndex = keys.indexOf("id");
|
|
204
|
+
if (idIndex === keys.length - 1) continue;
|
|
205
|
+
|
|
206
|
+
const { id, ...partial } = args;
|
|
207
|
+
if (Object.keys(partial).length === 0) continue;
|
|
208
|
+
const target = resolveTarget(id);
|
|
209
|
+
if (!target) continue;
|
|
210
|
+
|
|
211
|
+
const baseline = streamBaselines.get(toolCallId);
|
|
212
|
+
const arrayBaseline =
|
|
213
|
+
baseline?.targetId === target.id ? baseline.state : target.state;
|
|
214
|
+
if (!baseline || baseline.targetId !== target.id) {
|
|
215
|
+
streamBaselines.set(toolCallId, {
|
|
216
|
+
targetId: target.id,
|
|
217
|
+
state: target.state,
|
|
218
|
+
});
|
|
69
219
|
}
|
|
70
|
-
|
|
71
|
-
|
|
220
|
+
|
|
221
|
+
setDefState(target.id, (prev) =>
|
|
222
|
+
shallowMergeInteractableState(prev, partial, { arrayBaseline }),
|
|
223
|
+
);
|
|
72
224
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
225
|
+
} catch {
|
|
226
|
+
// Non-fatal: execute handles the final state
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
execute: async (args: unknown, { toolCallId }) => {
|
|
230
|
+
const { id, ...partial } = (args ?? {}) as Record<string, unknown>;
|
|
231
|
+
const target = resolveTarget(id);
|
|
232
|
+
if (!target) {
|
|
233
|
+
const validIds = instances.map((d) => d.id);
|
|
234
|
+
return {
|
|
235
|
+
success: false,
|
|
236
|
+
error: `Unknown id ${JSON.stringify(id)} for interactable "${name}". Valid ids: ${validIds.join(", ")}`,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const baseline = streamBaselines.get(toolCallId);
|
|
240
|
+
streamBaselines.delete(toolCallId);
|
|
241
|
+
const addedItemIds: Record<string, string[]> = {};
|
|
242
|
+
setDefState(target.id, (prev) =>
|
|
243
|
+
shallowMergeInteractableState(prev, partial, {
|
|
244
|
+
arrayBaseline:
|
|
245
|
+
baseline?.targetId === target.id ? baseline.state : undefined,
|
|
246
|
+
idFactory: (field) => {
|
|
247
|
+
const itemId = generateId();
|
|
248
|
+
(addedItemIds[field] ??= []).push(itemId);
|
|
249
|
+
return itemId;
|
|
250
|
+
},
|
|
251
|
+
idKeyedFields,
|
|
252
|
+
}),
|
|
253
|
+
);
|
|
254
|
+
// The resolved id lets an id-less call's UI (and the model) address
|
|
255
|
+
// the instance that was actually updated.
|
|
256
|
+
const result: {
|
|
257
|
+
success: true;
|
|
258
|
+
id: string;
|
|
259
|
+
addedItemIds?: Record<string, string[]>;
|
|
260
|
+
} = { success: true, id: target.id };
|
|
261
|
+
if (Object.keys(addedItemIds).length > 0) {
|
|
262
|
+
result.addedItemIds = addedItemIds;
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
},
|
|
266
|
+
};
|
|
80
267
|
}
|
|
81
268
|
|
|
82
|
-
|
|
269
|
+
const interactables: Unstable_InteractableSnapshotEntry[] = entries.map(
|
|
270
|
+
(def) => ({
|
|
271
|
+
id: def.id,
|
|
272
|
+
name: def.name,
|
|
273
|
+
state: def.state,
|
|
274
|
+
}),
|
|
275
|
+
);
|
|
276
|
+
return { tools, unstable_composerMetadata: { interactables } };
|
|
83
277
|
}
|
package/src/react/index.ts
CHANGED
|
@@ -52,11 +52,42 @@ export {
|
|
|
52
52
|
defineMcpToolkit,
|
|
53
53
|
type McpToolkitDefinition,
|
|
54
54
|
} from "./model-context/define-mcp-toolkit";
|
|
55
|
+
/**
|
|
56
|
+
* @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API.
|
|
57
|
+
* Scheduled for removal on/after 2026-09-14. See
|
|
58
|
+
* {@link https://www.assistant-ui.com/docs/tools/interactables#migrating-from-the-previous-api | Interactables migration guide}.
|
|
59
|
+
*/
|
|
55
60
|
export {
|
|
56
61
|
useAssistantInteractable,
|
|
57
62
|
type AssistantInteractableProps,
|
|
58
|
-
} from "./
|
|
59
|
-
|
|
63
|
+
} from "./interactables-legacy/useAssistantInteractable";
|
|
64
|
+
/**
|
|
65
|
+
* @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API.
|
|
66
|
+
* Scheduled for removal on/after 2026-09-14. See
|
|
67
|
+
* {@link https://www.assistant-ui.com/docs/tools/interactables#migrating-from-the-previous-api | Interactables migration guide}.
|
|
68
|
+
*/
|
|
69
|
+
export { useInteractableState } from "./interactables-legacy/useInteractableState";
|
|
70
|
+
export {
|
|
71
|
+
/** @deprecated Unstable / Experimental — may change in any release. */
|
|
72
|
+
unstable_useInteractable,
|
|
73
|
+
type Unstable_InteractableConfig,
|
|
74
|
+
type Unstable_InferInteractableState,
|
|
75
|
+
type Unstable_InteractableVersionInfo,
|
|
76
|
+
} from "./model-context/useInteractable";
|
|
77
|
+
export {
|
|
78
|
+
/** @deprecated Unstable / Experimental — may change in any release. */
|
|
79
|
+
unstable_useInteractableState,
|
|
80
|
+
} from "./model-context/useInteractableState";
|
|
81
|
+
export {
|
|
82
|
+
/** @deprecated Unstable / Experimental — may change in any release. */
|
|
83
|
+
unstable_useInteractableVersions,
|
|
84
|
+
} from "./model-context/useInteractableVersions";
|
|
85
|
+
export {
|
|
86
|
+
/** @deprecated Unstable / Experimental — may change in any release. */
|
|
87
|
+
unstable_interactableTool,
|
|
88
|
+
type Unstable_InteractableToolConfig,
|
|
89
|
+
type Unstable_InteractableToolRenderProps,
|
|
90
|
+
} from "./model-context/interactableTool";
|
|
60
91
|
export {
|
|
61
92
|
useToolArgsStatus,
|
|
62
93
|
type ToolArgsStatus,
|
|
@@ -65,7 +96,16 @@ export {
|
|
|
65
96
|
// client
|
|
66
97
|
export { Tools, type McpAppResourceOutput } from "./client/Tools";
|
|
67
98
|
export { DataRenderers } from "./client/DataRenderers";
|
|
68
|
-
|
|
99
|
+
/**
|
|
100
|
+
* @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API.
|
|
101
|
+
* Scheduled for removal on/after 2026-09-14. See
|
|
102
|
+
* {@link https://www.assistant-ui.com/docs/tools/interactables#migrating-from-the-previous-api | Interactables migration guide}.
|
|
103
|
+
*/
|
|
104
|
+
export { Interactables } from "./interactables-legacy/Interactables";
|
|
105
|
+
export {
|
|
106
|
+
/** @deprecated Unstable / Experimental — may change in any release. */
|
|
107
|
+
unstable_Interactables,
|
|
108
|
+
} from "./client/Interactables";
|
|
69
109
|
|
|
70
110
|
// types
|
|
71
111
|
export type {
|
|
@@ -107,15 +147,36 @@ export type {
|
|
|
107
147
|
DataRenderersClientSchema,
|
|
108
148
|
} from "./types/scopes/dataRenderers";
|
|
109
149
|
export type {
|
|
150
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
110
151
|
InteractableStateSchema,
|
|
152
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
111
153
|
InteractablesState,
|
|
154
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
112
155
|
InteractableDefinition,
|
|
156
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
113
157
|
InteractableRegistration,
|
|
158
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
114
159
|
InteractablesMethods,
|
|
160
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
115
161
|
InteractablePersistedState,
|
|
162
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
116
163
|
InteractablePersistenceAdapter,
|
|
164
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
117
165
|
InteractablePersistenceStatus,
|
|
166
|
+
/** @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API. */
|
|
118
167
|
InteractablesClientSchema,
|
|
168
|
+
} from "./interactables-legacy/scopes";
|
|
169
|
+
export type {
|
|
170
|
+
Unstable_InteractableStateSchema,
|
|
171
|
+
Unstable_InteractablesState,
|
|
172
|
+
Unstable_InteractableDefinition,
|
|
173
|
+
Unstable_InteractableRegistration,
|
|
174
|
+
Unstable_InteractablesMethods,
|
|
175
|
+
Unstable_InteractablePersistedState,
|
|
176
|
+
Unstable_InteractablePersistenceAdapter,
|
|
177
|
+
Unstable_InteractablePersistenceStatus,
|
|
178
|
+
Unstable_InteractablesClientSchema,
|
|
179
|
+
Unstable_InteractablesConfig,
|
|
119
180
|
} from "./types/scopes/interactables";
|
|
120
181
|
|
|
121
182
|
// providers
|
|
@@ -157,6 +218,12 @@ export {
|
|
|
157
218
|
} from "./runtimes/external-message-converter";
|
|
158
219
|
export type { JoinStrategy } from "./runtimes/external-message-converter";
|
|
159
220
|
export { createMessageConverter } from "./runtimes/createMessageConverter";
|
|
221
|
+
export {
|
|
222
|
+
useStreamingTiming,
|
|
223
|
+
type StreamingTimingAccessors,
|
|
224
|
+
type StreamingTimingOptions,
|
|
225
|
+
type StreamingTimingState,
|
|
226
|
+
} from "./runtimes/useStreamingTiming";
|
|
160
227
|
export { RemoteThreadListHookInstanceManager } from "./runtimes/RemoteThreadListHookInstanceManager";
|
|
161
228
|
export { RemoteThreadListThreadListRuntimeCore } from "./runtimes/RemoteThreadListThreadListRuntimeCore";
|
|
162
229
|
export { useRemoteThreadListRuntime } from "./runtimes/useRemoteThreadListRuntime";
|
|
@@ -184,6 +251,7 @@ export {
|
|
|
184
251
|
ThreadPrimitiveMessages,
|
|
185
252
|
ThreadPrimitiveMessagesImpl,
|
|
186
253
|
ThreadPrimitiveMessageByIndex,
|
|
254
|
+
ThreadPrimitiveUnstable_MessageById,
|
|
187
255
|
} from "./primitives/thread/ThreadMessages";
|
|
188
256
|
export {
|
|
189
257
|
MessagePrimitiveParts,
|
|
@@ -234,6 +302,7 @@ export { getMessageQuote } from "./utils/getMessageQuote";
|
|
|
234
302
|
|
|
235
303
|
// Primitive hooks (shared behavior logic)
|
|
236
304
|
export { useThreadMessages } from "./primitive-hooks/useThreadMessages";
|
|
305
|
+
export { unstable_useThreadMessageIds } from "./primitive-hooks/useThreadMessageIds";
|
|
237
306
|
export { useThreadIsRunning } from "./primitive-hooks/useThreadIsRunning";
|
|
238
307
|
export { useThreadIsEmpty } from "./primitive-hooks/useThreadIsEmpty";
|
|
239
308
|
export { useComposerSend } from "./primitive-hooks/useComposerSend";
|