diff --git a/.changeset/sour-dancers-fetch.md b/.changeset/sour-dancers-fetch.md
new file mode 100644
index 000000000..950832526
--- /dev/null
+++ b/.changeset/sour-dancers-fetch.md
@@ -0,0 +1,6 @@
+---
+"@assistant-ui/react-ai-sdk": patch
+"@assistant-ui/react": patch
+---
+
+feat: lift thread composer state to ThreadRuntime.Composer
diff --git a/apps/docs/components/docs/parameters/context.tsx b/apps/docs/components/docs/parameters/context.tsx
index da1084984..9f8a64ce8 100644
--- a/apps/docs/components/docs/parameters/context.tsx
+++ b/apps/docs/components/docs/parameters/context.tsx
@@ -259,16 +259,16 @@ export const BaseComposerState: ParametersTableProps = {
type: "BaseComposerState",
parameters: [
{
- name: "value",
+ name: "text",
type: "string",
required: true,
- description: "The current value of the composer.",
+ description: "The current text of the composer.",
},
{
- name: "setValue",
- type: "(value: string) => void",
+ name: "setText",
+ type: "(text: string) => void",
required: true,
- description: "A function to set the value of the composer.",
+ description: "A function to set the text of the composer.",
},
],
};
diff --git a/apps/docs/content/docs/reference/context.mdx b/apps/docs/content/docs/reference/context.mdx
index 81acab5c9..3e885cf3d 100644
--- a/apps/docs/content/docs/reference/context.mdx
+++ b/apps/docs/content/docs/reference/context.mdx
@@ -169,8 +169,8 @@ const { useComposer } = useThreadContext();
const value = useComposer((m) => m.value);
const value = useComposer.getState().value;
-const setValue = useComposer((m) => m.setValue);
-const setValue = useComposer.getState().setValue;
+const setText = useComposer((m) => m.setText);
+const setText = useComposer.getState().setText;
```
@@ -254,8 +254,8 @@ const { useEditComposer } = useMessageContext();
const value = useEditComposer((m) => m.value);
const value = useEditComposer.getState().value;
-const setValue = useEditComposer((m) => m.setValue);
-const setValue = useEditComposer.getState().setValue;
+const setText = useEditComposer((m) => m.setText);
+const setText = useEditComposer.getState().setText;
```
@@ -328,6 +328,6 @@ const { useComposer } = useComposerContext();
const value = useComposer((m) => m.value);
const value = useComposer.getState().value;
-const setValue = useComposer((m) => m.setValue);
-const setValue = useComposer.getState().setValue;
+const setText = useComposer((m) => m.setText);
+const setText = useComposer.getState().setText;
```
diff --git a/packages/react-ai-sdk/src/ui/use-assistant/VercelUseAssistantThreadRuntime.tsx b/packages/react-ai-sdk/src/ui/use-assistant/VercelUseAssistantThreadRuntime.tsx
index 62bf93b3c..f577437d1 100644
--- a/packages/react-ai-sdk/src/ui/use-assistant/VercelUseAssistantThreadRuntime.tsx
+++ b/packages/react-ai-sdk/src/ui/use-assistant/VercelUseAssistantThreadRuntime.tsx
@@ -30,6 +30,16 @@ export class VercelUseAssistantThreadRuntime implements ReactThreadRuntime {
>;
public messages: readonly ThreadMessage[] = [];
+
+ public readonly composer = {
+ text: "",
+ setText: (value: string) => {
+ this.composer.text = value;
+
+ for (const callback of this._subscriptions) callback();
+ },
+ };
+
public readonly isDisabled = false;
constructor(public vercel: ReturnType) {
diff --git a/packages/react-ai-sdk/src/ui/use-chat/VercelUseChatThreadRuntime.tsx b/packages/react-ai-sdk/src/ui/use-chat/VercelUseChatThreadRuntime.tsx
index dc53c2afd..651e5df08 100644
--- a/packages/react-ai-sdk/src/ui/use-chat/VercelUseChatThreadRuntime.tsx
+++ b/packages/react-ai-sdk/src/ui/use-chat/VercelUseChatThreadRuntime.tsx
@@ -45,6 +45,15 @@ export class VercelUseChatThreadRuntime implements ReactThreadRuntime {
public messages: ThreadMessage[] = [];
public readonly isDisabled = false;
+ public readonly composer = {
+ text: "",
+ setText: (value: string) => {
+ this.composer.text = value;
+
+ for (const callback of this._subscriptions) callback();
+ },
+ };
+
constructor(public vercel: ReturnType) {
this.useVercel = create(() => ({
vercel,
diff --git a/packages/react-ai-sdk/src/ui/utils/useVercelAIComposerSync.tsx b/packages/react-ai-sdk/src/ui/utils/useVercelAIComposerSync.tsx
index 0ef102c26..b66a0d21e 100644
--- a/packages/react-ai-sdk/src/ui/utils/useVercelAIComposerSync.tsx
+++ b/packages/react-ai-sdk/src/ui/utils/useVercelAIComposerSync.tsx
@@ -9,8 +9,8 @@ export const useVercelAIComposerSync = (vercel: VercelHelpers) => {
useEffect(() => {
(useComposer as unknown as StoreApi).setState({
- value: vercel.input,
- setValue: vercel.setInput,
+ text: vercel.input,
+ setText: vercel.setInput,
});
}, [useComposer, vercel.input, vercel.setInput]);
};
diff --git a/packages/react-playground/src/components/ui/assistant-ui/thread.tsx b/packages/react-playground/src/components/ui/assistant-ui/thread.tsx
index 7ff31ad51..a65262a58 100644
--- a/packages/react-playground/src/components/ui/assistant-ui/thread.tsx
+++ b/packages/react-playground/src/components/ui/assistant-ui/thread.tsx
@@ -105,19 +105,19 @@ const Composer: FC = () => {
useThreadContext();
const isRunning = useThread((t) => t.isRunning);
- const hasValue = useComposer((c) => c.value.length > 0);
+ const hasText = useComposer((c) => c.text.length > 0);
const performAdd = () => {
const composer = useComposer.getState();
- const value = composer.value;
- if (!value) return;
+ const text = composer.text;
+ if (!text) return;
- composer.setValue("");
+ composer.setText("");
useThreadActions.getState().append({
parentId: useThreadMessages.getState().at(-1)?.id ?? null,
role,
- content: [{ type: "text", text: value }],
+ content: [{ type: "text", text }],
});
setRole("user");
@@ -167,7 +167,7 @@ const Composer: FC = () => {