@tangle-network/sandbox-ui 0.2.1 → 0.3.3

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.
Files changed (68) hide show
  1. package/README.md +201 -10
  2. package/dist/auth.js +2 -2
  3. package/dist/chat-container-C8eHLw8z.d.ts +67 -0
  4. package/dist/chat.d.ts +70 -78
  5. package/dist/chat.js +8 -8
  6. package/dist/chunk-4F2GJRGU.js +756 -0
  7. package/dist/{chunk-HYEAX3DC.js → chunk-5LV6DZZF.js} +445 -114
  8. package/dist/chunk-67C53XVV.js +1106 -0
  9. package/dist/{chunk-QSQBDR3N.js → chunk-BX6AQMUS.js} +5 -2
  10. package/dist/chunk-CCKNIAS7.js +124 -0
  11. package/dist/chunk-CJ2RYVZH.js +128 -0
  12. package/dist/{chunk-KMXV7DDX.js → chunk-CNWVHQFY.js} +1 -1
  13. package/dist/{chunk-OU4TRNQZ.js → chunk-COCSO7FG.js} +3 -3
  14. package/dist/chunk-FJSVPBKY.js +85 -0
  15. package/dist/chunk-FRGMMANX.js +102 -0
  16. package/dist/{chunk-E6FS7R4X.js → chunk-HWLX5NME.js} +1 -1
  17. package/dist/chunk-JF6E2DS5.js +610 -0
  18. package/dist/chunk-MUOL44AE.js +121 -0
  19. package/dist/chunk-MXCSSOGH.js +105 -0
  20. package/dist/{chunk-J4OADEUK.js → chunk-OM6ON27W.js} +24 -9
  21. package/dist/{chunk-NI2EI43H.js → chunk-PDV7W4NY.js} +9 -124
  22. package/dist/chunk-TQN3VR4F.js +92 -0
  23. package/dist/{chunk-SOT2V7TX.js → chunk-TXI4MZAZ.js} +62 -144
  24. package/dist/chunk-WUR652Y3.js +1140 -0
  25. package/dist/chunk-YDBXQQLC.js +336 -0
  26. package/dist/{chunk-4EIWPJMJ.js → chunk-ZP6GSX4D.js} +36 -27
  27. package/dist/dashboard.d.ts +5 -2
  28. package/dist/dashboard.js +5 -4
  29. package/dist/{expanded-tool-detail-OkXGqTHe.d.ts → expanded-tool-detail-BDi_h_dZ.d.ts} +11 -4
  30. package/dist/file-tabs-CmaoDVBI.d.ts +72 -0
  31. package/dist/files.d.ts +25 -44
  32. package/dist/files.js +8 -3
  33. package/{src/styles → dist}/globals.css +16 -67
  34. package/dist/hooks.d.ts +5 -4
  35. package/dist/hooks.js +14 -9
  36. package/dist/index.d.ts +38 -9
  37. package/dist/index.js +100 -126
  38. package/dist/markdown.d.ts +1 -24
  39. package/dist/markdown.js +1 -7
  40. package/dist/openui.d.ts +115 -0
  41. package/dist/openui.js +11 -0
  42. package/dist/pages.d.ts +3 -2
  43. package/dist/pages.js +19 -16
  44. package/dist/primitives.d.ts +8 -1
  45. package/dist/primitives.js +25 -19
  46. package/dist/run.d.ts +2 -2
  47. package/dist/run.js +8 -7
  48. package/dist/{use-sidecar-auth-Bb0-w3lX.d.ts → sdk-hooks.d.ts} +61 -72
  49. package/dist/sdk-hooks.js +29 -0
  50. package/dist/styles.css +179 -0
  51. package/dist/tokens.css +165 -0
  52. package/dist/{tool-display-BvsVW_Ur.d.ts → tool-display-Ct9nFAzJ.d.ts} +1 -1
  53. package/dist/types.d.ts +1 -1
  54. package/dist/{usage-chart-DINgSVL5.d.ts → usage-chart-CY9xo3KX.d.ts} +8 -3
  55. package/dist/use-pty-session-DeZSxOCN.d.ts +69 -0
  56. package/dist/utils.d.ts +1 -1
  57. package/dist/utils.js +1 -1
  58. package/dist/workspace.d.ts +171 -33
  59. package/dist/workspace.js +25 -1
  60. package/package.json +10 -3
  61. package/dist/chunk-2UHPE5T7.js +0 -201
  62. package/dist/chunk-6MQIDUPA.js +0 -502
  63. package/dist/chunk-KYY2X6LY.js +0 -318
  64. package/dist/chunk-L6ZDH5F4.js +0 -334
  65. package/dist/chunk-M34OA6PQ.js +0 -233
  66. package/dist/chunk-M6VLC32S.js +0 -219
  67. package/dist/chunk-U62G5TS7.js +0 -472
  68. package/src/styles/tokens.css +0 -73
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseToolEvent
3
- } from "./chunk-M6VLC32S.js";
3
+ } from "./chunk-CCKNIAS7.js";
4
4
 
5
5
  // src/hooks/use-tool-call-stream.ts
6
6
  import { useState, useCallback, useRef } from "react";
@@ -66,88 +66,8 @@ function useToolCallStream() {
66
66
  return { segments, pushEvent, pushText, completeToolCall, reset };
67
67
  }
68
68
 
69
- // src/hooks/use-auth.ts
70
- import * as React from "react";
71
- function useAuth({
72
- apiBaseUrl,
73
- revalidateOnFocus = false,
74
- shouldRetryOnError = false
75
- }) {
76
- const [user, setUser] = React.useState(null);
77
- const [isLoading, setIsLoading] = React.useState(true);
78
- const [error, setError] = React.useState(null);
79
- const fetchSession = React.useCallback(async () => {
80
- setIsLoading(true);
81
- setError(null);
82
- try {
83
- const res = await fetch(`${apiBaseUrl}/auth/session`, {
84
- credentials: "include"
85
- });
86
- if (!res.ok) {
87
- throw new Error("Not authenticated");
88
- }
89
- const data = await res.json();
90
- if (data.success && data.data) {
91
- setUser(data.data);
92
- } else {
93
- setUser(null);
94
- }
95
- } catch (err) {
96
- setError(err instanceof Error ? err : new Error("Unknown error"));
97
- setUser(null);
98
- if (shouldRetryOnError) {
99
- setTimeout(fetchSession, 5e3);
100
- }
101
- } finally {
102
- setIsLoading(false);
103
- }
104
- }, [apiBaseUrl, shouldRetryOnError]);
105
- React.useEffect(() => {
106
- fetchSession();
107
- }, [fetchSession]);
108
- React.useEffect(() => {
109
- if (!revalidateOnFocus) return;
110
- const handleFocus = () => {
111
- fetchSession();
112
- };
113
- window.addEventListener("focus", handleFocus);
114
- return () => window.removeEventListener("focus", handleFocus);
115
- }, [revalidateOnFocus, fetchSession]);
116
- return {
117
- user,
118
- isLoading,
119
- isError: !!error,
120
- error,
121
- mutate: fetchSession
122
- };
123
- }
124
- function createAuthFetcher(_apiBaseUrl) {
125
- return async function authFetcher(url, options) {
126
- const res = await fetch(url, {
127
- ...options,
128
- credentials: "include",
129
- headers: {
130
- ...options?.headers
131
- }
132
- });
133
- if (!res.ok) {
134
- throw new Error(`Request failed with status ${res.status}`);
135
- }
136
- return res.json();
137
- };
138
- }
139
- function useApiKey() {
140
- const [apiKey, setApiKey] = React.useState(null);
141
- React.useEffect(() => {
142
- if (typeof window !== "undefined") {
143
- setApiKey(localStorage.getItem("apiKey"));
144
- }
145
- }, []);
146
- return apiKey;
147
- }
148
-
149
69
  // src/hooks/use-sse-stream.ts
150
- import * as React2 from "react";
70
+ import * as React from "react";
151
71
  function useSSEStream(options) {
152
72
  const {
153
73
  url,
@@ -162,27 +82,27 @@ function useSSEStream(options) {
162
82
  headers,
163
83
  enabled = true
164
84
  } = options;
165
- const [state, setState] = React2.useState("disconnected");
166
- const [events, setEvents] = React2.useState([]);
167
- const [lastEvent, setLastEvent] = React2.useState(null);
168
- const [error, setError] = React2.useState(null);
169
- const [retryCount, setRetryCount] = React2.useState(0);
170
- const [lastEventTime, setLastEventTime] = React2.useState(Date.now());
171
- const [timeSinceLastEvent, setTimeSinceLastEvent] = React2.useState(0);
172
- const eventSourceRef = React2.useRef(null);
173
- const abortControllerRef = React2.useRef(null);
174
- const reconnectTimeoutRef = React2.useRef(null);
175
- const lastEventIdRef = React2.useRef(void 0);
176
- React2.useEffect(() => {
85
+ const [state, setState] = React.useState("disconnected");
86
+ const [events, setEvents] = React.useState([]);
87
+ const [lastEvent, setLastEvent] = React.useState(null);
88
+ const [error, setError] = React.useState(null);
89
+ const [retryCount, setRetryCount] = React.useState(0);
90
+ const [lastEventTime, setLastEventTime] = React.useState(Date.now());
91
+ const [timeSinceLastEvent, setTimeSinceLastEvent] = React.useState(0);
92
+ const eventSourceRef = React.useRef(null);
93
+ const abortControllerRef = React.useRef(null);
94
+ const reconnectTimeoutRef = React.useRef(null);
95
+ const lastEventIdRef = React.useRef(void 0);
96
+ React.useEffect(() => {
177
97
  const interval = setInterval(() => {
178
98
  setTimeSinceLastEvent(Date.now() - lastEventTime);
179
99
  }, 1e3);
180
100
  return () => clearInterval(interval);
181
101
  }, [lastEventTime]);
182
- React2.useEffect(() => {
102
+ React.useEffect(() => {
183
103
  onStateChange?.(state);
184
104
  }, [state, onStateChange]);
185
- const handleEvent = React2.useCallback(
105
+ const handleEvent = React.useCallback(
186
106
  (eventType, data, id) => {
187
107
  const event = {
188
108
  id,
@@ -200,7 +120,7 @@ function useSSEStream(options) {
200
120
  },
201
121
  [onEvent]
202
122
  );
203
- const disconnect = React2.useCallback(() => {
123
+ const disconnect = React.useCallback(() => {
204
124
  if (reconnectTimeoutRef.current) {
205
125
  clearTimeout(reconnectTimeoutRef.current);
206
126
  reconnectTimeoutRef.current = null;
@@ -215,7 +135,7 @@ function useSSEStream(options) {
215
135
  }
216
136
  setState("disconnected");
217
137
  }, []);
218
- const connect = React2.useCallback(() => {
138
+ const connect = React.useCallback(() => {
219
139
  disconnect();
220
140
  if (!url || !enabled) {
221
141
  return;
@@ -388,13 +308,13 @@ function useSSEStream(options) {
388
308
  onError,
389
309
  disconnect
390
310
  ]);
391
- React2.useEffect(() => {
311
+ React.useEffect(() => {
392
312
  if (enabled) {
393
313
  connect();
394
314
  }
395
315
  return () => disconnect();
396
316
  }, [enabled, connect, disconnect]);
397
- const clearEvents = React2.useCallback(() => {
317
+ const clearEvents = React.useCallback(() => {
398
318
  setEvents([]);
399
319
  setLastEvent(null);
400
320
  }, []);
@@ -411,8 +331,421 @@ function useSSEStream(options) {
411
331
  };
412
332
  }
413
333
 
334
+ // src/hooks/use-sdk-session.ts
335
+ import { useCallback as useCallback3, useMemo, useRef as useRef3, useState as useState3 } from "react";
336
+ function uid() {
337
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
338
+ return crypto.randomUUID();
339
+ }
340
+ return `sdk-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
341
+ }
342
+ function toMillis(value) {
343
+ if (value == null) return void 0;
344
+ if (typeof value === "number") return value;
345
+ if (value instanceof Date) return value.getTime();
346
+ const millis = new Date(value).getTime();
347
+ return Number.isFinite(millis) ? millis : void 0;
348
+ }
349
+ function asRecord(value) {
350
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
351
+ }
352
+ function asString(value) {
353
+ return typeof value === "string" && value.length > 0 ? value : void 0;
354
+ }
355
+ function textPartsFromContent(content, attachments) {
356
+ const attachmentText = attachments?.length ? `
357
+
358
+ Attachments:
359
+ ${attachments.map((attachment) => `- ${attachment.name}`).join("\n")}` : "";
360
+ const text = `${content}${attachmentText}`.trim();
361
+ return text ? [{ type: "text", text }] : [];
362
+ }
363
+ function normalizeTime(value) {
364
+ const record = asRecord(value);
365
+ if (!record) return void 0;
366
+ const start = Number(record.start ?? record.startedAt ?? record.started_at);
367
+ const end = Number(record.end ?? record.completedAt ?? record.completed_at);
368
+ if (!Number.isFinite(start) && !Number.isFinite(end)) {
369
+ return void 0;
370
+ }
371
+ return {
372
+ start: Number.isFinite(start) ? start : void 0,
373
+ end: Number.isFinite(end) ? end : void 0
374
+ };
375
+ }
376
+ function normalizeStatus(value, output, error) {
377
+ if (value === "pending" || value === "running" || value === "completed" || value === "error") {
378
+ return value;
379
+ }
380
+ if (typeof error === "string" && error.length > 0) {
381
+ return "error";
382
+ }
383
+ if (output !== void 0) {
384
+ return "completed";
385
+ }
386
+ return "running";
387
+ }
388
+ function resolveToolIdentity(rawPart) {
389
+ return String(
390
+ rawPart.id ?? rawPart.callID ?? rawPart.callId ?? rawPart.toolUseId ?? rawPart.toolCallId ?? rawPart.tool ?? rawPart.name ?? "tool"
391
+ );
392
+ }
393
+ function normalizePart(rawPart) {
394
+ const type = String(rawPart.type ?? "");
395
+ if (type === "text") {
396
+ return {
397
+ type: "text",
398
+ text: asString(rawPart.text) ?? asString(rawPart.content) ?? ""
399
+ };
400
+ }
401
+ if (type === "reasoning") {
402
+ return {
403
+ type: "reasoning",
404
+ text: asString(rawPart.text) ?? asString(rawPart.content) ?? "",
405
+ time: normalizeTime(rawPart.time)
406
+ };
407
+ }
408
+ if (type === "tool") {
409
+ const stateRecord = asRecord(rawPart.state);
410
+ const input = stateRecord?.input ?? rawPart.input;
411
+ const output = stateRecord?.output ?? rawPart.output;
412
+ const error = stateRecord?.error ?? rawPart.error;
413
+ return {
414
+ type: "tool",
415
+ id: resolveToolIdentity(rawPart),
416
+ tool: String(rawPart.tool ?? rawPart.name ?? "tool"),
417
+ callID: rawPart.callID != null || rawPart.callId != null ? String(rawPart.callID ?? rawPart.callId) : void 0,
418
+ state: {
419
+ status: normalizeStatus(stateRecord?.status ?? rawPart.status, output, error),
420
+ input,
421
+ output,
422
+ error: typeof error === "string" ? error : void 0,
423
+ metadata: asRecord(stateRecord?.metadata) ?? asRecord(rawPart.metadata),
424
+ time: normalizeTime(stateRecord?.time ?? rawPart.time)
425
+ }
426
+ };
427
+ }
428
+ return null;
429
+ }
430
+ function getPartKey(rawPart) {
431
+ const type = String(rawPart.type ?? "unknown");
432
+ if (type === "tool") {
433
+ return `tool:${resolveToolIdentity(rawPart)}`;
434
+ }
435
+ if (type === "reasoning") {
436
+ return `reasoning:${String(rawPart.id ?? rawPart.partId ?? rawPart.index ?? "current")}`;
437
+ }
438
+ return `text:${String(rawPart.id ?? rawPart.partId ?? rawPart.index ?? "current")}`;
439
+ }
440
+ function mergePart(existing, incoming, delta) {
441
+ if (!existing) {
442
+ if (incoming.type === "text" && delta) {
443
+ return { type: "text", text: delta };
444
+ }
445
+ return incoming;
446
+ }
447
+ if (existing.type === "text" && incoming.type === "text") {
448
+ return {
449
+ type: "text",
450
+ text: delta ? `${existing.text}${delta}` : incoming.text,
451
+ synthetic: incoming.synthetic ?? existing.synthetic
452
+ };
453
+ }
454
+ if (existing.type === "reasoning" && incoming.type === "reasoning") {
455
+ return {
456
+ ...existing,
457
+ ...incoming,
458
+ text: delta && incoming.text === existing.text ? `${existing.text}${delta}` : incoming.text || existing.text,
459
+ time: incoming.time ?? existing.time
460
+ };
461
+ }
462
+ if (existing.type === "tool" && incoming.type === "tool") {
463
+ return {
464
+ ...existing,
465
+ ...incoming,
466
+ state: {
467
+ ...existing.state,
468
+ ...incoming.state,
469
+ time: incoming.state.time ?? existing.state.time
470
+ }
471
+ };
472
+ }
473
+ return incoming;
474
+ }
475
+ function mapSeeds(messages) {
476
+ return {
477
+ messages: messages.map((message, index) => ({
478
+ id: message.id,
479
+ role: message.role,
480
+ _insertionIndex: index,
481
+ time: {
482
+ created: toMillis(message.createdAt) ?? Date.now()
483
+ }
484
+ })),
485
+ partMap: Object.fromEntries(
486
+ messages.map((message) => [
487
+ message.id,
488
+ message.parts ?? textPartsFromContent(message.content ?? "", message.attachments)
489
+ ])
490
+ )
491
+ };
492
+ }
493
+ function useSdkSession({
494
+ initialMessages = []
495
+ } = {}) {
496
+ const initialConversation = useMemo(
497
+ () => mapSeeds(initialMessages),
498
+ [initialMessages]
499
+ );
500
+ const [conversation, setConversation] = useState3(initialConversation);
501
+ const [isStreaming, setIsStreaming] = useState3(false);
502
+ const activeAssistantIdRef = useRef3(null);
503
+ const insertionIndexRef = useRef3(initialConversation.messages.length);
504
+ const partIndexRef = useRef3({});
505
+ const replaceHistory = useCallback3((messages) => {
506
+ const next = mapSeeds(messages);
507
+ setConversation(next);
508
+ setIsStreaming(false);
509
+ activeAssistantIdRef.current = null;
510
+ insertionIndexRef.current = next.messages.length;
511
+ partIndexRef.current = {};
512
+ }, []);
513
+ const appendUserMessage = useCallback3(
514
+ ({
515
+ id = uid(),
516
+ role = "user",
517
+ content,
518
+ createdAt,
519
+ attachments
520
+ }) => {
521
+ setConversation((prev) => ({
522
+ messages: [
523
+ ...prev.messages,
524
+ {
525
+ id,
526
+ role,
527
+ _insertionIndex: insertionIndexRef.current++,
528
+ time: {
529
+ created: toMillis(createdAt) ?? Date.now()
530
+ }
531
+ }
532
+ ],
533
+ partMap: {
534
+ ...prev.partMap,
535
+ [id]: textPartsFromContent(content, attachments)
536
+ }
537
+ }));
538
+ return id;
539
+ },
540
+ []
541
+ );
542
+ const beginAssistantMessage = useCallback3(
543
+ ({
544
+ id = uid(),
545
+ role = "assistant",
546
+ createdAt
547
+ } = {}) => {
548
+ setConversation((prev) => ({
549
+ messages: [
550
+ ...prev.messages,
551
+ {
552
+ id,
553
+ role,
554
+ _insertionIndex: insertionIndexRef.current++,
555
+ time: {
556
+ created: toMillis(createdAt) ?? Date.now()
557
+ }
558
+ }
559
+ ],
560
+ partMap: {
561
+ ...prev.partMap,
562
+ [id]: prev.partMap[id] ?? []
563
+ }
564
+ }));
565
+ activeAssistantIdRef.current = id;
566
+ partIndexRef.current[id] = partIndexRef.current[id] ?? {};
567
+ setIsStreaming(true);
568
+ return id;
569
+ },
570
+ []
571
+ );
572
+ const completeAssistantMessage = useCallback3(
573
+ ({ messageId, finalText } = {}) => {
574
+ const targetId = messageId ?? activeAssistantIdRef.current;
575
+ if (!targetId) {
576
+ setIsStreaming(false);
577
+ return;
578
+ }
579
+ if (finalText) {
580
+ setConversation((prev) => {
581
+ const existingParts = prev.partMap[targetId] ?? [];
582
+ const nextParts = [...existingParts];
583
+ const textIndex = nextParts.findIndex((part) => part.type === "text");
584
+ if (textIndex === -1) {
585
+ nextParts.push({ type: "text", text: finalText });
586
+ } else {
587
+ nextParts[textIndex] = { type: "text", text: finalText };
588
+ }
589
+ return {
590
+ ...prev,
591
+ partMap: {
592
+ ...prev.partMap,
593
+ [targetId]: nextParts
594
+ }
595
+ };
596
+ });
597
+ }
598
+ delete partIndexRef.current[targetId];
599
+ if (activeAssistantIdRef.current === targetId) {
600
+ activeAssistantIdRef.current = null;
601
+ }
602
+ setIsStreaming(false);
603
+ },
604
+ []
605
+ );
606
+ const failAssistantMessage = useCallback3(
607
+ (error, options) => {
608
+ const targetId = options?.messageId ?? activeAssistantIdRef.current;
609
+ if (!targetId) {
610
+ setIsStreaming(false);
611
+ return;
612
+ }
613
+ setConversation((prev) => ({
614
+ ...prev,
615
+ partMap: {
616
+ ...prev.partMap,
617
+ [targetId]: [{ type: "text", text: `Error: ${error}` }]
618
+ }
619
+ }));
620
+ delete partIndexRef.current[targetId];
621
+ if (activeAssistantIdRef.current === targetId) {
622
+ activeAssistantIdRef.current = null;
623
+ }
624
+ setIsStreaming(false);
625
+ },
626
+ []
627
+ );
628
+ const applySdkEvent = useCallback3(
629
+ (event, options) => {
630
+ const eventData = asRecord(event.data) ?? {};
631
+ if (event.type === "message.updated") {
632
+ const id = asString(eventData.id) ?? asString(eventData.messageId) ?? options?.messageId;
633
+ const role = asString(eventData.role) ?? "assistant";
634
+ if (!id) {
635
+ return;
636
+ }
637
+ setConversation((prev) => {
638
+ if (prev.messages.some((message) => message.id === id)) {
639
+ return prev;
640
+ }
641
+ return {
642
+ ...prev,
643
+ messages: [
644
+ ...prev.messages,
645
+ {
646
+ id,
647
+ role,
648
+ _insertionIndex: insertionIndexRef.current++,
649
+ time: { created: Date.now() }
650
+ }
651
+ ],
652
+ partMap: {
653
+ ...prev.partMap,
654
+ [id]: prev.partMap[id] ?? []
655
+ }
656
+ };
657
+ });
658
+ if (role === "assistant" || role === "system") {
659
+ activeAssistantIdRef.current = id;
660
+ partIndexRef.current[id] = partIndexRef.current[id] ?? {};
661
+ setIsStreaming(true);
662
+ }
663
+ return;
664
+ }
665
+ if (event.type === "message.part.updated") {
666
+ const rawPart = asRecord(eventData.part) ?? eventData;
667
+ const targetId = options?.messageId ?? activeAssistantIdRef.current;
668
+ const delta = asString(eventData.delta);
669
+ if (!targetId || !rawPart) {
670
+ return;
671
+ }
672
+ const normalizedPart = normalizePart(rawPart);
673
+ if (!normalizedPart) {
674
+ return;
675
+ }
676
+ const key = getPartKey(rawPart);
677
+ setConversation((prev) => {
678
+ const existingParts = prev.partMap[targetId] ?? [];
679
+ const nextParts = [...existingParts];
680
+ const indexMap = partIndexRef.current[targetId] ?? (partIndexRef.current[targetId] = {});
681
+ const existingIndex = indexMap[key];
682
+ if (existingIndex == null) {
683
+ indexMap[key] = nextParts.length;
684
+ nextParts.push(mergePart(void 0, normalizedPart, delta));
685
+ } else {
686
+ nextParts[existingIndex] = mergePart(
687
+ nextParts[existingIndex],
688
+ normalizedPart,
689
+ delta
690
+ );
691
+ }
692
+ return {
693
+ ...prev,
694
+ partMap: {
695
+ ...prev.partMap,
696
+ [targetId]: nextParts
697
+ }
698
+ };
699
+ });
700
+ activeAssistantIdRef.current = targetId;
701
+ setIsStreaming(true);
702
+ return;
703
+ }
704
+ if (event.type === "result") {
705
+ completeAssistantMessage({
706
+ messageId: options?.messageId,
707
+ finalText: asString(eventData.finalText)
708
+ });
709
+ return;
710
+ }
711
+ if (event.type === "done") {
712
+ completeAssistantMessage({ messageId: options?.messageId });
713
+ return;
714
+ }
715
+ if (event.type === "error") {
716
+ failAssistantMessage(
717
+ asString(eventData.message) ?? "Agent error",
718
+ { messageId: options?.messageId }
719
+ );
720
+ }
721
+ },
722
+ [completeAssistantMessage, failAssistantMessage]
723
+ );
724
+ const reset = useCallback3(() => {
725
+ setConversation({ messages: [], partMap: {} });
726
+ setIsStreaming(false);
727
+ activeAssistantIdRef.current = null;
728
+ insertionIndexRef.current = 0;
729
+ partIndexRef.current = {};
730
+ }, []);
731
+ return {
732
+ messages: conversation.messages,
733
+ partMap: conversation.partMap,
734
+ isStreaming,
735
+ activeAssistantMessageId: activeAssistantIdRef.current,
736
+ replaceHistory,
737
+ appendUserMessage,
738
+ beginAssistantMessage,
739
+ applySdkEvent,
740
+ completeAssistantMessage,
741
+ failAssistantMessage,
742
+ setStreaming: setIsStreaming,
743
+ reset
744
+ };
745
+ }
746
+
414
747
  // src/hooks/use-session-stream.ts
415
- import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
748
+ import { useCallback as useCallback4, useEffect as useEffect2, useRef as useRef4, useState as useState4 } from "react";
416
749
  var _insertionCounter = 0;
417
750
  function mapApiMessage(msg) {
418
751
  const created = msg.info.timestamp ? new Date(msg.info.timestamp).getTime() : Date.now();
@@ -467,8 +800,8 @@ function useSessionStream({
467
800
  const [isStreaming, setIsStreaming] = useState4(false);
468
801
  const [error, setError] = useState4(null);
469
802
  const [connected, setConnected] = useState4(false);
470
- const abortRef = useRef3(null);
471
- const streamingMsgIdRef = useRef3(null);
803
+ const abortRef = useRef4(null);
804
+ const streamingMsgIdRef = useRef4(null);
472
805
  const refetch = useCallback4(async () => {
473
806
  if (!token || !sessionId || !apiUrl) return;
474
807
  try {
@@ -655,7 +988,7 @@ function useSessionStream({
655
988
  setError(msg);
656
989
  }
657
990
  }, [apiUrl, token, sessionId]);
658
- useEffect3(() => {
991
+ useEffect2(() => {
659
992
  if (!enabled || !token || !sessionId) return;
660
993
  refetch();
661
994
  connectSSE();
@@ -668,12 +1001,12 @@ function useSessionStream({
668
1001
  }
669
1002
 
670
1003
  // src/hooks/use-dropdown-menu.ts
671
- import { useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
1004
+ import { useEffect as useEffect3, useRef as useRef5, useState as useState5 } from "react";
672
1005
  function useDropdownMenu(options) {
673
1006
  const closeOnEsc = options?.closeOnEsc ?? true;
674
1007
  const [open, setOpen] = useState5(false);
675
- const ref = useRef4(null);
676
- useEffect4(() => {
1008
+ const ref = useRef5(null);
1009
+ useEffect3(() => {
677
1010
  function handleClick(e) {
678
1011
  if (ref.current && !ref.current.contains(e.target)) {
679
1012
  setOpen(false);
@@ -684,7 +1017,7 @@ function useDropdownMenu(options) {
684
1017
  }
685
1018
  return () => document.removeEventListener("mousedown", handleClick);
686
1019
  }, [open]);
687
- useEffect4(() => {
1020
+ useEffect3(() => {
688
1021
  if (!open || !closeOnEsc) return;
689
1022
  function handleKey(e) {
690
1023
  if (e.key === "Escape") setOpen(false);
@@ -702,7 +1035,7 @@ function useDropdownMenu(options) {
702
1035
  }
703
1036
 
704
1037
  // src/hooks/use-sidecar-auth.ts
705
- import { useState as useState6, useCallback as useCallback5, useEffect as useEffect5, useRef as useRef5 } from "react";
1038
+ import { useState as useState6, useCallback as useCallback5, useEffect as useEffect4, useRef as useRef6 } from "react";
706
1039
  function storageKey(resourceId, apiUrl) {
707
1040
  return `sidecar_session_${resourceId}__${apiUrl}`;
708
1041
  }
@@ -738,7 +1071,7 @@ function useSidecarAuth({ resourceId, apiUrl, signMessage }) {
738
1071
  const [expiresAt, setExpiresAt] = useState6(cached?.expiresAt ?? 0);
739
1072
  const [isAuthenticating, setIsAuthenticating] = useState6(false);
740
1073
  const [error, setError] = useState6(null);
741
- const refreshTimerRef = useRef5(void 0);
1074
+ const refreshTimerRef = useRef6(void 0);
742
1075
  const clearCachedToken = useCallback5(() => {
743
1076
  setToken(null);
744
1077
  setExpiresAt(0);
@@ -779,7 +1112,7 @@ function useSidecarAuth({ resourceId, apiUrl, signMessage }) {
779
1112
  setIsAuthenticating(false);
780
1113
  }
781
1114
  }, [resourceId, apiUrl, signMessage, clearCachedToken]);
782
- useEffect5(() => {
1115
+ useEffect4(() => {
783
1116
  if (refreshTimerRef.current) {
784
1117
  clearTimeout(refreshTimerRef.current);
785
1118
  }
@@ -812,10 +1145,8 @@ function useSidecarAuth({ resourceId, apiUrl, signMessage }) {
812
1145
 
813
1146
  export {
814
1147
  useToolCallStream,
815
- useAuth,
816
- createAuthFetcher,
817
- useApiKey,
818
1148
  useSSEStream,
1149
+ useSdkSession,
819
1150
  useSessionStream,
820
1151
  useDropdownMenu,
821
1152
  useSidecarAuth