@pear-protocol/agent-sdk 0.4.1 → 0.5.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.
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { X as TradeLink, $ as TwitterSource, n as CitationSource, N as SuggestedAction, A as AgentChatClient } from '../client-BSUkCr7k.js';
2
+ import { a9 as TradeLink, ad as TwitterSource, n as CitationSource, a1 as SuggestedAction, A as AgentChatClient, l as ChatSurface, x as OnboardingQuestion } from '../client-ETT3B7Kt.js';
3
3
  import 'zod';
4
4
 
5
5
  interface DisplayMessage {
@@ -75,6 +75,54 @@ declare function useAgentSessions(client: AgentChatClient): {
75
75
  deleteSession: (id: string) => Promise<void>;
76
76
  };
77
77
 
78
+ declare function useOnboarding(args: {
79
+ client: AgentChatClient;
80
+ surface: ChatSurface;
81
+ enabled?: boolean;
82
+ }): {
83
+ needsOnboarding: boolean;
84
+ onboardingState: "not_started" | "skipped" | "completed" | null;
85
+ currentQuestion: {
86
+ id: "experience" | "trading_style" | "risk_appetite" | "note";
87
+ prompt: string;
88
+ freeform: boolean;
89
+ options?: {
90
+ value: string;
91
+ label: string;
92
+ description?: string | undefined;
93
+ }[] | undefined;
94
+ } | null;
95
+ questions: {
96
+ id: "experience" | "trading_style" | "risk_appetite" | "note";
97
+ prompt: string;
98
+ freeform: boolean;
99
+ options?: {
100
+ value: string;
101
+ label: string;
102
+ description?: string | undefined;
103
+ }[] | undefined;
104
+ }[];
105
+ profile: {
106
+ experience?: "new" | "intermediate" | "seasoned" | undefined;
107
+ tradingStyle?: "scalper" | "swing" | "position" | "passive" | undefined;
108
+ riskAppetite?: "conservative" | "balanced" | "aggressive" | undefined;
109
+ favoriteSectors?: string[] | undefined;
110
+ avoidAssets?: string[] | undefined;
111
+ note?: string | undefined;
112
+ };
113
+ isLast: boolean;
114
+ progress: {
115
+ answered: number;
116
+ total: number;
117
+ };
118
+ submitAnswer: (questionIdOrValue: OnboardingQuestion["id"] | string, maybeValue?: string) => Promise<void>;
119
+ skip: () => Promise<void>;
120
+ reset: () => Promise<void>;
121
+ loading: boolean;
122
+ error: Error | null;
123
+ refresh: () => Promise<void>;
124
+ };
125
+
78
126
  declare function useWalletLink(client: AgentChatClient, opts?: {
79
127
  enabled?: boolean;
80
128
  }): {
@@ -96,4 +144,4 @@ declare function useWalletLink(client: AgentChatClient, opts?: {
96
144
  refresh: () => Promise<void>;
97
145
  };
98
146
 
99
- export { type DisplayMessage, type UseAgentChatOptions, useAgentChat, useAgentSessions, useWalletLink };
147
+ export { type DisplayMessage, type UseAgentChatOptions, useAgentChat, useAgentSessions, useOnboarding, useWalletLink };
@@ -273,6 +273,112 @@ function useAgentSessions(client) {
273
273
  );
274
274
  return { sessions, isLoading, error, refresh, createSession, deleteSession };
275
275
  }
276
+ function useOnboarding(args) {
277
+ const { client, surface } = args;
278
+ const enabled = args.enabled ?? true;
279
+ const [state, setState] = useState(null);
280
+ const [questions, setQuestions] = useState([]);
281
+ const [loading, setLoading] = useState(true);
282
+ const [error, setError] = useState(null);
283
+ const mountedRef = useRef(true);
284
+ useEffect(() => {
285
+ mountedRef.current = true;
286
+ return () => {
287
+ mountedRef.current = false;
288
+ };
289
+ }, []);
290
+ const refresh = useCallback(async () => {
291
+ setError(null);
292
+ try {
293
+ const [next, qs] = await Promise.all([
294
+ client.getOnboardingState(surface),
295
+ client.getOnboardingQuestions(surface)
296
+ ]);
297
+ if (mountedRef.current) {
298
+ setState(next);
299
+ setQuestions(qs);
300
+ }
301
+ } catch (err) {
302
+ if (mountedRef.current) {
303
+ setError(err instanceof Error ? err : new Error(String(err)));
304
+ }
305
+ } finally {
306
+ if (mountedRef.current) setLoading(false);
307
+ }
308
+ }, [client, surface]);
309
+ useEffect(() => {
310
+ if (!enabled) {
311
+ setState(null);
312
+ setQuestions([]);
313
+ setError(null);
314
+ setLoading(true);
315
+ return;
316
+ }
317
+ void refresh();
318
+ }, [refresh, enabled]);
319
+ const submitAnswer = useCallback(
320
+ async (questionIdOrValue, maybeValue) => {
321
+ const questionId = maybeValue === void 0 ? state?.nextQuestion?.id : questionIdOrValue;
322
+ const value = maybeValue === void 0 ? questionIdOrValue : maybeValue;
323
+ if (!questionId) return;
324
+ setError(null);
325
+ try {
326
+ const next = await client.submitOnboardingAnswer(surface, {
327
+ questionId,
328
+ value
329
+ });
330
+ if (mountedRef.current) setState(next);
331
+ } catch (err) {
332
+ const e = err instanceof Error ? err : new Error(String(err));
333
+ if (mountedRef.current) setError(e);
334
+ throw e;
335
+ }
336
+ },
337
+ [client, surface, state?.nextQuestion?.id]
338
+ );
339
+ const skip = useCallback(async () => {
340
+ setError(null);
341
+ try {
342
+ const next = await client.skipOnboarding(surface);
343
+ if (mountedRef.current) setState(next);
344
+ } catch (err) {
345
+ const e = err instanceof Error ? err : new Error(String(err));
346
+ if (mountedRef.current) setError(e);
347
+ throw e;
348
+ }
349
+ }, [client, surface]);
350
+ const reset = useCallback(async () => {
351
+ setError(null);
352
+ try {
353
+ await client.resetOnboarding();
354
+ await refresh();
355
+ } catch (err) {
356
+ const e = err instanceof Error ? err : new Error(String(err));
357
+ if (mountedRef.current) setError(e);
358
+ throw e;
359
+ }
360
+ }, [client, refresh]);
361
+ const currentQuestion = state?.nextQuestion ?? null;
362
+ const onboardingState = state?.onboardingState ?? null;
363
+ const profile = state?.profile ?? {};
364
+ return {
365
+ needsOnboarding: state?.needsOnboarding ?? false,
366
+ onboardingState,
367
+ // First-run sequential wizard: the next unanswered question.
368
+ currentQuestion,
369
+ // Edit form: the full ordered question set + the user's current picks.
370
+ questions,
371
+ profile,
372
+ isLast: state?.isLast ?? false,
373
+ progress: { answered: state?.answered ?? 0, total: state?.total ?? 0 },
374
+ submitAnswer,
375
+ skip,
376
+ reset,
377
+ loading,
378
+ error,
379
+ refresh
380
+ };
381
+ }
276
382
  function useWalletLink(client, opts) {
277
383
  const enabled = opts?.enabled ?? true;
278
384
  const [linked, setLinked] = useState(null);
@@ -341,6 +447,6 @@ function useWalletLink(client, opts) {
341
447
  return { linked, isWorking, error, link, unlink, refresh };
342
448
  }
343
449
 
344
- export { useAgentChat, useAgentSessions, useWalletLink };
450
+ export { useAgentChat, useAgentSessions, useOnboarding, useWalletLink };
345
451
  //# sourceMappingURL=index.js.map
346
452
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/useAgentChat.ts","../../src/react/useAgentSessions.ts","../../src/react/useWalletLink.ts"],"names":["useState","useRef","useEffect","useCallback","opts"],"mappings":"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","file":"index.js","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\nimport type {\n\tAgentChatMessage,\n\tChatMode,\n\tChatSurface,\n\tCitationSource,\n\tPendingAction,\n\tSuggestedAction,\n\tTradeLink,\n\tTwitterSource,\n} from \"../protocol\";\n\n/** A persisted message worth rendering. A user-stopped turn can persist an\n * EMPTY assistant row (no text, no attachments) — skip it on history load,\n * the same way `stop()` removes the live placeholder. */\nfunction isRenderableMessage(m: AgentChatMessage): boolean {\n\tif (m.role === \"user\") return true;\n\treturn Boolean(\n\t\tm.content ||\n\t\t\tm.images?.length ||\n\t\t\tm.tradeLinks?.length ||\n\t\t\tm.twitterSources?.length ||\n\t\t\tm.researchAnnotations?.length ||\n\t\t\tm.suggestedAction,\n\t);\n}\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\t// Declared client surface — drives per-surface behavior server-side. Defaults\n\t// to pear_v3 (retail web); switch it (e.g. base_mini) to test venue awareness.\n\tconst [surface, setSurface] = useState<ChatSurface>(\"pear_v3\");\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 surfaceRef = useRef(surface);\n\tsurfaceRef.current = surface;\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). A stopped turn that\n\t * produced NOTHING removes its placeholder bubble entirely — otherwise an\n\t * empty assistant bubble (typing dots frozen) lingers in the thread. */\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\tsetMessages((prev) => {\n\t\t\tif (prev.length === 0) return prev;\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (last.isUser) return prev;\n\t\t\tif (!last.text && !last.reasoning) return prev.slice(0, -1);\n\t\t\treturn [...prev.slice(0, -1), { ...last, isStreaming: false }];\n\t\t});\n\t}, []);\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\tsurface: surfaceRef.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.filter(isRenderableMessage).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\tsurface,\n\t\tsetSurface,\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","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\n\n/**\n * Backend-verified wallet-link state + link/unlink actions. `linked` is\n * `null` while the initial status fetch is in flight — render a loading\n * state, not a gate (a flash of \"not linked\" for a linked user is the bug\n * this hook exists to kill; never cache link state in localStorage).\n *\n * Pass `enabled: false` until the caller is authenticated — the status\n * fetch needs a bearer token, and firing it pre-auth surfaces a stale 401\n * (\"Authorization header must be Bearer...\") on whatever gate renders next.\n */\nexport function useWalletLink(\n\tclient: AgentChatClient,\n\topts?: { enabled?: boolean },\n) {\n\tconst enabled = opts?.enabled ?? true;\n\tconst [linked, setLinked] = useState<boolean | null>(null);\n\tconst [isWorking, setIsWorking] = 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\tsetError(null);\n\t\ttry {\n\t\t\tconst status = await client.getLinkStatus();\n\t\t\tif (mountedRef.current) setLinked(status.linked);\n\t\t} catch (err) {\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\tsetLinked(null);\n\t\t\t}\n\t\t}\n\t}, [client]);\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\t// Pre-auth: unknown status, and any earlier pre-auth failure is noise.\n\t\t\tsetLinked(null);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\t\tvoid refresh();\n\t}, [refresh, enabled]);\n\n\tconst link = useCallback(\n\t\tasync (opts?: { force?: boolean; code?: string }) => {\n\t\t\tsetIsWorking(true);\n\t\t\tsetError(null);\n\t\t\ttry {\n\t\t\t\tconst out = await client.linkWallet(opts);\n\t\t\t\tif (mountedRef.current) setLinked(out.linked);\n\t\t\t\treturn out;\n\t\t\t} catch (err) {\n\t\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\t\tif (mountedRef.current) setError(e);\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\tif (mountedRef.current) setIsWorking(false);\n\t\t\t}\n\t\t},\n\t\t[client],\n\t);\n\n\tconst unlink = useCallback(async () => {\n\t\tsetIsWorking(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst out = await client.unlinkWallet();\n\t\t\tif (mountedRef.current) setLinked(false);\n\t\t\treturn out;\n\t\t} catch (err) {\n\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\tif (mountedRef.current) setError(e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tif (mountedRef.current) setIsWorking(false);\n\t\t}\n\t}, [client]);\n\n\treturn { linked, isWorking, error, link, unlink, refresh };\n}\n"]}
1
+ {"version":3,"sources":["../../src/react/useAgentChat.ts","../../src/react/useAgentSessions.ts","../../src/react/useOnboarding.ts","../../src/react/useWalletLink.ts"],"names":["useState","useRef","useEffect","useCallback","opts"],"mappings":"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","file":"index.js","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\nimport type {\n\tAgentChatMessage,\n\tChatMode,\n\tChatSurface,\n\tCitationSource,\n\tPendingAction,\n\tSuggestedAction,\n\tTradeLink,\n\tTwitterSource,\n} from \"../protocol\";\n\n/** A persisted message worth rendering. A user-stopped turn can persist an\n * EMPTY assistant row (no text, no attachments) — skip it on history load,\n * the same way `stop()` removes the live placeholder. */\nfunction isRenderableMessage(m: AgentChatMessage): boolean {\n\tif (m.role === \"user\") return true;\n\treturn Boolean(\n\t\tm.content ||\n\t\t\tm.images?.length ||\n\t\t\tm.tradeLinks?.length ||\n\t\t\tm.twitterSources?.length ||\n\t\t\tm.researchAnnotations?.length ||\n\t\t\tm.suggestedAction,\n\t);\n}\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\t// Declared client surface — drives per-surface behavior server-side. Defaults\n\t// to pear_v3 (retail web); switch it (e.g. base_mini) to test venue awareness.\n\tconst [surface, setSurface] = useState<ChatSurface>(\"pear_v3\");\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 surfaceRef = useRef(surface);\n\tsurfaceRef.current = surface;\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). A stopped turn that\n\t * produced NOTHING removes its placeholder bubble entirely — otherwise an\n\t * empty assistant bubble (typing dots frozen) lingers in the thread. */\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\tsetMessages((prev) => {\n\t\t\tif (prev.length === 0) return prev;\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (last.isUser) return prev;\n\t\t\tif (!last.text && !last.reasoning) return prev.slice(0, -1);\n\t\t\treturn [...prev.slice(0, -1), { ...last, isStreaming: false }];\n\t\t});\n\t}, []);\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\tsurface: surfaceRef.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.filter(isRenderableMessage).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\tsurface,\n\t\tsetSurface,\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","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\nimport type {\n\tChatSurface,\n\tOnboardingProfile,\n\tOnboardingQuestion,\n\tOnboardingState,\n\tOnboardingStateResponse,\n} from \"../protocol\";\n\n/**\n * Deterministic, FE-controlled onboarding. Fetches state on mount, exposes the\n * current question + progress, and actions that call the client then refresh so\n * `needsOnboarding` / `currentQuestion` always reflect the server.\n *\n * Two modes off ONE hook:\n * • First run — drive a sequential wizard off `currentQuestion` (the next\n * unanswered question) + `progress`.\n * • Edit — render ALL `questions` PRE-FILLED from `profile` (the current\n * picks) and update single fields via `submitAnswer(questionId, value)`.\n * Editing is a non-destructive MERGE server-side — NEVER call `reset()` to\n * edit. `reset()` is \"start over\" only.\n *\n * Gate the wizard on `needsOnboarding` once `loading` is false (a flash of the\n * wizard for an already-onboarded user is the bug this hook avoids — render a\n * loading state while the initial fetch is in flight). Pass `enabled: false`\n * until the caller is authenticated; the state fetch needs a bearer token.\n */\nexport function useOnboarding(args: {\n\tclient: AgentChatClient;\n\tsurface: ChatSurface;\n\tenabled?: boolean;\n}) {\n\tconst { client, surface } = args;\n\tconst enabled = args.enabled ?? true;\n\tconst [state, setState] = useState<OnboardingStateResponse | null>(null);\n\t// The full ordered question set (surface-static). Fetched once so an edit\n\t// form can render EVERY question pre-filled from `profile`, not just the\n\t// next-unanswered one.\n\tconst [questions, setQuestions] = useState<OnboardingQuestion[]>([]);\n\tconst [loading, setLoading] = useState(true);\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\tsetError(null);\n\t\ttry {\n\t\t\tconst [next, qs] = await Promise.all([\n\t\t\t\tclient.getOnboardingState(surface),\n\t\t\t\tclient.getOnboardingQuestions(surface),\n\t\t\t]);\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetState(next);\n\t\t\t\tsetQuestions(qs);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t}\n\t\t} finally {\n\t\t\tif (mountedRef.current) setLoading(false);\n\t\t}\n\t}, [client, surface]);\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\t// Pre-auth: unknown state, suppress any earlier pre-auth failure.\n\t\t\tsetState(null);\n\t\t\tsetQuestions([]);\n\t\t\tsetError(null);\n\t\t\tsetLoading(true);\n\t\t\treturn;\n\t\t}\n\t\tvoid refresh();\n\t}, [refresh, enabled]);\n\n\t// Each action drives the server then re-syncs from the returned shape (no\n\t// optimistic local state — the server is the source of truth for the flow).\n\t//\n\t// First run: call `submitAnswer(value)` — the id defaults to the next\n\t// unanswered question. Edit: call `submitAnswer(questionId, value)` to update\n\t// a SPECIFIC field. Either way the server MERGES (non-destructive); the\n\t// returned `profile` reflects the change.\n\tconst submitAnswer = useCallback(\n\t\tasync (\n\t\t\tquestionIdOrValue: OnboardingQuestion[\"id\"] | string,\n\t\t\tmaybeValue?: string,\n\t\t) => {\n\t\t\t// Two-arg form is an explicit edit; one-arg form answers the next question.\n\t\t\tconst questionId =\n\t\t\t\tmaybeValue === undefined\n\t\t\t\t\t? state?.nextQuestion?.id\n\t\t\t\t\t: (questionIdOrValue as OnboardingQuestion[\"id\"]);\n\t\t\tconst value = maybeValue === undefined ? questionIdOrValue : maybeValue;\n\t\t\tif (!questionId) return;\n\t\t\tsetError(null);\n\t\t\ttry {\n\t\t\t\tconst next = await client.submitOnboardingAnswer(surface, {\n\t\t\t\t\tquestionId,\n\t\t\t\t\tvalue,\n\t\t\t\t});\n\t\t\t\tif (mountedRef.current) setState(next);\n\t\t\t} catch (err) {\n\t\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\t\tif (mountedRef.current) setError(e);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t},\n\t\t[client, surface, state?.nextQuestion?.id],\n\t);\n\n\tconst skip = useCallback(async () => {\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst next = await client.skipOnboarding(surface);\n\t\t\tif (mountedRef.current) setState(next);\n\t\t} catch (err) {\n\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\tif (mountedRef.current) setError(e);\n\t\t\tthrow e;\n\t\t}\n\t}, [client, surface]);\n\n\tconst reset = useCallback(async () => {\n\t\tsetError(null);\n\t\ttry {\n\t\t\tawait client.resetOnboarding();\n\t\t\t// reset takes no surface; re-fetch with THIS surface for the right shape.\n\t\t\tawait refresh();\n\t\t} catch (err) {\n\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\tif (mountedRef.current) setError(e);\n\t\t\tthrow e;\n\t\t}\n\t}, [client, refresh]);\n\n\tconst currentQuestion: OnboardingQuestion | null =\n\t\tstate?.nextQuestion ?? null;\n\tconst onboardingState: OnboardingState | null =\n\t\tstate?.onboardingState ?? null;\n\t// Current picks — pre-fill an edit form from this. `{}` for a new user.\n\tconst profile: OnboardingProfile = state?.profile ?? {};\n\n\treturn {\n\t\tneedsOnboarding: state?.needsOnboarding ?? false,\n\t\tonboardingState,\n\t\t// First-run sequential wizard: the next unanswered question.\n\t\tcurrentQuestion,\n\t\t// Edit form: the full ordered question set + the user's current picks.\n\t\tquestions,\n\t\tprofile,\n\t\tisLast: state?.isLast ?? false,\n\t\tprogress: { answered: state?.answered ?? 0, total: state?.total ?? 0 },\n\t\tsubmitAnswer,\n\t\tskip,\n\t\treset,\n\t\tloading,\n\t\terror,\n\t\trefresh,\n\t};\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { AgentChatClient } from \"../client\";\n\n/**\n * Backend-verified wallet-link state + link/unlink actions. `linked` is\n * `null` while the initial status fetch is in flight — render a loading\n * state, not a gate (a flash of \"not linked\" for a linked user is the bug\n * this hook exists to kill; never cache link state in localStorage).\n *\n * Pass `enabled: false` until the caller is authenticated — the status\n * fetch needs a bearer token, and firing it pre-auth surfaces a stale 401\n * (\"Authorization header must be Bearer...\") on whatever gate renders next.\n */\nexport function useWalletLink(\n\tclient: AgentChatClient,\n\topts?: { enabled?: boolean },\n) {\n\tconst enabled = opts?.enabled ?? true;\n\tconst [linked, setLinked] = useState<boolean | null>(null);\n\tconst [isWorking, setIsWorking] = 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\tsetError(null);\n\t\ttry {\n\t\t\tconst status = await client.getLinkStatus();\n\t\t\tif (mountedRef.current) setLinked(status.linked);\n\t\t} catch (err) {\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\tsetLinked(null);\n\t\t\t}\n\t\t}\n\t}, [client]);\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\t// Pre-auth: unknown status, and any earlier pre-auth failure is noise.\n\t\t\tsetLinked(null);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\t\tvoid refresh();\n\t}, [refresh, enabled]);\n\n\tconst link = useCallback(\n\t\tasync (opts?: { force?: boolean; code?: string }) => {\n\t\t\tsetIsWorking(true);\n\t\t\tsetError(null);\n\t\t\ttry {\n\t\t\t\tconst out = await client.linkWallet(opts);\n\t\t\t\tif (mountedRef.current) setLinked(out.linked);\n\t\t\t\treturn out;\n\t\t\t} catch (err) {\n\t\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\t\tif (mountedRef.current) setError(e);\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\tif (mountedRef.current) setIsWorking(false);\n\t\t\t}\n\t\t},\n\t\t[client],\n\t);\n\n\tconst unlink = useCallback(async () => {\n\t\tsetIsWorking(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst out = await client.unlinkWallet();\n\t\t\tif (mountedRef.current) setLinked(false);\n\t\t\treturn out;\n\t\t} catch (err) {\n\t\t\tconst e = err instanceof Error ? err : new Error(String(err));\n\t\t\tif (mountedRef.current) setError(e);\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tif (mountedRef.current) setIsWorking(false);\n\t\t}\n\t}, [client]);\n\n\treturn { linked, isWorking, error, link, unlink, refresh };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pear-protocol/agent-sdk",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,