@assistant-ui/react 0.14.29 → 0.15.0

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 (138) hide show
  1. package/dist/client/ExternalThread.js +4 -3
  2. package/dist/client/ExternalThread.js.map +1 -1
  3. package/dist/client/InMemoryThreadList.js +3 -3
  4. package/dist/client/InMemoryThreadList.js.map +1 -1
  5. package/dist/context/index.d.ts +1 -8
  6. package/dist/context/index.js +1 -8
  7. package/dist/index.d.ts +1 -8
  8. package/dist/index.js +1 -8
  9. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +3 -3
  10. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  11. package/dist/mcp-apps/McpAppRenderer.js +1 -1
  12. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  13. package/dist/model-context/makeAssistantVisible.js +26 -25
  14. package/dist/model-context/makeAssistantVisible.js.map +1 -1
  15. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +3 -3
  16. package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
  17. package/dist/primitives/attachment/AttachmentRemove.js +3 -3
  18. package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
  19. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +3 -3
  20. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  21. package/dist/primitives/composer/ComposerAddAttachment.js +3 -3
  22. package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
  23. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -1
  24. package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
  25. package/dist/primitives/composer/ComposerInput.js +13 -13
  26. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  27. package/dist/primitives/composer/ComposerQuote.js +1 -1
  28. package/dist/primitives/composer/ComposerQuote.js.map +1 -1
  29. package/dist/primitives/composer/ComposerStopDictation.js +3 -3
  30. package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
  31. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  32. package/dist/primitives/composer/trigger/triggerSelectionResource.js +3 -3
  33. package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
  34. package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
  35. package/dist/primitives/message/MessagePartsGrouped.js +67 -89
  36. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  37. package/dist/primitives/message/MessageRoot.js +3 -3
  38. package/dist/primitives/message/MessageRoot.js.map +1 -1
  39. package/dist/primitives/queueItem/QueueItemRemove.js +3 -3
  40. package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
  41. package/dist/primitives/queueItem/QueueItemSteer.js +3 -3
  42. package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
  43. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -1
  44. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -1
  45. package/dist/primitives/suggestion/SuggestionTrigger.js +16 -15
  46. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
  47. package/dist/unstable/useComposerInput.js +2 -2
  48. package/dist/unstable/useComposerInput.js.map +1 -1
  49. package/dist/unstable/useComposerInputHistory.js +6 -6
  50. package/dist/unstable/useComposerInputHistory.js.map +1 -1
  51. package/dist/unstable/useMentionAdapter.js +1 -1
  52. package/dist/unstable/useMentionAdapter.js.map +1 -1
  53. package/dist/utils/smooth/SmoothContext.js +3 -3
  54. package/dist/utils/smooth/SmoothContext.js.map +1 -1
  55. package/dist/utils/smooth/useSmooth.js +1 -1
  56. package/dist/utils/smooth/useSmooth.js.map +1 -1
  57. package/package.json +5 -5
  58. package/src/client/ExternalThread.ts +5 -3
  59. package/src/client/InMemoryThreadList.ts +3 -3
  60. package/src/context/index.ts +0 -44
  61. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.test.tsx +5 -9
  62. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts +1 -1
  63. package/src/mcp-apps/McpAppRenderer.tsx +1 -1
  64. package/src/model-context/makeAssistantVisible.test.tsx +1 -1
  65. package/src/model-context/makeAssistantVisible.tsx +1 -1
  66. package/src/primitives/actionBar/ActionBarExportMarkdown.tsx +1 -1
  67. package/src/primitives/attachment/AttachmentRemove.ts +1 -1
  68. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.ts +1 -1
  69. package/src/primitives/composer/ComposerAddAttachment.test.tsx +2 -2
  70. package/src/primitives/composer/ComposerAddAttachment.ts +1 -1
  71. package/src/primitives/composer/ComposerAttachmentDropzone.test.tsx +2 -2
  72. package/src/primitives/composer/ComposerAttachmentDropzone.tsx +1 -1
  73. package/src/primitives/composer/ComposerInput.test.tsx +7 -7
  74. package/src/primitives/composer/ComposerInput.tsx +13 -13
  75. package/src/primitives/composer/ComposerQuote.tsx +1 -1
  76. package/src/primitives/composer/ComposerStopDictation.ts +1 -1
  77. package/src/primitives/composer/trigger/triggerSelectionResource.ts +7 -9
  78. package/src/primitives/message/MessagePartsGrouped.tsx +6 -8
  79. package/src/primitives/message/MessageRoot.tsx +1 -1
  80. package/src/primitives/queueItem/QueueItemRemove.ts +1 -1
  81. package/src/primitives/queueItem/QueueItemSteer.ts +1 -1
  82. package/src/primitives/selectionToolbar/SelectionToolbarQuote.tsx +1 -1
  83. package/src/primitives/suggestion/SuggestionTrigger.ts +9 -9
  84. package/src/tests/DataRenderers.test.tsx +1 -1
  85. package/src/tests/RemoteThreadListRuntime.deferredProvider.test.tsx +3 -3
  86. package/src/tests/external-thread-attachments.test.tsx +21 -23
  87. package/src/tests/external-thread-branches.test.tsx +10 -10
  88. package/src/tests/external-thread-parity.test.tsx +18 -20
  89. package/src/tests/local-runtime-queue.test.tsx +29 -34
  90. package/src/tests/messagePartSwitchRace.test.tsx +30 -13
  91. package/src/unstable/useComposerInput.test.tsx +2 -2
  92. package/src/unstable/useComposerInput.ts +2 -2
  93. package/src/unstable/useComposerInputHistory.test.tsx +3 -3
  94. package/src/unstable/useComposerInputHistory.ts +6 -6
  95. package/src/unstable/useMentionAdapter.ts +1 -1
  96. package/src/utils/smooth/SmoothContext.tsx +1 -1
  97. package/src/utils/smooth/useSmooth.test.tsx +1 -1
  98. package/src/utils/smooth/useSmooth.ts +1 -1
  99. package/dist/context/react/utils/createStateHookForRuntime.d.ts +0 -34
  100. package/dist/context/react/utils/createStateHookForRuntime.d.ts.map +0 -1
  101. package/dist/context/react/utils/createStateHookForRuntime.js +0 -21
  102. package/dist/context/react/utils/createStateHookForRuntime.js.map +0 -1
  103. package/dist/legacy-runtime/hooks/AssistantContext.d.ts +0 -74
  104. package/dist/legacy-runtime/hooks/AssistantContext.d.ts.map +0 -1
  105. package/dist/legacy-runtime/hooks/AssistantContext.js +0 -29
  106. package/dist/legacy-runtime/hooks/AssistantContext.js.map +0 -1
  107. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts +0 -1007
  108. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts.map +0 -1
  109. package/dist/legacy-runtime/hooks/AttachmentContext.js +0 -47
  110. package/dist/legacy-runtime/hooks/AttachmentContext.js.map +0 -1
  111. package/dist/legacy-runtime/hooks/ComposerContext.d.ts +0 -141
  112. package/dist/legacy-runtime/hooks/ComposerContext.d.ts.map +0 -1
  113. package/dist/legacy-runtime/hooks/ComposerContext.js +0 -65
  114. package/dist/legacy-runtime/hooks/ComposerContext.js.map +0 -1
  115. package/dist/legacy-runtime/hooks/MessageContext.d.ts +0 -155
  116. package/dist/legacy-runtime/hooks/MessageContext.d.ts.map +0 -1
  117. package/dist/legacy-runtime/hooks/MessageContext.js +0 -68
  118. package/dist/legacy-runtime/hooks/MessageContext.js.map +0 -1
  119. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts +0 -44
  120. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts.map +0 -1
  121. package/dist/legacy-runtime/hooks/MessagePartContext.js +0 -26
  122. package/dist/legacy-runtime/hooks/MessagePartContext.js.map +0 -1
  123. package/dist/legacy-runtime/hooks/ThreadContext.d.ts +0 -139
  124. package/dist/legacy-runtime/hooks/ThreadContext.d.ts.map +0 -1
  125. package/dist/legacy-runtime/hooks/ThreadContext.js +0 -84
  126. package/dist/legacy-runtime/hooks/ThreadContext.js.map +0 -1
  127. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts +0 -44
  128. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts.map +0 -1
  129. package/dist/legacy-runtime/hooks/ThreadListItemContext.js +0 -26
  130. package/dist/legacy-runtime/hooks/ThreadListItemContext.js.map +0 -1
  131. package/src/context/react/utils/createStateHookForRuntime.ts +0 -82
  132. package/src/legacy-runtime/hooks/AssistantContext.ts +0 -67
  133. package/src/legacy-runtime/hooks/AttachmentContext.ts +0 -99
  134. package/src/legacy-runtime/hooks/ComposerContext.ts +0 -131
  135. package/src/legacy-runtime/hooks/MessageContext.ts +0 -127
  136. package/src/legacy-runtime/hooks/MessagePartContext.ts +0 -32
  137. package/src/legacy-runtime/hooks/ThreadContext.ts +0 -120
  138. package/src/legacy-runtime/hooks/ThreadListItemContext.ts +0 -36
@@ -27,8 +27,7 @@ const createCountingAdapter = () => {
27
27
  };
28
28
 
29
29
  const userTexts = (aui: ReturnType<typeof useAui>) =>
30
- aui
31
- .thread()
30
+ aui.thread
32
31
  .getState()
33
32
  .messages.filter((m) => m.role === "user")
34
33
  .map((m) =>
@@ -57,8 +56,8 @@ const renderWithRuntime = (adapter: ChatModelAdapter, enableQueue: boolean) => {
57
56
 
58
57
  const send = async (aui: ReturnType<typeof useAui>, text: string) => {
59
58
  await act(async () => {
60
- aui.thread().composer().setText(text);
61
- aui.thread().composer().send();
59
+ aui.thread.composer().setText(text);
60
+ aui.thread.composer().send();
62
61
  await flush();
63
62
  });
64
63
  };
@@ -69,13 +68,12 @@ describe("local runtime message queue", () => {
69
68
  const aui = renderWithRuntime(adapter, true);
70
69
 
71
70
  await send(aui, "first");
72
- expect(aui.thread().getState().isRunning).toBe(true);
73
- expect(aui.thread().getState().capabilities.queue).toBe(true);
71
+ expect(aui.thread.getState().isRunning).toBe(true);
72
+ expect(aui.thread.getState().capabilities.queue).toBe(true);
74
73
 
75
74
  await send(aui, "second");
76
75
  expect(
77
- aui
78
- .thread()
76
+ aui.thread
79
77
  .composer()
80
78
  .getState()
81
79
  .queue.map((q) => q.prompt),
@@ -87,7 +85,7 @@ describe("local runtime message queue", () => {
87
85
  await flush();
88
86
  await flush();
89
87
  });
90
- expect(aui.thread().composer().getState().queue).toEqual([]);
88
+ expect(aui.thread.composer().getState().queue).toEqual([]);
91
89
  expect(userTexts(aui)).toContain("second");
92
90
  });
93
91
 
@@ -100,7 +98,7 @@ describe("local runtime message queue", () => {
100
98
 
101
99
  await send(aui, "a");
102
100
  await send(aui, "b");
103
- expect(aui.thread().composer().getState().queue).toHaveLength(2);
101
+ expect(aui.thread.composer().getState().queue).toHaveLength(2);
104
102
 
105
103
  await act(async () => {
106
104
  releases[0]!();
@@ -109,8 +107,7 @@ describe("local runtime message queue", () => {
109
107
  });
110
108
  expect(getRunCount()).toBe(2);
111
109
  expect(
112
- aui
113
- .thread()
110
+ aui.thread
114
111
  .composer()
115
112
  .getState()
116
113
  .queue.map((q) => q.prompt),
@@ -124,13 +121,13 @@ describe("local runtime message queue", () => {
124
121
  await send(aui, "first");
125
122
  await send(aui, "a");
126
123
  await send(aui, "b");
127
- expect(aui.thread().composer().getState().queue).toHaveLength(2);
124
+ expect(aui.thread.composer().getState().queue).toHaveLength(2);
128
125
 
129
126
  await act(async () => {
130
- aui.thread().composer().queueItem({ index: 0 }).remove();
127
+ aui.thread.composer().queueItem({ index: 0 }).remove();
131
128
  await flush();
132
129
  });
133
- const queue = aui.thread().composer().getState().queue;
130
+ const queue = aui.thread.composer().getState().queue;
134
131
  expect(queue).toHaveLength(1);
135
132
  expect(queue[0]!.prompt).toBe("b");
136
133
  });
@@ -142,15 +139,15 @@ describe("local runtime message queue", () => {
142
139
  await send(aui, "first");
143
140
  await send(aui, "a");
144
141
  await send(aui, "b");
145
- expect(aui.thread().composer().getState().queue).toHaveLength(2);
142
+ expect(aui.thread.composer().getState().queue).toHaveLength(2);
146
143
 
147
144
  await act(async () => {
148
- aui.thread().cancelRun();
145
+ aui.thread.cancelRun();
149
146
  await flush();
150
147
  await flush();
151
148
  });
152
149
 
153
- expect(aui.thread().composer().getState().queue).toEqual([]);
150
+ expect(aui.thread.composer().getState().queue).toEqual([]);
154
151
  // cancelling must not start the next queued message
155
152
  expect(getRunCount()).toBe(1);
156
153
  });
@@ -168,11 +165,11 @@ describe("local runtime message queue", () => {
168
165
  // start a second run and queue a message behind it
169
166
  await send(aui, "second");
170
167
  await send(aui, "queued");
171
- expect(aui.thread().composer().getState().queue).toHaveLength(1);
168
+ expect(aui.thread.composer().getState().queue).toHaveLength(1);
172
169
 
173
170
  // edit the first message while the run is in progress
174
171
  await act(async () => {
175
- const message = aui.thread().message({ index: 0 });
172
+ const message = aui.thread.message({ index: 0 });
176
173
  message.composer().beginEdit();
177
174
  message.composer().setText("edited");
178
175
  message.composer().send();
@@ -180,7 +177,7 @@ describe("local runtime message queue", () => {
180
177
  });
181
178
 
182
179
  // the edit is applied (branches the thread) and the stale queue is cleared
183
- expect(aui.thread().composer().getState().queue).toEqual([]);
180
+ expect(aui.thread.composer().getState().queue).toEqual([]);
184
181
  });
185
182
 
186
183
  it("buffers a send during a regenerate instead of interrupting it", async () => {
@@ -196,22 +193,21 @@ describe("local runtime message queue", () => {
196
193
 
197
194
  // regenerate the assistant message: a run started outside the queue
198
195
  await act(async () => {
199
- aui.thread().message({ index: 1 }).reload();
196
+ aui.thread.message({ index: 1 }).reload();
200
197
  await flush();
201
198
  });
202
199
  expect(getRunCount()).toBe(2);
203
- expect(aui.thread().getState().isRunning).toBe(true);
200
+ expect(aui.thread.getState().isRunning).toBe(true);
204
201
 
205
202
  // sending now must buffer, not interrupt the regenerate
206
203
  await act(async () => {
207
- aui.thread().composer().setText("Y");
208
- aui.thread().composer().send();
204
+ aui.thread.composer().setText("Y");
205
+ aui.thread.composer().send();
209
206
  await flush();
210
207
  });
211
208
  expect(getRunCount()).toBe(2);
212
209
  expect(
213
- aui
214
- .thread()
210
+ aui.thread
215
211
  .composer()
216
212
  .getState()
217
213
  .queue.map((q) => q.prompt),
@@ -239,7 +235,7 @@ describe("local runtime message queue", () => {
239
235
  await send(aui, "first");
240
236
  await send(aui, "a");
241
237
  await send(aui, "b");
242
- expect(aui.thread().composer().getState().queue).toHaveLength(2);
238
+ expect(aui.thread.composer().getState().queue).toHaveLength(2);
243
239
 
244
240
  // run 1 settles -> "a" drains (run 2 throws) -> "b" drains (run 3)
245
241
  await act(async () => {
@@ -248,18 +244,17 @@ describe("local runtime message queue", () => {
248
244
  await flush();
249
245
  });
250
246
  expect(runCount).toBe(3);
251
- expect(aui.thread().composer().getState().queue).toEqual([]);
247
+ expect(aui.thread.composer().getState().queue).toEqual([]);
252
248
 
253
249
  // "b" is running; a new send must buffer behind it, not interrupt it
254
250
  await act(async () => {
255
- aui.thread().composer().setText("c");
256
- aui.thread().composer().send();
251
+ aui.thread.composer().setText("c");
252
+ aui.thread.composer().send();
257
253
  await flush();
258
254
  });
259
255
  expect(runCount).toBe(3);
260
256
  expect(
261
- aui
262
- .thread()
257
+ aui.thread
263
258
  .composer()
264
259
  .getState()
265
260
  .queue.map((q) => q.prompt),
@@ -269,7 +264,7 @@ describe("local runtime message queue", () => {
269
264
  it("does not expose the queue capability when the flag is off", async () => {
270
265
  const { adapter } = createCountingAdapter();
271
266
  const aui = renderWithRuntime(adapter, false);
272
- expect(aui.thread().getState().capabilities.queue).toBe(false);
267
+ expect(aui.thread.getState().capabilities.queue).toBe(false);
273
268
  });
274
269
 
275
270
  it("tears the queue down when the flag is toggled off at runtime", async () => {
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { act, cleanup, render, waitFor } from "@testing-library/react";
4
4
  import { flushSync } from "react-dom";
5
- import { useEffect, useState, type FC } from "react";
5
+ import { Component, useEffect, useState, type FC, type ReactNode } from "react";
6
6
  import { afterEach, describe, expect, it, vi } from "vitest";
7
7
  import { useAui, useAuiState } from "@assistant-ui/store";
8
8
  import { AssistantRuntimeProvider, PartByIndexProvider } from "../context";
@@ -85,16 +85,33 @@ const ChildrenMessage: FC = () => (
85
85
  const InvalidPartReader: FC = () => {
86
86
  const part = useAuiState((s) => s.part);
87
87
  return (
88
- <p data-testid="clamped-part">
88
+ <p data-testid="invalid-part">
89
89
  {part.type === "text" ? part.text : part.type}
90
90
  </p>
91
91
  );
92
92
  };
93
93
 
94
+ class PartErrorBoundary extends Component<
95
+ { children: ReactNode },
96
+ { error: Error | null }
97
+ > {
98
+ override state: { error: Error | null } = { error: null };
99
+ static getDerivedStateFromError(error: Error) {
100
+ return { error };
101
+ }
102
+ override render() {
103
+ if (this.state.error)
104
+ return <p data-testid="part-error">{this.state.error.message}</p>;
105
+ return this.props.children;
106
+ }
107
+ }
108
+
94
109
  const InvalidPartMessage: FC = () => (
95
- <PartByIndexProvider index={2}>
96
- <InvalidPartReader />
97
- </PartByIndexProvider>
110
+ <PartErrorBoundary>
111
+ <PartByIndexProvider index={2}>
112
+ <InvalidPartReader />
113
+ </PartByIndexProvider>
114
+ </PartErrorBoundary>
98
115
  );
99
116
 
100
117
  const App: FC<{ MessageComponent?: FC }> = ({ MessageComponent = Message }) => {
@@ -152,21 +169,21 @@ describe("part hooks under a thread-switch race", () => {
152
169
  },
153
170
  );
154
171
 
155
- it("warns and clamps an index that was never valid", async () => {
156
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
172
+ it("throws to the error boundary for an index that was never valid", async () => {
173
+ const consoleError = vi
174
+ .spyOn(console, "error")
175
+ .mockImplementation(() => {});
157
176
  try {
158
177
  let view!: ReturnType<typeof render>;
159
178
  await act(async () => {
160
179
  view = render(<App MessageComponent={InvalidPartMessage} />);
161
180
  });
162
- expect(warn).toHaveBeenCalledWith(
163
- expect.stringContaining(
164
- "useClientLookup: Clamped stale index 2 to 1 (length: 2)",
165
- ),
181
+ expect(view.queryByTestId("invalid-part")).toBeNull();
182
+ expect(view.getByTestId("part-error").textContent).toContain(
183
+ "useClientLookup: index 2 out of bounds (length: 2)",
166
184
  );
167
- expect(view.getByTestId("clamped-part").textContent).toBe("world");
168
185
  } finally {
169
- warn.mockRestore();
186
+ consoleError.mockRestore();
170
187
  }
171
188
  });
172
189
  });
@@ -18,11 +18,11 @@ const flushTapSync = vi.fn((fn: () => void) => fn());
18
18
 
19
19
  vi.mock("@assistant-ui/store", () => ({
20
20
  useAui: () => ({
21
- composer: () => ({
21
+ composer: {
22
22
  getState: () => ({ isEditing: fixture.composer.isEditing }),
23
23
  setText: composerSetText,
24
24
  send: composerSend,
25
- }),
25
+ },
26
26
  }),
27
27
  useAuiState: (selector: (s: unknown) => unknown) =>
28
28
  selector({
@@ -83,9 +83,9 @@ export function unstable_useComposerInput(
83
83
 
84
84
  const setText = useCallback(
85
85
  (text: string) => {
86
- if (!aui.composer().getState().isEditing) return;
86
+ if (!aui.composer.getState().isEditing) return;
87
87
  flushTapSync(() => {
88
- aui.composer().setText(text);
88
+ aui.composer.setText(text);
89
89
  });
90
90
  },
91
91
  [aui],
@@ -12,11 +12,11 @@ const setText = vi.fn();
12
12
 
13
13
  vi.mock("@assistant-ui/store", () => ({
14
14
  useAui: () => ({
15
- composer: () => ({
15
+ composer: {
16
16
  getState: () => ({ type: fixture.composerType }),
17
17
  setText,
18
- }),
19
- thread: () => ({ getState: () => ({ messages: fixture.messages }) }),
18
+ },
19
+ thread: { getState: () => ({ messages: fixture.messages }) },
20
20
  on: (_event: string, cb: () => void) => {
21
21
  fixture.switchedToHandlers.push(cb);
22
22
  return () => {};
@@ -70,7 +70,7 @@ export function unstable_useComposerInputHistory(): Unstable_ComposerInputHistor
70
70
  const browseRef = useRef<BrowseState | null>(null);
71
71
 
72
72
  useEffect(() => {
73
- if (aui.composer().getState().type !== "thread") return undefined;
73
+ if (aui.composer.getState().type !== "thread") return undefined;
74
74
 
75
75
  return aui.on("threadListItem.switchedTo", () => {
76
76
  browseRef.current = null;
@@ -84,7 +84,7 @@ export function unstable_useComposerInputHistory(): Unstable_ComposerInputHistor
84
84
  if (e.nativeEvent.isComposing) return;
85
85
  if (e.shiftKey || e.ctrlKey || e.metaKey || e.altKey) return;
86
86
  if (popoverCtx && popoverCtx.getActiveAria() !== null) return;
87
- if (aui.composer().getState().type !== "thread") return;
87
+ if (aui.composer.getState().type !== "thread") return;
88
88
 
89
89
  const textarea = e.currentTarget;
90
90
  const { selectionStart, selectionEnd, value } = textarea;
@@ -96,7 +96,7 @@ export function unstable_useComposerInputHistory(): Unstable_ComposerInputHistor
96
96
  const browse = browseRef.current;
97
97
 
98
98
  const commitText = (text: string): void => {
99
- flushTapSync(() => aui.composer().setText(text));
99
+ flushTapSync(() => aui.composer.setText(text));
100
100
  // React's controlled-value commit restores the pre-recall caret;
101
101
  // reposition after the commit, before paint.
102
102
  requestAnimationFrame(() => {
@@ -124,13 +124,13 @@ export function unstable_useComposerInputHistory(): Unstable_ComposerInputHistor
124
124
 
125
125
  if (!browse) {
126
126
  if (value.trim() !== "") return;
127
- const history = deriveHistory(aui.thread().getState().messages);
127
+ const history = deriveHistory(aui.thread.getState().messages);
128
128
  if (history.length === 0) return;
129
129
  recall(history, 0, value);
130
130
  return;
131
131
  }
132
132
 
133
- const history = deriveHistory(aui.thread().getState().messages);
133
+ const history = deriveHistory(aui.thread.getState().messages);
134
134
  const next = browse.cursor + 1;
135
135
  if (next >= history.length) {
136
136
  e.preventDefault();
@@ -150,7 +150,7 @@ export function unstable_useComposerInputHistory(): Unstable_ComposerInputHistor
150
150
  return;
151
151
  }
152
152
 
153
- const history = deriveHistory(aui.thread().getState().messages);
153
+ const history = deriveHistory(aui.thread.getState().messages);
154
154
  recall(history, next, browse.draftSnapshot);
155
155
  },
156
156
  [aui, popoverCtx],
@@ -107,7 +107,7 @@ export function unstable_useMentionAdapter(
107
107
  const adapter = useMemo<Unstable_TriggerAdapter>(() => {
108
108
  const getModelContextTools = (): Unstable_TriggerItem[] => {
109
109
  if (!wantsTools) return [];
110
- const ctx = aui.thread().getModelContext();
110
+ const ctx = aui.thread.getModelContext();
111
111
  const tools = ctx.tools;
112
112
  if (!tools) return [];
113
113
  const formatLabel = toolsConfig?.formatLabel;
@@ -38,7 +38,7 @@ export const SmoothContextProvider: FC<PropsWithChildren> = ({ children }) => {
38
38
  const aui = useAui();
39
39
 
40
40
  const [context] = useState(() =>
41
- makeSmoothContext(aui.part().getState().status),
41
+ makeSmoothContext(aui.part.getState().status),
42
42
  );
43
43
 
44
44
  // do not wrap if there is an outer SmoothContextProvider
@@ -9,7 +9,7 @@ import type {
9
9
 
10
10
  const part = {};
11
11
  vi.mock("@assistant-ui/store", () => ({
12
- useAui: () => ({ part: () => part }),
12
+ useAui: () => ({ part }),
13
13
  useAuiState: (selector: () => unknown) => selector(),
14
14
  }));
15
15
  vi.mock("./SmoothContext", () => ({
@@ -181,7 +181,7 @@ export const useSmooth = (
181
181
  // of relying on a render-time proxy reference that may be stable
182
182
  // across thread swaps.
183
183
  const aui = useAui();
184
- const part = useAuiState(() => aui.part());
184
+ const part = useAuiState(() => aui.part);
185
185
  const [prevPart, setPrevPart] = useState(part);
186
186
  if (part !== prevPart || !text.startsWith(displayedText)) {
187
187
  setPrevPart(part);
@@ -1,34 +0,0 @@
1
- import { SubscribableRuntime } from "./useRuntimeState.js";
2
- //#region src/context/react/utils/createStateHookForRuntime.d.ts
3
- declare function createStateHookForRuntime<TState>(useRuntime: (options: {
4
- optional: boolean | undefined;
5
- }) => SubscribableRuntime<TState> | null): {
6
- (): TState;
7
- <TSelected>(selector: (state: TState) => TSelected): TSelected;
8
- <TSelected>(selector: ((state: TState) => TSelected) | undefined): TSelected | TState;
9
- (options: {
10
- optional?: false | undefined;
11
- }): TState;
12
- (options: {
13
- optional?: boolean | undefined;
14
- }): TState | null;
15
- <TSelected>(options: {
16
- optional?: false | undefined;
17
- selector: (state: TState) => TSelected;
18
- }): TSelected;
19
- <TSelected>(options: {
20
- optional?: false | undefined;
21
- selector: ((state: TState) => TSelected) | undefined;
22
- }): TSelected | TState;
23
- <TSelected>(options: {
24
- optional?: boolean | undefined;
25
- selector: (state: TState) => TSelected;
26
- }): TSelected | null;
27
- <TSelected>(options: {
28
- optional?: boolean | undefined;
29
- selector: ((state: TState) => TSelected) | undefined;
30
- }): TSelected | TState | null;
31
- };
32
- //#endregion
33
- export { createStateHookForRuntime };
34
- //# sourceMappingURL=createStateHookForRuntime.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createStateHookForRuntime.d.ts","names":[],"sources":["../../../../src/context/react/utils/createStateHookForRuntime.ts"],"mappings":";;iBAKgB,0BAA0B,QACxC,aAAa;EACX;MACI,oBAAoB;MAGD;GAGH,WAAS,WAClB,OAAO,WAAW,YAC5B;GAGmB,WAAS,YACjB,OAAO,WAAW,yBAC7B,YAAY;GAGgB;IAAE;MAAiC;GAGnC;IAC7B;MACE;GAGkB,WAAS;IAC7B;IACA,WAAW,OAAO,WAAW;MAC3B;GAGkB,WAAS;IAC7B;IACA,YAAY,OAAO,WAAW;MAC5B,YAAY;GAGM,WAAS;IAC7B;IACA,WAAW,OAAO,WAAW;MAC3B;GAGkB,WAAS;IAC7B;IACA,YAAY,OAAO,WAAW;MAC5B,YAAY"}
@@ -1,21 +0,0 @@
1
- import { useRuntimeStateInternal } from "./useRuntimeState.js";
2
- //#region src/context/react/utils/createStateHookForRuntime.ts
3
- function createStateHookForRuntime(useRuntime) {
4
- function useStoreHook(param) {
5
- let optional = false;
6
- let selector;
7
- if (typeof param === "function") selector = param;
8
- else if (param) {
9
- optional = !!param.optional;
10
- selector = param.selector;
11
- }
12
- const store = useRuntime({ optional });
13
- if (!store) return null;
14
- return useRuntimeStateInternal(store, selector);
15
- }
16
- return useStoreHook;
17
- }
18
- //#endregion
19
- export { createStateHookForRuntime };
20
-
21
- //# sourceMappingURL=createStateHookForRuntime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createStateHookForRuntime.js","names":["SubscribableRuntime","useRuntimeStateInternal","createStateHookForRuntime","useRuntime","options","optional","TState","useStoreHook","selector","state","TSelected","param","store"],"sources":["../../../../src/context/react/utils/createStateHookForRuntime.ts"],"sourcesContent":["import {\n type SubscribableRuntime,\n useRuntimeStateInternal,\n} from \"./useRuntimeState\";\n\nexport function createStateHookForRuntime<TState>(\n useRuntime: (options: {\n optional: boolean | undefined;\n }) => SubscribableRuntime<TState> | null,\n) {\n // empty\n function useStoreHook(): TState;\n\n // selector\n function useStoreHook<TSelected>(\n selector: (state: TState) => TSelected,\n ): TSelected;\n\n // selector?\n function useStoreHook<TSelected>(\n selector: ((state: TState) => TSelected) | undefined,\n ): TSelected | TState;\n\n // optional=false\n function useStoreHook(options: { optional?: false | undefined }): TState;\n\n // optional?\n function useStoreHook(options: {\n optional?: boolean | undefined;\n }): TState | null;\n\n // optional=false, selector\n function useStoreHook<TSelected>(options: {\n optional?: false | undefined;\n selector: (state: TState) => TSelected;\n }): TSelected;\n\n // optional=false, selector?\n function useStoreHook<TSelected>(options: {\n optional?: false | undefined;\n selector: ((state: TState) => TSelected) | undefined;\n }): TSelected | TState;\n\n // optional?, selector\n function useStoreHook<TSelected>(options: {\n optional?: boolean | undefined;\n selector: (state: TState) => TSelected;\n }): TSelected | null;\n\n // optional?, selector?\n function useStoreHook<TSelected>(options: {\n optional?: boolean | undefined;\n selector: ((state: TState) => TSelected) | undefined;\n }): TSelected | TState | null;\n\n function useStoreHook<TSelected>(\n param?:\n | ((state: TState) => TSelected)\n | {\n optional?: boolean | undefined;\n selector?: ((state: TState) => TSelected) | undefined;\n },\n ): TSelected | TState | null {\n let optional = false;\n let selector: ((state: TState) => TSelected) | undefined;\n\n if (typeof param === \"function\") {\n selector = param;\n } else if (param) {\n optional = !!param.optional;\n selector = param.selector;\n }\n\n const store = useRuntime({ optional });\n if (!store) return null;\n\n // it is ok to call useRuntimeStateInternal conditionally because it will never become null if its available\n return useRuntimeStateInternal(store, selector);\n }\n\n return useStoreHook;\n}\n"],"mappings":";;AAKA,SAAgBE,0BACdC,YAGA;CA8CA,SAASI,aACPI,OAM2B;EAC3B,IAAIN,WAAW;EACf,IAAIG;EAEJ,IAAI,OAAOG,UAAU,YACnBH,WAAWG;OACN,IAAIA,OAAO;GAChBN,WAAW,CAAC,CAACM,MAAMN;GACnBG,WAAWG,MAAMH;EACnB;EAEA,MAAMI,QAAQT,WAAW,EAAEE,SAAS,CAAC;EACrC,IAAI,CAACO,OAAO,OAAO;EAGnB,OAAOX,wBAAwBW,OAAOJ,QAAQ;CAChD;CAEA,OAAOD;AACT"}
@@ -1,74 +0,0 @@
1
- import { AssistantRuntime } from "../runtime/AssistantRuntime.js";
2
- //#region src/legacy-runtime/hooks/AssistantContext.d.ts
3
- /**
4
- * @deprecated Use {@link useAui} instead. See the {@link https://assistant-ui.com/docs/migrations/v0-12 migration guide}.
5
- *
6
- * Hook to access the AssistantRuntime from the current context.
7
- *
8
- * The AssistantRuntime provides access to the top-level assistant state and actions,
9
- * including thread management, tool registration, and configuration.
10
- *
11
- * @param options Configuration options
12
- * @param options.optional Whether the hook should return null if no context is found
13
- * @returns The AssistantRuntime instance, or null if optional is true and no context exists
14
- *
15
- * @example
16
- * ```tsx
17
- * // Before:
18
- * function MyComponent() {
19
- * const runtime = useAssistantRuntime();
20
- * const handleNewThread = () => {
21
- * runtime.switchToNewThread();
22
- * };
23
- * return <button onClick={handleNewThread}>New Thread</button>;
24
- * }
25
- *
26
- * // After:
27
- * function MyComponent() {
28
- * const aui = useAui();
29
- * const handleNewThread = () => {
30
- * aui.threads().switchToNewThread();
31
- * };
32
- * return <button onClick={handleNewThread}>New Thread</button>;
33
- * }
34
- * ```
35
- */
36
- declare function useAssistantRuntime(options?: {
37
- optional?: false | undefined;
38
- }): AssistantRuntime;
39
- declare function useAssistantRuntime(options?: {
40
- optional?: boolean | undefined;
41
- }): AssistantRuntime | null;
42
- /**
43
- * @deprecated Use {@link useAuiState}: `useAuiState((s) => s.threads)`. See the {@link https://assistant-ui.com/docs/migrations/v0-12 migration guide}.
44
- */
45
- declare const useThreadList: {
46
- (): import("@assistant-ui/core").ThreadListState;
47
- <TSelected>(selector: (state: import("@assistant-ui/core").ThreadListState) => TSelected): TSelected;
48
- <TSelected>(selector: ((state: import("@assistant-ui/core").ThreadListState) => TSelected) | undefined): import("@assistant-ui/core").ThreadListState | TSelected;
49
- (options: {
50
- optional?: false | undefined;
51
- }): import("@assistant-ui/core").ThreadListState;
52
- (options: {
53
- optional?: boolean | undefined;
54
- }): import("@assistant-ui/core").ThreadListState | null;
55
- <TSelected>(options: {
56
- optional?: false | undefined;
57
- selector: (state: import("@assistant-ui/core").ThreadListState) => TSelected;
58
- }): TSelected;
59
- <TSelected>(options: {
60
- optional?: false | undefined;
61
- selector: ((state: import("@assistant-ui/core").ThreadListState) => TSelected) | undefined;
62
- }): import("@assistant-ui/core").ThreadListState | TSelected;
63
- <TSelected>(options: {
64
- optional?: boolean | undefined;
65
- selector: (state: import("@assistant-ui/core").ThreadListState) => TSelected;
66
- }): TSelected | null;
67
- <TSelected>(options: {
68
- optional?: boolean | undefined;
69
- selector: ((state: import("@assistant-ui/core").ThreadListState) => TSelected) | undefined;
70
- }): import("@assistant-ui/core").ThreadListState | TSelected | null;
71
- };
72
- //#endregion
73
- export { useAssistantRuntime, useThreadList };
74
- //# sourceMappingURL=AssistantContext.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AssistantContext.d.ts","names":[],"sources":["../../../src/legacy-runtime/hooks/AssistantContext.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCgB,oBAAoB;EAClC;IACE;iBACY,oBAAoB;EAClC;IACE;;;;cAqBS"}
@@ -1,29 +0,0 @@
1
- "use client";
2
- import { createStateHookForRuntime } from "../../context/react/utils/createStateHookForRuntime.js";
3
- import { useAui } from "@assistant-ui/store";
4
- import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
5
- //#region src/legacy-runtime/hooks/AssistantContext.ts
6
- function useAssistantRuntime(options) {
7
- const $ = c(2);
8
- const aui = useAui();
9
- let t0;
10
- if ($[0] !== aui) {
11
- t0 = aui.threads().__internal_getAssistantRuntime?.() ?? null;
12
- $[0] = aui;
13
- $[1] = t0;
14
- } else t0 = $[1];
15
- const runtime = t0;
16
- if (!runtime && !options?.optional) throw new Error("AssistantRuntime is not available");
17
- return runtime;
18
- }
19
- const useThreadListRuntime = (opt) => {
20
- return useAssistantRuntime(opt)?.threads ?? null;
21
- };
22
- /**
23
- * @deprecated Use {@link useAuiState}: `useAuiState((s) => s.threads)`. See the {@link https://assistant-ui.com/docs/migrations/v0-12 migration guide}.
24
- */
25
- const useThreadList = createStateHookForRuntime(useThreadListRuntime);
26
- //#endregion
27
- export { useAssistantRuntime, useThreadList };
28
-
29
- //# sourceMappingURL=AssistantContext.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AssistantContext.js","names":["c","_c","useAui","AssistantRuntime","ThreadListRuntime","createStateHookForRuntime","useAssistantRuntime","options","optional","$","aui","t0","threads","__internal_getAssistantRuntime","runtime","Error","useThreadListRuntime","opt","useThreadList"],"sources":["../../../src/legacy-runtime/hooks/AssistantContext.ts"],"sourcesContent":["\"use client\";\n\nimport { useAui } from \"@assistant-ui/store\";\nimport type { AssistantRuntime } from \"../runtime/AssistantRuntime\";\nimport type { ThreadListRuntime } from \"../runtime/ThreadListRuntime\";\nimport { createStateHookForRuntime } from \"../../context/react/utils/createStateHookForRuntime\";\n\n/**\n * @deprecated Use {@link useAui} instead. See the {@link https://assistant-ui.com/docs/migrations/v0-12 migration guide}.\n *\n * Hook to access the AssistantRuntime from the current context.\n *\n * The AssistantRuntime provides access to the top-level assistant state and actions,\n * including thread management, tool registration, and configuration.\n *\n * @param options Configuration options\n * @param options.optional Whether the hook should return null if no context is found\n * @returns The AssistantRuntime instance, or null if optional is true and no context exists\n *\n * @example\n * ```tsx\n * // Before:\n * function MyComponent() {\n * const runtime = useAssistantRuntime();\n * const handleNewThread = () => {\n * runtime.switchToNewThread();\n * };\n * return <button onClick={handleNewThread}>New Thread</button>;\n * }\n *\n * // After:\n * function MyComponent() {\n * const aui = useAui();\n * const handleNewThread = () => {\n * aui.threads().switchToNewThread();\n * };\n * return <button onClick={handleNewThread}>New Thread</button>;\n * }\n * ```\n */\nexport function useAssistantRuntime(options?: {\n optional?: false | undefined;\n}): AssistantRuntime;\nexport function useAssistantRuntime(options?: {\n optional?: boolean | undefined;\n}): AssistantRuntime | null;\nexport function useAssistantRuntime(options?: {\n optional?: boolean | undefined;\n}) {\n const aui = useAui();\n const runtime = aui.threads().__internal_getAssistantRuntime?.() ?? null;\n\n if (!runtime && !options?.optional) {\n throw new Error(\"AssistantRuntime is not available\");\n }\n\n return runtime;\n}\n\nconst useThreadListRuntime = (opt: {\n optional: boolean | undefined;\n}): ThreadListRuntime | null => useAssistantRuntime(opt)?.threads ?? null;\n\n/**\n * @deprecated Use {@link useAuiState}: `useAuiState((s) => s.threads)`. See the {@link https://assistant-ui.com/docs/migrations/v0-12 migration guide}.\n */\nexport const useThreadList = createStateHookForRuntime(useThreadListRuntime);\n"],"mappings":";;;;;AA8CA,SAAOM,oBAAAC,SAAA;CAAA,MAAAE,IAAAR,EAAA,CAAA;CAGL,MAAAS,MAAYR,OAAO;CAAE,IAAAS;CAAA,IAAAF,EAAA,OAAAC,KAAA;EACLC,KAAAD,IAAGE,QAAS,CAAC,CAAAC,iCAA0C,KAAvD;EAAwDJ,EAAA,KAAAC;EAAAD,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAxE,MAAAK,UAAgBH;CAEhB,IAAI,CAACG,WAAD,CAAaP,SAAOC,UACtB,MAAM,IAAIO,MAAM,mCAAmC;CACpD,OAEMD;AAAO;AAGhB,MAAME,wBAAuBC,QAAA;CAAA,OAEGX,oBAAoBW,GAAY,CAAC,EAAAL,WAAjC;AAAyC;;;;AAKzE,MAAaM,gBAAgBb,0BAA0BW,oBAAoB"}