@assistant-ui/core 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/model-context/tool.d.ts +1 -1
  2. package/dist/model-context/tool.js +1 -1
  3. package/dist/model-context/tool.js.map +1 -1
  4. package/dist/model-context/types.js +17 -2
  5. package/dist/model-context/types.js.map +1 -1
  6. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  7. package/dist/react/adapters/LocalStorageThreadListAdapter.js +12 -2
  8. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  9. package/dist/react/client/Tools.d.ts.map +1 -1
  10. package/dist/react/client/Tools.js +9 -3
  11. package/dist/react/client/Tools.js.map +1 -1
  12. package/dist/react/index.d.ts +8 -2
  13. package/dist/react/index.js +7 -1
  14. package/dist/react/model-context/define-mcp-toolkit.d.ts +12 -0
  15. package/dist/react/model-context/define-mcp-toolkit.d.ts.map +1 -0
  16. package/dist/react/model-context/define-mcp-toolkit.js +14 -0
  17. package/dist/react/model-context/define-mcp-toolkit.js.map +1 -0
  18. package/dist/react/model-context/define-toolkit.d.ts +21 -0
  19. package/dist/react/model-context/define-toolkit.d.ts.map +1 -0
  20. package/dist/react/model-context/define-toolkit.js +8 -0
  21. package/dist/react/model-context/define-toolkit.js.map +1 -0
  22. package/dist/react/model-context/hitl.d.ts +23 -0
  23. package/dist/react/model-context/hitl.d.ts.map +1 -0
  24. package/dist/react/model-context/hitl.js +26 -0
  25. package/dist/react/model-context/hitl.js.map +1 -0
  26. package/dist/react/model-context/makeAssistantTool.d.ts +8 -0
  27. package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
  28. package/dist/react/model-context/makeAssistantTool.js +4 -0
  29. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  30. package/dist/react/model-context/makeAssistantToolUI.d.ts +8 -0
  31. package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
  32. package/dist/react/model-context/makeAssistantToolUI.js +4 -0
  33. package/dist/react/model-context/makeAssistantToolUI.js.map +1 -1
  34. package/dist/react/model-context/provider-tool.d.ts +15 -0
  35. package/dist/react/model-context/provider-tool.d.ts.map +1 -0
  36. package/dist/react/model-context/provider-tool.js +12 -0
  37. package/dist/react/model-context/provider-tool.js.map +1 -0
  38. package/dist/react/model-context/stub-tool.d.ts +12 -0
  39. package/dist/react/model-context/stub-tool.d.ts.map +1 -0
  40. package/dist/react/model-context/stub-tool.js +15 -0
  41. package/dist/react/model-context/stub-tool.js.map +1 -0
  42. package/dist/react/model-context/toolbox.d.ts +62 -15
  43. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  44. package/dist/react/model-context/toolbox.js +19 -1
  45. package/dist/react/model-context/toolbox.js.map +1 -1
  46. package/dist/react/model-context/useAssistantTool.d.ts +11 -1
  47. package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
  48. package/dist/react/model-context/useAssistantTool.js +12 -6
  49. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  50. package/dist/react/model-context/useAssistantToolUI.d.ts +13 -4
  51. package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
  52. package/dist/react/model-context/useAssistantToolUI.js +6 -3
  53. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  54. package/dist/react/model-context/useAuiToolOverrides.d.ts +22 -0
  55. package/dist/react/model-context/useAuiToolOverrides.d.ts.map +1 -0
  56. package/dist/react/model-context/useAuiToolOverrides.js +31 -0
  57. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -0
  58. package/dist/react/primitives/part/PartMessages.d.ts +13 -11
  59. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  60. package/dist/react/primitives/part/PartMessages.js +13 -11
  61. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  62. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +1 -0
  63. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  64. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +28 -0
  65. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  66. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  67. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +9 -2
  68. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  69. package/dist/runtime/api/thread-list-item-runtime.d.ts +2 -0
  70. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  71. package/dist/runtime/api/thread-list-item-runtime.js +6 -0
  72. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  73. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
  74. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  75. package/dist/runtimes/external-store/external-store-adapter.d.ts +2 -0
  76. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  77. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -0
  78. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  79. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +5 -0
  80. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  81. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts +1 -0
  82. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  83. package/dist/runtimes/remote-thread-list/adapter/in-memory.js +3 -0
  84. package/dist/runtimes/remote-thread-list/adapter/in-memory.js.map +1 -1
  85. package/dist/runtimes/remote-thread-list/types.d.ts +1 -0
  86. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  87. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -0
  88. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  89. package/dist/store/scopes/thread-list-item.d.ts +1 -0
  90. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  91. package/package.json +5 -5
  92. package/src/model-context/tool.ts +1 -1
  93. package/src/model-context/types.ts +21 -3
  94. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +15 -2
  95. package/src/react/client/Tools.ts +22 -7
  96. package/src/react/index.ts +15 -2
  97. package/src/react/model-context/define-mcp-toolkit.ts +16 -0
  98. package/src/react/model-context/define-toolkit.test.ts +101 -0
  99. package/src/react/model-context/define-toolkit.ts +41 -0
  100. package/src/react/model-context/hitl.ts +27 -0
  101. package/src/react/model-context/makeAssistantTool.ts +8 -0
  102. package/src/react/model-context/makeAssistantToolUI.ts +8 -0
  103. package/src/react/model-context/provider-tool.ts +30 -0
  104. package/src/react/model-context/stub-tool.ts +14 -0
  105. package/src/react/model-context/toolbox.test.ts +182 -0
  106. package/src/react/model-context/toolbox.ts +189 -21
  107. package/src/react/model-context/useAssistantTool.ts +28 -8
  108. package/src/react/model-context/useAssistantToolUI.ts +13 -4
  109. package/src/react/model-context/useAuiToolOverrides.ts +38 -0
  110. package/src/react/primitives/part/PartMessages.tsx +13 -11
  111. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +43 -0
  112. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +9 -0
  113. package/src/runtime/api/thread-list-item-runtime.ts +15 -0
  114. package/src/runtime/interfaces/thread-list-runtime-core.ts +4 -0
  115. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  116. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +13 -0
  117. package/src/runtimes/remote-thread-list/adapter/in-memory.ts +4 -0
  118. package/src/runtimes/remote-thread-list/types.ts +4 -0
  119. package/src/store/clients/model-context-client.test.ts +87 -2
  120. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +1 -0
  121. package/src/store/scopes/thread-list-item.ts +1 -0
  122. package/src/tests/RemoteThreadListThreadListRuntimeCore-custom-metadata.test.ts +69 -1
  123. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
@@ -6,6 +6,7 @@ import type {
6
6
  ModelContext as ModelContextValue,
7
7
  ModelContextProvider,
8
8
  } from "../../model-context/types";
9
+ import { mergeModelContexts } from "../../model-context/types";
9
10
 
10
11
  const tick = () => new Promise<void>((resolve) => setTimeout(resolve, 0));
11
12
 
@@ -13,7 +14,7 @@ const provider = (ctx: ModelContextValue): ModelContextProvider => ({
13
14
  getModelContext: () => ctx,
14
15
  });
15
16
 
16
- const stubTool = (): Tool<any, any> =>
17
+ const toolFixture = (): Tool<any, any> =>
17
18
  ({ description: "", parameters: {} as any }) as unknown as Tool<any, any>;
18
19
 
19
20
  const render = () => {
@@ -51,7 +52,9 @@ describe("ModelContext", () => {
51
52
  try {
52
53
  sub
53
54
  .getValue()
54
- .register(provider({ tools: { foo: stubTool(), bar: stubTool() } }));
55
+ .register(
56
+ provider({ tools: { foo: toolFixture(), bar: toolFixture() } }),
57
+ );
55
58
  await tick();
56
59
 
57
60
  expect(sub.getValue().getState().toolNames).toEqual(["bar", "foo"]);
@@ -106,3 +109,85 @@ describe("ModelContext", () => {
106
109
  }
107
110
  });
108
111
  });
112
+
113
+ describe("mergeModelContexts", () => {
114
+ it("merges a higher-priority tool override into an existing tool", () => {
115
+ const execute = async () => ({ ok: true });
116
+ const merged = mergeModelContexts(
117
+ new Set([
118
+ provider({
119
+ priority: 0,
120
+ tools: {
121
+ add_task: {
122
+ type: "frontend",
123
+ description: "Add a task",
124
+ parameters: { type: "object", properties: {} } as any,
125
+ renderText: { running: "Adding task" },
126
+ } as Tool<any, any>,
127
+ },
128
+ }),
129
+ provider({
130
+ priority: 1000,
131
+ tools: {
132
+ add_task: {
133
+ execute,
134
+ } as unknown as Tool<any, any>,
135
+ },
136
+ }),
137
+ ]),
138
+ );
139
+
140
+ expect(merged.tools?.add_task).toMatchObject({
141
+ type: "frontend",
142
+ description: "Add a task",
143
+ });
144
+ expect(merged.tools?.add_task?.execute).toBe(execute);
145
+ expect(merged.tools?.add_task?.parameters).toEqual({
146
+ type: "object",
147
+ properties: {},
148
+ });
149
+ });
150
+
151
+ it("still rejects duplicate tools at the same priority", () => {
152
+ expect(() =>
153
+ mergeModelContexts(
154
+ new Set([
155
+ provider({ tools: { duplicate: toolFixture() } }),
156
+ provider({ tools: { duplicate: toolFixture() } }),
157
+ ]),
158
+ ),
159
+ ).toThrow(/already exists/);
160
+ });
161
+
162
+ it("preserves the highest priority when a lower-priority provider reuses the same tool object", () => {
163
+ const shared = {
164
+ ...toolFixture(),
165
+ description: "high priority",
166
+ } as Tool<any, any>;
167
+ const execute = async () => ({ ok: true });
168
+ const merged = mergeModelContexts(
169
+ new Set([
170
+ provider({
171
+ priority: 1000,
172
+ tools: { shared },
173
+ }),
174
+ provider({
175
+ priority: 0,
176
+ tools: { shared },
177
+ }),
178
+ provider({
179
+ priority: 500,
180
+ tools: {
181
+ shared: {
182
+ description: "medium priority",
183
+ execute,
184
+ } as unknown as Tool<any, any>,
185
+ },
186
+ }),
187
+ ]),
188
+ );
189
+
190
+ expect(merged.tools?.shared?.description).toBe("high priority");
191
+ expect(merged.tools?.shared?.execute).toBe(execute);
192
+ });
193
+ });
@@ -44,6 +44,7 @@ export const ThreadListItemClient = resource(
44
44
  getState: () => state,
45
45
  switchTo: runtime.switchTo,
46
46
  rename: runtime.rename,
47
+ updateCustom: runtime.updateCustom,
47
48
  archive: runtime.archive,
48
49
  unarchive: runtime.unarchive,
49
50
  delete: runtime.delete,
@@ -14,6 +14,7 @@ export type ThreadListItemMethods = {
14
14
  getState(): ThreadListItemState;
15
15
  switchTo(options?: { unarchive?: boolean }): void;
16
16
  rename(newTitle: string): void;
17
+ updateCustom(custom: Record<string, unknown> | undefined): void;
17
18
  archive(): void;
18
19
  unarchive(): void;
19
20
  delete(): void;
@@ -1,5 +1,9 @@
1
1
  import { describe, it, expect, vi } from "vitest";
2
- import { createCore, makeAdapter } from "./remote-thread-list-test-helpers";
2
+ import {
3
+ createCore,
4
+ deferred,
5
+ makeAdapter,
6
+ } from "./remote-thread-list-test-helpers";
3
7
 
4
8
  describe("RemoteThreadListThreadListRuntimeCore custom metadata", () => {
5
9
  it("preserves custom field from list() through to threadItems", async () => {
@@ -120,4 +124,68 @@ describe("RemoteThreadListThreadListRuntimeCore custom metadata", () => {
120
124
  workspaceId: "ws-1",
121
125
  });
122
126
  });
127
+
128
+ it("updates custom through the adapter with optimistic state", async () => {
129
+ const updateDeferred = deferred<void>();
130
+ const adapter = makeAdapter({
131
+ list: vi.fn(async () => ({
132
+ threads: [
133
+ {
134
+ status: "regular" as const,
135
+ remoteId: "thread-6",
136
+ externalId: "ext-6",
137
+ title: "Test",
138
+ custom: { tag: "old" },
139
+ },
140
+ ],
141
+ })),
142
+ updateCustom: vi.fn(() => updateDeferred.promise),
143
+ });
144
+
145
+ const core = createCore(adapter);
146
+ await core.getLoadThreadsPromise();
147
+
148
+ const updateTask = core.updateCustom("thread-6", { tag: "new" });
149
+
150
+ await Promise.resolve();
151
+
152
+ expect(adapter.updateCustom).toHaveBeenCalledWith("thread-6", {
153
+ tag: "new",
154
+ });
155
+ expect(core.getItemById("thread-6")?.custom).toEqual({ tag: "new" });
156
+
157
+ updateDeferred.resolve();
158
+ await updateTask;
159
+
160
+ expect(core.getItemById("thread-6")?.custom).toEqual({ tag: "new" });
161
+ });
162
+
163
+ it("rolls back custom when adapter update fails", async () => {
164
+ const updateDeferred = deferred<void>();
165
+ const adapter = makeAdapter({
166
+ list: vi.fn(async () => ({
167
+ threads: [
168
+ {
169
+ status: "regular" as const,
170
+ remoteId: "thread-7",
171
+ externalId: "ext-7",
172
+ title: "Test",
173
+ custom: { tag: "old" },
174
+ },
175
+ ],
176
+ })),
177
+ updateCustom: vi.fn(() => updateDeferred.promise),
178
+ });
179
+
180
+ const core = createCore(adapter);
181
+ await core.getLoadThreadsPromise();
182
+
183
+ const updateTask = core.updateCustom("thread-7", { tag: "new" });
184
+ expect(core.getItemById("thread-7")?.custom).toEqual({ tag: "new" });
185
+
186
+ updateDeferred.reject(new Error("update failed"));
187
+ await expect(updateTask).rejects.toThrow("update failed");
188
+
189
+ expect(core.getItemById("thread-7")?.custom).toEqual({ tag: "old" });
190
+ });
123
191
  });
@@ -41,6 +41,7 @@ const createMockCore = (
41
41
  getLoadThreadsPromise: () => loadPromise,
42
42
  detach: () => Promise.resolve(),
43
43
  rename: () => Promise.resolve(),
44
+ updateCustom: () => Promise.resolve(),
44
45
  archive: () => Promise.resolve(),
45
46
  unarchive: () => Promise.resolve(),
46
47
  delete: () => Promise.resolve(),