@assistant-ui/react 0.11.7 → 0.11.9

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.
@@ -140,7 +140,7 @@ var extendApi = (api, api2) => {
140
140
  var AssistantProvider = ({ api: api2, children }) => {
141
141
  const api = useAssistantApi();
142
142
  const extendedApi = useMemo(() => extendApi(api, api2), [api, api2]);
143
- return /* @__PURE__ */ jsx(AssistantApiContext, { value: extendedApi, children: /* @__PURE__ */ jsx(ThreadViewportProvider, { children }) });
143
+ return /* @__PURE__ */ jsx(AssistantApiContext.Provider, { value: extendedApi, children: /* @__PURE__ */ jsx(ThreadViewportProvider, { children }) });
144
144
  };
145
145
  export {
146
146
  AssistantProvider,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/context/react/AssistantApiContext.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n FC,\n PropsWithChildren,\n useContext,\n useMemo,\n} from \"react\";\n\nimport { ToolUIApi, ToolUIState, ToolUIMeta } from \"../../client/types/ToolUI\";\nimport {\n MessageClientApi,\n MessageClientState,\n} from \"../../client/types/Message\";\nimport {\n ThreadListItemClientApi,\n ThreadListItemClientState,\n} from \"../../client/types/ThreadListItem\";\nimport {\n MessagePartClientApi,\n MessagePartClientState,\n} from \"../../client/types/Part\";\nimport { ThreadClientApi, ThreadClientState } from \"../../client/types/Thread\";\nimport {\n ComposerClientApi,\n ComposerClientState,\n} from \"../../client/types/Composer\";\nimport {\n AttachmentClientApi,\n AttachmentClientState,\n} from \"../../client/types/Attachment\";\nimport { Unsubscribe } from \"@assistant-ui/tap\";\nimport { ModelContextProvider } from \"../../model-context\";\nimport { AssistantRuntime } from \"../../legacy-runtime/runtime/AssistantRuntime\";\nimport {\n AssistantEvent,\n AssistantEventCallback,\n AssistantEventSelector,\n normalizeEventSelector,\n} from \"../../types/EventTypes\";\nimport {\n ThreadListClientApi,\n ThreadListClientState,\n} from \"../../client/types/ThreadList\";\nimport { ThreadViewportProvider } from \"../providers/ThreadViewportProvider\";\n\nexport type AssistantState = {\n readonly threads: ThreadListClientState;\n readonly toolUIs: ToolUIState;\n\n readonly threadListItem: ThreadListItemClientState;\n readonly thread: ThreadClientState;\n readonly composer: ComposerClientState;\n readonly message: MessageClientState;\n readonly part: MessagePartClientState;\n readonly attachment: AttachmentClientState;\n};\n\ntype AssistantApiField<\n TApi,\n TMeta extends { source: string | null; query: any },\n> = (() => TApi) & (TMeta | { source: null; query: Record<string, never> });\n\n// Meta types for each API method\ntype ThreadsMeta = {\n source: \"root\";\n query: Record<string, never>;\n};\n\ntype ThreadListItemMeta = {\n source: \"threads\";\n query:\n | { type: \"index\"; index: number; archived: boolean }\n | { type: \"main\" }\n | { type: \"id\"; id: string };\n};\n\ntype ThreadMeta = {\n source: \"threads\";\n query: { type: \"main\" };\n};\n\ntype ComposerMeta = {\n source: \"message\" | \"thread\";\n query: Record<string, never>;\n};\n\ntype MessageMeta = {\n source: \"thread\";\n query: { type: \"index\"; index: number };\n};\n\ntype PartMeta = {\n source: \"message\" | \"root\";\n query: { type: \"index\"; index: number } | Record<string, never>;\n};\n\ntype AttachmentMeta = {\n source: \"message\" | \"composer\";\n query: { type: \"index\"; index: number };\n};\n\nexport type AssistantApi = {\n threads: AssistantApiField<ThreadListClientApi, ThreadsMeta>;\n toolUIs: AssistantApiField<ToolUIApi, ToolUIMeta>;\n threadListItem: AssistantApiField<\n ThreadListItemClientApi,\n ThreadListItemMeta\n >;\n thread: AssistantApiField<ThreadClientApi, ThreadMeta>;\n composer: AssistantApiField<ComposerClientApi, ComposerMeta>;\n message: AssistantApiField<MessageClientApi, MessageMeta>;\n part: AssistantApiField<MessagePartClientApi, PartMeta>;\n attachment: AssistantApiField<AttachmentClientApi, AttachmentMeta>;\n\n subscribe(listener: () => void): Unsubscribe;\n flushSync(): void;\n\n on<TEvent extends AssistantEvent>(\n event: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n ): Unsubscribe;\n\n // temp\n registerModelContextProvider(provider: ModelContextProvider): void;\n /** @internal */\n __internal_getRuntime(): AssistantRuntime | null;\n};\n\nexport const createAssistantApiField = <\n TApi,\n TMeta extends { source: any; query: any },\n>(\n config: {\n get: () => TApi;\n } & (TMeta | { source: null; query: Record<string, never> }),\n): AssistantApiField<TApi, TMeta> => {\n const fn = config.get as AssistantApiField<TApi, TMeta>;\n fn.source = config.source;\n fn.query = config.query;\n return fn;\n};\n\nconst NO_OP_FN = () => () => {};\n\nconst AssistantApiContext = createContext<AssistantApi>({\n threads: createAssistantApiField({\n source: null,\n query: {},\n get: () => {\n throw new Error(\"Threads is only available inside <AssistantProvider />\");\n },\n }),\n toolUIs: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\"ToolUIs is only available inside <AssistantProvider />\");\n },\n }),\n threadListItem: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"ThreadListItem is only available inside <AssistantProvider />\",\n );\n },\n }),\n thread: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\"Thread is only available inside <AssistantProvider />\");\n },\n }),\n composer: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Composer is only available inside <AssistantProvider />\",\n );\n },\n }),\n message: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Message is only available inside <ThreadPrimitive.Messages />\",\n );\n },\n }),\n part: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Part is only available inside <MessagePrimitive.Parts />\",\n );\n },\n }),\n attachment: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Attachment is only available inside <MessagePrimitive.Attachments /> or <ComposerPrimitive.Attachments />\",\n );\n },\n }),\n\n subscribe: NO_OP_FN,\n flushSync: NO_OP_FN,\n on: (selector) => {\n const { scope } = normalizeEventSelector(selector);\n throw new Error(`Event scope is not available in this component: ${scope}`);\n },\n\n registerModelContextProvider: () => {\n throw new Error(\n \"Registering model context providers is only available inside <AssistantProvider />\",\n );\n },\n __internal_getRuntime: () => {\n return null;\n },\n});\n\nexport const useAssistantApi = (): AssistantApi => {\n return useContext(AssistantApiContext);\n};\n\nconst mergeFns = <TArgs extends Array<unknown>>(\n fn1: (...args: TArgs) => void,\n fn2: (...args: TArgs) => void,\n) => {\n if (fn1 === NO_OP_FN) return fn2;\n if (fn2 === NO_OP_FN) return fn1;\n\n return (...args: TArgs) => {\n fn1(...args);\n fn2(...args);\n };\n};\n\nconst mergeFnsWithUnsubscribe = <TArgs extends Array<unknown>>(\n fn1: (...args: TArgs) => Unsubscribe,\n fn2: (...args: TArgs) => Unsubscribe,\n) => {\n if (fn1 === NO_OP_FN) return fn2;\n if (fn2 === NO_OP_FN) return fn1;\n\n return (...args: TArgs) => {\n const unsubscribe1 = fn1(...args);\n const unsubscribe2 = fn2(...args);\n\n return () => {\n unsubscribe1();\n unsubscribe2();\n };\n };\n};\n\nconst extendApi = (\n api: AssistantApi,\n api2: Partial<AssistantApi>,\n): AssistantApi => {\n const api2Subscribe = api2.subscribe;\n const api2FlushSync = api2.flushSync;\n return {\n ...api,\n ...api2,\n subscribe: mergeFnsWithUnsubscribe(\n api.subscribe,\n api2Subscribe ?? NO_OP_FN,\n ),\n flushSync: mergeFns(api.flushSync, api2FlushSync ?? NO_OP_FN),\n };\n};\n\nexport const AssistantProvider: FC<\n PropsWithChildren<{ api: Partial<AssistantApi> }>\n> = ({ api: api2, children }) => {\n const api = useAssistantApi();\n const extendedApi = useMemo(() => extendApi(api, api2), [api, api2]);\n\n return (\n <AssistantApiContext value={extendedApi}>\n {/* TODO temporarily allow accessing viewport state from outside the viewport */}\n {/* TODO figure out if this behavior should be deprecated, since it is quite hacky */}\n <ThreadViewportProvider>{children}</ThreadViewportProvider>\n </AssistantApiContext>\n );\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/context/react/AssistantApiContext.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n FC,\n PropsWithChildren,\n useContext,\n useMemo,\n} from \"react\";\n\nimport { ToolUIApi, ToolUIState, ToolUIMeta } from \"../../client/types/ToolUI\";\nimport {\n MessageClientApi,\n MessageClientState,\n} from \"../../client/types/Message\";\nimport {\n ThreadListItemClientApi,\n ThreadListItemClientState,\n} from \"../../client/types/ThreadListItem\";\nimport {\n MessagePartClientApi,\n MessagePartClientState,\n} from \"../../client/types/Part\";\nimport { ThreadClientApi, ThreadClientState } from \"../../client/types/Thread\";\nimport {\n ComposerClientApi,\n ComposerClientState,\n} from \"../../client/types/Composer\";\nimport {\n AttachmentClientApi,\n AttachmentClientState,\n} from \"../../client/types/Attachment\";\nimport { Unsubscribe } from \"@assistant-ui/tap\";\nimport { ModelContextProvider } from \"../../model-context\";\nimport { AssistantRuntime } from \"../../legacy-runtime/runtime/AssistantRuntime\";\nimport {\n AssistantEvent,\n AssistantEventCallback,\n AssistantEventSelector,\n normalizeEventSelector,\n} from \"../../types/EventTypes\";\nimport {\n ThreadListClientApi,\n ThreadListClientState,\n} from \"../../client/types/ThreadList\";\nimport { ThreadViewportProvider } from \"../providers/ThreadViewportProvider\";\n\nexport type AssistantState = {\n readonly threads: ThreadListClientState;\n readonly toolUIs: ToolUIState;\n\n readonly threadListItem: ThreadListItemClientState;\n readonly thread: ThreadClientState;\n readonly composer: ComposerClientState;\n readonly message: MessageClientState;\n readonly part: MessagePartClientState;\n readonly attachment: AttachmentClientState;\n};\n\ntype AssistantApiField<\n TApi,\n TMeta extends { source: string | null; query: any },\n> = (() => TApi) & (TMeta | { source: null; query: Record<string, never> });\n\n// Meta types for each API method\ntype ThreadsMeta = {\n source: \"root\";\n query: Record<string, never>;\n};\n\ntype ThreadListItemMeta = {\n source: \"threads\";\n query:\n | { type: \"index\"; index: number; archived: boolean }\n | { type: \"main\" }\n | { type: \"id\"; id: string };\n};\n\ntype ThreadMeta = {\n source: \"threads\";\n query: { type: \"main\" };\n};\n\ntype ComposerMeta = {\n source: \"message\" | \"thread\";\n query: Record<string, never>;\n};\n\ntype MessageMeta = {\n source: \"thread\";\n query: { type: \"index\"; index: number };\n};\n\ntype PartMeta = {\n source: \"message\" | \"root\";\n query: { type: \"index\"; index: number } | Record<string, never>;\n};\n\ntype AttachmentMeta = {\n source: \"message\" | \"composer\";\n query: { type: \"index\"; index: number };\n};\n\nexport type AssistantApi = {\n threads: AssistantApiField<ThreadListClientApi, ThreadsMeta>;\n toolUIs: AssistantApiField<ToolUIApi, ToolUIMeta>;\n threadListItem: AssistantApiField<\n ThreadListItemClientApi,\n ThreadListItemMeta\n >;\n thread: AssistantApiField<ThreadClientApi, ThreadMeta>;\n composer: AssistantApiField<ComposerClientApi, ComposerMeta>;\n message: AssistantApiField<MessageClientApi, MessageMeta>;\n part: AssistantApiField<MessagePartClientApi, PartMeta>;\n attachment: AssistantApiField<AttachmentClientApi, AttachmentMeta>;\n\n subscribe(listener: () => void): Unsubscribe;\n flushSync(): void;\n\n on<TEvent extends AssistantEvent>(\n event: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n ): Unsubscribe;\n\n // temp\n registerModelContextProvider(provider: ModelContextProvider): void;\n /** @internal */\n __internal_getRuntime(): AssistantRuntime | null;\n};\n\nexport const createAssistantApiField = <\n TApi,\n TMeta extends { source: any; query: any },\n>(\n config: {\n get: () => TApi;\n } & (TMeta | { source: null; query: Record<string, never> }),\n): AssistantApiField<TApi, TMeta> => {\n const fn = config.get as AssistantApiField<TApi, TMeta>;\n fn.source = config.source;\n fn.query = config.query;\n return fn;\n};\n\nconst NO_OP_FN = () => () => {};\n\nconst AssistantApiContext = createContext<AssistantApi>({\n threads: createAssistantApiField({\n source: null,\n query: {},\n get: () => {\n throw new Error(\"Threads is only available inside <AssistantProvider />\");\n },\n }),\n toolUIs: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\"ToolUIs is only available inside <AssistantProvider />\");\n },\n }),\n threadListItem: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"ThreadListItem is only available inside <AssistantProvider />\",\n );\n },\n }),\n thread: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\"Thread is only available inside <AssistantProvider />\");\n },\n }),\n composer: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Composer is only available inside <AssistantProvider />\",\n );\n },\n }),\n message: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Message is only available inside <ThreadPrimitive.Messages />\",\n );\n },\n }),\n part: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Part is only available inside <MessagePrimitive.Parts />\",\n );\n },\n }),\n attachment: createAssistantApiField({\n source: null,\n query: {},\n get: (): never => {\n throw new Error(\n \"Attachment is only available inside <MessagePrimitive.Attachments /> or <ComposerPrimitive.Attachments />\",\n );\n },\n }),\n\n subscribe: NO_OP_FN,\n flushSync: NO_OP_FN,\n on: (selector) => {\n const { scope } = normalizeEventSelector(selector);\n throw new Error(`Event scope is not available in this component: ${scope}`);\n },\n\n registerModelContextProvider: () => {\n throw new Error(\n \"Registering model context providers is only available inside <AssistantProvider />\",\n );\n },\n __internal_getRuntime: () => {\n return null;\n },\n});\n\nexport const useAssistantApi = (): AssistantApi => {\n return useContext(AssistantApiContext);\n};\n\nconst mergeFns = <TArgs extends Array<unknown>>(\n fn1: (...args: TArgs) => void,\n fn2: (...args: TArgs) => void,\n) => {\n if (fn1 === NO_OP_FN) return fn2;\n if (fn2 === NO_OP_FN) return fn1;\n\n return (...args: TArgs) => {\n fn1(...args);\n fn2(...args);\n };\n};\n\nconst mergeFnsWithUnsubscribe = <TArgs extends Array<unknown>>(\n fn1: (...args: TArgs) => Unsubscribe,\n fn2: (...args: TArgs) => Unsubscribe,\n) => {\n if (fn1 === NO_OP_FN) return fn2;\n if (fn2 === NO_OP_FN) return fn1;\n\n return (...args: TArgs) => {\n const unsubscribe1 = fn1(...args);\n const unsubscribe2 = fn2(...args);\n\n return () => {\n unsubscribe1();\n unsubscribe2();\n };\n };\n};\n\nconst extendApi = (\n api: AssistantApi,\n api2: Partial<AssistantApi>,\n): AssistantApi => {\n const api2Subscribe = api2.subscribe;\n const api2FlushSync = api2.flushSync;\n return {\n ...api,\n ...api2,\n subscribe: mergeFnsWithUnsubscribe(\n api.subscribe,\n api2Subscribe ?? NO_OP_FN,\n ),\n flushSync: mergeFns(api.flushSync, api2FlushSync ?? NO_OP_FN),\n };\n};\n\nexport const AssistantProvider: FC<\n PropsWithChildren<{ api: Partial<AssistantApi> }>\n> = ({ api: api2, children }) => {\n const api = useAssistantApi();\n const extendedApi = useMemo(() => extendApi(api, api2), [api, api2]);\n\n return (\n <AssistantApiContext.Provider value={extendedApi}>\n {/* TODO temporarily allow accessing viewport state from outside the viewport */}\n {/* TODO figure out if this behavior should be deprecated, since it is quite hacky */}\n <ThreadViewportProvider>{children}</ThreadViewportProvider>\n </AssistantApiContext.Provider>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantTransportRuntime.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAQlE,OAAO,EACL,yBAAyB,EAK1B,MAAM,SAAS,CAAC;AAmMjB;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,EAC5C,SAAS,yBAAyB,CAAC,CAAC,CAAC,KACpC,gBAQF,CAAC"}
1
+ {"version":3,"file":"useAssistantTransportRuntime.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAQlE,OAAO,EACL,yBAAyB,EAK1B,MAAM,SAAS,CAAC;AA0MjB;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,EAC5C,SAAS,yBAAyB,CAAC,CAAC,CAAC,KACpC,gBAQF,CAAC"}
@@ -119,12 +119,18 @@ var useAssistantTransportThreadRuntime = (options) => {
119
119
  messages: converted.messages,
120
120
  adapters: options.adapters,
121
121
  onNew: async (message) => {
122
+ if (message.role !== "user")
123
+ throw new Error("Only user messages are supported");
122
124
  const parts = [];
123
- for (const content of message.content) {
124
- if (content.type === "text") {
125
- parts.push({ type: "text", text: content.text });
126
- } else if (content.type === "image") {
127
- parts.push({ type: "image", image: content.image });
125
+ const content = [
126
+ ...message.content,
127
+ ...message.attachments?.flatMap((a) => a.content) ?? []
128
+ ];
129
+ for (const contentPart of content) {
130
+ if (contentPart.type === "text") {
131
+ parts.push({ type: "text", text: contentPart.text });
132
+ } else if (contentPart.type === "image") {
133
+ parts.push({ type: "image", image: contentPart.image });
128
134
  }
129
135
  }
130
136
  const command = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n asAsyncIterableStream,\n} from \"assistant-stream/utils\";\nimport { AppendMessage } from \"../../../types\";\nimport { useExternalStoreRuntime } from \"../external-store/useExternalStoreRuntime\";\nimport { AssistantRuntime } from \"../../runtime/AssistantRuntime\";\nimport { AddToolResultOptions } from \"../core\";\nimport { useState, useRef, useMemo } from \"react\";\nimport {\n AssistantMessageAccumulator,\n DataStreamDecoder,\n unstable_createInitialMessage as createInitialMessage,\n} from \"assistant-stream\";\nimport {\n AssistantTransportOptions,\n AddMessageCommand,\n AddToolResultCommand,\n UserMessagePart,\n QueuedCommand,\n} from \"./types\";\nimport { useCommandQueue } from \"./commandQueue\";\nimport { useRunManager } from \"./runManager\";\nimport { useConvertedState } from \"./useConvertedState\";\nimport { useToolInvocations } from \"./useToolInvocations\";\nimport { toAISDKTools, getEnabledTools, createRequestHeaders } from \"./utils\";\nimport { useRemoteThreadListRuntime } from \"../remote-thread-list/useRemoteThreadListRuntime\";\nimport { InMemoryThreadListAdapter } from \"../remote-thread-list/adapter/in-memory\";\n\nconst useAssistantTransportThreadRuntime = <T,>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const agentStateRef = useRef(options.initialState);\n const [, rerender] = useState(0);\n const resumeFlagRef = useRef(false);\n const commandQueue = useCommandQueue({\n onQueue: () => runManager.schedule(),\n });\n\n const runManager = useRunManager({\n onRun: async (signal: AbortSignal) => {\n const isResume = resumeFlagRef.current;\n resumeFlagRef.current = false;\n const commands: QueuedCommand[] = isResume ? [] : commandQueue.flush();\n if (commands.length === 0 && !isResume)\n throw new Error(\"No commands to send\");\n\n const headers = await createRequestHeaders(options.headers);\n const context = runtime.thread.getModelContext();\n\n const response = await fetch(\n isResume ? options.resumeApi! : options.api,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n commands,\n state: agentStateRef.current,\n system: context.system,\n tools: context.tools\n ? toAISDKTools(getEnabledTools(context.tools))\n : undefined,\n ...context.callSettings,\n ...context.config,\n ...options.body,\n }),\n signal,\n },\n );\n\n options.onResponse?.(response);\n\n if (!response.ok) {\n throw new Error(`Status ${response.status}: ${await response.text()}`);\n }\n\n if (!response.body) {\n throw new Error(\"Response body is null\");\n }\n\n const stream = response.body\n .pipeThrough(new DataStreamDecoder())\n .pipeThrough(\n new AssistantMessageAccumulator({\n initialMessage: createInitialMessage({\n unstable_state:\n (agentStateRef.current as ReadonlyJSONValue) ?? null,\n }),\n }),\n );\n\n let markedDelivered = false;\n\n for await (const chunk of asAsyncIterableStream(stream)) {\n if (chunk.metadata.unstable_state === agentStateRef.current) continue;\n\n if (!markedDelivered) {\n commandQueue.markDelivered();\n markedDelivered = true;\n }\n\n agentStateRef.current = chunk.metadata.unstable_state as T;\n rerender((prev) => prev + 1);\n }\n },\n onFinish: options.onFinish,\n onError: (error) => {\n if (error instanceof Error && error.name === \"AbortError\") {\n const cmds = [\n ...commandQueue.state.inTransit,\n ...commandQueue.state.queued,\n ];\n options.onCancel?.({\n commands: cmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n\n commandQueue.reset();\n } else {\n const cmds = [...commandQueue.state.inTransit];\n options.onError?.(error as Error, {\n commands: cmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n commandQueue.markDelivered();\n }\n },\n });\n\n // Reactive conversion of agent state + connection metadata → UI state\n const pendingCommands = useMemo(\n () => [...commandQueue.state.inTransit, ...commandQueue.state.queued],\n [commandQueue.state],\n );\n const converted = useConvertedState(\n options.converter,\n agentStateRef.current,\n pendingCommands,\n runManager.isRunning,\n );\n\n // Create runtime\n const runtime = useExternalStoreRuntime({\n isRunning: converted.isRunning,\n messages: converted.messages,\n adapters: options.adapters,\n onNew: async (message: AppendMessage): Promise<void> => {\n // Convert AppendMessage to AddMessageCommand\n const parts: UserMessagePart[] = [];\n\n for (const content of message.content) {\n if (content.type === \"text\") {\n parts.push({ type: \"text\", text: content.text });\n } else if (content.type === \"image\") {\n parts.push({ type: \"image\", image: content.image });\n }\n }\n\n const command: AddMessageCommand = {\n type: \"add-message\",\n message: {\n role: \"user\",\n parts,\n },\n };\n\n commandQueue.enqueue(command);\n },\n onCancel: async () => {\n runManager.cancel();\n toolInvocations.abort();\n },\n onResume: async () => {\n if (!options.resumeApi)\n throw new Error(\"Must pass resumeApi to options to resume runs\");\n\n resumeFlagRef.current = true;\n runManager.schedule();\n },\n onAddToolResult: async (\n toolOptions: AddToolResultOptions,\n ): Promise<void> => {\n const command: AddToolResultCommand = {\n type: \"add-tool-result\",\n toolCallId: toolOptions.toolCallId,\n result: toolOptions.result as ReadonlyJSONObject,\n toolName: toolOptions.toolName,\n isError: toolOptions.isError,\n ...(toolOptions.artifact && { artifact: toolOptions.artifact }),\n };\n\n commandQueue.enqueue(command);\n },\n onLoadExternalState: async (state) => {\n agentStateRef.current = state as T;\n toolInvocations.reset();\n rerender((prev) => prev + 1);\n },\n });\n\n const toolInvocations = useToolInvocations({\n state: converted,\n getTools: () => runtime.thread.getModelContext().tools,\n onResult: commandQueue.enqueue,\n });\n\n return runtime;\n};\n\n/**\n * @alpha This is an experimental API that is subject to change.\n */\nexport const useAssistantTransportRuntime = <T,>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const runtime = useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useAssistantTransportThreadRuntime(options);\n },\n adapter: new InMemoryThreadListAdapter(),\n });\n return runtime;\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n asAsyncIterableStream,\n} from \"assistant-stream/utils\";\nimport { AppendMessage } from \"../../../types\";\nimport { useExternalStoreRuntime } from \"../external-store/useExternalStoreRuntime\";\nimport { AssistantRuntime } from \"../../runtime/AssistantRuntime\";\nimport { AddToolResultOptions } from \"../core\";\nimport { useState, useRef, useMemo } from \"react\";\nimport {\n AssistantMessageAccumulator,\n DataStreamDecoder,\n unstable_createInitialMessage as createInitialMessage,\n} from \"assistant-stream\";\nimport {\n AssistantTransportOptions,\n AddMessageCommand,\n AddToolResultCommand,\n UserMessagePart,\n QueuedCommand,\n} from \"./types\";\nimport { useCommandQueue } from \"./commandQueue\";\nimport { useRunManager } from \"./runManager\";\nimport { useConvertedState } from \"./useConvertedState\";\nimport { useToolInvocations } from \"./useToolInvocations\";\nimport { toAISDKTools, getEnabledTools, createRequestHeaders } from \"./utils\";\nimport { useRemoteThreadListRuntime } from \"../remote-thread-list/useRemoteThreadListRuntime\";\nimport { InMemoryThreadListAdapter } from \"../remote-thread-list/adapter/in-memory\";\n\nconst useAssistantTransportThreadRuntime = <T,>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const agentStateRef = useRef(options.initialState);\n const [, rerender] = useState(0);\n const resumeFlagRef = useRef(false);\n const commandQueue = useCommandQueue({\n onQueue: () => runManager.schedule(),\n });\n\n const runManager = useRunManager({\n onRun: async (signal: AbortSignal) => {\n const isResume = resumeFlagRef.current;\n resumeFlagRef.current = false;\n const commands: QueuedCommand[] = isResume ? [] : commandQueue.flush();\n if (commands.length === 0 && !isResume)\n throw new Error(\"No commands to send\");\n\n const headers = await createRequestHeaders(options.headers);\n const context = runtime.thread.getModelContext();\n\n const response = await fetch(\n isResume ? options.resumeApi! : options.api,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n commands,\n state: agentStateRef.current,\n system: context.system,\n tools: context.tools\n ? toAISDKTools(getEnabledTools(context.tools))\n : undefined,\n ...context.callSettings,\n ...context.config,\n ...options.body,\n }),\n signal,\n },\n );\n\n options.onResponse?.(response);\n\n if (!response.ok) {\n throw new Error(`Status ${response.status}: ${await response.text()}`);\n }\n\n if (!response.body) {\n throw new Error(\"Response body is null\");\n }\n\n const stream = response.body\n .pipeThrough(new DataStreamDecoder())\n .pipeThrough(\n new AssistantMessageAccumulator({\n initialMessage: createInitialMessage({\n unstable_state:\n (agentStateRef.current as ReadonlyJSONValue) ?? null,\n }),\n }),\n );\n\n let markedDelivered = false;\n\n for await (const chunk of asAsyncIterableStream(stream)) {\n if (chunk.metadata.unstable_state === agentStateRef.current) continue;\n\n if (!markedDelivered) {\n commandQueue.markDelivered();\n markedDelivered = true;\n }\n\n agentStateRef.current = chunk.metadata.unstable_state as T;\n rerender((prev) => prev + 1);\n }\n },\n onFinish: options.onFinish,\n onError: (error) => {\n if (error instanceof Error && error.name === \"AbortError\") {\n const cmds = [\n ...commandQueue.state.inTransit,\n ...commandQueue.state.queued,\n ];\n options.onCancel?.({\n commands: cmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n\n commandQueue.reset();\n } else {\n const cmds = [...commandQueue.state.inTransit];\n options.onError?.(error as Error, {\n commands: cmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n commandQueue.markDelivered();\n }\n },\n });\n\n // Reactive conversion of agent state + connection metadata → UI state\n const pendingCommands = useMemo(\n () => [...commandQueue.state.inTransit, ...commandQueue.state.queued],\n [commandQueue.state],\n );\n const converted = useConvertedState(\n options.converter,\n agentStateRef.current,\n pendingCommands,\n runManager.isRunning,\n );\n\n // Create runtime\n const runtime = useExternalStoreRuntime({\n isRunning: converted.isRunning,\n messages: converted.messages,\n adapters: options.adapters,\n onNew: async (message: AppendMessage): Promise<void> => {\n if (message.role !== \"user\")\n throw new Error(\"Only user messages are supported\");\n\n // Convert AppendMessage to AddMessageCommand\n const parts: UserMessagePart[] = [];\n\n const content = [\n ...message.content,\n ...(message.attachments?.flatMap((a) => a.content) ?? []),\n ];\n for (const contentPart of content) {\n if (contentPart.type === \"text\") {\n parts.push({ type: \"text\", text: contentPart.text });\n } else if (contentPart.type === \"image\") {\n parts.push({ type: \"image\", image: contentPart.image });\n }\n }\n\n const command: AddMessageCommand = {\n type: \"add-message\",\n message: {\n role: \"user\",\n parts,\n },\n };\n\n commandQueue.enqueue(command);\n },\n onCancel: async () => {\n runManager.cancel();\n toolInvocations.abort();\n },\n onResume: async () => {\n if (!options.resumeApi)\n throw new Error(\"Must pass resumeApi to options to resume runs\");\n\n resumeFlagRef.current = true;\n runManager.schedule();\n },\n onAddToolResult: async (\n toolOptions: AddToolResultOptions,\n ): Promise<void> => {\n const command: AddToolResultCommand = {\n type: \"add-tool-result\",\n toolCallId: toolOptions.toolCallId,\n result: toolOptions.result as ReadonlyJSONObject,\n toolName: toolOptions.toolName,\n isError: toolOptions.isError,\n ...(toolOptions.artifact && { artifact: toolOptions.artifact }),\n };\n\n commandQueue.enqueue(command);\n },\n onLoadExternalState: async (state) => {\n agentStateRef.current = state as T;\n toolInvocations.reset();\n rerender((prev) => prev + 1);\n },\n });\n\n const toolInvocations = useToolInvocations({\n state: converted,\n getTools: () => runtime.thread.getModelContext().tools,\n onResult: commandQueue.enqueue,\n });\n\n return runtime;\n};\n\n/**\n * @alpha This is an experimental API that is subject to change.\n */\nexport const useAssistantTransportRuntime = <T,>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const runtime = useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useAssistantTransportThreadRuntime(options);\n },\n adapter: new InMemoryThreadListAdapter(),\n });\n return runtime;\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "conversational-ui",
29
29
  "conversational-ai"
30
30
  ],
31
- "version": "0.11.7",
31
+ "version": "0.11.9",
32
32
  "license": "MIT",
33
33
  "type": "module",
34
34
  "exports": {
@@ -59,7 +59,7 @@
59
59
  "@radix-ui/react-use-callback-ref": "^1.1.1",
60
60
  "@radix-ui/react-use-escape-keydown": "^1.1.1",
61
61
  "@standard-schema/spec": "^1.0.0",
62
- "assistant-stream": "^0.2.23",
62
+ "assistant-stream": "^0.2.26",
63
63
  "json-schema": "^0.4.0",
64
64
  "nanoid": "5.1.5",
65
65
  "react-textarea-autosize": "^8.5.9",
@@ -288,10 +288,10 @@ export const AssistantProvider: FC<
288
288
  const extendedApi = useMemo(() => extendApi(api, api2), [api, api2]);
289
289
 
290
290
  return (
291
- <AssistantApiContext value={extendedApi}>
291
+ <AssistantApiContext.Provider value={extendedApi}>
292
292
  {/* TODO temporarily allow accessing viewport state from outside the viewport */}
293
293
  {/* TODO figure out if this behavior should be deprecated, since it is quite hacky */}
294
294
  <ThreadViewportProvider>{children}</ThreadViewportProvider>
295
- </AssistantApiContext>
295
+ </AssistantApiContext.Provider>
296
296
  );
297
297
  };
@@ -154,14 +154,21 @@ const useAssistantTransportThreadRuntime = <T,>(
154
154
  messages: converted.messages,
155
155
  adapters: options.adapters,
156
156
  onNew: async (message: AppendMessage): Promise<void> => {
157
+ if (message.role !== "user")
158
+ throw new Error("Only user messages are supported");
159
+
157
160
  // Convert AppendMessage to AddMessageCommand
158
161
  const parts: UserMessagePart[] = [];
159
162
 
160
- for (const content of message.content) {
161
- if (content.type === "text") {
162
- parts.push({ type: "text", text: content.text });
163
- } else if (content.type === "image") {
164
- parts.push({ type: "image", image: content.image });
163
+ const content = [
164
+ ...message.content,
165
+ ...(message.attachments?.flatMap((a) => a.content) ?? []),
166
+ ];
167
+ for (const contentPart of content) {
168
+ if (contentPart.type === "text") {
169
+ parts.push({ type: "text", text: contentPart.text });
170
+ } else if (contentPart.type === "image") {
171
+ parts.push({ type: "image", image: contentPart.image });
165
172
  }
166
173
  }
167
174