@assistant-ui/react 0.11.34 → 0.11.35

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.
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "conversational-ui",
29
29
  "conversational-ai"
30
30
  ],
31
- "version": "0.11.34",
31
+ "version": "0.11.35",
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.37",
62
+ "assistant-stream": "^0.2.38",
63
63
  "json-schema": "^0.4.0",
64
64
  "nanoid": "5.1.6",
65
65
  "react-textarea-autosize": "^8.5.9",
@@ -11,6 +11,12 @@
11
11
  * data: string;
12
12
  * };
13
13
  * }
14
+ *
15
+ * interface ExternalState {
16
+ * myCustomState: {
17
+ * foo: string;
18
+ * };
19
+ * }
14
20
  * }
15
21
  * }
16
22
  * ```
@@ -18,6 +24,12 @@
18
24
  export namespace Assistant {
19
25
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
20
26
  export interface Commands {}
27
+
28
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
29
+ export interface ExternalState {}
21
30
  }
22
31
 
23
32
  export type UserCommands = Assistant.Commands[keyof Assistant.Commands];
33
+ export type UserExternalState = keyof Assistant.ExternalState extends never
34
+ ? Record<string, unknown>
35
+ : Assistant.ExternalState[keyof Assistant.ExternalState];
@@ -1,8 +1,10 @@
1
1
  export {
2
2
  useAssistantTransportRuntime,
3
3
  useAssistantTransportSendCommand,
4
+ useAssistantTransportState,
4
5
  } from "./useAssistantTransportRuntime";
5
6
  export type {
6
7
  AssistantTransportConnectionMetadata,
7
8
  AssistantTransportCommand,
9
+ AssistantTransportProtocol,
8
10
  } from "./types";
@@ -79,10 +79,13 @@ export type QueuedCommand = AssistantTransportCommand;
79
79
  // Options types
80
80
  export type HeadersValue = Record<string, string> | Headers;
81
81
 
82
+ export type AssistantTransportProtocol = "data-stream" | "assistant-transport";
83
+
82
84
  export type AssistantTransportOptions<T> = {
83
85
  initialState: T;
84
86
  api: string;
85
87
  resumeApi?: string;
88
+ protocol?: AssistantTransportProtocol;
86
89
  converter: AssistantTransportStateConverter<T>;
87
90
  headers: HeadersValue | (() => Promise<HeadersValue>);
88
91
  body?: object;
@@ -13,6 +13,7 @@ import { useState, useRef, useMemo } from "react";
13
13
  import {
14
14
  AssistantMessageAccumulator,
15
15
  DataStreamDecoder,
16
+ AssistantTransportDecoder,
16
17
  unstable_createInitialMessage as createInitialMessage,
17
18
  } from "assistant-stream";
18
19
  import {
@@ -30,12 +31,14 @@ import { ToolExecutionStatus, useToolInvocations } from "./useToolInvocations";
30
31
  import { toAISDKTools, getEnabledTools, createRequestHeaders } from "./utils";
31
32
  import { useRemoteThreadListRuntime } from "../remote-thread-list/useRemoteThreadListRuntime";
32
33
  import { InMemoryThreadListAdapter } from "../remote-thread-list/adapter/in-memory";
33
- import { useAssistantApi } from "../../../context/react";
34
+ import { useAssistantApi, useAssistantState } from "../../../context/react";
35
+ import { UserExternalState } from "../../../augmentations";
34
36
 
35
37
  const symbolAssistantTransportExtras = Symbol("assistant-transport-extras");
36
38
  type AssistantTransportExtras = {
37
39
  [symbolAssistantTransportExtras]: true;
38
40
  sendCommand: (command: AssistantTransportCommand) => void;
41
+ state: UserExternalState;
39
42
  };
40
43
 
41
44
  const asAssistantTransportExtras = (
@@ -63,6 +66,18 @@ export const useAssistantTransportSendCommand = () => {
63
66
  };
64
67
  };
65
68
 
69
+ export function useAssistantTransportState(): UserExternalState;
70
+ export function useAssistantTransportState<T>(
71
+ selector: (state: UserExternalState) => T,
72
+ ): T;
73
+ export function useAssistantTransportState<T>(
74
+ selector: (state: UserExternalState) => T = (t) => t as T,
75
+ ): T | UserExternalState {
76
+ return useAssistantState(({ thread }) =>
77
+ selector(asAssistantTransportExtras(thread.extras).state),
78
+ );
79
+ }
80
+
66
81
  const useAssistantTransportThreadRuntime = <T,>(
67
82
  options: AssistantTransportOptions<T>,
68
83
  ): AssistantRuntime => {
@@ -114,21 +129,26 @@ const useAssistantTransportThreadRuntime = <T,>(
114
129
  throw new Error("Response body is null");
115
130
  }
116
131
 
132
+ // Select decoder based on protocol option
133
+ const protocol = options.protocol ?? "data-stream";
134
+ const decoder =
135
+ protocol === "assistant-transport"
136
+ ? new AssistantTransportDecoder()
137
+ : new DataStreamDecoder();
138
+
117
139
  let err: string | undefined;
118
- const stream = response.body
119
- .pipeThrough(new DataStreamDecoder())
120
- .pipeThrough(
121
- new AssistantMessageAccumulator({
122
- initialMessage: createInitialMessage({
123
- unstable_state:
124
- (agentStateRef.current as ReadonlyJSONValue) ?? null,
125
- }),
126
- throttle: isResume,
127
- onError: (error) => {
128
- err = error;
129
- },
140
+ const stream = response.body.pipeThrough(decoder).pipeThrough(
141
+ new AssistantMessageAccumulator({
142
+ initialMessage: createInitialMessage({
143
+ unstable_state:
144
+ (agentStateRef.current as ReadonlyJSONValue) ?? null,
130
145
  }),
131
- );
146
+ throttle: isResume,
147
+ onError: (error) => {
148
+ err = error;
149
+ },
150
+ }),
151
+ );
132
152
 
133
153
  let markedDelivered = false;
134
154
 
@@ -206,6 +226,7 @@ const useAssistantTransportThreadRuntime = <T,>(
206
226
  sendCommand: (command: AssistantTransportCommand) => {
207
227
  commandQueue.enqueue(command);
208
228
  },
229
+ state: agentStateRef.current as UserExternalState,
209
230
  } satisfies AssistantTransportExtras,
210
231
  onNew: async (message: AppendMessage): Promise<void> => {
211
232
  if (message.role !== "user")
@@ -1,11 +1,5 @@
1
1
  // This file contains setup code for tests
2
2
  import { vi } from "vitest";
3
3
 
4
- // Set up global mocks if needed
5
- // Using a fixed date to avoid recursive calls
6
- const OriginalDate = global.Date;
7
- const fixedDate = new OriginalDate("2023-01-01");
8
- global.Date = vi.fn(() => fixedDate) as any;
9
- global.Date.now = vi.fn(() => fixedDate.getTime());
10
-
11
- // Add any other global setup needed for tests
4
+ // Use Vitest's built-in to mock Date
5
+ vi.setSystemTime(new Date("2023-01-01"));