@assistant-ui/react 0.5.93 → 0.5.94

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.
@@ -1 +1 @@
1
- {"version":3,"file":"MessageRuntime.d.ts","sourceRoot":"","sources":["../../src/api/MessageRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MessageRuntime.d.ts","sourceRoot":"","sources":["../../src/api/MessageRuntime.ts"],"names":[],"mappings":"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"}
@@ -35,18 +35,16 @@ const COMPLETE_STATUS = {
35
35
  };
36
36
  const toContentPartStatus = (message, partIndex, part) => {
37
37
  if (message.role !== "assistant") return COMPLETE_STATUS;
38
- const isLastPart = partIndex === Math.max(0, message.content.length - 1);
39
- if (part.type !== "tool-call") {
40
- if ("reason" in message.status && message.status.reason === "tool-calls" && isLastPart)
41
- throw new Error(
42
- "Encountered unexpected requires-action status. This is likely an internal bug in assistant-ui."
43
- );
44
- return isLastPart ? message.status : COMPLETE_STATUS;
45
- }
46
- if (!!part.result) {
47
- return COMPLETE_STATUS;
38
+ if (part.type === "tool-call") {
39
+ if (!part.result) {
40
+ return message.status;
41
+ } else {
42
+ return COMPLETE_STATUS;
43
+ }
48
44
  }
49
- return message.status;
45
+ const isLastPart = partIndex === Math.max(0, message.content.length - 1);
46
+ if (message.status.type === "requires-action") return COMPLETE_STATUS;
47
+ return isLastPart ? message.status : COMPLETE_STATUS;
50
48
  };
51
49
  const EMPTY_CONTENT = Object.freeze({ type: "text", text: "" });
52
50
  const getContentPartState = (message, partIndex) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api/MessageRuntime.ts"],"sourcesContent":["import {\n SpeechState,\n SubmittedFeedback,\n} from \"../runtimes/core/ThreadRuntimeCore\";\nimport {\n ThreadMessage,\n ThreadAssistantContentPart,\n ThreadUserContentPart,\n Unsubscribe,\n} from \"../types\";\nimport {\n ContentPartStatus,\n ToolCallContentPartStatus,\n} from \"../types/AssistantTypes\";\nimport { getThreadMessageText } from \"../utils/getThreadMessageText\";\nimport {\n AttachmentRuntime,\n AttachmentState,\n MessageAttachmentRuntimeImpl,\n} from \"./AttachmentRuntime\";\nimport {\n EditComposerRuntime,\n EditComposerRuntimeImpl,\n} from \"./ComposerRuntime\";\nimport {\n ContentPartRuntime,\n ContentPartRuntimeImpl,\n ContentPartState,\n} from \"./ContentPartRuntime\";\nimport { MessageRuntimePath } from \"./RuntimePathTypes\";\nimport { ThreadRuntimeCoreBinding } from \"./ThreadRuntime\";\nimport { NestedSubscriptionSubject } from \"./subscribable/NestedSubscriptionSubject\";\nimport { SKIP_UPDATE } from \"./subscribable/SKIP_UPDATE\";\nimport { ShallowMemoizeSubject } from \"./subscribable/ShallowMemoizeSubject\";\nimport { SubscribableWithState } from \"./subscribable/Subscribable\";\n\nconst COMPLETE_STATUS: ContentPartStatus = {\n type: \"complete\",\n};\n\nexport const toContentPartStatus = (\n message: ThreadMessage,\n partIndex: number,\n part: ThreadUserContentPart | ThreadAssistantContentPart,\n): ToolCallContentPartStatus => {\n if (message.role !== \"assistant\") return COMPLETE_STATUS;\n\n const isLastPart = partIndex === Math.max(0, message.content.length - 1);\n if (part.type !== \"tool-call\") {\n if (\n \"reason\" in message.status &&\n message.status.reason === \"tool-calls\" &&\n isLastPart\n )\n throw new Error(\n \"Encountered unexpected requires-action status. This is likely an internal bug in assistant-ui.\",\n );\n\n return isLastPart ? (message.status as ContentPartStatus) : COMPLETE_STATUS;\n }\n\n if (!!part.result) {\n return COMPLETE_STATUS;\n }\n\n return message.status as ToolCallContentPartStatus;\n};\n\nexport const EMPTY_CONTENT = Object.freeze({ type: \"text\", text: \"\" });\n\nconst getContentPartState = (\n message: MessageState,\n partIndex: number,\n): ContentPartState | SKIP_UPDATE => {\n let part = message.content[partIndex];\n if (!part) {\n // for empty messages, show an empty text content part\n if (message.content.length === 0 && partIndex === 0) {\n part = EMPTY_CONTENT;\n } else {\n return SKIP_UPDATE;\n }\n } else if (\n message.content.length === 1 &&\n part.type === \"text\" &&\n part.text.length === 0\n ) {\n // ensure reference equality for equivalent empty text parts\n part = EMPTY_CONTENT;\n }\n\n // if the content part is the same, don't update\n const status = toContentPartStatus(message, partIndex, part);\n return Object.freeze({ ...part, part, status });\n};\n\nexport type MessageState = ThreadMessage & {\n /**\n * @deprecated You can directly access message fields in the state. Replace `.message.content` with `.content` etc. This will be removed in 0.6.0.\n */\n message: ThreadMessage;\n parentId: string | null;\n isLast: boolean;\n /**\n * @deprecated Use `branchNumber` and `branchCount` instead. This will be removed in 0.6.0.\n */\n branches: readonly string[];\n\n branchNumber: number;\n branchCount: number;\n\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speech: SpeechState | undefined;\n submittedFeedback: SubmittedFeedback | undefined;\n};\n\nexport type MessageStateBinding = SubscribableWithState<\n MessageState,\n MessageRuntimePath\n>;\n\nexport type MessageRuntime = {\n readonly path: MessageRuntimePath;\n\n readonly composer: EditComposerRuntime;\n\n getState(): MessageState;\n reload(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speak(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n stopSpeaking(): void;\n submitFeedback({ type }: { type: \"positive\" | \"negative\" }): void;\n switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }): void;\n unstable_getCopyText(): string;\n\n subscribe(callback: () => void): Unsubscribe;\n\n getContentPartByIndex(idx: number): ContentPartRuntime;\n getContentPartByToolCallId(toolCallId: string): ContentPartRuntime;\n\n getAttachmentByIndex(idx: number): AttachmentRuntime & { source: \"message\" };\n};\n\nexport class MessageRuntimeImpl implements MessageRuntime {\n public get path() {\n return this._core.path;\n }\n\n constructor(\n private _core: MessageStateBinding,\n private _threadBinding: ThreadRuntimeCoreBinding,\n ) {\n this.composer = new EditComposerRuntimeImpl(\n new NestedSubscriptionSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.composer`,\n composerSource: \"edit\",\n },\n getState: () =>\n this._threadBinding\n .getState()\n .getEditComposer(this._core.getState().id),\n subscribe: (callback) => this._threadBinding.subscribe(callback),\n }),\n () => this._threadBinding.getState().beginEdit(this._core.getState().id),\n );\n }\n\n public composer;\n\n public getState() {\n return this._core.getState();\n }\n\n public reload() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n if (state.role !== \"assistant\")\n throw new Error(\"Can only reload assistant messages\");\n\n this._threadBinding.getState().startRun(state.parentId);\n }\n\n public speak() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n return this._threadBinding.getState().speak(state.id);\n }\n\n public stopSpeaking() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n const thread = this._threadBinding.getState();\n if (thread.speech?.messageId === state.id) {\n this._threadBinding.getState().stopSpeaking();\n } else {\n throw new Error(\"Message is not being spoken\");\n }\n }\n\n public submitFeedback({ type }: { type: \"positive\" | \"negative\" }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n this._threadBinding.getState().submitFeedback({\n messageId: state.id,\n type,\n });\n }\n\n public switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n if (branchId && position) {\n throw new Error(\"May not specify both branchId and position\");\n } else if (!branchId && !position) {\n throw new Error(\"Must specify either branchId or position\");\n }\n\n const thread = this._threadBinding.getState();\n const branches = thread.getBranches(state.id);\n let targetBranch = branchId;\n if (position === \"previous\") {\n targetBranch = branches[state.branchNumber - 2];\n } else if (position === \"next\") {\n targetBranch = branches[state.branchNumber];\n }\n if (!targetBranch) throw new Error(\"Branch not found\");\n\n this._threadBinding.getState().switchToBranch(targetBranch);\n }\n\n public unstable_getCopyText() {\n return getThreadMessageText(this.getState());\n }\n\n public subscribe(callback: () => void) {\n return this._core.subscribe(callback);\n }\n\n public getContentPartByIndex(idx: number) {\n if (idx < 0) throw new Error(\"Content part index must be >= 0\");\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.content[${idx}]`,\n contentPartSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n return getContentPartState(this.getState(), idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getContentPartByToolCallId(toolCallId: string) {\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref:\n this.path.ref +\n `${this.path.ref}.content[toolCallId=${JSON.stringify(toolCallId)}]`,\n contentPartSelector: { type: \"toolCallId\", toolCallId },\n },\n getState: () => {\n const state = this._core.getState();\n const idx = state.content.findIndex(\n (part) =>\n part.type === \"tool-call\" && part.toolCallId === toolCallId,\n );\n if (idx === -1) return SKIP_UPDATE;\n return getContentPartState(state, idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getAttachmentByIndex(idx: number) {\n return new MessageAttachmentRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`,\n attachmentSource: \"message\",\n attachmentSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n const attachments = this.getState().attachments;\n const attachment = attachments?.[idx];\n if (!attachment) return SKIP_UPDATE;\n\n return {\n ...attachment,\n attachment: attachment,\n source: \"message\",\n } satisfies AttachmentState & { source: \"message\" };\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/api/MessageRuntime.ts"],"sourcesContent":["import {\n SpeechState,\n SubmittedFeedback,\n} from \"../runtimes/core/ThreadRuntimeCore\";\nimport {\n ThreadMessage,\n ThreadAssistantContentPart,\n ThreadUserContentPart,\n Unsubscribe,\n} from \"../types\";\nimport {\n ContentPartStatus,\n ToolCallContentPartStatus,\n} from \"../types/AssistantTypes\";\nimport { getThreadMessageText } from \"../utils/getThreadMessageText\";\nimport {\n AttachmentRuntime,\n AttachmentState,\n MessageAttachmentRuntimeImpl,\n} from \"./AttachmentRuntime\";\nimport {\n EditComposerRuntime,\n EditComposerRuntimeImpl,\n} from \"./ComposerRuntime\";\nimport {\n ContentPartRuntime,\n ContentPartRuntimeImpl,\n ContentPartState,\n} from \"./ContentPartRuntime\";\nimport { MessageRuntimePath } from \"./RuntimePathTypes\";\nimport { ThreadRuntimeCoreBinding } from \"./ThreadRuntime\";\nimport { NestedSubscriptionSubject } from \"./subscribable/NestedSubscriptionSubject\";\nimport { SKIP_UPDATE } from \"./subscribable/SKIP_UPDATE\";\nimport { ShallowMemoizeSubject } from \"./subscribable/ShallowMemoizeSubject\";\nimport { SubscribableWithState } from \"./subscribable/Subscribable\";\n\nconst COMPLETE_STATUS: ContentPartStatus = {\n type: \"complete\",\n};\n\nexport const toContentPartStatus = (\n message: ThreadMessage,\n partIndex: number,\n part: ThreadUserContentPart | ThreadAssistantContentPart,\n): ToolCallContentPartStatus => {\n if (message.role !== \"assistant\") return COMPLETE_STATUS;\n\n if (part.type === \"tool-call\") {\n if (!part.result) {\n return message.status as ToolCallContentPartStatus;\n } else {\n return COMPLETE_STATUS;\n }\n }\n\n const isLastPart = partIndex === Math.max(0, message.content.length - 1);\n if (message.status.type === \"requires-action\") return COMPLETE_STATUS;\n return isLastPart ? (message.status as ContentPartStatus) : COMPLETE_STATUS;\n};\n\nexport const EMPTY_CONTENT = Object.freeze({ type: \"text\", text: \"\" });\n\nconst getContentPartState = (\n message: MessageState,\n partIndex: number,\n): ContentPartState | SKIP_UPDATE => {\n let part = message.content[partIndex];\n if (!part) {\n // for empty messages, show an empty text content part\n if (message.content.length === 0 && partIndex === 0) {\n part = EMPTY_CONTENT;\n } else {\n return SKIP_UPDATE;\n }\n } else if (\n message.content.length === 1 &&\n part.type === \"text\" &&\n part.text.length === 0\n ) {\n // ensure reference equality for equivalent empty text parts\n part = EMPTY_CONTENT;\n }\n\n // if the content part is the same, don't update\n const status = toContentPartStatus(message, partIndex, part);\n return Object.freeze({ ...part, part, status });\n};\n\nexport type MessageState = ThreadMessage & {\n /**\n * @deprecated You can directly access message fields in the state. Replace `.message.content` with `.content` etc. This will be removed in 0.6.0.\n */\n message: ThreadMessage;\n parentId: string | null;\n isLast: boolean;\n /**\n * @deprecated Use `branchNumber` and `branchCount` instead. This will be removed in 0.6.0.\n */\n branches: readonly string[];\n\n branchNumber: number;\n branchCount: number;\n\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speech: SpeechState | undefined;\n submittedFeedback: SubmittedFeedback | undefined;\n};\n\nexport type MessageStateBinding = SubscribableWithState<\n MessageState,\n MessageRuntimePath\n>;\n\nexport type MessageRuntime = {\n readonly path: MessageRuntimePath;\n\n readonly composer: EditComposerRuntime;\n\n getState(): MessageState;\n reload(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speak(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n stopSpeaking(): void;\n submitFeedback({ type }: { type: \"positive\" | \"negative\" }): void;\n switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }): void;\n unstable_getCopyText(): string;\n\n subscribe(callback: () => void): Unsubscribe;\n\n getContentPartByIndex(idx: number): ContentPartRuntime;\n getContentPartByToolCallId(toolCallId: string): ContentPartRuntime;\n\n getAttachmentByIndex(idx: number): AttachmentRuntime & { source: \"message\" };\n};\n\nexport class MessageRuntimeImpl implements MessageRuntime {\n public get path() {\n return this._core.path;\n }\n\n constructor(\n private _core: MessageStateBinding,\n private _threadBinding: ThreadRuntimeCoreBinding,\n ) {\n this.composer = new EditComposerRuntimeImpl(\n new NestedSubscriptionSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.composer`,\n composerSource: \"edit\",\n },\n getState: () =>\n this._threadBinding\n .getState()\n .getEditComposer(this._core.getState().id),\n subscribe: (callback) => this._threadBinding.subscribe(callback),\n }),\n () => this._threadBinding.getState().beginEdit(this._core.getState().id),\n );\n }\n\n public composer;\n\n public getState() {\n return this._core.getState();\n }\n\n public reload() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n if (state.role !== \"assistant\")\n throw new Error(\"Can only reload assistant messages\");\n\n this._threadBinding.getState().startRun(state.parentId);\n }\n\n public speak() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n return this._threadBinding.getState().speak(state.id);\n }\n\n public stopSpeaking() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n const thread = this._threadBinding.getState();\n if (thread.speech?.messageId === state.id) {\n this._threadBinding.getState().stopSpeaking();\n } else {\n throw new Error(\"Message is not being spoken\");\n }\n }\n\n public submitFeedback({ type }: { type: \"positive\" | \"negative\" }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n this._threadBinding.getState().submitFeedback({\n messageId: state.id,\n type,\n });\n }\n\n public switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n if (branchId && position) {\n throw new Error(\"May not specify both branchId and position\");\n } else if (!branchId && !position) {\n throw new Error(\"Must specify either branchId or position\");\n }\n\n const thread = this._threadBinding.getState();\n const branches = thread.getBranches(state.id);\n let targetBranch = branchId;\n if (position === \"previous\") {\n targetBranch = branches[state.branchNumber - 2];\n } else if (position === \"next\") {\n targetBranch = branches[state.branchNumber];\n }\n if (!targetBranch) throw new Error(\"Branch not found\");\n\n this._threadBinding.getState().switchToBranch(targetBranch);\n }\n\n public unstable_getCopyText() {\n return getThreadMessageText(this.getState());\n }\n\n public subscribe(callback: () => void) {\n return this._core.subscribe(callback);\n }\n\n public getContentPartByIndex(idx: number) {\n if (idx < 0) throw new Error(\"Content part index must be >= 0\");\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.content[${idx}]`,\n contentPartSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n return getContentPartState(this.getState(), idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getContentPartByToolCallId(toolCallId: string) {\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref:\n this.path.ref +\n `${this.path.ref}.content[toolCallId=${JSON.stringify(toolCallId)}]`,\n contentPartSelector: { type: \"toolCallId\", toolCallId },\n },\n getState: () => {\n const state = this._core.getState();\n const idx = state.content.findIndex(\n (part) =>\n part.type === \"tool-call\" && part.toolCallId === toolCallId,\n );\n if (idx === -1) return SKIP_UPDATE;\n return getContentPartState(state, idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getAttachmentByIndex(idx: number) {\n return new MessageAttachmentRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`,\n attachmentSource: \"message\",\n attachmentSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n const attachments = this.getState().attachments;\n const attachment = attachments?.[idx];\n if (!attachment) return SKIP_UPDATE;\n\n return {\n ...attachment,\n attachment: attachment,\n source: \"message\",\n } satisfies AttachmentState & { source: \"message\" };\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -16,18 +16,16 @@ const COMPLETE_STATUS = {
16
16
  };
17
17
  const toContentPartStatus = (message, partIndex, part) => {
18
18
  if (message.role !== "assistant") return COMPLETE_STATUS;
19
- const isLastPart = partIndex === Math.max(0, message.content.length - 1);
20
- if (part.type !== "tool-call") {
21
- if ("reason" in message.status && message.status.reason === "tool-calls" && isLastPart)
22
- throw new Error(
23
- "Encountered unexpected requires-action status. This is likely an internal bug in assistant-ui."
24
- );
25
- return isLastPart ? message.status : COMPLETE_STATUS;
26
- }
27
- if (!!part.result) {
28
- return COMPLETE_STATUS;
19
+ if (part.type === "tool-call") {
20
+ if (!part.result) {
21
+ return message.status;
22
+ } else {
23
+ return COMPLETE_STATUS;
24
+ }
29
25
  }
30
- return message.status;
26
+ const isLastPart = partIndex === Math.max(0, message.content.length - 1);
27
+ if (message.status.type === "requires-action") return COMPLETE_STATUS;
28
+ return isLastPart ? message.status : COMPLETE_STATUS;
31
29
  };
32
30
  const EMPTY_CONTENT = Object.freeze({ type: "text", text: "" });
33
31
  const getContentPartState = (message, partIndex) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api/MessageRuntime.ts"],"sourcesContent":["import {\n SpeechState,\n SubmittedFeedback,\n} from \"../runtimes/core/ThreadRuntimeCore\";\nimport {\n ThreadMessage,\n ThreadAssistantContentPart,\n ThreadUserContentPart,\n Unsubscribe,\n} from \"../types\";\nimport {\n ContentPartStatus,\n ToolCallContentPartStatus,\n} from \"../types/AssistantTypes\";\nimport { getThreadMessageText } from \"../utils/getThreadMessageText\";\nimport {\n AttachmentRuntime,\n AttachmentState,\n MessageAttachmentRuntimeImpl,\n} from \"./AttachmentRuntime\";\nimport {\n EditComposerRuntime,\n EditComposerRuntimeImpl,\n} from \"./ComposerRuntime\";\nimport {\n ContentPartRuntime,\n ContentPartRuntimeImpl,\n ContentPartState,\n} from \"./ContentPartRuntime\";\nimport { MessageRuntimePath } from \"./RuntimePathTypes\";\nimport { ThreadRuntimeCoreBinding } from \"./ThreadRuntime\";\nimport { NestedSubscriptionSubject } from \"./subscribable/NestedSubscriptionSubject\";\nimport { SKIP_UPDATE } from \"./subscribable/SKIP_UPDATE\";\nimport { ShallowMemoizeSubject } from \"./subscribable/ShallowMemoizeSubject\";\nimport { SubscribableWithState } from \"./subscribable/Subscribable\";\n\nconst COMPLETE_STATUS: ContentPartStatus = {\n type: \"complete\",\n};\n\nexport const toContentPartStatus = (\n message: ThreadMessage,\n partIndex: number,\n part: ThreadUserContentPart | ThreadAssistantContentPart,\n): ToolCallContentPartStatus => {\n if (message.role !== \"assistant\") return COMPLETE_STATUS;\n\n const isLastPart = partIndex === Math.max(0, message.content.length - 1);\n if (part.type !== \"tool-call\") {\n if (\n \"reason\" in message.status &&\n message.status.reason === \"tool-calls\" &&\n isLastPart\n )\n throw new Error(\n \"Encountered unexpected requires-action status. This is likely an internal bug in assistant-ui.\",\n );\n\n return isLastPart ? (message.status as ContentPartStatus) : COMPLETE_STATUS;\n }\n\n if (!!part.result) {\n return COMPLETE_STATUS;\n }\n\n return message.status as ToolCallContentPartStatus;\n};\n\nexport const EMPTY_CONTENT = Object.freeze({ type: \"text\", text: \"\" });\n\nconst getContentPartState = (\n message: MessageState,\n partIndex: number,\n): ContentPartState | SKIP_UPDATE => {\n let part = message.content[partIndex];\n if (!part) {\n // for empty messages, show an empty text content part\n if (message.content.length === 0 && partIndex === 0) {\n part = EMPTY_CONTENT;\n } else {\n return SKIP_UPDATE;\n }\n } else if (\n message.content.length === 1 &&\n part.type === \"text\" &&\n part.text.length === 0\n ) {\n // ensure reference equality for equivalent empty text parts\n part = EMPTY_CONTENT;\n }\n\n // if the content part is the same, don't update\n const status = toContentPartStatus(message, partIndex, part);\n return Object.freeze({ ...part, part, status });\n};\n\nexport type MessageState = ThreadMessage & {\n /**\n * @deprecated You can directly access message fields in the state. Replace `.message.content` with `.content` etc. This will be removed in 0.6.0.\n */\n message: ThreadMessage;\n parentId: string | null;\n isLast: boolean;\n /**\n * @deprecated Use `branchNumber` and `branchCount` instead. This will be removed in 0.6.0.\n */\n branches: readonly string[];\n\n branchNumber: number;\n branchCount: number;\n\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speech: SpeechState | undefined;\n submittedFeedback: SubmittedFeedback | undefined;\n};\n\nexport type MessageStateBinding = SubscribableWithState<\n MessageState,\n MessageRuntimePath\n>;\n\nexport type MessageRuntime = {\n readonly path: MessageRuntimePath;\n\n readonly composer: EditComposerRuntime;\n\n getState(): MessageState;\n reload(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speak(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n stopSpeaking(): void;\n submitFeedback({ type }: { type: \"positive\" | \"negative\" }): void;\n switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }): void;\n unstable_getCopyText(): string;\n\n subscribe(callback: () => void): Unsubscribe;\n\n getContentPartByIndex(idx: number): ContentPartRuntime;\n getContentPartByToolCallId(toolCallId: string): ContentPartRuntime;\n\n getAttachmentByIndex(idx: number): AttachmentRuntime & { source: \"message\" };\n};\n\nexport class MessageRuntimeImpl implements MessageRuntime {\n public get path() {\n return this._core.path;\n }\n\n constructor(\n private _core: MessageStateBinding,\n private _threadBinding: ThreadRuntimeCoreBinding,\n ) {\n this.composer = new EditComposerRuntimeImpl(\n new NestedSubscriptionSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.composer`,\n composerSource: \"edit\",\n },\n getState: () =>\n this._threadBinding\n .getState()\n .getEditComposer(this._core.getState().id),\n subscribe: (callback) => this._threadBinding.subscribe(callback),\n }),\n () => this._threadBinding.getState().beginEdit(this._core.getState().id),\n );\n }\n\n public composer;\n\n public getState() {\n return this._core.getState();\n }\n\n public reload() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n if (state.role !== \"assistant\")\n throw new Error(\"Can only reload assistant messages\");\n\n this._threadBinding.getState().startRun(state.parentId);\n }\n\n public speak() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n return this._threadBinding.getState().speak(state.id);\n }\n\n public stopSpeaking() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n const thread = this._threadBinding.getState();\n if (thread.speech?.messageId === state.id) {\n this._threadBinding.getState().stopSpeaking();\n } else {\n throw new Error(\"Message is not being spoken\");\n }\n }\n\n public submitFeedback({ type }: { type: \"positive\" | \"negative\" }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n this._threadBinding.getState().submitFeedback({\n messageId: state.id,\n type,\n });\n }\n\n public switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n if (branchId && position) {\n throw new Error(\"May not specify both branchId and position\");\n } else if (!branchId && !position) {\n throw new Error(\"Must specify either branchId or position\");\n }\n\n const thread = this._threadBinding.getState();\n const branches = thread.getBranches(state.id);\n let targetBranch = branchId;\n if (position === \"previous\") {\n targetBranch = branches[state.branchNumber - 2];\n } else if (position === \"next\") {\n targetBranch = branches[state.branchNumber];\n }\n if (!targetBranch) throw new Error(\"Branch not found\");\n\n this._threadBinding.getState().switchToBranch(targetBranch);\n }\n\n public unstable_getCopyText() {\n return getThreadMessageText(this.getState());\n }\n\n public subscribe(callback: () => void) {\n return this._core.subscribe(callback);\n }\n\n public getContentPartByIndex(idx: number) {\n if (idx < 0) throw new Error(\"Content part index must be >= 0\");\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.content[${idx}]`,\n contentPartSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n return getContentPartState(this.getState(), idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getContentPartByToolCallId(toolCallId: string) {\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref:\n this.path.ref +\n `${this.path.ref}.content[toolCallId=${JSON.stringify(toolCallId)}]`,\n contentPartSelector: { type: \"toolCallId\", toolCallId },\n },\n getState: () => {\n const state = this._core.getState();\n const idx = state.content.findIndex(\n (part) =>\n part.type === \"tool-call\" && part.toolCallId === toolCallId,\n );\n if (idx === -1) return SKIP_UPDATE;\n return getContentPartState(state, idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getAttachmentByIndex(idx: number) {\n return new MessageAttachmentRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`,\n attachmentSource: \"message\",\n attachmentSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n const attachments = this.getState().attachments;\n const attachment = attachments?.[idx];\n if (!attachment) return SKIP_UPDATE;\n\n return {\n ...attachment,\n attachment: attachment,\n source: \"message\",\n } satisfies AttachmentState & { source: \"message\" };\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/api/MessageRuntime.ts"],"sourcesContent":["import {\n SpeechState,\n SubmittedFeedback,\n} from \"../runtimes/core/ThreadRuntimeCore\";\nimport {\n ThreadMessage,\n ThreadAssistantContentPart,\n ThreadUserContentPart,\n Unsubscribe,\n} from \"../types\";\nimport {\n ContentPartStatus,\n ToolCallContentPartStatus,\n} from \"../types/AssistantTypes\";\nimport { getThreadMessageText } from \"../utils/getThreadMessageText\";\nimport {\n AttachmentRuntime,\n AttachmentState,\n MessageAttachmentRuntimeImpl,\n} from \"./AttachmentRuntime\";\nimport {\n EditComposerRuntime,\n EditComposerRuntimeImpl,\n} from \"./ComposerRuntime\";\nimport {\n ContentPartRuntime,\n ContentPartRuntimeImpl,\n ContentPartState,\n} from \"./ContentPartRuntime\";\nimport { MessageRuntimePath } from \"./RuntimePathTypes\";\nimport { ThreadRuntimeCoreBinding } from \"./ThreadRuntime\";\nimport { NestedSubscriptionSubject } from \"./subscribable/NestedSubscriptionSubject\";\nimport { SKIP_UPDATE } from \"./subscribable/SKIP_UPDATE\";\nimport { ShallowMemoizeSubject } from \"./subscribable/ShallowMemoizeSubject\";\nimport { SubscribableWithState } from \"./subscribable/Subscribable\";\n\nconst COMPLETE_STATUS: ContentPartStatus = {\n type: \"complete\",\n};\n\nexport const toContentPartStatus = (\n message: ThreadMessage,\n partIndex: number,\n part: ThreadUserContentPart | ThreadAssistantContentPart,\n): ToolCallContentPartStatus => {\n if (message.role !== \"assistant\") return COMPLETE_STATUS;\n\n if (part.type === \"tool-call\") {\n if (!part.result) {\n return message.status as ToolCallContentPartStatus;\n } else {\n return COMPLETE_STATUS;\n }\n }\n\n const isLastPart = partIndex === Math.max(0, message.content.length - 1);\n if (message.status.type === \"requires-action\") return COMPLETE_STATUS;\n return isLastPart ? (message.status as ContentPartStatus) : COMPLETE_STATUS;\n};\n\nexport const EMPTY_CONTENT = Object.freeze({ type: \"text\", text: \"\" });\n\nconst getContentPartState = (\n message: MessageState,\n partIndex: number,\n): ContentPartState | SKIP_UPDATE => {\n let part = message.content[partIndex];\n if (!part) {\n // for empty messages, show an empty text content part\n if (message.content.length === 0 && partIndex === 0) {\n part = EMPTY_CONTENT;\n } else {\n return SKIP_UPDATE;\n }\n } else if (\n message.content.length === 1 &&\n part.type === \"text\" &&\n part.text.length === 0\n ) {\n // ensure reference equality for equivalent empty text parts\n part = EMPTY_CONTENT;\n }\n\n // if the content part is the same, don't update\n const status = toContentPartStatus(message, partIndex, part);\n return Object.freeze({ ...part, part, status });\n};\n\nexport type MessageState = ThreadMessage & {\n /**\n * @deprecated You can directly access message fields in the state. Replace `.message.content` with `.content` etc. This will be removed in 0.6.0.\n */\n message: ThreadMessage;\n parentId: string | null;\n isLast: boolean;\n /**\n * @deprecated Use `branchNumber` and `branchCount` instead. This will be removed in 0.6.0.\n */\n branches: readonly string[];\n\n branchNumber: number;\n branchCount: number;\n\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speech: SpeechState | undefined;\n submittedFeedback: SubmittedFeedback | undefined;\n};\n\nexport type MessageStateBinding = SubscribableWithState<\n MessageState,\n MessageRuntimePath\n>;\n\nexport type MessageRuntime = {\n readonly path: MessageRuntimePath;\n\n readonly composer: EditComposerRuntime;\n\n getState(): MessageState;\n reload(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n speak(): void;\n /**\n * @deprecated This API is still under active development and might change without notice.\n */\n stopSpeaking(): void;\n submitFeedback({ type }: { type: \"positive\" | \"negative\" }): void;\n switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }): void;\n unstable_getCopyText(): string;\n\n subscribe(callback: () => void): Unsubscribe;\n\n getContentPartByIndex(idx: number): ContentPartRuntime;\n getContentPartByToolCallId(toolCallId: string): ContentPartRuntime;\n\n getAttachmentByIndex(idx: number): AttachmentRuntime & { source: \"message\" };\n};\n\nexport class MessageRuntimeImpl implements MessageRuntime {\n public get path() {\n return this._core.path;\n }\n\n constructor(\n private _core: MessageStateBinding,\n private _threadBinding: ThreadRuntimeCoreBinding,\n ) {\n this.composer = new EditComposerRuntimeImpl(\n new NestedSubscriptionSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.composer`,\n composerSource: \"edit\",\n },\n getState: () =>\n this._threadBinding\n .getState()\n .getEditComposer(this._core.getState().id),\n subscribe: (callback) => this._threadBinding.subscribe(callback),\n }),\n () => this._threadBinding.getState().beginEdit(this._core.getState().id),\n );\n }\n\n public composer;\n\n public getState() {\n return this._core.getState();\n }\n\n public reload() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n if (state.role !== \"assistant\")\n throw new Error(\"Can only reload assistant messages\");\n\n this._threadBinding.getState().startRun(state.parentId);\n }\n\n public speak() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n return this._threadBinding.getState().speak(state.id);\n }\n\n public stopSpeaking() {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n const thread = this._threadBinding.getState();\n if (thread.speech?.messageId === state.id) {\n this._threadBinding.getState().stopSpeaking();\n } else {\n throw new Error(\"Message is not being spoken\");\n }\n }\n\n public submitFeedback({ type }: { type: \"positive\" | \"negative\" }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n this._threadBinding.getState().submitFeedback({\n messageId: state.id,\n type,\n });\n }\n\n public switchToBranch({\n position,\n branchId,\n }: {\n position?: \"previous\" | \"next\" | undefined;\n branchId?: string | undefined;\n }) {\n const state = this._core.getState();\n if (!state) throw new Error(\"Message is not available\");\n\n if (branchId && position) {\n throw new Error(\"May not specify both branchId and position\");\n } else if (!branchId && !position) {\n throw new Error(\"Must specify either branchId or position\");\n }\n\n const thread = this._threadBinding.getState();\n const branches = thread.getBranches(state.id);\n let targetBranch = branchId;\n if (position === \"previous\") {\n targetBranch = branches[state.branchNumber - 2];\n } else if (position === \"next\") {\n targetBranch = branches[state.branchNumber];\n }\n if (!targetBranch) throw new Error(\"Branch not found\");\n\n this._threadBinding.getState().switchToBranch(targetBranch);\n }\n\n public unstable_getCopyText() {\n return getThreadMessageText(this.getState());\n }\n\n public subscribe(callback: () => void) {\n return this._core.subscribe(callback);\n }\n\n public getContentPartByIndex(idx: number) {\n if (idx < 0) throw new Error(\"Content part index must be >= 0\");\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.content[${idx}]`,\n contentPartSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n return getContentPartState(this.getState(), idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getContentPartByToolCallId(toolCallId: string) {\n return new ContentPartRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref:\n this.path.ref +\n `${this.path.ref}.content[toolCallId=${JSON.stringify(toolCallId)}]`,\n contentPartSelector: { type: \"toolCallId\", toolCallId },\n },\n getState: () => {\n const state = this._core.getState();\n const idx = state.content.findIndex(\n (part) =>\n part.type === \"tool-call\" && part.toolCallId === toolCallId,\n );\n if (idx === -1) return SKIP_UPDATE;\n return getContentPartState(state, idx);\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n this._core,\n this._threadBinding,\n );\n }\n\n public getAttachmentByIndex(idx: number) {\n return new MessageAttachmentRuntimeImpl(\n new ShallowMemoizeSubject({\n path: {\n ...this.path,\n ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`,\n attachmentSource: \"message\",\n attachmentSelector: { type: \"index\", index: idx },\n },\n getState: () => {\n const attachments = this.getState().attachments;\n const attachment = attachments?.[idx];\n if (!attachment) return SKIP_UPDATE;\n\n return {\n ...attachment,\n attachment: attachment,\n source: \"message\",\n } satisfies AttachmentState & { source: \"message\" };\n },\n subscribe: (callback) => this._core.subscribe(callback),\n }),\n );\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -29,7 +29,7 @@
29
29
  "conversational-ui",
30
30
  "conversational-ai"
31
31
  ],
32
- "version": "0.5.93",
32
+ "version": "0.5.94",
33
33
  "license": "MIT",
34
34
  "exports": {
35
35
  ".": {
@@ -118,8 +118,8 @@
118
118
  "tailwindcss-animate": "^1.0.7",
119
119
  "tsup": "8.3.0",
120
120
  "tsx": "^4.19.1",
121
- "@assistant-ui/tailwindcss-transformer": "0.1.0",
122
- "@assistant-ui/tsconfig": "0.0.0"
121
+ "@assistant-ui/tsconfig": "0.0.0",
122
+ "@assistant-ui/tailwindcss-transformer": "0.1.0"
123
123
  },
124
124
  "publishConfig": {
125
125
  "access": "public",
@@ -134,7 +134,7 @@
134
134
  "url": "https://github.com/Yonom/assistant-ui/issues"
135
135
  },
136
136
  "scripts": {
137
- "build": "tsx scripts/build.mts && pnpm run build:declarations",
137
+ "build": "tsx scripts/build.mts && pnpm build:declarations",
138
138
  "build:declarations": "tsc -p tsconfig.declarations.json"
139
139
  }
140
140
  }
@@ -45,25 +45,17 @@ export const toContentPartStatus = (
45
45
  ): ToolCallContentPartStatus => {
46
46
  if (message.role !== "assistant") return COMPLETE_STATUS;
47
47
 
48
- const isLastPart = partIndex === Math.max(0, message.content.length - 1);
49
- if (part.type !== "tool-call") {
50
- if (
51
- "reason" in message.status &&
52
- message.status.reason === "tool-calls" &&
53
- isLastPart
54
- )
55
- throw new Error(
56
- "Encountered unexpected requires-action status. This is likely an internal bug in assistant-ui.",
57
- );
58
-
59
- return isLastPart ? (message.status as ContentPartStatus) : COMPLETE_STATUS;
60
- }
61
-
62
- if (!!part.result) {
63
- return COMPLETE_STATUS;
48
+ if (part.type === "tool-call") {
49
+ if (!part.result) {
50
+ return message.status as ToolCallContentPartStatus;
51
+ } else {
52
+ return COMPLETE_STATUS;
53
+ }
64
54
  }
65
55
 
66
- return message.status as ToolCallContentPartStatus;
56
+ const isLastPart = partIndex === Math.max(0, message.content.length - 1);
57
+ if (message.status.type === "requires-action") return COMPLETE_STATUS;
58
+ return isLastPart ? (message.status as ContentPartStatus) : COMPLETE_STATUS;
67
59
  };
68
60
 
69
61
  export const EMPTY_CONTENT = Object.freeze({ type: "text", text: "" });