@pear-protocol/agent-sdk 0.1.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.
@@ -0,0 +1,264 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/react/useAgentChat.ts
6
+ function toDisplayMessage(m) {
7
+ return {
8
+ id: m.id,
9
+ text: m.content,
10
+ isUser: m.role === "user",
11
+ tradeLinks: m.tradeLinks ?? void 0,
12
+ images: m.images ?? void 0,
13
+ twitterSources: m.twitterSources ?? void 0,
14
+ researchAnnotations: m.researchAnnotations ?? void 0,
15
+ suggestedAction: m.suggestedAction ?? void 0
16
+ };
17
+ }
18
+ function useAgentChat(opts) {
19
+ const { client } = opts;
20
+ const [messages, setMessages] = react.useState([]);
21
+ const [isStreaming, setIsStreaming] = react.useState(false);
22
+ const [status, setStatus] = react.useState("");
23
+ const [statusNode, setStatusNode] = react.useState(null);
24
+ const [mode, setMode] = react.useState("standard");
25
+ const [pendingAction, setPendingAction] = react.useState(
26
+ null
27
+ );
28
+ const [error, setError] = react.useState(null);
29
+ const sessionIdRef = react.useRef(opts.sessionId ?? null);
30
+ const [sessionId, setSessionId] = react.useState(
31
+ opts.sessionId ?? null
32
+ );
33
+ const abortRef = react.useRef(null);
34
+ const streamingRef = react.useRef(false);
35
+ const modeRef = react.useRef(mode);
36
+ modeRef.current = mode;
37
+ const counterRef = react.useRef(0);
38
+ const nextId = react.useCallback(
39
+ () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `m${Date.now()}-${++counterRef.current}`,
40
+ []
41
+ );
42
+ react.useEffect(() => () => abortRef.current?.abort(), []);
43
+ const patchLast = react.useCallback(
44
+ (patch) => {
45
+ setMessages((prev) => {
46
+ if (prev.length === 0) return prev;
47
+ const next = [...prev];
48
+ const last = next[next.length - 1];
49
+ if (!last.isUser) next[next.length - 1] = patch(last);
50
+ return next;
51
+ });
52
+ },
53
+ []
54
+ );
55
+ const stop = react.useCallback(() => {
56
+ abortRef.current?.abort();
57
+ streamingRef.current = false;
58
+ setIsStreaming(false);
59
+ setStatus("");
60
+ setStatusNode(null);
61
+ patchLast((m) => ({ ...m, isStreaming: false }));
62
+ }, [patchLast]);
63
+ const sendMessage = react.useCallback(
64
+ async (text, cta) => {
65
+ if (!text.trim() || streamingRef.current) return;
66
+ let sid = sessionIdRef.current;
67
+ if (!sid) {
68
+ sid = (await client.createSession()).id;
69
+ sessionIdRef.current = sid;
70
+ setSessionId(sid);
71
+ }
72
+ setPendingAction(null);
73
+ setStatusNode(null);
74
+ setError(null);
75
+ setMessages((prev) => [
76
+ ...prev,
77
+ { id: nextId(), text, isUser: true },
78
+ { id: nextId(), text: "", isUser: false, isStreaming: true }
79
+ ]);
80
+ streamingRef.current = true;
81
+ setIsStreaming(true);
82
+ setStatus("thinking");
83
+ abortRef.current?.abort();
84
+ const controller = new AbortController();
85
+ abortRef.current = controller;
86
+ try {
87
+ for await (const ev of client.streamChat({
88
+ sessionId: sid,
89
+ message: text,
90
+ mode: modeRef.current,
91
+ signal: controller.signal,
92
+ cta: cta ? {
93
+ previousText: cta.previousText,
94
+ question: cta.question,
95
+ selectedOption: text
96
+ } : void 0
97
+ })) {
98
+ if (controller.signal.aborted) return;
99
+ switch (ev.type) {
100
+ case "token":
101
+ patchLast((m) => ({ ...m, text: m.text + ev.delta }));
102
+ break;
103
+ case "thinking":
104
+ patchLast((m) => ({
105
+ ...m,
106
+ reasoning: (m.reasoning ?? "") + ev.delta
107
+ }));
108
+ break;
109
+ case "status":
110
+ setStatus(ev.text);
111
+ setStatusNode(ev.node ?? null);
112
+ break;
113
+ case "sources":
114
+ patchLast((m) => ({
115
+ ...m,
116
+ tradeLinks: ev.tradeLinks ?? m.tradeLinks,
117
+ images: ev.images ?? m.images,
118
+ twitterSources: ev.twitterSources ?? m.twitterSources,
119
+ researchAnnotations: ev.researchAnnotations ?? m.researchAnnotations,
120
+ suggestedAction: ev.suggestedAction ?? m.suggestedAction
121
+ }));
122
+ break;
123
+ case "done":
124
+ if (ev.result.pendingAction) {
125
+ setPendingAction(ev.result.pendingAction);
126
+ }
127
+ break;
128
+ default:
129
+ break;
130
+ }
131
+ }
132
+ } catch (err) {
133
+ if (err?.name === "AbortError" || controller.signal.aborted) {
134
+ return;
135
+ }
136
+ console.error("[useAgentChat] stream failed:", err);
137
+ setError(err instanceof Error ? err : new Error(String(err)));
138
+ patchLast((m) => ({
139
+ ...m,
140
+ text: m.text || "Something went wrong. Try again."
141
+ }));
142
+ } finally {
143
+ if (abortRef.current === controller) {
144
+ streamingRef.current = false;
145
+ setIsStreaming(false);
146
+ setStatus("");
147
+ setStatusNode(null);
148
+ patchLast((m) => ({ ...m, isStreaming: false }));
149
+ }
150
+ }
151
+ },
152
+ [client, nextId, patchLast]
153
+ );
154
+ const confirmTicket = react.useCallback(
155
+ async (ticketId) => {
156
+ const out = await client.confirmTicket(ticketId);
157
+ setPendingAction(null);
158
+ return out;
159
+ },
160
+ [client]
161
+ );
162
+ const cancelTicket = react.useCallback(
163
+ async (ticketId) => {
164
+ const out = await client.cancelTicket(ticketId);
165
+ setPendingAction(null);
166
+ return out;
167
+ },
168
+ [client]
169
+ );
170
+ const loadSession = react.useCallback(
171
+ async (id) => {
172
+ abortRef.current?.abort();
173
+ streamingRef.current = false;
174
+ setIsStreaming(false);
175
+ setStatus("");
176
+ setStatusNode(null);
177
+ setPendingAction(null);
178
+ setError(null);
179
+ sessionIdRef.current = id;
180
+ setSessionId(id);
181
+ try {
182
+ const history = await client.getMessages(id);
183
+ setMessages(history.map(toDisplayMessage));
184
+ } catch {
185
+ setMessages([]);
186
+ }
187
+ },
188
+ [client]
189
+ );
190
+ const newSession = react.useCallback(() => {
191
+ abortRef.current?.abort();
192
+ streamingRef.current = false;
193
+ setIsStreaming(false);
194
+ setStatus("");
195
+ setStatusNode(null);
196
+ setPendingAction(null);
197
+ setError(null);
198
+ sessionIdRef.current = null;
199
+ setSessionId(null);
200
+ setMessages([]);
201
+ }, []);
202
+ return {
203
+ messages,
204
+ isStreaming,
205
+ status,
206
+ statusNode,
207
+ error,
208
+ mode,
209
+ setMode,
210
+ pendingAction,
211
+ sessionId,
212
+ sendMessage,
213
+ stop,
214
+ confirmTicket,
215
+ cancelTicket,
216
+ loadSession,
217
+ newSession
218
+ };
219
+ }
220
+ function useAgentSessions(client) {
221
+ const [sessions, setSessions] = react.useState([]);
222
+ const [isLoading, setIsLoading] = react.useState(false);
223
+ const [error, setError] = react.useState(null);
224
+ const mountedRef = react.useRef(true);
225
+ react.useEffect(() => {
226
+ mountedRef.current = true;
227
+ return () => {
228
+ mountedRef.current = false;
229
+ };
230
+ }, []);
231
+ const refresh = react.useCallback(async () => {
232
+ setIsLoading(true);
233
+ setError(null);
234
+ try {
235
+ const data = await client.listSessionSummaries();
236
+ if (mountedRef.current) setSessions(data);
237
+ } catch (err) {
238
+ if (mountedRef.current) setError(err);
239
+ } finally {
240
+ if (mountedRef.current) setIsLoading(false);
241
+ }
242
+ }, [client]);
243
+ react.useEffect(() => {
244
+ void refresh();
245
+ }, [refresh]);
246
+ const createSession = react.useCallback(async () => {
247
+ const out = await client.createSession();
248
+ await refresh();
249
+ return out;
250
+ }, [client, refresh]);
251
+ const deleteSession = react.useCallback(
252
+ async (id) => {
253
+ await client.deleteSession(id);
254
+ await refresh();
255
+ },
256
+ [client, refresh]
257
+ );
258
+ return { sessions, isLoading, error, refresh, createSession, deleteSession };
259
+ }
260
+
261
+ exports.useAgentChat = useAgentChat;
262
+ exports.useAgentSessions = useAgentSessions;
263
+ //# sourceMappingURL=index.cjs.map
264
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/useAgentChat.ts","../../src/react/useAgentSessions.ts"],"names":["useState","useRef","useCallback","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\nimport type {\n\tAgentChatMessage,\n\tChatMode,\n\tCitationSource,\n\tPendingAction,\n\tSuggestedAction,\n\tTradeLink,\n\tTwitterSource,\n} from \"../protocol\";\n\n/** Map a persisted history message to the display shape. */\nfunction toDisplayMessage(m: AgentChatMessage): DisplayMessage {\n\treturn {\n\t\tid: m.id,\n\t\ttext: m.content,\n\t\tisUser: m.role === \"user\",\n\t\ttradeLinks: m.tradeLinks ?? undefined,\n\t\timages: m.images ?? undefined,\n\t\ttwitterSources: m.twitterSources ?? undefined,\n\t\tresearchAnnotations: m.researchAnnotations ?? undefined,\n\t\tsuggestedAction: m.suggestedAction ?? undefined,\n\t};\n}\n\nexport interface DisplayMessage {\n\tid: string;\n\ttext: string;\n\tisUser: boolean;\n\tisStreaming?: boolean;\n\treasoning?: string;\n\ttradeLinks?: TradeLink[];\n\timages?: string[];\n\ttwitterSources?: TwitterSource[];\n\tresearchAnnotations?: CitationSource[];\n\tsuggestedAction?: SuggestedAction | null;\n}\n\nexport interface UseAgentChatOptions {\n\tclient: AgentChatClient;\n\t/** Optional existing session to resume. */\n\tsessionId?: string;\n}\n\nexport function useAgentChat(opts: UseAgentChatOptions) {\n\tconst { client } = opts;\n\tconst [messages, setMessages] = useState<DisplayMessage[]>([]);\n\tconst [isStreaming, setIsStreaming] = useState(false);\n\tconst [status, setStatus] = useState(\"\");\n\t// The node of the latest status event (e.g. \"research\", \"compose\") so the UI\n\t// can map to its own per-node \"thinking\" phrasing. null between turns.\n\tconst [statusNode, setStatusNode] = useState<string | null>(null);\n\tconst [mode, setMode] = useState<ChatMode>(\"standard\");\n\tconst [pendingAction, setPendingAction] = useState<PendingAction | null>(\n\t\tnull,\n\t);\n\t// Last turn's failure (null while healthy). Mid-stream errors land here too —\n\t// without it, a stream that dies after a few tokens renders a truncated\n\t// answer that looks complete and the app has no way to know.\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst sessionIdRef = useRef<string | null>(opts.sessionId ?? null);\n\tconst [sessionId, setSessionId] = useState<string | null>(\n\t\topts.sessionId ?? null,\n\t);\n\tconst abortRef = useRef<AbortController | null>(null);\n\tconst streamingRef = useRef(false);\n\tconst modeRef = useRef(mode);\n\tmodeRef.current = mode;\n\tconst counterRef = useRef(0);\n\n\t// Per-instance id factory — never a module-level counter (SSR-hostile: a\n\t// shared singleton collides across concurrent requests / hydration).\n\tconst nextId = useCallback(\n\t\t() =>\n\t\t\ttypeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n\t\t\t\t? crypto.randomUUID()\n\t\t\t\t: `m${Date.now()}-${++counterRef.current}`,\n\t\t[],\n\t);\n\n\t// Abort any in-flight stream on unmount (otherwise the SSE keeps running).\n\tuseEffect(() => () => abortRef.current?.abort(), []);\n\n\tconst patchLast = useCallback(\n\t\t(patch: (m: DisplayMessage) => DisplayMessage) => {\n\t\t\tsetMessages((prev) => {\n\t\t\t\tif (prev.length === 0) return prev;\n\t\t\t\tconst next = [...prev];\n\t\t\t\tconst last = next[next.length - 1];\n\t\t\t\tif (!last.isUser) next[next.length - 1] = patch(last);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\n\t/** Abort a running stream (e.g. a Stop button). */\n\tconst stop = useCallback(() => {\n\t\tabortRef.current?.abort();\n\t\tstreamingRef.current = false;\n\t\tsetIsStreaming(false);\n\t\tsetStatus(\"\");\n\t\tsetStatusNode(null);\n\t\tpatchLast((m) => ({ ...m, isStreaming: false }));\n\t}, [patchLast]);\n\n\tconst sendMessage = useCallback(\n\t\tasync (text: string, cta?: { question: string; previousText: string }) => {\n\t\t\tif (!text.trim() || streamingRef.current) return;\n\n\t\t\tlet sid = sessionIdRef.current;\n\t\t\tif (!sid) {\n\t\t\t\tsid = (await client.createSession()).id;\n\t\t\t\tsessionIdRef.current = sid;\n\t\t\t\tsetSessionId(sid);\n\t\t\t}\n\n\t\t\tsetPendingAction(null);\n\t\t\tsetStatusNode(null);\n\t\t\tsetError(null);\n\t\t\tsetMessages((prev) => [\n\t\t\t\t...prev,\n\t\t\t\t{ id: nextId(), text, isUser: true },\n\t\t\t\t{ id: nextId(), text: \"\", isUser: false, isStreaming: true },\n\t\t\t]);\n\t\t\tstreamingRef.current = true;\n\t\t\tsetIsStreaming(true);\n\t\t\tsetStatus(\"thinking\");\n\n\t\t\tabortRef.current?.abort();\n\t\t\tconst controller = new AbortController();\n\t\t\tabortRef.current = controller;\n\n\t\t\ttry {\n\t\t\t\tfor await (const ev of client.streamChat({\n\t\t\t\t\tsessionId: sid,\n\t\t\t\t\tmessage: text,\n\t\t\t\t\tmode: modeRef.current,\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tcta: cta\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tpreviousText: cta.previousText,\n\t\t\t\t\t\t\t\tquestion: cta.question,\n\t\t\t\t\t\t\t\tselectedOption: text,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t})) {\n\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\tswitch (ev.type) {\n\t\t\t\t\t\tcase \"token\":\n\t\t\t\t\t\t\tpatchLast((m) => ({ ...m, text: m.text + ev.delta }));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"thinking\":\n\t\t\t\t\t\t\tpatchLast((m) => ({\n\t\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\t\treasoning: (m.reasoning ?? \"\") + ev.delta,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"status\":\n\t\t\t\t\t\t\tsetStatus(ev.text);\n\t\t\t\t\t\t\tsetStatusNode(ev.node ?? null);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"sources\":\n\t\t\t\t\t\t\tpatchLast((m) => ({\n\t\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\t\ttradeLinks: ev.tradeLinks ?? m.tradeLinks,\n\t\t\t\t\t\t\t\timages: ev.images ?? m.images,\n\t\t\t\t\t\t\t\ttwitterSources: ev.twitterSources ?? m.twitterSources,\n\t\t\t\t\t\t\t\tresearchAnnotations:\n\t\t\t\t\t\t\t\t\tev.researchAnnotations ?? m.researchAnnotations,\n\t\t\t\t\t\t\t\tsuggestedAction: ev.suggestedAction ?? m.suggestedAction,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"done\":\n\t\t\t\t\t\t\tif (ev.result.pendingAction) {\n\t\t\t\t\t\t\t\tsetPendingAction(ev.result.pendingAction);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tif (\n\t\t\t\t\t(err as { name?: string })?.name === \"AbortError\" ||\n\t\t\t\t\tcontroller.signal.aborted\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Surface the cause to the console for debugging; keep the on-screen\n\t\t\t\t// copy generic.\n\t\t\t\tconsole.error(\"[useAgentChat] stream failed:\", err);\n\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\tpatchLast((m) => ({\n\t\t\t\t\t...m,\n\t\t\t\t\ttext: m.text || \"Something went wrong. Try again.\",\n\t\t\t\t}));\n\t\t\t} finally {\n\t\t\t\t// Guarded: after stop() → sendMessage(next), this controller is\n\t\t\t\t// superseded — patching here would mark the NEW turn's streaming\n\t\t\t\t// placeholder as finished (its caret/status vanish mid-stream).\n\t\t\t\tif (abortRef.current === controller) {\n\t\t\t\t\tstreamingRef.current = false;\n\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\tsetStatus(\"\");\n\t\t\t\t\tsetStatusNode(null);\n\t\t\t\t\tpatchLast((m) => ({ ...m, isStreaming: false }));\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[client, nextId, patchLast],\n\t);\n\n\tconst confirmTicket = useCallback(\n\t\tasync (ticketId: string) => {\n\t\t\tconst out = await client.confirmTicket(ticketId);\n\t\t\tsetPendingAction(null);\n\t\t\treturn out;\n\t\t},\n\t\t[client],\n\t);\n\n\tconst cancelTicket = useCallback(\n\t\tasync (ticketId: string) => {\n\t\t\tconst out = await client.cancelTicket(ticketId);\n\t\t\tsetPendingAction(null);\n\t\t\treturn out;\n\t\t},\n\t\t[client],\n\t);\n\n\t/** Switch to an existing session and load its history into view. */\n\tconst loadSession = useCallback(\n\t\tasync (id: string) => {\n\t\t\tabortRef.current?.abort();\n\t\t\tstreamingRef.current = false;\n\t\t\tsetIsStreaming(false);\n\t\t\tsetStatus(\"\");\n\t\t\tsetStatusNode(null);\n\t\t\tsetPendingAction(null);\n\t\t\tsetError(null);\n\t\t\tsessionIdRef.current = id;\n\t\t\tsetSessionId(id);\n\t\t\ttry {\n\t\t\t\tconst history = await client.getMessages(id);\n\t\t\t\tsetMessages(history.map(toDisplayMessage));\n\t\t\t} catch {\n\t\t\t\tsetMessages([]);\n\t\t\t}\n\t\t},\n\t\t[client],\n\t);\n\n\t/** Start a fresh session — clears the view; the next send creates it. */\n\tconst newSession = useCallback(() => {\n\t\tabortRef.current?.abort();\n\t\tstreamingRef.current = false;\n\t\tsetIsStreaming(false);\n\t\tsetStatus(\"\");\n\t\tsetStatusNode(null);\n\t\tsetPendingAction(null);\n\t\tsetError(null);\n\t\tsessionIdRef.current = null;\n\t\tsetSessionId(null);\n\t\tsetMessages([]);\n\t}, []);\n\n\treturn {\n\t\tmessages,\n\t\tisStreaming,\n\t\tstatus,\n\t\tstatusNode,\n\t\terror,\n\t\tmode,\n\t\tsetMode,\n\t\tpendingAction,\n\t\tsessionId,\n\t\tsendMessage,\n\t\tstop,\n\t\tconfirmTicket,\n\t\tcancelTicket,\n\t\tloadSession,\n\t\tnewSession,\n\t};\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\nimport type { SessionSummary } from \"../protocol\";\n\n/** Minimal session-list hook (load + refresh + create + delete). Apps that use\n * TanStack Query can skip this and call the client directly. */\nexport function useAgentSessions(client: AgentChatClient) {\n\tconst [sessions, setSessions] = useState<SessionSummary[]>([]);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst mountedRef = useRef(true);\n\n\tuseEffect(() => {\n\t\tmountedRef.current = true;\n\t\treturn () => {\n\t\t\tmountedRef.current = false;\n\t\t};\n\t}, []);\n\n\tconst refresh = useCallback(async () => {\n\t\tsetIsLoading(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst data = await client.listSessionSummaries();\n\t\t\tif (mountedRef.current) setSessions(data);\n\t\t} catch (err) {\n\t\t\tif (mountedRef.current) setError(err as Error);\n\t\t} finally {\n\t\t\tif (mountedRef.current) setIsLoading(false);\n\t\t}\n\t}, [client]);\n\n\tuseEffect(() => {\n\t\tvoid refresh();\n\t}, [refresh]);\n\n\tconst createSession = useCallback(async () => {\n\t\tconst out = await client.createSession();\n\t\tawait refresh();\n\t\treturn out;\n\t}, [client, refresh]);\n\n\tconst deleteSession = useCallback(\n\t\tasync (id: string) => {\n\t\t\tawait client.deleteSession(id);\n\t\t\tawait refresh();\n\t\t},\n\t\t[client, refresh],\n\t);\n\n\treturn { sessions, isLoading, error, refresh, createSession, deleteSession };\n}\n"]}
@@ -0,0 +1,76 @@
1
+ import * as react from 'react';
2
+ import { M as TradeLink, R as TwitterSource, l as CitationSource, F as SuggestedAction, A as AgentChatClient } from '../client-EVhAAxSx.cjs';
3
+ import 'zod';
4
+
5
+ interface DisplayMessage {
6
+ id: string;
7
+ text: string;
8
+ isUser: boolean;
9
+ isStreaming?: boolean;
10
+ reasoning?: string;
11
+ tradeLinks?: TradeLink[];
12
+ images?: string[];
13
+ twitterSources?: TwitterSource[];
14
+ researchAnnotations?: CitationSource[];
15
+ suggestedAction?: SuggestedAction | null;
16
+ }
17
+ interface UseAgentChatOptions {
18
+ client: AgentChatClient;
19
+ sessionId?: string;
20
+ }
21
+ declare function useAgentChat(opts: UseAgentChatOptions): {
22
+ messages: DisplayMessage[];
23
+ isStreaming: boolean;
24
+ status: string;
25
+ statusNode: string | null;
26
+ error: Error | null;
27
+ mode: "standard" | "advanced";
28
+ setMode: react.Dispatch<react.SetStateAction<"standard" | "advanced">>;
29
+ pendingAction: {
30
+ ticketId: string;
31
+ action: string;
32
+ consequence: string;
33
+ options: string[];
34
+ } | null;
35
+ sessionId: string | null;
36
+ sendMessage: (text: string, cta?: {
37
+ question: string;
38
+ previousText: string;
39
+ }) => Promise<void>;
40
+ stop: () => void;
41
+ confirmTicket: (ticketId: string) => Promise<{
42
+ [x: string]: unknown;
43
+ ok: boolean;
44
+ status: "EXECUTED" | "FAILED";
45
+ result?: unknown;
46
+ positionsSnapshot?: unknown;
47
+ images?: string[] | undefined;
48
+ }>;
49
+ cancelTicket: (ticketId: string) => Promise<{
50
+ ok: true;
51
+ status: "CANCELLED";
52
+ }>;
53
+ loadSession: (id: string) => Promise<void>;
54
+ newSession: () => void;
55
+ };
56
+
57
+ declare function useAgentSessions(client: AgentChatClient): {
58
+ sessions: {
59
+ id: string;
60
+ appType: string;
61
+ createdAt: string;
62
+ firstUserMessage?: string | undefined;
63
+ lastUserMessage?: string | undefined;
64
+ lastUserMessageAt?: string | undefined;
65
+ lastAssistantMessageAt?: string | undefined;
66
+ }[];
67
+ isLoading: boolean;
68
+ error: Error | null;
69
+ refresh: () => Promise<void>;
70
+ createSession: () => Promise<{
71
+ id: string;
72
+ }>;
73
+ deleteSession: (id: string) => Promise<void>;
74
+ };
75
+
76
+ export { type DisplayMessage, type UseAgentChatOptions, useAgentChat, useAgentSessions };
@@ -0,0 +1,76 @@
1
+ import * as react from 'react';
2
+ import { M as TradeLink, R as TwitterSource, l as CitationSource, F as SuggestedAction, A as AgentChatClient } from '../client-EVhAAxSx.js';
3
+ import 'zod';
4
+
5
+ interface DisplayMessage {
6
+ id: string;
7
+ text: string;
8
+ isUser: boolean;
9
+ isStreaming?: boolean;
10
+ reasoning?: string;
11
+ tradeLinks?: TradeLink[];
12
+ images?: string[];
13
+ twitterSources?: TwitterSource[];
14
+ researchAnnotations?: CitationSource[];
15
+ suggestedAction?: SuggestedAction | null;
16
+ }
17
+ interface UseAgentChatOptions {
18
+ client: AgentChatClient;
19
+ sessionId?: string;
20
+ }
21
+ declare function useAgentChat(opts: UseAgentChatOptions): {
22
+ messages: DisplayMessage[];
23
+ isStreaming: boolean;
24
+ status: string;
25
+ statusNode: string | null;
26
+ error: Error | null;
27
+ mode: "standard" | "advanced";
28
+ setMode: react.Dispatch<react.SetStateAction<"standard" | "advanced">>;
29
+ pendingAction: {
30
+ ticketId: string;
31
+ action: string;
32
+ consequence: string;
33
+ options: string[];
34
+ } | null;
35
+ sessionId: string | null;
36
+ sendMessage: (text: string, cta?: {
37
+ question: string;
38
+ previousText: string;
39
+ }) => Promise<void>;
40
+ stop: () => void;
41
+ confirmTicket: (ticketId: string) => Promise<{
42
+ [x: string]: unknown;
43
+ ok: boolean;
44
+ status: "EXECUTED" | "FAILED";
45
+ result?: unknown;
46
+ positionsSnapshot?: unknown;
47
+ images?: string[] | undefined;
48
+ }>;
49
+ cancelTicket: (ticketId: string) => Promise<{
50
+ ok: true;
51
+ status: "CANCELLED";
52
+ }>;
53
+ loadSession: (id: string) => Promise<void>;
54
+ newSession: () => void;
55
+ };
56
+
57
+ declare function useAgentSessions(client: AgentChatClient): {
58
+ sessions: {
59
+ id: string;
60
+ appType: string;
61
+ createdAt: string;
62
+ firstUserMessage?: string | undefined;
63
+ lastUserMessage?: string | undefined;
64
+ lastUserMessageAt?: string | undefined;
65
+ lastAssistantMessageAt?: string | undefined;
66
+ }[];
67
+ isLoading: boolean;
68
+ error: Error | null;
69
+ refresh: () => Promise<void>;
70
+ createSession: () => Promise<{
71
+ id: string;
72
+ }>;
73
+ deleteSession: (id: string) => Promise<void>;
74
+ };
75
+
76
+ export { type DisplayMessage, type UseAgentChatOptions, useAgentChat, useAgentSessions };