@assistant-ui/core 0.3.6 → 0.3.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/index.d.ts +1 -1
- package/dist/react/RuntimeAdapter.js +1 -1
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/client/Interactables.js +1 -1
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.d.ts +1 -1
- package/dist/react/client/Tools.js +1 -1
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +9 -9
- package/dist/react/index.js +4 -4
- package/dist/react/model-context/interactableTool.d.ts +1 -1
- package/dist/react/model-context/useAssistantTool.d.ts +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +1 -0
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +2 -1
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/createMessageConverter.d.ts +1 -1
- package/dist/react/runtimes/createRuntimeExtras.d.ts +4 -1
- package/dist/react/runtimes/createRuntimeExtras.d.ts.map +1 -1
- package/dist/react/runtimes/createRuntimeExtras.js +6 -17
- package/dist/react/runtimes/createRuntimeExtras.js.map +1 -1
- package/dist/react/types/scopes/dataRenderers.d.ts +1 -1
- package/dist/react/types/scopes/interactables.d.ts +1 -1
- package/dist/react/types/scopes/tools.d.ts +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +0 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +18 -25
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/utils/runtime-extras-brand.d.ts +21 -0
- package/dist/runtime/utils/runtime-extras-brand.d.ts.map +1 -0
- package/dist/runtime/utils/runtime-extras-brand.js +37 -0
- package/dist/runtime/utils/runtime-extras-brand.js.map +1 -0
- package/dist/runtime/utils/thread-message-like.js +3 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
- package/dist/store/clients/runtime-adapter.js +1 -1
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/clients/suggestions.js +1 -1
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-message-client.js +1 -1
- package/dist/store/clients/thread-message-client.js.map +1 -1
- package/dist/store/index.d.ts +10 -1
- package/dist/store/index.js +7 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/types/message.d.ts +1 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/package.json +3 -3
- package/src/react/RuntimeAdapter.test.ts +85 -0
- package/src/react/RuntimeAdapter.ts +1 -1
- package/src/react/client/Interactables.test.ts +3 -2
- package/src/react/client/Interactables.ts +4 -4
- package/src/react/client/Tools.ts +4 -4
- package/src/react/index.ts +1 -0
- package/src/react/runtimes/cloud/auiV0.ts +8 -1
- package/src/react/runtimes/createRuntimeExtras.test.ts +14 -1
- package/src/react/runtimes/createRuntimeExtras.ts +15 -26
- package/src/runtime/base/default-edit-composer-runtime-core.ts +32 -50
- package/src/runtime/utils/runtime-extras-brand.ts +47 -0
- package/src/runtime/utils/thread-message-like.ts +5 -1
- package/src/store/clients/runtime-adapter.ts +2 -5
- package/src/store/clients/suggestions.ts +1 -1
- package/src/store/clients/thread-message-client.ts +1 -1
- package/src/store/index.ts +31 -0
- package/src/store/runtime-clients/composer-runtime-client.ts +2 -5
- package/src/store/runtime-clients/lookup-domains.test.ts +109 -0
- package/src/store/runtime-clients/message-runtime-client.ts +2 -5
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +2 -1
- package/src/store/runtime-clients/thread-list-runtime-client.ts +2 -5
- package/src/store/runtime-clients/thread-runtime-client.ts +2 -2
- package/src/tests/auiV0Encode.test.ts +97 -0
- package/src/tests/default-edit-composer-runtime-core.test.ts +6 -2
- package/src/tests/framework-neutral-boundary.test.ts +60 -24
- package/src/tests/thread-message-like.test.ts +43 -0
- package/src/types/message.ts +1 -0
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
withKey,
|
|
6
6
|
type ResourceElement,
|
|
7
7
|
} from "@assistant-ui/tap";
|
|
8
|
+
import type { ClientOutput } from "@assistant-ui/store";
|
|
8
9
|
import {
|
|
9
|
-
useAssistantClientRef,
|
|
10
|
-
type ClientOutput,
|
|
11
10
|
attachTransformScopes,
|
|
12
|
-
|
|
11
|
+
useAssistantClientRef,
|
|
12
|
+
} from "@assistant-ui/store/client";
|
|
13
13
|
import type { McpAppResourceOutput, ToolsState } from "../types/scopes/tools";
|
|
14
14
|
import type { Tool } from "assistant-stream";
|
|
15
15
|
import {
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
type Toolkit,
|
|
19
19
|
} from "../model-context/toolbox";
|
|
20
20
|
import type { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes";
|
|
21
|
-
import { ModelContext } from "../../store";
|
|
21
|
+
import { ModelContext } from "../../store/clients/model-context-client";
|
|
22
22
|
|
|
23
23
|
export type { McpAppResourceOutput };
|
|
24
24
|
|
package/src/react/index.ts
CHANGED
|
@@ -228,6 +228,7 @@ export {
|
|
|
228
228
|
} from "./runtimes/useStreamingTiming";
|
|
229
229
|
export {
|
|
230
230
|
createRuntimeExtras,
|
|
231
|
+
unstable_createRuntimeExtrasFromBrand,
|
|
231
232
|
type RuntimeExtras,
|
|
232
233
|
} from "./runtimes/createRuntimeExtras";
|
|
233
234
|
export { RemoteThreadListHookInstanceManager } from "./runtimes/RemoteThreadListHookInstanceManager";
|
|
@@ -32,6 +32,7 @@ type AuiV0MessagePart =
|
|
|
32
32
|
| {
|
|
33
33
|
readonly type: "reasoning";
|
|
34
34
|
readonly text: string;
|
|
35
|
+
readonly unstable_summary?: string;
|
|
35
36
|
}
|
|
36
37
|
| {
|
|
37
38
|
readonly type: "source";
|
|
@@ -226,7 +227,13 @@ export function auiV0Encode(message: ThreadMessage): AuiV0Message {
|
|
|
226
227
|
return { type: "text", text: part.text };
|
|
227
228
|
|
|
228
229
|
case "reasoning":
|
|
229
|
-
return {
|
|
230
|
+
return {
|
|
231
|
+
type: "reasoning",
|
|
232
|
+
text: part.text,
|
|
233
|
+
...(part.unstable_summary !== undefined
|
|
234
|
+
? { unstable_summary: part.unstable_summary }
|
|
235
|
+
: undefined),
|
|
236
|
+
};
|
|
230
237
|
|
|
231
238
|
case "source":
|
|
232
239
|
if (part.sourceType === "url") {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import type { AssistantClient } from "@assistant-ui/store";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createRuntimeExtras,
|
|
5
|
+
unstable_createRuntimeExtrasFromBrand,
|
|
6
|
+
} from "./createRuntimeExtras";
|
|
7
|
+
import { createRuntimeExtrasBrand } from "../../runtime/utils/runtime-extras-brand";
|
|
4
8
|
|
|
5
9
|
type Extras = { value: number; greet: () => string };
|
|
6
10
|
|
|
@@ -55,4 +59,13 @@ describe("createRuntimeExtras", () => {
|
|
|
55
59
|
|
|
56
60
|
expect(() => channel.get(clientWith(undefined))).toThrow("useTestRuntime");
|
|
57
61
|
});
|
|
62
|
+
|
|
63
|
+
it("reads extras provided through a standalone brand instance", () => {
|
|
64
|
+
const brand = createRuntimeExtrasBrand<Extras>("useTestRuntime");
|
|
65
|
+
const channel = unstable_createRuntimeExtrasFromBrand(brand);
|
|
66
|
+
const branded = brand.provide({ value: 7, greet: () => "hi" });
|
|
67
|
+
|
|
68
|
+
expect(channel.is(branded)).toBe(true);
|
|
69
|
+
expect(channel.get(clientWith(branded)).value).toBe(7);
|
|
70
|
+
});
|
|
58
71
|
});
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { useAuiState } from "@assistant-ui/store";
|
|
4
4
|
import type { AssistantClient } from "@assistant-ui/store";
|
|
5
|
+
import {
|
|
6
|
+
createRuntimeExtrasBrand,
|
|
7
|
+
type RuntimeExtrasBrand,
|
|
8
|
+
} from "../../runtime/utils/runtime-extras-brand";
|
|
5
9
|
|
|
6
10
|
/** @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice. */
|
|
7
11
|
export type RuntimeExtras<T extends object> = {
|
|
@@ -17,33 +21,10 @@ export type RuntimeExtras<T extends object> = {
|
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
/** @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice. */
|
|
20
|
-
export const
|
|
21
|
-
|
|
24
|
+
export const unstable_createRuntimeExtrasFromBrand = <T extends object>(
|
|
25
|
+
brand: RuntimeExtrasBrand<T>,
|
|
22
26
|
): RuntimeExtras<T> => {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const is = (extras: unknown): extras is T =>
|
|
26
|
-
typeof extras === "object" && extras !== null && brand in extras;
|
|
27
|
-
|
|
28
|
-
const assert = (extras: unknown): T => {
|
|
29
|
-
if (!is(extras))
|
|
30
|
-
throw new Error(
|
|
31
|
-
`The current thread is not backed by the ${runtimeName} runtime.`,
|
|
32
|
-
);
|
|
33
|
-
return extras;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const provide = (value: T): T => {
|
|
37
|
-
Object.defineProperty(value, brand, {
|
|
38
|
-
value: true,
|
|
39
|
-
enumerable: false,
|
|
40
|
-
configurable: true,
|
|
41
|
-
});
|
|
42
|
-
return value;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const tryGet = (extras: unknown): T | undefined =>
|
|
46
|
-
is(extras) ? extras : undefined;
|
|
27
|
+
const { provide, is, tryGet, assert } = brand;
|
|
47
28
|
|
|
48
29
|
const get = (client: AssistantClient): T =>
|
|
49
30
|
assert(client.thread.getState().extras);
|
|
@@ -66,3 +47,11 @@ export const createRuntimeExtras = <T extends object>(
|
|
|
66
47
|
|
|
67
48
|
return { provide, is, tryGet, get, use: use as RuntimeExtras<T>["use"] };
|
|
68
49
|
};
|
|
50
|
+
|
|
51
|
+
/** @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice. */
|
|
52
|
+
export const createRuntimeExtras = <T extends object>(
|
|
53
|
+
runtimeName: string,
|
|
54
|
+
): RuntimeExtras<T> =>
|
|
55
|
+
unstable_createRuntimeExtrasFromBrand(
|
|
56
|
+
createRuntimeExtrasBrand<T>(runtimeName),
|
|
57
|
+
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AppendMessage, ThreadMessage } from "../../types/message";
|
|
2
2
|
import type { CompleteAttachment } from "../../types/attachment";
|
|
3
3
|
import { getThreadMessageText } from "../../utils/text";
|
|
4
|
-
import {
|
|
4
|
+
import { liftNonTextParts } from "../../adapters/attachment";
|
|
5
5
|
import type { AttachmentAdapter } from "../../adapters/attachment";
|
|
6
6
|
import type { DictationAdapter } from "../../adapters/speech";
|
|
7
7
|
import type { SendOptions } from "../interfaces/composer-runtime-core";
|
|
@@ -26,8 +26,6 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
|
|
|
26
26
|
return this.runtime.adapters?.dictation;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
private _previousText;
|
|
30
|
-
private _previousAttachments: readonly CompleteAttachment[];
|
|
31
29
|
private _nonTextPassthrough: readonly ThreadMessage["content"][number][];
|
|
32
30
|
private _parentId: string | null;
|
|
33
31
|
private _sourceId: string | null;
|
|
@@ -58,24 +56,24 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
|
|
|
58
56
|
this.endEditCallback = endEditCallback;
|
|
59
57
|
this._parentId = parentId;
|
|
60
58
|
this._sourceId = message.id;
|
|
61
|
-
this.
|
|
62
|
-
this.setText(this._previousText);
|
|
59
|
+
this.setText(getThreadMessageText(message));
|
|
63
60
|
|
|
64
61
|
this.setRole(message.role);
|
|
65
62
|
|
|
63
|
+
let attachments: readonly CompleteAttachment[];
|
|
66
64
|
if (message.role === "user") {
|
|
67
|
-
|
|
65
|
+
attachments = [
|
|
68
66
|
...(message.attachments ?? []),
|
|
69
67
|
...liftNonTextParts(message.content),
|
|
70
68
|
];
|
|
71
69
|
this._nonTextPassthrough = [];
|
|
72
70
|
} else {
|
|
73
|
-
|
|
71
|
+
attachments = message.attachments ?? [];
|
|
74
72
|
this._nonTextPassthrough = message.content.filter(
|
|
75
73
|
(p) => p.type !== "text",
|
|
76
74
|
);
|
|
77
75
|
}
|
|
78
|
-
this.setAttachments(
|
|
76
|
+
this.setAttachments(attachments);
|
|
79
77
|
|
|
80
78
|
this.setRunConfig({ ...runtime.composer.runConfig });
|
|
81
79
|
}
|
|
@@ -92,49 +90,33 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
|
|
|
92
90
|
message: Omit<AppendMessage, "parentId" | "sourceId">,
|
|
93
91
|
options?: SendOptions,
|
|
94
92
|
) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
const content =
|
|
94
|
+
this._nonTextPassthrough.length > 0
|
|
95
|
+
? ([
|
|
96
|
+
...message.content,
|
|
97
|
+
...this._nonTextPassthrough,
|
|
98
|
+
] as AppendMessage["content"])
|
|
99
|
+
: message.content;
|
|
100
|
+
// Gate live state against the new branch's prefix (messages up to the
|
|
101
|
+
// parent): an unchanged interactable re-stamps the prior baseline, an
|
|
102
|
+
// interactable edited since the original message stamps its newest state.
|
|
103
|
+
const messages = this.runtime.messages;
|
|
104
|
+
const parentIndex =
|
|
105
|
+
this._parentId === null
|
|
106
|
+
? -1
|
|
107
|
+
: messages.findIndex((m) => m.id === this._parentId);
|
|
108
|
+
const composerMetadata = gateInteractableComposerMetadata(
|
|
109
|
+
this.runtime.getModelContext().unstable_composerMetadata,
|
|
110
|
+
messages.slice(0, parentIndex + 1),
|
|
100
111
|
);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
? ([
|
|
110
|
-
...message.content,
|
|
111
|
-
...this._nonTextPassthrough,
|
|
112
|
-
] as AppendMessage["content"])
|
|
113
|
-
: message.content;
|
|
114
|
-
// Gate live state against the new branch's prefix (messages up to the
|
|
115
|
-
// parent): an unchanged interactable re-stamps the prior baseline, an
|
|
116
|
-
// interactable edited since the original message stamps its newest state.
|
|
117
|
-
const messages = this.runtime.messages;
|
|
118
|
-
const parentIndex =
|
|
119
|
-
this._parentId === null
|
|
120
|
-
? -1
|
|
121
|
-
: messages.findIndex((m) => m.id === this._parentId);
|
|
122
|
-
const composerMetadata = gateInteractableComposerMetadata(
|
|
123
|
-
this.runtime.getModelContext().unstable_composerMetadata,
|
|
124
|
-
messages.slice(0, parentIndex + 1),
|
|
125
|
-
);
|
|
126
|
-
const enriched = this.enrichWithComposerMetadata(
|
|
127
|
-
message,
|
|
128
|
-
composerMetadata,
|
|
129
|
-
);
|
|
130
|
-
appendTask = this.runtime.append({
|
|
131
|
-
...enriched,
|
|
132
|
-
content,
|
|
133
|
-
parentId: this._parentId,
|
|
134
|
-
sourceId: this._sourceId,
|
|
135
|
-
startRun: options?.startRun,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
112
|
+
const enriched = this.enrichWithComposerMetadata(message, composerMetadata);
|
|
113
|
+
const appendTask = this.runtime.append({
|
|
114
|
+
...enriched,
|
|
115
|
+
content,
|
|
116
|
+
parentId: this._parentId,
|
|
117
|
+
sourceId: this._sourceId,
|
|
118
|
+
startRun: options?.startRun,
|
|
119
|
+
});
|
|
138
120
|
|
|
139
121
|
this.handleCancel();
|
|
140
122
|
return appendTask;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice. */
|
|
2
|
+
export type RuntimeExtrasBrand<T extends object> = {
|
|
3
|
+
provide: (value: T) => T;
|
|
4
|
+
is: (extras: unknown) => extras is T;
|
|
5
|
+
tryGet: (extras: unknown) => T | undefined;
|
|
6
|
+
assert: (extras: unknown) => T;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates the framework-neutral half of a runtime extras channel: the brand
|
|
11
|
+
* symbol with its provide/read primitives. A runtime factory provides extras
|
|
12
|
+
* through the brand on any framework; the React entry wraps the same brand
|
|
13
|
+
* with a `use()` hook. The symbol is per-instance, so the adapter package
|
|
14
|
+
* creates the brand once and every binding imports that instance.
|
|
15
|
+
*
|
|
16
|
+
* @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice.
|
|
17
|
+
*/
|
|
18
|
+
export const createRuntimeExtrasBrand = <T extends object>(
|
|
19
|
+
runtimeName: string,
|
|
20
|
+
): RuntimeExtrasBrand<T> => {
|
|
21
|
+
const brand = Symbol(`${runtimeName} extras`);
|
|
22
|
+
|
|
23
|
+
const is = (extras: unknown): extras is T =>
|
|
24
|
+
typeof extras === "object" && extras !== null && brand in extras;
|
|
25
|
+
|
|
26
|
+
const assert = (extras: unknown): T => {
|
|
27
|
+
if (!is(extras))
|
|
28
|
+
throw new Error(
|
|
29
|
+
`The current thread is not backed by the ${runtimeName} runtime.`,
|
|
30
|
+
);
|
|
31
|
+
return extras;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const provide = (value: T): T => {
|
|
35
|
+
Object.defineProperty(value, brand, {
|
|
36
|
+
value: true,
|
|
37
|
+
enumerable: false,
|
|
38
|
+
configurable: true,
|
|
39
|
+
});
|
|
40
|
+
return value;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const tryGet = (extras: unknown): T | undefined =>
|
|
44
|
+
is(extras) ? extras : undefined;
|
|
45
|
+
|
|
46
|
+
return { provide, is, tryGet, assert };
|
|
47
|
+
};
|
|
@@ -160,10 +160,14 @@ export const fromThreadMessageLike = (
|
|
|
160
160
|
const type = part.type;
|
|
161
161
|
switch (type) {
|
|
162
162
|
case "text":
|
|
163
|
-
case "reasoning":
|
|
164
163
|
if (!part.text?.trim()) return null;
|
|
165
164
|
return part;
|
|
166
165
|
|
|
166
|
+
case "reasoning":
|
|
167
|
+
if (!part.text?.trim() && !part.unstable_summary?.trim())
|
|
168
|
+
return null;
|
|
169
|
+
return part;
|
|
170
|
+
|
|
167
171
|
case "file":
|
|
168
172
|
case "source":
|
|
169
173
|
return part;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
type ScopesConfig,
|
|
4
|
-
type AssistantClient,
|
|
5
|
-
} from "@assistant-ui/store";
|
|
1
|
+
import type { AssistantClient, ScopesConfig } from "@assistant-ui/store";
|
|
2
|
+
import { Derived } from "@assistant-ui/store/client";
|
|
6
3
|
import { ModelContext } from "./model-context-client";
|
|
7
4
|
import { Suggestions } from "./suggestions";
|
|
8
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
import { resource, withKey } from "@assistant-ui/tap";
|
|
3
3
|
import type { ClientOutput } from "@assistant-ui/store";
|
|
4
|
-
import { useClientLookup } from "@assistant-ui/store";
|
|
4
|
+
import { useClientLookup } from "@assistant-ui/store/client";
|
|
5
5
|
import type { SuggestionsState } from "../scopes/suggestions";
|
|
6
6
|
import type { SuggestionState } from "../scopes/suggestion";
|
|
7
7
|
|
|
@@ -7,7 +7,7 @@ import type { Attachment } from "../../types/attachment";
|
|
|
7
7
|
import { useMemo, useState } from "react";
|
|
8
8
|
import { useResource, resource, withKey } from "@assistant-ui/tap";
|
|
9
9
|
import type { ClientOutput } from "@assistant-ui/store";
|
|
10
|
-
import { useClientLookup } from "@assistant-ui/store";
|
|
10
|
+
import { useClientLookup } from "@assistant-ui/store/client";
|
|
11
11
|
import type { MessageState } from "../scopes/message";
|
|
12
12
|
import type { PartState } from "../scopes/part";
|
|
13
13
|
import { NoOpComposerClient } from "./no-op-composer-client";
|
package/src/store/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference path="./scope-registration.ts" />
|
|
2
|
+
/// <reference path="../react/types/store-augmentation.ts" />
|
|
2
3
|
|
|
3
4
|
// scopes
|
|
4
5
|
export type {
|
|
@@ -77,6 +78,36 @@ export type {
|
|
|
77
78
|
ChainOfThoughtPart,
|
|
78
79
|
} from "./scopes/chain-of-thought";
|
|
79
80
|
|
|
81
|
+
// runtime wiring
|
|
82
|
+
export { RuntimeAdapter } from "../react/RuntimeAdapter";
|
|
83
|
+
export {
|
|
84
|
+
useExternalMessageConverter,
|
|
85
|
+
convertExternalMessages,
|
|
86
|
+
type JoinStrategy,
|
|
87
|
+
} from "../react/runtimes/external-message-converter";
|
|
88
|
+
export {
|
|
89
|
+
useStreamingTiming,
|
|
90
|
+
type StreamingTimingAccessors,
|
|
91
|
+
type StreamingTimingOptions,
|
|
92
|
+
type StreamingTimingState,
|
|
93
|
+
} from "../react/runtimes/useStreamingTiming";
|
|
94
|
+
export {
|
|
95
|
+
createRuntimeExtrasBrand,
|
|
96
|
+
type RuntimeExtrasBrand,
|
|
97
|
+
} from "../runtime/utils/runtime-extras-brand";
|
|
98
|
+
export { defineToolkit } from "../react/model-context/define-toolkit";
|
|
99
|
+
export {
|
|
100
|
+
defineMcpToolkit,
|
|
101
|
+
type McpToolkitDefinition,
|
|
102
|
+
type McpToolkitEntry,
|
|
103
|
+
type McpToolkitToolConfig,
|
|
104
|
+
} from "../react/model-context/define-mcp-toolkit";
|
|
105
|
+
export type {
|
|
106
|
+
Toolkit,
|
|
107
|
+
ToolkitDefinition,
|
|
108
|
+
ToolkitDefinitionEntry,
|
|
109
|
+
} from "../react/model-context/toolbox";
|
|
110
|
+
|
|
80
111
|
// clients
|
|
81
112
|
export { NoOpComposerClient } from "./clients/no-op-composer-client";
|
|
82
113
|
export { Suggestions, type SuggestionConfig } from "./clients/suggestions";
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
2
2
|
import { useMemo, useEffect } from "react";
|
|
3
3
|
import { useResource, resource, withKey } from "@assistant-ui/tap";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
useAssistantEmit,
|
|
7
|
-
useClientLookup,
|
|
8
|
-
} from "@assistant-ui/store";
|
|
4
|
+
import type { ClientOutput } from "@assistant-ui/store";
|
|
5
|
+
import { useAssistantEmit, useClientLookup } from "@assistant-ui/store/client";
|
|
9
6
|
import type {
|
|
10
7
|
ComposerRuntime,
|
|
11
8
|
EditComposerRuntime,
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { AuiConfig, createAssistantClient } from "@assistant-ui/store/client";
|
|
3
|
+
import { RuntimeAdapter, Suggestions } from "../index";
|
|
4
|
+
import { ExternalStoreRuntimeCore } from "../../runtimes/internal";
|
|
5
|
+
import { AssistantRuntimeImpl } from "../../runtime/internal";
|
|
6
|
+
import type { ExternalStoreAdapter } from "../../runtimes/external-store/external-store-adapter";
|
|
7
|
+
|
|
8
|
+
type DemoMessage = { id: string; role: "user" | "assistant"; text: string };
|
|
9
|
+
|
|
10
|
+
const createClient = () => {
|
|
11
|
+
const adapter: ExternalStoreAdapter<DemoMessage> = {
|
|
12
|
+
messages: [
|
|
13
|
+
{ id: "u1", role: "user", text: "hi" },
|
|
14
|
+
{ id: "a1", role: "assistant", text: "hello" },
|
|
15
|
+
],
|
|
16
|
+
convertMessage: (message) => ({
|
|
17
|
+
id: message.id,
|
|
18
|
+
role: message.role,
|
|
19
|
+
content: [{ type: "text", text: message.text }],
|
|
20
|
+
}),
|
|
21
|
+
onNew: async () => {},
|
|
22
|
+
adapters: {
|
|
23
|
+
threadList: {
|
|
24
|
+
threadId: "t1",
|
|
25
|
+
threads: [{ status: "regular", id: "t1", title: "one" }],
|
|
26
|
+
archivedThreads: [{ status: "archived", id: "t2", title: "two" }],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
const runtime = new AssistantRuntimeImpl(
|
|
31
|
+
new ExternalStoreRuntimeCore(adapter),
|
|
32
|
+
);
|
|
33
|
+
return createAssistantClient(
|
|
34
|
+
AuiConfig({
|
|
35
|
+
threads: RuntimeAdapter(runtime),
|
|
36
|
+
suggestions: Suggestions([
|
|
37
|
+
{ title: "a", label: "a", prompt: "a" },
|
|
38
|
+
{ title: "b", label: "b", prompt: "b" },
|
|
39
|
+
]),
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Pins each by-index lookup's valid domain to the state array that backs it.
|
|
46
|
+
* Consumers (the vue by-index providers) guard with `index < array.length`
|
|
47
|
+
* against these arrays; a lookup changing its backing array must fail here.
|
|
48
|
+
*/
|
|
49
|
+
describe("by-index lookup domains", () => {
|
|
50
|
+
it("thread.message is indexed by thread.getState().messages", () => {
|
|
51
|
+
const handle = createClient();
|
|
52
|
+
const aui = handle.getClient();
|
|
53
|
+
const length = aui.thread.getState().messages.length;
|
|
54
|
+
expect(length).toBe(2);
|
|
55
|
+
expect(aui.thread.message({ index: length - 1 }).getState().id).toBe("a1");
|
|
56
|
+
expect(() => aui.thread.message({ index: length }).getState()).toThrow(
|
|
57
|
+
/out of bounds/,
|
|
58
|
+
);
|
|
59
|
+
handle.destroy();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("message.part is indexed by message.getState().parts", () => {
|
|
63
|
+
const handle = createClient();
|
|
64
|
+
const aui = handle.getClient();
|
|
65
|
+
const message = aui.thread.message({ index: 1 });
|
|
66
|
+
const length = message.getState().parts.length;
|
|
67
|
+
expect(length).toBe(1);
|
|
68
|
+
expect(message.part({ index: length - 1 }).getState().type).toBe("text");
|
|
69
|
+
expect(() => message.part({ index: length }).getState()).toThrow(
|
|
70
|
+
/out of bounds/,
|
|
71
|
+
);
|
|
72
|
+
handle.destroy();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("suggestions.suggestion is indexed by suggestions.getState().suggestions", () => {
|
|
76
|
+
const handle = createClient();
|
|
77
|
+
const aui = handle.getClient();
|
|
78
|
+
const length = aui.suggestions.getState().suggestions.length;
|
|
79
|
+
expect(length).toBe(2);
|
|
80
|
+
expect(
|
|
81
|
+
aui.suggestions.suggestion({ index: length - 1 }).getState().title,
|
|
82
|
+
).toBe("b");
|
|
83
|
+
expect(() =>
|
|
84
|
+
aui.suggestions.suggestion({ index: length }).getState(),
|
|
85
|
+
).toThrow(/out of bounds/);
|
|
86
|
+
handle.destroy();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("threads.item is indexed by threadIds and archivedThreadIds", () => {
|
|
90
|
+
const handle = createClient();
|
|
91
|
+
const aui = handle.getClient();
|
|
92
|
+
const state = aui.threads.getState();
|
|
93
|
+
expect(state.threadIds).toHaveLength(1);
|
|
94
|
+
expect(state.archivedThreadIds).toHaveLength(1);
|
|
95
|
+
expect(aui.threads.item({ index: 0, archived: false }).getState().id).toBe(
|
|
96
|
+
"t1",
|
|
97
|
+
);
|
|
98
|
+
expect(aui.threads.item({ index: 0, archived: true }).getState().id).toBe(
|
|
99
|
+
"t2",
|
|
100
|
+
);
|
|
101
|
+
expect(() =>
|
|
102
|
+
aui.threads.item({ index: 1, archived: false }).getState(),
|
|
103
|
+
).toThrow(/not found|out of bounds/);
|
|
104
|
+
expect(() =>
|
|
105
|
+
aui.threads.item({ index: 1, archived: true }).getState(),
|
|
106
|
+
).toThrow(/not found|out of bounds/);
|
|
107
|
+
handle.destroy();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { useMemo, useState } from "react";
|
|
2
2
|
import { useResource, withKey, resource } from "@assistant-ui/tap";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
useClientLookup,
|
|
6
|
-
useClientResource,
|
|
7
|
-
} from "@assistant-ui/store";
|
|
3
|
+
import type { ClientOutput } from "@assistant-ui/store";
|
|
4
|
+
import { useClientLookup, useClientResource } from "@assistant-ui/store/client";
|
|
8
5
|
import type { MessageRuntime } from "../../runtime/api/message-runtime";
|
|
9
6
|
import { useSubscribable } from "./useSubscribable";
|
|
10
7
|
import { liveRef } from "./liveRef";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
2
2
|
import { useEffect, useMemo } from "react";
|
|
3
3
|
import { resource } from "@assistant-ui/tap";
|
|
4
|
-
import {
|
|
4
|
+
import type { ClientOutput } from "@assistant-ui/store";
|
|
5
|
+
import { useAssistantEmit } from "@assistant-ui/store/client";
|
|
5
6
|
import type {
|
|
6
7
|
ThreadListItemEventType,
|
|
7
8
|
ThreadListItemRuntime,
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
import { useResource, withKey, resource } from "@assistant-ui/tap";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
useClientLookup,
|
|
6
|
-
useClientResource,
|
|
7
|
-
} from "@assistant-ui/store";
|
|
3
|
+
import type { ClientOutput } from "@assistant-ui/store";
|
|
4
|
+
import { useClientLookup, useClientResource } from "@assistant-ui/store/client";
|
|
8
5
|
import type { ThreadListRuntime } from "../../runtime/api/thread-list-runtime";
|
|
9
6
|
import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
|
|
10
7
|
import { useSubscribable } from "./useSubscribable";
|
|
@@ -4,12 +4,12 @@ import type { ThreadRuntime } from "../../runtime/api/thread-runtime";
|
|
|
4
4
|
import { useMemo, useEffect, type RefObject } from "react";
|
|
5
5
|
import { useResource, resource, withKey } from "@assistant-ui/tap";
|
|
6
6
|
import { liveRef } from "./liveRef";
|
|
7
|
+
import type { ClientOutput } from "@assistant-ui/store";
|
|
7
8
|
import {
|
|
8
|
-
type ClientOutput,
|
|
9
9
|
useAssistantEmit,
|
|
10
10
|
useClientLookup,
|
|
11
11
|
useClientResource,
|
|
12
|
-
} from "@assistant-ui/store";
|
|
12
|
+
} from "@assistant-ui/store/client";
|
|
13
13
|
import { ComposerClient } from "./composer-runtime-client";
|
|
14
14
|
import { MessageClient } from "./message-runtime-client";
|
|
15
15
|
import { useSubscribable } from "./useSubscribable";
|