@workerdeck/react 3.3.0 → 3.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.
package/build/index.d.mts CHANGED
@@ -47,6 +47,7 @@ type TranscriptItem = {
47
47
  executionId?: string;
48
48
  backend?: ToolExecutionBackend;
49
49
  logs?: string[];
50
+ liveTail?: string;
50
51
  } | {
51
52
  kind: 'turn_result';
52
53
  id: string;
@@ -93,7 +94,9 @@ type ProducedFileRef = {
93
94
  type TranscriptState = {
94
95
  status: SessionStatus;
95
96
  statusDetail?: string;
97
+ engineAsleep?: boolean;
96
98
  model?: string;
99
+ effort?: string | null;
97
100
  cwd?: string;
98
101
  sdkSessionId?: string;
99
102
  engine?: ProfileEngine;
@@ -157,10 +160,12 @@ type UseClaudeSessionResult = {
157
160
  approve: (requestId: string, updatedInput?: Record<string, unknown>) => void;
158
161
  deny: (requestId: string, message?: string, interrupt?: boolean) => void;
159
162
  interrupt: () => void;
163
+ backgroundTask: (toolUseId?: string) => void;
160
164
  clearContext: () => void;
161
165
  runShell: (command: string) => void;
162
166
  setPermissionMode: (mode: PermissionMode) => void;
163
167
  setModel: (model?: string) => void;
168
+ setEffort: (effort?: string) => void;
164
169
  closeSession: () => void;
165
170
  reconnectNow: () => void;
166
171
  loadFullResult: (toolUseId: string) => Promise<boolean>;
@@ -272,6 +277,7 @@ type PeerSessionOption = {
272
277
  id: string;
273
278
  slug: string;
274
279
  label: string;
280
+ gateway?: string;
275
281
  engine?: SessionInfo['engine'];
276
282
  status: SessionInfo['status'];
277
283
  cwd: string;
package/build/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
2
2
  import { WorkerDeckError } from "@workerdeck/client";
3
- import { DEFAULT_PRICING, ENGINE_CAPABILITIES, PEER_MENTION_SIGIL, PROMPT_SENTENCE_TAIL, PROTOCOL_VERSION, errorMessage, isPeerMentionBody, mergePricing, mergeUsage, orderUsageWindows, peerMentionKey, peerMentionSlug, sessionLabel } from "@workerdeck/protocol";
3
+ import { DEFAULT_PRICING, ENGINE_CAPABILITIES, PEER_MENTION_SIGIL, PROMPT_SENTENCE_TAIL, PROTOCOL_VERSION, errorMessage, isPeerMentionBody, mergePricing, mergeUsage, orderUsageWindows, peerMentionKey, peerMentionSlug } from "@workerdeck/protocol";
4
4
  //#region src/lib/transcript.ts
5
5
  const initialTranscriptState = {
6
6
  status: "starting",
@@ -115,7 +115,9 @@ function seedFromSessionInfo(state, info) {
115
115
  return {
116
116
  ...state,
117
117
  status: state.lastSeq === 0 ? info.status : state.status,
118
+ engineAsleep: state.lastSeq === 0 ? info.engineAsleep : state.engineAsleep,
118
119
  model: state.model ?? info.model,
120
+ effort: state.effort !== void 0 ? state.effort : info.effort,
119
121
  permissionMode: state.permissionMode ?? info.permissionMode,
120
122
  cwd: state.cwd ?? info.cwd,
121
123
  sdkSessionId: state.sdkSessionId ?? info.sdkSessionId,
@@ -199,6 +201,10 @@ function applyEvent(state, event) {
199
201
  status: event.status,
200
202
  statusDetail: event.detail
201
203
  };
204
+ case "engine_sleep": return {
205
+ ...base,
206
+ engineAsleep: event.asleep || void 0
207
+ };
202
208
  case "capabilities": return {
203
209
  ...base,
204
210
  models: event.models,
@@ -235,6 +241,10 @@ function applyEvent(state, event) {
235
241
  ...base,
236
242
  model: event.model
237
243
  };
244
+ case "effort_changed": return {
245
+ ...base,
246
+ effort: event.effort
247
+ };
238
248
  case "permission_mode_changed": return {
239
249
  ...base,
240
250
  permissionMode: event.mode
@@ -261,7 +271,12 @@ function applyEvent(state, event) {
261
271
  };
262
272
  case "conversation_reset": return {
263
273
  ...base,
264
- items: [],
274
+ items: event.agentReason === void 0 ? [] : [{
275
+ kind: "notice",
276
+ id: `reset-${event.seq}`,
277
+ level: "info",
278
+ text: agentResetNotice(event.agentReason)
279
+ }],
265
280
  contextUsage: void 0,
266
281
  checklist: void 0,
267
282
  sdkSessionId: event.sdkSessionId ?? base.sdkSessionId
@@ -286,6 +301,7 @@ function applyEvent(state, event) {
286
301
  const isError = toolResult.is_error === true;
287
302
  items = items.map((item) => item.kind === "tool_call" && item.id === toolResult.tool_use_id ? {
288
303
  ...item,
304
+ liveTail: void 0,
289
305
  status: isError ? "failed" : "settled",
290
306
  result: {
291
307
  text: blockText(toolResult.content),
@@ -447,6 +463,20 @@ function applyEvent(state, event) {
447
463
  ...base,
448
464
  pendingApprovals: base.pendingApprovals.filter((r) => r.id !== event.requestId)
449
465
  };
466
+ case "tool_output": {
467
+ const at = base.items.findIndex((item) => item.kind === "tool_call" && item.id === event.toolUseId);
468
+ const target = base.items[at];
469
+ if (target?.kind !== "tool_call" || target.status !== "running" && target.status !== "pending" || target.liveTail === event.tail) return base;
470
+ const items = base.items.slice();
471
+ items[at] = {
472
+ ...target,
473
+ liveTail: event.tail
474
+ };
475
+ return {
476
+ ...base,
477
+ items
478
+ };
479
+ }
450
480
  case "execution_dispatched": return {
451
481
  ...base,
452
482
  items: base.items.map((item) => item.kind === "tool_call" && item.id === event.executionId ? {
@@ -513,6 +543,9 @@ function applyEvent(state, event) {
513
543
  default: return base;
514
544
  }
515
545
  }
546
+ function agentResetNotice(reason) {
547
+ return `The agent cleared its context: ${reason}`;
548
+ }
516
549
  //#endregion
517
550
  //#region src/lib/transcript-cache.ts
518
551
  const MAX_ENTRIES = 5;
@@ -772,10 +805,12 @@ function useClaudeSession(client, sessionId, options) {
772
805
  approve: (requestId, updatedInput) => handleRef.current?.approve(requestId, updatedInput),
773
806
  deny: (requestId, message, interrupt) => handleRef.current?.deny(requestId, message, interrupt),
774
807
  interrupt: () => handleRef.current?.interrupt(),
808
+ backgroundTask: (toolUseId) => handleRef.current?.backgroundTask(toolUseId),
775
809
  clearContext: () => handleRef.current?.clearContext(),
776
810
  runShell: (command) => handleRef.current?.runShell(command),
777
811
  setPermissionMode: (mode) => handleRef.current?.setPermissionMode(mode),
778
812
  setModel: (model) => handleRef.current?.setModel(model),
813
+ setEffort: (effort) => handleRef.current?.setEffort(effort),
779
814
  closeSession: () => handleRef.current?.closeSession()
780
815
  }), []);
781
816
  return useMemo(() => ({
@@ -1409,6 +1444,20 @@ function useHostFileTree(client, cwd) {
1409
1444
  }
1410
1445
  //#endregion
1411
1446
  //#region src/hooks/use-peer-sessions.ts
1447
+ function peerSessionOption(row) {
1448
+ const name = row.agent ?? row.title;
1449
+ return {
1450
+ id: row.id,
1451
+ slug: peerMentionSlug(name, row.id),
1452
+ label: name ?? peerMentionSlug(void 0, row.id),
1453
+ gateway: row.gateway,
1454
+ engine: row.engine,
1455
+ status: row.status,
1456
+ cwd: row.cwd,
1457
+ project: row.project,
1458
+ lastActivityAt: row.lastActivityAt
1459
+ };
1460
+ }
1412
1461
  const EMPTY$1 = {
1413
1462
  available: false,
1414
1463
  peers: [],
@@ -1416,16 +1465,16 @@ const EMPTY$1 = {
1416
1465
  };
1417
1466
  const IDLE_MS = 2e4;
1418
1467
  function usePeerSessions(client, sessionId, enabled = true) {
1419
- const [sessions, setSessions] = useState(void 0);
1468
+ const [rows, setRows] = useState(void 0);
1420
1469
  const [unsupported, setUnsupported] = useState(false);
1421
1470
  const alive = useAliveRef();
1422
1471
  useEffect(() => {
1423
- if (!enabled || unsupported) return;
1472
+ setRows(void 0);
1473
+ if (!enabled || unsupported || !sessionId) return;
1424
1474
  let timer;
1425
1475
  const tick = () => {
1426
- client.listSessions().then((rows) => {
1427
- if (!alive.current) return;
1428
- setSessions(rows);
1476
+ client.listPeers(sessionId).then((peers) => {
1477
+ if (alive.current) setRows(peers);
1429
1478
  }).catch((e) => {
1430
1479
  if (alive.current && isRouteUnsupported(e)) setUnsupported(true);
1431
1480
  }).finally(() => {
@@ -1439,20 +1488,12 @@ function usePeerSessions(client, sessionId, enabled = true) {
1439
1488
  }, [
1440
1489
  client,
1441
1490
  enabled,
1491
+ sessionId,
1442
1492
  unsupported
1443
1493
  ]);
1444
1494
  return useMemo(() => {
1445
- if (!enabled || unsupported || !sessions) return EMPTY$1;
1446
- const peers = sessions.filter((info) => info.id !== sessionId).sort((a, b) => (b.lastActivityAt ?? b.createdAt) - (a.lastActivityAt ?? a.createdAt)).map((info) => ({
1447
- id: info.id,
1448
- slug: peerMentionSlug(info.title, info.id),
1449
- label: sessionLabel(info),
1450
- engine: info.engine,
1451
- status: info.status,
1452
- cwd: info.cwd,
1453
- project: info.project?.name,
1454
- lastActivityAt: info.lastActivityAt
1455
- }));
1495
+ if (!enabled || unsupported || !rows) return EMPTY$1;
1496
+ const peers = rows.map(peerSessionOption);
1456
1497
  return {
1457
1498
  available: peers.length > 0,
1458
1499
  peers,
@@ -1460,8 +1501,7 @@ function usePeerSessions(client, sessionId, enabled = true) {
1460
1501
  };
1461
1502
  }, [
1462
1503
  enabled,
1463
- sessionId,
1464
- sessions,
1504
+ rows,
1465
1505
  unsupported
1466
1506
  ]);
1467
1507
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["entries","storage","EMPTY"],"sources":["../src/lib/transcript.ts","../src/lib/transcript-cache.ts","../src/lib/attach-plan.ts","../src/hooks/use-session.ts","../src/lib/profile-usage-cache.ts","../src/lib/draft-store.ts","../src/hooks/use-attachments.ts","../src/lib/prompt-tokens.ts","../src/lib/async-guards.ts","../src/lib/host-tree.ts","../src/hooks/use-host-files.ts","../src/hooks/use-peer-sessions.ts","../src/hooks/use-project-icons.ts","../src/lib/bookmark-store.ts","../src/hooks/use-bookmarks.ts","../src/hooks/use-draft.ts","../src/hooks/use-profile-usage.ts","../src/hooks/use-session-info.ts","../src/lib/open-files.ts","../src/hooks/use-open-files.ts","../src/lib/tool-host.ts","../src/hooks/use-tool-host.ts","../src/lib/recap.ts","../src/hooks/use-shell-terminal.ts"],"sourcesContent":["import { ENGINE_CAPABILITIES, mergeUsage, orderUsageWindows } from '@workerdeck/protocol'\nimport type {\n ApiMessage,\n ByModel,\n ChecklistItem,\n ContentBlock,\n ContextUsage,\n EngineCapabilities,\n FilePatch,\n MessageAttachment,\n MessageOrigin,\n ModelOption,\n PermissionMode,\n PermissionRequest,\n ProfileEngine,\n RateLimitInfo,\n SessionEvent,\n SessionInfo,\n SessionStatus,\n ShellInfo,\n SkillInfo,\n SlashCommandInfo,\n ToolExecutionBackend,\n ToolExecutionOutput,\n ToolResultBlock,\n UsageWindowRow,\n} from '@workerdeck/protocol'\n\nexport type ToolResultImageRef = { partIndex: number; mediaType: string; bytes: number; sourceSeq: number }\n\nexport type TranscriptItem =\n | {\n kind: 'user'\n id: string\n text: string\n attachments?: MessageAttachment[]\n origin?: MessageOrigin\n // Optional, not `string | null` like the other kinds: there forgetting to stamp it must not typecheck; here almost every prompt has no parent.\n parentToolUseId?: string\n }\n | {\n kind: 'assistant_text'\n id: string\n text: string\n streaming: boolean\n parentToolUseId: string | null\n }\n | { kind: 'thinking'; id: string; text: string; parentToolUseId: string | null }\n | {\n kind: 'tool_call'\n id: string\n name: string\n input: unknown\n parentToolUseId: string | null\n // The event's own `ts`, never a receive time - replay-stable, stamped at creation only; absent reads as \"no elapsed\", never as the epoch.\n ts?: number\n status: 'running' | 'pending' | 'deferred' | 'settled' | 'failed'\n result?: {\n text: string\n isError: boolean\n truncated?: boolean\n totalChars?: number\n sourceSeq?: number\n images?: ReadonlyArray<ToolResultImageRef>\n }\n patch?: FilePatch\n executionId?: string\n backend?: ToolExecutionBackend\n logs?: string[]\n }\n | {\n kind: 'turn_result'\n id: string\n subtype: string\n isError: boolean\n durationMs: number\n totalCostUsd: number\n costUsd?: number\n errors?: string[]\n }\n | { kind: 'notice'; id: string; level: 'info' | 'error'; text: string }\n | {\n kind: 'compaction'\n id: string\n parentToolUseId: string | null\n pending?: boolean\n trigger?: 'manual' | 'auto'\n preTokens?: number\n postTokens?: number\n error?: string\n }\n | { kind: 'file_delivered'; id: string; path: string; bytes: number; description?: string }\n | {\n kind: 'shell'\n id: string\n shell: ShellInfo\n text: string\n truncated: boolean\n expanded?: string\n // The record is gone from the gateway: swept past its TTL, or minted by a gateway this client is not talking to.\n missing?: boolean\n }\n\nexport type ProducedFileRef = {\n fileId: string\n mediaType?: string\n bytes?: number\n}\n\nexport type TranscriptState = {\n status: SessionStatus\n statusDetail?: string\n model?: string\n cwd?: string\n sdkSessionId?: string\n engine?: ProfileEngine\n capabilities: EngineCapabilities\n session?: SessionInfo\n models?: ModelOption[]\n commands?: SlashCommandInfo[]\n skills?: SkillInfo[]\n checklist?: ChecklistItem[]\n // Only what the client cannot derive: host- and MCP-declared titles. `toolTitle()` folds the\n // built-in table in on top of this.\n toolTitles?: Record<string, string>\n // Keyed by the absolute path the runner reported: a tool card looks up the `savedPath` in its input and resolves it via `client.producedFileUrl`.\n producedFiles?: Record<string, ProducedFileRef>\n\n defaultModel?: string\n permissionMode?: PermissionMode\n contextUsage?: ContextUsage\n rateLimits?: Record<string, RateLimitInfo>\n rateLimitsUpdatedAt?: number\n subscriptionType?: string\n items: TranscriptItem[]\n pendingApprovals: PermissionRequest[]\n totalCostUsd: number\n costUsd?: number\n usageByModel?: ByModel\n lastSeq: number\n}\n\nexport const initialTranscriptState: TranscriptState = {\n status: 'starting',\n capabilities: ENGINE_CAPABILITIES.claude,\n items: [],\n pendingApprovals: [],\n totalCostUsd: 0,\n lastSeq: 0,\n}\n\nconst STREAMING_ID = 'streaming'\nconst STREAMING_THINKING_ID = 'streaming-thinking'\n\nconst LOCAL_COMMAND_OUTPUT = /^<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>$/\nconst LOCAL_COMMAND_ELEMENT = /<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>/g\nconst LOCAL_COMMAND_CAVEAT = '<local-command-caveat>'\n\nconst SHELL_MORE_OUTPUT = /^\\[\\.\\.\\. more output \\.\\.\\.\\]$/\nconst SHELL_END_LINE = /^\\[(exit -?\\d+|killed|timed out|ended|failed to start)[^\\]]*\\]$/\n\nexport type ShellItem = Extract<TranscriptItem, { kind: 'shell' }>\n\n// The row's text is core's `shellInlineText`: one framed element whose first line is the command and whose\n// last is the end line, both of which the row draws from the record instead.\nexport function shellRowText(shell: ShellInfo, text: string): { text: string; truncated: boolean } {\n const body = LOCAL_COMMAND_OUTPUT.exec(text.trim())?.[2] ?? text\n const lines = body.split('\\n')\n if (lines[0]?.startsWith('$ ')) {\n lines.shift()\n }\n if (shell.status === 'exited' && lines.length > 0 && SHELL_END_LINE.test(lines[lines.length - 1]!)) {\n lines.pop()\n }\n let truncated = false\n const kept = lines.filter((line) => {\n if (!SHELL_MORE_OUTPUT.test(line)) {\n return true\n }\n truncated = true\n return false\n })\n return { text: kept.join('\\n').trimEnd(), truncated }\n}\n\nfunction shellItem(id: string, shell: ShellInfo, text: string, previous: ShellItem | undefined): ShellItem {\n const row = shellRowText(shell, text)\n return {\n kind: 'shell',\n id,\n shell,\n text: row.text,\n truncated: row.truncated,\n // Carried across the re-emit: a row the reader expanded must not collapse under them when the shell ticks.\n ...(previous?.expanded !== undefined && { expanded: previous.expanded }),\n }\n}\n\nfunction findShell(items: readonly TranscriptItem[], shellId: string): ShellItem | undefined {\n return items.find((item): item is ShellItem => item.kind === 'shell' && item.shell.id === shellId)\n}\n\nconst COMMAND_NAME = /<command-name>([\\s\\S]*?)<\\/command-name>/\nconst COMMAND_ARGS = /<command-args>([\\s\\S]*?)<\\/command-args>/\n// A message whose first text block is the deferred `!` flush is synthetic as a whole, but the block after it is\n// the person's own message. Only that shape earns the exemption - `<task-notification>` and the rest stay hidden.\nfunction carriesCaveat(content: ApiMessage['content']): boolean {\n return contentToBlocks(content).some(\n (block) => block.type === 'text' && (block as { text: string }).text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT),\n )\n}\n\nfunction streamingTextId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_ID : `${STREAMING_ID}:${parentToolUseId}`\n}\nfunction streamingThinkingId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_THINKING_ID : `${STREAMING_THINKING_ID}:${parentToolUseId}`\n}\nfunction isStreamingItem(item: TranscriptItem): boolean {\n return (\n (item.kind === 'assistant_text' && item.id.startsWith(STREAMING_ID)) ||\n (item.kind === 'thinking' && item.id.startsWith(STREAMING_THINKING_ID))\n )\n}\n\nexport function blockText(content: ToolResultBlock['content']): string {\n if (content === undefined) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n return content\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n}\n\nfunction imageRefsOf(content: ToolResultBlock['content'], seq: number): ReadonlyArray<ToolResultImageRef> | undefined {\n if (!Array.isArray(content)) {\n return undefined\n }\n const refs = content.flatMap((part) =>\n part.type === 'image_ref'\n ? [\n {\n partIndex: Number(part.part_index),\n mediaType: String(part.media_type ?? 'application/octet-stream'),\n bytes: Number(part.bytes ?? 0),\n sourceSeq: seq,\n },\n ]\n : [],\n )\n return refs.length > 0 ? refs : undefined\n}\n\nfunction contentToBlocks(content: string | ContentBlock[]): ContentBlock[] {\n return typeof content === 'string' ? [{ type: 'text', text: content }] : content\n}\n\nfunction outputText(output: ToolExecutionOutput): string {\n if (output.type === 'text') {\n return output.value\n }\n try {\n return JSON.stringify(output.value)\n } catch {\n return String(output.value)\n }\n}\n\nfunction slashCommandText(text: string): string | undefined {\n const name = COMMAND_NAME.exec(text)?.[1]?.trim()\n if (!name) {\n return undefined\n }\n const args = COMMAND_ARGS.exec(text)?.[1]?.trim()\n return args ? `${name} ${args}` : name\n}\n\n// Streaming ids are unique per agent and the in-flight row sits at the tail, so a token scans a few items, not the transcript.\nfunction findLastIndexOf(items: readonly TranscriptItem[], kind: TranscriptItem['kind'], id: string): number {\n for (let index = items.length - 1; index >= 0; index--) {\n const item = items[index]\n if (item?.id === id && item.kind === kind) {\n return index\n }\n }\n return -1\n}\n\nfunction replaceAt(items: TranscriptItem[], index: number, item: TranscriptItem): TranscriptItem[] {\n if (index === -1) {\n return [...items, item]\n }\n const next = [...items]\n next[index] = item\n return next\n}\n\nfunction upsert(items: TranscriptItem[], item: TranscriptItem): TranscriptItem[] {\n const index = items.findIndex((existing) => existing.id === item.id && existing.kind === item.kind)\n return replaceAt(items, index, item)\n}\n\nexport function seedFromSessionInfo(state: TranscriptState, info: SessionInfo): TranscriptState {\n // No event carries the engine - the snapshot is the only source.\n const engine = info.engine ?? state.engine\n return {\n ...state,\n // With held state (reconnect, warm cache seed) the held status stands: any change since is a `status_changed` in the replay span - events stay the one authority.\n status: state.lastSeq === 0 ? info.status : state.status,\n model: state.model ?? info.model,\n permissionMode: state.permissionMode ?? info.permissionMode,\n cwd: state.cwd ?? info.cwd,\n sdkSessionId: state.sdkSessionId ?? info.sdkSessionId,\n engine,\n capabilities: info.capabilities ?? ENGINE_CAPABILITIES[engine ?? 'claude'],\n // Spend outlives the log a replay is built from: a dormant wake starts a fresh log with no `turn_result` in it,\n // so the snapshot is the only thing that still knows what the session cost before it slept.\n totalCostUsd: state.totalCostUsd || (info.totalCostUsd ?? 0),\n costUsd: state.costUsd ?? info.costUsd,\n usageByModel: state.usageByModel ?? info.usageByModel,\n session: info,\n }\n}\n\nexport function rateLimitWindows(state: Pick<TranscriptState, 'rateLimits' | 'rateLimitsUpdatedAt'>): UsageWindowRow[] {\n return orderUsageWindows(mergeUsage({ rateLimits: state.rateLimits, updatedAt: state.rateLimitsUpdatedAt }, undefined))\n}\n\nexport function hydrateToolResult(state: TranscriptState, toolUseId: string, text: string): TranscriptState {\n let changed = false\n const items = state.items.map((item) => {\n if (item.kind !== 'tool_call' || item.id !== toolUseId || !item.result?.truncated) {\n return item\n }\n changed = true\n // `images` survives the text hydration: the refs carry their own `sourceSeq` because the result's clears here, and without them the row's pictures are unloadable.\n return {\n ...item,\n result: {\n text,\n isError: item.result.isError,\n ...(item.result.images && { images: item.result.images }),\n },\n }\n })\n return changed ? { ...state, items } : state\n}\n\n// `shell` absent is the 404: the record was swept or belongs to a gateway generation this one cannot answer for.\nexport function hydrateShellRow(state: TranscriptState, shellId: string, shell: ShellInfo | undefined): TranscriptState {\n const current = findShell(state.items, shellId)\n if (!current) {\n return state\n }\n const next: ShellItem = shell === undefined ? { ...current, missing: true } : { ...current, shell, missing: undefined }\n return { ...state, items: state.items.map((item) => (item === current ? next : item)) }\n}\n\nexport function hydrateShellOutput(state: TranscriptState, shellId: string, text: string): TranscriptState {\n const current = findShell(state.items, shellId)\n if (!current) {\n return state\n }\n return { ...state, items: state.items.map((item) => (item === current ? { ...current, expanded: text, missing: undefined } : item)) }\n}\n\nexport function applyEvent(state: TranscriptState, event: SessionEvent): TranscriptState {\n if (event.seq <= state.lastSeq) {\n return state\n }\n const base: TranscriptState = { ...state, lastSeq: event.seq }\n\n switch (event.type) {\n case 'system_init': {\n return {\n ...base,\n model: event.model,\n cwd: event.cwd,\n sdkSessionId: event.sdkSessionId,\n permissionMode: event.permissionMode,\n }\n }\n\n case 'status_changed': {\n return { ...base, status: event.status, statusDetail: event.detail }\n }\n\n case 'capabilities': {\n return {\n ...base,\n models: event.models,\n commands: event.commands,\n defaultModel: event.defaultModel ?? base.defaultModel,\n }\n }\n\n case 'skills': {\n return { ...base, skills: event.skills }\n }\n\n case 'checklist': {\n return { ...base, checklist: event.items.length > 0 ? event.items : undefined }\n }\n\n case 'tool_titles': {\n return { ...base, toolTitles: { ...base.toolTitles, ...event.titles } }\n }\n\n case 'file_produced': {\n return {\n ...base,\n producedFiles: {\n ...base.producedFiles,\n [event.path]: {\n fileId: event.fileId,\n ...(event.mediaType ? { mediaType: event.mediaType } : {}),\n ...(event.bytes !== undefined ? { bytes: event.bytes } : {}),\n },\n },\n }\n }\n\n case 'model_changed': {\n return event.model === undefined ? base : { ...base, model: event.model }\n }\n\n case 'permission_mode_changed': {\n return { ...base, permissionMode: event.mode }\n }\n\n case 'context_usage': {\n return { ...base, contextUsage: event.usage }\n }\n\n case 'rate_limit': {\n const key = event.info.rateLimitType\n if (!key) {\n return base\n }\n return {\n ...base,\n rateLimits: { ...base.rateLimits, [key]: event.info },\n rateLimitsUpdatedAt: event.ts,\n }\n }\n\n case 'plan_info': {\n return { ...base, subscriptionType: event.subscriptionType }\n }\n\n case 'conversation_reset': {\n return {\n ...base,\n items: [],\n contextUsage: undefined,\n checklist: undefined,\n sdkSessionId: event.sdkSessionId ?? base.sdkSessionId,\n }\n }\n\n // Appends where the reset above empties, and leaves `contextUsage` alone: the engine reports post-compaction occupancy itself.\n case 'context_compacted': {\n return {\n ...base,\n items: upsert(base.items, {\n kind: 'compaction',\n id: event.uuid,\n parentToolUseId: event.parentToolUseId ?? null,\n pending: event.pending,\n trigger: event.trigger,\n preTokens: event.preTokens,\n postTokens: event.postTokens,\n error: event.error,\n }),\n }\n }\n\n case 'user_message': {\n let items = base.items\n for (const block of contentToBlocks(event.message.content)) {\n if (block.type === 'tool_result') {\n const toolResult = block as ToolResultBlock\n const isError = toolResult.is_error === true\n items = items.map((item) =>\n item.kind === 'tool_call' && item.id === toolResult.tool_use_id\n ? {\n ...item,\n status: isError ? 'failed' : 'settled',\n result: {\n text: blockText(toolResult.content),\n isError,\n ...(toolResult.truncated && {\n truncated: true as const,\n totalChars: toolResult.total_chars,\n sourceSeq: event.seq,\n }),\n ...(imageRefsOf(toolResult.content, event.seq) && {\n images: imageRefsOf(toolResult.content, event.seq),\n }),\n },\n ...(event.patch && { patch: event.patch }),\n }\n : item,\n )\n } else if (block.type === 'text') {\n const text = (block as { text: string }).text\n const rowId = event.uuid ?? `user-${event.seq}`\n // Both branches sit ahead of the synthetic guard on purpose. A `!` shell run is emitted synthetic so it\n // scores zero activity and zero prose, but it is the one synthetic message a person is meant to see; and\n // on resume the SDK hands back the shell output and the user's own text as one message, which\n // `isSyntheticUserText` then marks synthetic whole. Without this the user's own words vanish on reload.\n const localOutput = LOCAL_COMMAND_OUTPUT.exec(text.trim())\n if (event.shell) {\n const existing = items.find((item): item is ShellItem => item.kind === 'shell' && item.id === rowId)\n items = upsert(items, shellItem(rowId, event.shell, text, existing))\n } else if (localOutput) {\n items = upsert(items, {\n kind: 'notice',\n id: rowId,\n level: localOutput[1] === 'stderr' ? 'error' : 'info',\n text: localOutput[2].trim(),\n })\n } else if (text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT)) {\n let index = 0\n for (const match of text.matchAll(LOCAL_COMMAND_ELEMENT)) {\n items = upsert(items, {\n kind: 'notice',\n id: `${rowId}#${index++}`,\n level: match[1] === 'stderr' ? 'error' : 'info',\n text: match[2].trim(),\n })\n }\n } else if (!event.synthetic || carriesCaveat(event.message.content)) {\n items = upsert(items, {\n kind: 'user',\n id: event.uuid ?? `user-${event.seq}`,\n text: slashCommandText(text) ?? text,\n attachments: event.attachments,\n ...(event.origin && { origin: event.origin }),\n ...(event.parentToolUseId != null && {\n parentToolUseId: event.parentToolUseId,\n }),\n })\n }\n }\n }\n return { ...base, items }\n }\n\n case 'assistant_message': {\n const streamingText = streamingTextId(event.parentToolUseId)\n const streamingThought = streamingThinkingId(event.parentToolUseId)\n let streamedThinking =\n base.items.find(\n (item): item is Extract<TranscriptItem, { kind: 'thinking' }> => item.kind === 'thinking' && item.id === streamingThought,\n )?.text ?? ''\n let items = base.items.filter(\n (item) =>\n !(item.kind === 'assistant_text' && item.id === streamingText) && !(item.kind === 'thinking' && item.id === streamingThought),\n )\n const blocks = contentToBlocks(event.message.content)\n blocks.forEach((block, index) => {\n const id = `${event.uuid}-${index}`\n if (block.type === 'text') {\n items = upsert(items, {\n kind: 'assistant_text',\n id,\n text: (block as { text: string }).text,\n streaming: false,\n parentToolUseId: event.parentToolUseId,\n })\n } else if (block.type === 'thinking') {\n const text = (block as { thinking: string }).thinking || streamedThinking\n streamedThinking = ''\n if (text.trim() === '') {\n return\n }\n items = upsert(items, {\n kind: 'thinking',\n id,\n text,\n parentToolUseId: event.parentToolUseId,\n })\n } else if (block.type === 'tool_use') {\n const toolUse = block as { id: string; name: string; input: unknown }\n items = upsert(items, {\n kind: 'tool_call',\n id: toolUse.id,\n name: toolUse.name,\n input: toolUse.input,\n parentToolUseId: event.parentToolUseId,\n status: 'running',\n ts: event.ts,\n })\n }\n })\n return { ...base, items }\n }\n\n case 'stream_delta': {\n const delta = event.event as {\n type: string\n delta?: { type?: string; text?: string; thinking?: string }\n }\n if (delta.type !== 'content_block_delta') {\n return base\n }\n if (delta.delta?.type === 'text_delta') {\n const id = streamingTextId(event.parentToolUseId)\n const index = findLastIndexOf(base.items, 'assistant_text', id)\n const existing = index === -1 ? undefined : (base.items[index] as Extract<TranscriptItem, { kind: 'assistant_text' }>)\n const item: TranscriptItem = {\n kind: 'assistant_text',\n id,\n text: (existing?.text ?? '') + (delta.delta.text ?? ''),\n streaming: true,\n parentToolUseId: event.parentToolUseId,\n }\n return { ...base, items: replaceAt(base.items, index, item) }\n }\n if (delta.delta?.type === 'thinking_delta') {\n const id = streamingThinkingId(event.parentToolUseId)\n const index = findLastIndexOf(base.items, 'thinking', id)\n const existing = index === -1 ? undefined : (base.items[index] as Extract<TranscriptItem, { kind: 'thinking' }>)\n const text = (existing?.text ?? '') + (delta.delta.thinking ?? '')\n // Whitespace-only (encrypted) thinking creates no item - `turn_result` would finalize a permanent empty row; text rebuilds from `existing`, so skipping loses nothing.\n if (text.trim() === '') {\n return base\n }\n const item: TranscriptItem = {\n kind: 'thinking',\n id,\n text,\n parentToolUseId: event.parentToolUseId,\n }\n return { ...base, items: replaceAt(base.items, index, item) }\n }\n return base\n }\n\n case 'turn_result': {\n return {\n ...base,\n totalCostUsd: event.totalCostUsd,\n costUsd: event.costUsd ?? base.costUsd,\n usageByModel: event.usageByModel ?? base.usageByModel,\n items: [\n ...base.items.map((item) => {\n if (!isStreamingItem(item)) {\n return item\n }\n const agent = 'parentToolUseId' in item && item.parentToolUseId ? `-${item.parentToolUseId}` : ''\n return item.kind === 'assistant_text'\n ? { ...item, id: `text-${event.seq}${agent}`, streaming: false }\n : { ...item, id: `thinking-${event.seq}${agent}` }\n }),\n {\n kind: 'turn_result',\n id: `turn-${event.seq}`,\n subtype: event.subtype,\n isError: event.isError,\n durationMs: event.durationMs,\n totalCostUsd: event.totalCostUsd,\n costUsd: event.costUsd,\n errors: event.errors,\n },\n ],\n }\n }\n\n case 'permission_requested': {\n return { ...base, pendingApprovals: [...base.pendingApprovals, event.request] }\n }\n\n case 'permission_resolved': {\n return {\n ...base,\n pendingApprovals: base.pendingApprovals.filter((r) => r.id !== event.requestId),\n }\n }\n\n case 'execution_dispatched': {\n return {\n ...base,\n items: base.items.map((item) =>\n item.kind === 'tool_call' && item.id === event.executionId\n ? {\n ...item,\n status: event.deferred ? 'deferred' : 'pending',\n executionId: event.executionId,\n backend: event.backend,\n }\n : item,\n ),\n }\n }\n\n case 'execution_result': {\n return {\n ...base,\n items: base.items.map((item) =>\n item.kind === 'tool_call' && item.id === event.executionId\n ? {\n ...item,\n status: 'settled',\n executionId: event.executionId,\n result: { text: outputText(event.output), isError: false },\n logs: event.logs ?? item.logs,\n }\n : item,\n ),\n }\n }\n\n case 'execution_failed': {\n return {\n ...base,\n items: base.items.map((item) =>\n item.kind === 'tool_call' && item.id === event.executionId\n ? {\n ...item,\n status: 'failed',\n executionId: event.executionId,\n result: { text: `${event.reason}: ${event.error}`, isError: true },\n logs: event.logs ?? item.logs,\n }\n : item,\n ),\n }\n }\n\n case 'file_delivered': {\n return {\n ...base,\n items: [\n ...base.items,\n {\n kind: 'file_delivered',\n id: `file-${event.seq}`,\n path: event.path,\n bytes: event.bytes,\n description: event.description,\n },\n ],\n }\n }\n\n case 'session_error': {\n return {\n ...base,\n items: [...base.items, { kind: 'notice', id: `err-${event.seq}`, level: 'error', text: event.message }],\n }\n }\n\n case 'session_closed': {\n return {\n ...base,\n items: [\n ...base.items,\n {\n kind: 'notice',\n id: `closed-${event.seq}`,\n level: 'info',\n text: `Session closed (${event.reason})`,\n },\n ],\n }\n }\n\n case 'sdk_event':\n default: {\n return base\n }\n }\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\nimport type { TranscriptState } from './transcript.ts'\n\nconst MAX_ENTRIES = 5\n\nconst entries = new Map<string, TranscriptState>()\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function transcriptCacheKey(client: WorkerDeckClient, sessionId: string): string {\n return `${client.identityKey}\\u0000${sessionId}`\n}\n\nexport function readTranscriptCache(key: string): TranscriptState | undefined {\n return entries.get(key)\n}\n\nexport function writeTranscriptCache(key: string, state: TranscriptState): void {\n entries.delete(key)\n entries.set(key, state)\n if (entries.size > MAX_ENTRIES) {\n const oldest = entries.keys().next().value\n if (oldest !== undefined) {\n entries.delete(oldest)\n }\n }\n}\n\nexport function deleteTranscriptCache(key: string): void {\n entries.delete(key)\n}\n\nexport function clearTranscriptCache(): void {\n entries.clear()\n}\n","import { initialTranscriptState, type TranscriptState } from './transcript.ts'\n\nexport function attachSeedToken(resyncSeq: number, key: string): string {\n return `${resyncSeq}:${key}`\n}\n\nexport type AttachInputs = {\n resyncSeq: number\n key: string\n seededFor: string\n current: TranscriptState\n cacheEnabled: boolean\n skipCache: boolean\n warm: TranscriptState | undefined\n}\n\nexport type AttachPlan = {\n held: TranscriptState\n seed: boolean\n seedToken: string\n afterSeq?: number\n}\n\nexport function planAttach(input: AttachInputs): AttachPlan {\n const seedToken = attachSeedToken(input.resyncSeq, input.key)\n const warm = input.cacheEnabled && !input.skipCache ? input.warm : undefined\n const seed = input.seededFor !== seedToken\n const held = seed ? (warm ?? initialTranscriptState) : input.current\n // `afterSeq` derives from the state held and never from a second cache read, which a racing write could move.\n return { held, seed, seedToken, ...(held.lastSeq > 0 ? { afterSeq: held.lastSeq } : {}) }\n}\n\nexport function shouldWriteParting(input: { cacheEnabled: boolean; skipCache: boolean; parting: TranscriptState }): boolean {\n return input.cacheEnabled && !input.skipCache && input.parting.lastSeq > 0 && input.parting.session !== undefined\n}\n","import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'\nimport { WorkerDeckError } from '@workerdeck/client'\nimport type { WorkerDeckClient, SessionHandle } from '@workerdeck/client'\nimport { DEFAULT_PRICING, PROTOCOL_VERSION, mergePricing } from '@workerdeck/protocol'\nimport type { AttachedFrame, ModelOption, PermissionMode, PricingTable, SessionEvent, ShellInfo } from '@workerdeck/protocol'\nimport {\n applyEvent,\n blockText,\n initialTranscriptState,\n hydrateShellOutput,\n hydrateShellRow,\n hydrateToolResult,\n seedFromSessionInfo,\n type TranscriptState,\n} from '../lib/transcript.ts'\nimport { deleteTranscriptCache, readTranscriptCache, transcriptCacheKey, writeTranscriptCache } from '../lib/transcript-cache.ts'\nimport { attachSeedToken, planAttach, shouldWriteParting } from '../lib/attach-plan.ts'\n\ntype SeedAction = { type: 'transcript_seed'; state: TranscriptState }\ntype HydrateAction = { type: 'transcript_hydrate_result'; toolUseId: string; text: string }\ntype ShellRowAction = { type: 'transcript_hydrate_shell'; shellId: string; shell: ShellInfo | undefined }\ntype ShellOutputAction = { type: 'transcript_hydrate_shell_output'; shellId: string; text: string }\n\ntype TranscriptAction = SessionEvent | AttachedFrame | SeedAction | HydrateAction | ShellRowAction | ShellOutputAction\n\nfunction reduce(state: TranscriptState, action: TranscriptAction): TranscriptState {\n if (action.type === 'transcript_seed') {\n return action.state\n }\n if (action.type === 'transcript_hydrate_result') {\n return hydrateToolResult(state, action.toolUseId, action.text)\n }\n if (action.type === 'transcript_hydrate_shell') {\n return hydrateShellRow(state, action.shellId, action.shell)\n }\n if (action.type === 'transcript_hydrate_shell_output') {\n return hydrateShellOutput(state, action.shellId, action.text)\n }\n return action.type === 'attached' ? seedFromSessionInfo(state, action.session) : applyEvent(state, action)\n}\n\nexport type ConnectionState = 'live' | 'reconnecting' | 'offline'\n\n// Three failed attempts is ~3.5s of backoff - past a blip; the iOS client hardcodes the same threshold.\nconst OFFLINE_AFTER_ATTEMPTS = 3\n\nexport function initialReplayTarget(frame: AttachedFrame): number | undefined {\n return frame.replayingFrom === 0 && frame.session.lastSeq > 0 ? frame.session.lastSeq : undefined\n}\n\nexport function staleAttach(frame: AttachedFrame, held: TranscriptState): boolean {\n if (frame.replayingFrom === 0 || held.lastSeq === 0) {\n return false\n }\n if (frame.session.lastSeq < held.lastSeq) {\n return true\n }\n return held.session !== undefined && frame.session.createdAt !== held.session.createdAt\n}\n\nexport const REPLAY_HOLD_MAX_MS = 1500\n\nexport type UseClaudeSessionOptions = {\n onProtocolError?: (message: string) => void\n cacheTranscript?: boolean\n}\n\nexport type UseClaudeSessionResult = {\n state: TranscriptState\n connected: boolean\n connection: ConnectionState\n replaying: boolean\n protocolMismatch?: number\n // The gateway offers `$` shell mode to this principal on this session. Absent from an older gateway, so falsy by default.\n shell: boolean\n // The gateway's rate table, its own overrides merged over the bundled one, for every figure this client prices itself.\n pricing: PricingTable\n models: ModelOption[]\n effectiveModel?: string\n handle: SessionHandle | undefined\n send: (text: string, attachmentIds?: string[]) => void\n approve: (requestId: string, updatedInput?: Record<string, unknown>) => void\n deny: (requestId: string, message?: string, interrupt?: boolean) => void\n interrupt: () => void\n clearContext: () => void\n runShell: (command: string) => void\n setPermissionMode: (mode: PermissionMode) => void\n setModel: (model?: string) => void\n closeSession: () => void\n reconnectNow: () => void\n loadFullResult: (toolUseId: string) => Promise<boolean>\n // The artifact's text view, fetched for one expanded row. It never reaches the model: the two budgets never touch.\n loadShellOutput: (shellId: string) => Promise<boolean>\n // A `running` row is a claim from the event log, which can be older than the process. Fetched once per shell id.\n verifyShell: (shellId: string) => Promise<boolean>\n killShell: (shellId: string) => Promise<boolean>\n setShellAgentWrite: (shellId: string, enabled: boolean) => Promise<boolean>\n}\n\nexport function useClaudeSession(\n client: WorkerDeckClient,\n sessionId: string | undefined,\n options?: UseClaudeSessionOptions,\n): UseClaudeSessionResult {\n const [state, dispatch] = useReducer(\n reduce,\n undefined,\n (): TranscriptState =>\n (options?.cacheTranscript !== false && sessionId !== undefined\n ? readTranscriptCache(transcriptCacheKey(client, sessionId))\n : undefined) ?? initialTranscriptState,\n )\n const [connection, setConnection] = useState<ConnectionState>('reconnecting')\n const [protocolMismatch, setProtocolMismatch] = useState<number | undefined>()\n const [shell, setShell] = useState(false)\n const [pricing, setPricing] = useState<PricingTable>(DEFAULT_PRICING)\n const [replayTarget, setReplayTarget] = useState<number | undefined>()\n const [resyncSeq, setResyncSeq] = useState(0)\n // Ref for the stable callbacks below; state so consumers of `handle` re-render when the socket opens or the session switches.\n const [handleState, setHandleState] = useState<SessionHandle | undefined>()\n const handleRef = useRef<SessionHandle | null>(null)\n const optionsRef = useRef(options)\n optionsRef.current = options\n const stateRef = useRef(state)\n stateRef.current = state\n const seededForRef = useRef(attachSeedToken(0, sessionId === undefined ? '' : transcriptCacheKey(client, sessionId)))\n const skipCacheRef = useRef(false)\n\n useEffect(() => {\n if (!sessionId) {\n return\n }\n const cache = optionsRef.current?.cacheTranscript !== false\n const key = transcriptCacheKey(client, sessionId)\n const plan = planAttach({\n resyncSeq,\n key,\n seededFor: seededForRef.current,\n current: stateRef.current,\n cacheEnabled: cache,\n skipCache: skipCacheRef.current,\n warm: readTranscriptCache(key),\n })\n skipCacheRef.current = false\n if (plan.seed) {\n dispatch({ type: 'transcript_seed', state: plan.held })\n seededForRef.current = plan.seedToken\n }\n const handle = client.attach(sessionId, {\n truncateResults: true,\n imageRefs: true,\n ...(plan.afterSeq === undefined ? {} : { afterSeq: plan.afterSeq }),\n })\n handleRef.current = handle\n setHandleState(handle)\n const offEvent = handle.on('event', (event: SessionEvent) => dispatch(event))\n const offAttached = handle.on('attached', (frame: AttachedFrame) => {\n if (staleAttach(frame, stateRef.current)) {\n offEvent()\n deleteTranscriptCache(key)\n skipCacheRef.current = true\n setResyncSeq((n) => n + 1)\n return\n }\n dispatch(frame)\n setReplayTarget(initialReplayTarget(frame))\n setProtocolMismatch(frame.protocolVersion === PROTOCOL_VERSION ? undefined : frame.protocolVersion)\n setShell(frame.shell === true)\n setPricing(mergePricing(frame.pricingOverrides).pricing)\n })\n const offConn = handle.on('connectionChange', (open: boolean) => setConnection(open ? 'live' : 'reconnecting'))\n const offRetry = handle.on('reconnectAttempt', (attempts: number) =>\n setConnection(attempts >= OFFLINE_AFTER_ATTEMPTS ? 'offline' : 'reconnecting'),\n )\n const offProtocolError = handle.on('protocolError', (message: string) => {\n optionsRef.current?.onProtocolError?.(message)\n })\n return () => {\n offEvent()\n offAttached()\n offConn()\n offRetry()\n offProtocolError()\n handle.detach()\n handleRef.current = null\n setHandleState(undefined)\n setConnection('reconnecting')\n setProtocolMismatch(undefined)\n setShell(false)\n setReplayTarget(undefined)\n const parting = stateRef.current\n if (shouldWriteParting({ cacheEnabled: cache, skipCache: skipCacheRef.current, parting })) {\n writeTranscriptCache(key, parting)\n }\n }\n }, [client, sessionId, resyncSeq])\n\n useEffect(() => {\n if (replayTarget === undefined) {\n return\n }\n const timer = setTimeout(() => setReplayTarget(undefined), REPLAY_HOLD_MAX_MS)\n return () => clearTimeout(timer)\n }, [replayTarget])\n useEffect(() => {\n if (replayTarget !== undefined && state.lastSeq >= replayTarget) {\n setReplayTarget(undefined)\n }\n }, [replayTarget, state.lastSeq])\n\n const models = useProfileModelFallback(client, sessionId, state)\n\n const connected = connection === 'live'\n // Derived at render, not in an effect, so the reveal lands in the same commit as the replay's final event - an effect is one visible frame late.\n const replaying = replayTarget !== undefined && state.lastSeq < replayTarget\n const reconnectNow = useCallback(() => handleRef.current?.reconnectNow(), [])\n\n const loadFullResult = useCallback(\n async (toolUseId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n const item = stateRef.current.items.find((candidate) => candidate.kind === 'tool_call' && candidate.id === toolUseId)\n const result = item?.kind === 'tool_call' ? item.result : undefined\n if (!result?.truncated || result.sourceSeq === undefined) {\n return false\n }\n try {\n const full = await client.toolResult(sessionId, result.sourceSeq, toolUseId)\n dispatch({ type: 'transcript_hydrate_result', toolUseId, text: blockText(full.content) })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n const verifiedRef = useRef(new Set<string>())\n useEffect(() => {\n verifiedRef.current = new Set<string>()\n }, [sessionId])\n\n const loadShellOutput = useCallback(\n async (shellId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n try {\n const text = await client.shellOutput(sessionId, shellId, { view: 'text' })\n dispatch({ type: 'transcript_hydrate_shell_output', shellId, text })\n return true\n } catch (error) {\n if (isNotFound(error)) {\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: undefined })\n }\n return false\n }\n },\n [client, sessionId],\n )\n\n const verifyShell = useCallback(\n async (shellId: string): Promise<boolean> => {\n const verified = verifiedRef.current\n if (!sessionId || verified.has(shellId)) {\n return false\n }\n verified.add(shellId)\n try {\n const record = await client.getShell(sessionId, shellId)\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: record })\n return true\n } catch (error) {\n if (isNotFound(error)) {\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: undefined })\n } else {\n verified.delete(shellId)\n }\n return false\n }\n },\n [client, sessionId],\n )\n\n const killShell = useCallback(\n async (shellId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n try {\n const record = await client.killShell(sessionId, shellId)\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: record })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n const setShellAgentWrite = useCallback(\n async (shellId: string, enabled: boolean): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n try {\n const record = await client.setShellAgentWrite(sessionId, shellId, enabled)\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: record })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n const actions = useMemo(\n () => ({\n send: (text: string, attachmentIds?: string[]) => handleRef.current?.send(text, attachmentIds),\n approve: (requestId: string, updatedInput?: Record<string, unknown>) => handleRef.current?.approve(requestId, updatedInput),\n deny: (requestId: string, message?: string, interrupt?: boolean) => handleRef.current?.deny(requestId, message, interrupt),\n interrupt: () => handleRef.current?.interrupt(),\n clearContext: () => handleRef.current?.clearContext(),\n runShell: (command: string) => handleRef.current?.runShell(command),\n setPermissionMode: (mode: PermissionMode) => handleRef.current?.setPermissionMode(mode),\n setModel: (model?: string) => handleRef.current?.setModel(model),\n closeSession: () => handleRef.current?.closeSession(),\n }),\n [],\n )\n\n return useMemo(\n () => ({\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n shell,\n pricing,\n models,\n effectiveModel: state.model ?? state.defaultModel,\n handle: handleState,\n ...actions,\n reconnectNow,\n loadFullResult,\n loadShellOutput,\n verifyShell,\n killShell,\n setShellAgentWrite,\n }),\n [\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n shell,\n pricing,\n models,\n handleState,\n actions,\n reconnectNow,\n loadFullResult,\n loadShellOutput,\n verifyShell,\n killShell,\n setShellAgentWrite,\n ],\n )\n}\n\nfunction isNotFound(error: unknown): boolean {\n return error instanceof WorkerDeckError && error.status === 404\n}\n\nfunction useProfileModelFallback(client: WorkerDeckClient, sessionId: string | undefined, state: TranscriptState): ModelOption[] {\n const [catalog, setCatalog] = useState<ModelOption[]>([])\n const profile = state.session?.profile\n const reported = state.models\n const hasReported = !!reported?.length\n\n useEffect(() => setCatalog([]), [sessionId])\n\n useEffect(() => {\n if (!profile || hasReported) {\n return\n }\n let cancelled = false\n client\n .listProfiles()\n .then((response) => {\n if (!cancelled) {\n setCatalog(response.profiles.find((p) => p.name === profile)?.models ?? [])\n }\n })\n .catch(() => {})\n return () => {\n cancelled = true\n }\n }, [client, profile, hasReported])\n\n return hasReported ? reported : catalog\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\nimport type { ProfileUsage } from '@workerdeck/protocol'\n\n// Last known profile usage, kept outside React so a session switch does not blank it.\n//\n// Usage belongs to the *account*, not the session, but it is fetched by a hook that lives inside the per-session\n// panel - so remounting that panel used to drop the authoritative reading to `undefined` for a whole round trip,\n// leaving only the newly-attached session's own replayed (and possibly days-old) numbers to render. That is the\n// \"switching sessions resets my weekly usage to 1%, then it catches up\" report.\n//\n// Keyed by client identity + profile because a different profile is a different account's plan, never a stale view\n// of this one. Same shape and reasoning as `transcript-cache.ts` next door.\nconst entries = new Map<string, ProfileUsage>()\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function profileUsageCacheKey(client: WorkerDeckClient, profile: string): string {\n return `${client.identityKey}\\u0000${profile}`\n}\n\nexport function readProfileUsageCache(key: string): ProfileUsage | undefined {\n return entries.get(key)\n}\n\nexport function writeProfileUsageCache(key: string, usage: ProfileUsage | undefined): void {\n if (usage === undefined) {\n return\n }\n entries.set(key, usage)\n}\n\nexport function clearProfileUsageCache(): void {\n entries.clear()\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\n\n// Unsent composer text, kept per session on the client that typed it.\n//\n// A draft is not session state: it never reaches the gateway and never syncs between clients. Two people looking at\n// one session are each mid-sentence in their own way, and a half-written prompt is not something either of them\n// asked to publish.\n//\n// It is persisted rather than merely held in memory because the two ways drafts got lost are different failures. A\n// session switch remounts the composer, which a module-scope map alone would survive; a Vite HMR reload or a VS Code\n// `dev:host` webview re-render replaces the whole document, which it would not.\nconst KEY = 'workerdeck.drafts.v1'\n\n// Drafts are a convenience, so the store stays small and drops the least recently touched first.\nconst MAX_DRAFTS = 20\n\ntype Draft = { text: string; savedAt: number }\n\nlet memory: Record<string, Draft> | undefined\n\nfunction storage(): Storage | undefined {\n try {\n // Through globalThis: this package is typechecked with no DOM lib, and a webview may deny storage outright.\n return (globalThis as { localStorage?: Storage }).localStorage\n } catch {\n return undefined\n }\n}\n\nfunction load(): Record<string, Draft> {\n if (memory) {\n return memory\n }\n memory = {}\n const raw = storage()?.getItem(KEY)\n if (raw) {\n try {\n const parsed = JSON.parse(raw) as Record<string, Draft>\n for (const [key, draft] of Object.entries(parsed)) {\n if (typeof draft?.text === 'string' && typeof draft.savedAt === 'number') {\n memory[key] = draft\n }\n }\n } catch {\n // A corrupt blob is not worth a broken composer; start over.\n }\n }\n return memory\n}\n\nfunction persist(drafts: Record<string, Draft>): void {\n const entries = Object.entries(drafts)\n if (entries.length > MAX_DRAFTS) {\n entries.sort((a, b) => b[1].savedAt - a[1].savedAt)\n for (const [key] of entries.slice(MAX_DRAFTS)) {\n delete drafts[key]\n }\n }\n try {\n storage()?.setItem(KEY, JSON.stringify(drafts))\n } catch {\n // Out of quota, or storage denied. The in-memory copy still carries the session switch.\n }\n}\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function draftKey(client: WorkerDeckClient, sessionId: string): string {\n return `${client.identityKey}\\u0000${sessionId}`\n}\n\nexport function readDraft(key: string): string {\n return load()[key]?.text ?? ''\n}\n\nexport function writeDraft(key: string, text: string, now = Date.now()): void {\n const drafts = load()\n // An empty draft is the absence of one: keeping it would evict a real draft under the cap.\n if (text.trim() === '') {\n if (drafts[key] === undefined) {\n return\n }\n delete drafts[key]\n } else {\n drafts[key] = { text, savedAt: now }\n }\n persist(drafts)\n}\n\nexport function clearDrafts(): void {\n memory = {}\n try {\n storage()?.removeItem(KEY)\n } catch {}\n}\n","import { errorMessage } from '@workerdeck/protocol'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport type { EngineCapabilities, ProfileEngine } from '@workerdeck/protocol'\n\nexport type StagedAttachment = {\n key: string\n name: string\n mediaType: string\n bytes: number\n previewUrl?: string\n status: 'uploading' | 'ready' | 'failed'\n id?: string\n error?: string\n}\n\nexport type AttachmentKind = 'image' | 'pdf' | 'text'\n\nconst TEXTUAL_TYPES = new Set([\n 'application/json',\n 'application/xml',\n 'application/yaml',\n 'application/x-yaml',\n 'application/toml',\n 'application/javascript',\n 'application/typescript',\n 'application/x-sh',\n 'application/sql',\n])\n\nconst MAX_IMAGE_EDGE = 1568\n\nexport function attachmentKind(mediaType: string): AttachmentKind | undefined {\n const type = mediaType.split(';')[0]!.trim().toLowerCase()\n if (type.startsWith('image/')) {\n return 'image'\n }\n if (type === 'application/pdf') {\n return 'pdf'\n }\n if (type.startsWith('text/')) {\n return 'text'\n }\n if (TEXTUAL_TYPES.has(type)) {\n return 'text'\n }\n return undefined\n}\n\nexport type UseAttachmentsOptions = {\n capabilities: EngineCapabilities\n engine?: ProfileEngine\n}\n\nexport type UseAttachmentsResult = {\n items: StagedAttachment[]\n readyIds: string[]\n uploading: boolean\n hasFailure: boolean\n accept: string\n disabled: boolean\n add: (files: Iterable<File>) => void\n retry: (key: string) => void\n remove: (key: string) => void\n clear: () => void\n error?: string\n dismissError: () => void\n}\n\nexport function useAttachments(\n client: WorkerDeckClient,\n sessionId: string | undefined,\n { capabilities, engine }: UseAttachmentsOptions,\n): UseAttachmentsResult {\n const [items, setItems] = useState<StagedAttachment[]>([])\n const [error, setError] = useState<string | undefined>()\n const counter = useRef(0)\n const fileByKey = useRef(new Map<string, File>())\n const previewUrls = useRef<string[]>([])\n previewUrls.current = items.flatMap((item) => (item.previewUrl ? [item.previewUrl] : []))\n const accepts = capabilities.attachments\n\n useEffect(\n () => () => {\n for (const url of previewUrls.current) {\n URL.revokeObjectURL(url)\n }\n },\n [],\n )\n\n const patch = useCallback((key: string, next: Partial<StagedAttachment>) => {\n setItems((current) => current.map((item) => (item.key === key ? { ...item, ...next } : item)))\n }, [])\n\n const upload = useCallback(\n (key: string, file: File) => {\n if (!sessionId) {\n return\n }\n patch(key, { status: 'uploading', error: undefined })\n void (async () => {\n try {\n const data = await prepare(file)\n const uploaded = await client.uploadAttachment(sessionId, {\n name: file.name,\n mediaType: data.mediaType,\n data: data.body,\n })\n patch(key, { status: 'ready', id: uploaded.id, bytes: uploaded.bytes ?? file.size })\n } catch (e) {\n patch(key, { status: 'failed', error: errorMessage(e, 'Upload failed') })\n }\n })()\n },\n [client, patch, sessionId],\n )\n\n const add = useCallback(\n (files: Iterable<File>) => {\n const staged: StagedAttachment[] = []\n const pending: Array<{ key: string; file: File }> = []\n for (const file of files) {\n const mediaType = file.type || 'application/octet-stream'\n const kind = attachmentKind(mediaType)\n // An unclassifiable type still goes: the gateway's vocabulary is the authoritative one.\n if (kind && !accepts.includes(kind)) {\n setError(`The ${engine ?? 'claude'} engine does not take ${kind} attachments.`)\n continue\n }\n const key = `att-${++counter.current}`\n staged.push({\n key,\n name: file.name,\n mediaType,\n bytes: file.size,\n previewUrl: kind === 'image' ? URL.createObjectURL(file) : undefined,\n status: 'uploading',\n })\n pending.push({ key, file })\n }\n if (staged.length === 0) {\n return\n }\n setItems((current) => [...current, ...staged])\n fileByKey.current = new Map([...fileByKey.current, ...pending.map(({ key, file }) => [key, file] as const)])\n for (const { key, file } of pending) {\n upload(key, file)\n }\n },\n [accepts, engine, upload],\n )\n\n const forget = useCallback((keys: string[]) => {\n setItems((current) => {\n for (const item of current) {\n if (keys.includes(item.key) && item.previewUrl) {\n URL.revokeObjectURL(item.previewUrl)\n }\n }\n return current.filter((item) => !keys.includes(item.key))\n })\n for (const key of keys) {\n fileByKey.current.delete(key)\n }\n }, [])\n\n const remove = useCallback((key: string) => forget([key]), [forget])\n\n const clear = useCallback(() => {\n setItems((current) => {\n for (const item of current) {\n if (item.previewUrl) {\n URL.revokeObjectURL(item.previewUrl)\n }\n }\n return []\n })\n fileByKey.current.clear()\n }, [])\n\n const retry = useCallback(\n (key: string) => {\n const file = fileByKey.current.get(key)\n if (file) {\n upload(key, file)\n }\n },\n [upload],\n )\n\n return useMemo(\n () => ({\n items,\n readyIds: items.flatMap((item) => (item.id ? [item.id] : [])),\n uploading: items.some((item) => item.status === 'uploading'),\n hasFailure: items.some((item) => item.status === 'failed'),\n accept: acceptAttribute(accepts),\n disabled: accepts.length === 0 || !sessionId,\n add,\n retry,\n remove,\n clear,\n error,\n dismissError: () => setError(undefined),\n }),\n [items, accepts, sessionId, add, retry, remove, clear, error],\n )\n}\n\nfunction acceptAttribute(kinds: readonly AttachmentKind[]): string {\n if (kinds.length === 0) {\n return ''\n }\n const parts: string[] = []\n if (kinds.includes('image')) {\n parts.push('image/*')\n }\n if (kinds.includes('pdf')) {\n parts.push('application/pdf')\n }\n if (kinds.includes('text')) {\n parts.push('text/*', '.md', '.json', '.yaml', '.yml', '.toml')\n }\n // All three kinds is no narrowing at all, and an empty accept leaves the picker open.\n return kinds.length === 3 ? '' : parts.join(',')\n}\n\n// Reached through globalThis, not named directly: smoke/ typechecks this source with no DOM lib.\ntype ImageBitmapLike = { width: number; height: number; close(): void }\ntype CanvasLike = {\n width: number\n height: number\n getContext(contextId: '2d'): {\n drawImage(image: ImageBitmapLike, dx: number, dy: number, dw: number, dh: number): void\n } | null\n toBlob(callback: (blob: Blob | null) => void, type?: string, quality?: number): void\n}\nconst imaging = globalThis as unknown as {\n createImageBitmap?: (source: Blob) => Promise<ImageBitmapLike>\n document?: { createElement(tagName: 'canvas'): CanvasLike }\n}\n\nasync function prepare(file: File): Promise<{ body: Blob; mediaType: string }> {\n const mediaType = file.type || 'application/octet-stream'\n const { createImageBitmap, document } = imaging\n if (!createImageBitmap || !document || !mediaType.startsWith('image/')) {\n return { body: file, mediaType }\n }\n // A redraw of an animation would keep one frame of it.\n if (mediaType === 'image/gif') {\n return { body: file, mediaType }\n }\n try {\n const bitmap = await createImageBitmap(file)\n const longest = Math.max(bitmap.width, bitmap.height)\n if (longest <= MAX_IMAGE_EDGE) {\n bitmap.close()\n return { body: file, mediaType }\n }\n const scale = MAX_IMAGE_EDGE / longest\n const canvas = document.createElement('canvas')\n canvas.width = Math.round(bitmap.width * scale)\n canvas.height = Math.round(bitmap.height * scale)\n const context = canvas.getContext('2d')\n if (!context) {\n bitmap.close()\n return { body: file, mediaType }\n }\n context.drawImage(bitmap, 0, 0, canvas.width, canvas.height)\n bitmap.close()\n const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, 'image/jpeg', 0.85))\n return blob ? { body: blob, mediaType: 'image/jpeg' } : { body: file, mediaType }\n } catch {\n return { body: file, mediaType }\n }\n}\n","import { PEER_MENTION_SIGIL, PROMPT_SENTENCE_TAIL, isPeerMentionBody, peerMentionKey } from '@workerdeck/protocol'\n\nexport type PromptToken = {\n kind: 'file' | 'command' | 'skill' | 'session'\n start: number\n end: number\n text: string\n}\n\n// `$name` is codex's skill mention and `#Name` is another session on the gateway; in both cases only\n// a name this client knows is a token, so a dollar amount and a colour literal never badge. The\n// session list is *live*, so a mention drawn today may draw plain once that peer is renamed - the\n// characters never change, only the colour, which is why this does not break the rule that a\n// transcript must read on replay as it did live (that rule binds substituting a name for an id).\nexport type PromptTokenOptions = {\n skills?: readonly string[]\n // Folded slugs (`peerMentionKey(peerMentionSlug(title, id))`), not display titles.\n sessions?: readonly string[]\n}\n\n// No `/`, so a pasted absolute path is not a command; `:` is in for namespaced skills (`dev:wrapup`).\nconst COMMAND_BODY = /^[A-Za-z0-9\\-_.:]+$/\n\n// The same set the gateway peels with, so one boundary answers for every sigil.\nconst SENTENCE_TAIL = PROMPT_SENTENCE_TAIL\n\nexport function scanPromptTokens(text: string, options?: PromptTokenOptions): PromptToken[] {\n const tokens: PromptToken[] = []\n const skills = options?.skills?.length ? new Set(options.skills) : undefined\n const sessions = options?.sessions?.length ? new Set(options.sessions) : undefined\n const words = /\\S+/g\n let match: RegExpExecArray | null\n while ((match = words.exec(text)) !== null) {\n const word = match[0]\n const kind =\n word[0] === '@'\n ? 'file'\n : word[0] === '/'\n ? 'command'\n : word[0] === '$' && skills\n ? 'skill'\n : word[0] === PEER_MENTION_SIGIL && sessions\n ? 'session'\n : undefined\n if (!kind) {\n continue\n }\n let end = match.index + word.length\n while (end > match.index && SENTENCE_TAIL.has(text[end - 1]!)) {\n end--\n }\n const body = text.slice(match.index + 1, end)\n if (!body) {\n continue\n }\n if (kind === 'command' && !COMMAND_BODY.test(body)) {\n continue\n }\n if (kind === 'skill' && !skills!.has(body)) {\n continue\n }\n if (kind === 'session' && !(isPeerMentionBody(body) && sessions!.has(peerMentionKey(body)))) {\n continue\n }\n tokens.push({ kind, start: match.index, end, text: text.slice(match.index, end) })\n }\n return tokens\n}\n","import { useCallback, useEffect, useRef, useState, type DependencyList, type Dispatch, type RefObject, type SetStateAction } from 'react'\nimport { WorkerDeckError } from '@workerdeck/client'\n\nexport type UseAsyncOptions = {\n enabled?: boolean\n pollMs?: number\n}\n\nexport type UseAsyncResult<T> = {\n data: T | undefined\n error: unknown\n loading: boolean\n reload: () => Promise<void>\n setData: Dispatch<SetStateAction<T | undefined>>\n}\n\n// Set in an effect, not at declaration: StrictMode remounts, and a once-initialised ref stays false.\nexport function useAliveRef(): RefObject<boolean> {\n const alive = useRef(true)\n useEffect(() => {\n alive.current = true\n return () => {\n alive.current = false\n }\n }, [])\n return alive\n}\n\nexport function isRouteUnsupported(e: unknown): boolean {\n return e instanceof WorkerDeckError && e.status === 404\n}\n\n// A change of `deps` drops the previous answer; `enabled` flipping on, a poll and `reload` keep it until the next one lands.\nexport function useAsync<T>(\n load: () => Promise<T>,\n deps: DependencyList,\n { enabled = true, pollMs }: UseAsyncOptions = {},\n): UseAsyncResult<T> {\n const [data, setData] = useState<T | undefined>()\n const [error, setError] = useState<unknown>()\n const [loading, setLoading] = useState(enabled)\n const generation = useRef(0)\n const loadRef = useRef(load)\n loadRef.current = load\n\n const run = useCallback(async () => {\n const id = ++generation.current\n setLoading(true)\n try {\n const next = await loadRef.current()\n if (id === generation.current) {\n setData(() => next)\n setError(undefined)\n }\n } catch (e) {\n if (id === generation.current) {\n setError(e)\n }\n } finally {\n if (id === generation.current) {\n setLoading(false)\n }\n }\n }, [])\n\n useEffect(() => {\n setData(undefined)\n setError(undefined)\n }, deps)\n\n useEffect(() => {\n if (!enabled) {\n generation.current++\n setLoading(false)\n return\n }\n void run()\n const timer = pollMs ? setInterval(() => void run(), pollMs) : undefined\n return () => {\n generation.current++\n clearInterval(timer)\n }\n }, [enabled, pollMs, run, ...deps])\n\n return { data, error, loading, reload: run, setData }\n}\n","import type { HostDirEntry } from '@workerdeck/protocol'\n\nexport type HostDirState = {\n entries: HostDirEntry[]\n truncated?: boolean\n}\n\nexport type HostTreeRow = {\n entry: HostDirEntry\n depth: number\n expanded?: boolean\n loading?: boolean\n truncated?: boolean\n}\n\nexport function flattenHostTree(root: string, dirs: ReadonlyMap<string, HostDirState>, expanded: ReadonlySet<string>): HostTreeRow[] {\n const rows: HostTreeRow[] = []\n const rootState = dirs.get(root)\n if (!rootState) {\n return rows\n }\n // An explicit stack rather than recursion. Depth is bounded by how many directories the user has\n // expanded, not by tree size, so this is a small risk - but it is the user's clicks that set the\n // bound, and an expanded chain deep enough to exhaust the call stack should still just render.\n const stack: { entries: readonly HostDirEntry[]; index: number; depth: number }[] = [{ entries: rootState.entries, index: 0, depth: 0 }]\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]\n const entry = frame.entries[frame.index]\n if (entry === undefined) {\n stack.pop()\n continue\n }\n frame.index += 1\n const depth = frame.depth\n if (entry.type !== 'dir') {\n rows.push({ entry, depth })\n continue\n }\n const isExpanded = expanded.has(entry.path)\n const childState = dirs.get(entry.path)\n rows.push({\n entry,\n depth,\n expanded: isExpanded,\n loading: isExpanded && !childState,\n truncated: isExpanded ? childState?.truncated : undefined,\n })\n if (isExpanded && childState) {\n stack.push({ entries: childState.entries, index: 0, depth: depth + 1 })\n }\n }\n return rows\n}\n\nexport function ancestorsWithin(root: string, path: string): string[] {\n const base = root.endsWith('/') ? root.slice(0, -1) : root\n if (path === base || !path.startsWith(`${base}/`)) {\n return []\n }\n const rest = path.slice(base.length + 1).split('/')\n const out: string[] = []\n let current = base\n for (const segment of rest.slice(0, -1)) {\n current = `${current}/${segment}`\n out.push(current)\n }\n return out\n}\n","import { errorMessage } from '@workerdeck/protocol'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\nimport type { HostFileMatch } from '@workerdeck/protocol'\nimport { ancestorsWithin, flattenHostTree, type HostDirState, type HostTreeRow } from '../lib/host-tree.ts'\n\nexport type UseHostFileSearchResult = {\n available: boolean\n search: (query: string, options?: { limit?: number; signal?: AbortSignal }) => Promise<HostFileMatch[]>\n}\n\nexport function useHostFileSearch(client: WorkerDeckClient, cwd: string | undefined): UseHostFileSearchResult {\n const [unsupported, setUnsupported] = useState(false)\n const lastCwd = useRef(cwd)\n useEffect(() => {\n if (lastCwd.current !== cwd) {\n lastCwd.current = cwd\n setUnsupported(false)\n }\n }, [cwd])\n\n const search = useCallback(\n async (query: string, options?: { limit?: number; signal?: AbortSignal }) => {\n if (!cwd || unsupported) {\n return []\n }\n try {\n const response = await client.findHostFiles(cwd, query, options?.limit ?? 8)\n return options?.signal?.aborted ? [] : response.matches\n } catch (e) {\n if (isRouteUnsupported(e)) {\n setUnsupported(true)\n }\n return []\n }\n },\n [client, cwd, unsupported],\n )\n\n return { available: !!cwd && !unsupported, search }\n}\n\nexport type UseHostFileRootsResult = {\n available: boolean\n canWrite: boolean\n}\n\nexport function useHostFileRoots(client: WorkerDeckClient): UseHostFileRootsResult {\n const [result, setResult] = useState<UseHostFileRootsResult>({\n available: false,\n canWrite: false,\n })\n useEffect(() => {\n let cancelled = false\n client\n .listHostRoots()\n .then((response) => {\n if (!cancelled) {\n setResult({ available: true, canWrite: response.canWrite })\n }\n })\n .catch(() => {\n if (!cancelled) {\n setResult({ available: false, canWrite: false })\n }\n })\n return () => {\n cancelled = true\n }\n }, [client])\n return result\n}\n\nexport type UseHostFileTreeResult = {\n available: boolean\n root: string | undefined\n rows: HostTreeRow[]\n loading: boolean\n error: string | undefined\n toggle: (path: string) => void\n reveal: (path: string) => void\n refresh: (path?: string) => void\n}\n\nexport function useHostFileTree(client: WorkerDeckClient, cwd: string | undefined): UseHostFileTreeResult {\n const [dirs, setDirs] = useState<Map<string, HostDirState>>(() => new Map())\n const [expanded, setExpanded] = useState<Set<string>>(() => new Set())\n const [unsupported, setUnsupported] = useState(false)\n const [error, setError] = useState<string | undefined>()\n\n const lastCwd = useRef(cwd)\n useEffect(() => {\n if (lastCwd.current === cwd) {\n return\n }\n lastCwd.current = cwd\n setDirs(new Map())\n setExpanded(new Set())\n setUnsupported(false)\n setError(undefined)\n }, [cwd])\n\n const alive = useAliveRef()\n\n const requested = useRef(new Set<string>())\n\n const list = useCallback(\n (target: string, { force = false } = {}) => {\n if (unsupported) {\n return\n }\n if (!force && requested.current.has(target)) {\n return\n }\n requested.current.add(target)\n client\n .listHostDir(target)\n .then((response) => {\n if (!alive.current) {\n return\n }\n setDirs((previous) => {\n const next = new Map(previous)\n // Keyed on the path asked for, never the canonical one answered: re-keying orphans the node that asked.\n next.set(target, { entries: response.entries, truncated: response.truncated })\n return next\n })\n })\n .catch((e: unknown) => {\n if (!alive.current) {\n return\n }\n requested.current.delete(target)\n if (isRouteUnsupported(e)) {\n setUnsupported(true)\n return\n }\n setError(errorMessage(e, 'Could not read that directory'))\n })\n },\n [client, unsupported],\n )\n\n useEffect(() => {\n if (cwd) {\n list(cwd)\n }\n }, [cwd, list])\n\n const toggle = useCallback(\n (path: string) => {\n setExpanded((previous) => {\n const next = new Set(previous)\n if (next.has(path)) {\n next.delete(path)\n } else {\n next.add(path)\n }\n return next\n })\n // Outside the updater, which React may run twice; `requested` makes this a no-op on the collapse.\n list(path)\n },\n [list],\n )\n\n const reveal = useCallback(\n (path: string) => {\n if (!cwd) {\n return\n }\n const ancestors = ancestorsWithin(cwd, path)\n if (ancestors.length === 0) {\n return\n }\n for (const dir of ancestors) {\n list(dir)\n }\n setExpanded((previous) => {\n const next = new Set(previous)\n for (const dir of ancestors) {\n next.add(dir)\n }\n return next\n })\n },\n [cwd, list],\n )\n\n const refresh = useCallback(\n (path?: string) => {\n const target = path ?? cwd\n if (!target) {\n return\n }\n setError(undefined)\n list(target, { force: true })\n },\n [cwd, list],\n )\n\n const rows = useMemo(() => (cwd ? flattenHostTree(cwd, dirs, expanded) : []), [cwd, dirs, expanded])\n\n return {\n available: !!cwd && !unsupported,\n root: cwd,\n rows,\n loading: !!cwd && !unsupported && !dirs.has(cwd) && !error,\n error,\n toggle,\n reveal,\n refresh,\n }\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { peerMentionKey, peerMentionSlug, sessionLabel, type SessionInfo } from '@workerdeck/protocol'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\n\nexport type PeerSessionOption = {\n id: string\n // What the composer writes after the `#`, and what the gateway folds to resolve it.\n slug: string\n label: string\n engine?: SessionInfo['engine']\n status: SessionInfo['status']\n cwd: string\n project?: string\n lastActivityAt?: number\n}\n\nexport type UsePeerSessionsResult = {\n available: boolean\n peers: PeerSessionOption[]\n // Folded slugs, for `scanPromptTokens`'s `sessions` allowlist.\n names: string[]\n}\n\nconst EMPTY: UsePeerSessionsResult = { available: false, peers: [], names: [] }\n\nconst IDLE_MS = 20_000\n\n// The other sessions this gateway will show, for the composer's `#` picker. Polled slowly on\n// purpose: a name is not a reading, and this list only has to be right when a menu opens. The\n// gateway resolves what was typed against the sender's own scope, so a stale row costs nothing\n// worse than a mention that stays plain text.\nexport function usePeerSessions(client: WorkerDeckClient, sessionId: string | undefined, enabled = true): UsePeerSessionsResult {\n const [sessions, setSessions] = useState<SessionInfo[] | undefined>(undefined)\n const [unsupported, setUnsupported] = useState(false)\n const alive = useAliveRef()\n\n useEffect(() => {\n if (!enabled || unsupported) {\n return\n }\n let timer: ReturnType<typeof setTimeout> | undefined\n const tick = () => {\n client\n .listSessions()\n .then((rows) => {\n if (!alive.current) {\n return\n }\n setSessions(rows)\n })\n .catch((e: unknown) => {\n if (alive.current && isRouteUnsupported(e)) {\n setUnsupported(true)\n }\n })\n .finally(() => {\n if (alive.current) {\n timer = setTimeout(tick, IDLE_MS)\n }\n })\n }\n tick()\n return () => {\n if (timer) {\n clearTimeout(timer)\n }\n }\n }, [client, enabled, unsupported])\n\n return useMemo(() => {\n if (!enabled || unsupported || !sessions) {\n return EMPTY\n }\n const peers = sessions\n .filter((info) => info.id !== sessionId)\n .sort((a, b) => (b.lastActivityAt ?? b.createdAt) - (a.lastActivityAt ?? a.createdAt))\n .map((info) => ({\n id: info.id,\n slug: peerMentionSlug(info.title, info.id),\n label: sessionLabel(info),\n engine: info.engine,\n status: info.status,\n cwd: info.cwd,\n project: info.project?.name,\n lastActivityAt: info.lastActivityAt,\n }))\n return { available: peers.length > 0, peers, names: peers.map((peer) => peerMentionKey(peer.slug)) }\n }, [enabled, sessionId, sessions, unsupported])\n}\n","import { useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport type { SessionRow } from '@workerdeck/protocol'\n\nconst byHash = new Map<string, string>()\nconst inFlight = new Set<string>()\nconst failed = new Set<string>()\n\nexport type ClientForHost = (hostId: string) => WorkerDeckClient | undefined\n\nexport function useProjectIcons(rows: readonly SessionRow[], clientFor: ClientForHost): Record<string, string> {\n const [resolved, setResolved] = useState<Record<string, string>>(() => Object.fromEntries(byHash))\n\n useEffect(() => {\n let alive = true\n for (const row of rows) {\n const icon = row.info.project?.icon\n if (icon?.type !== 'image') {\n continue\n }\n const { hash } = icon\n if (byHash.has(hash) || inFlight.has(hash) || failed.has(hash)) {\n continue\n }\n const client = clientFor(row.hostId)\n // An unreachable gateway is not an iconless one: no failure recorded, so a later render retries.\n if (!client) {\n continue\n }\n inFlight.add(hash)\n void client\n .projectIcon(row.info.id)\n .then((blob) => {\n byHash.set(hash, URL.createObjectURL(blob))\n if (alive) {\n setResolved(Object.fromEntries(byHash))\n }\n })\n .catch(() => {\n failed.add(hash)\n })\n .finally(() => inFlight.delete(hash))\n }\n return () => {\n alive = false\n }\n }, [rows, clientFor])\n\n return resolved\n}\n","export const BOOKMARKS_STORAGE_KEY = 'workerdeck.bookmarks.v1'\n\ntype BookmarkMap = Record<string, readonly string[]>\ntype StorageListener = (event: { key: string | null }) => void\ntype StorageEventTarget = {\n addEventListener: (type: 'storage', listener: StorageListener) => void\n removeEventListener: (type: 'storage', listener: StorageListener) => void\n}\n\nconst EMPTY: readonly string[] = Object.freeze([])\nconst listeners = new Set<() => void>()\nlet loaded: BookmarkMap | undefined\nlet detachStorageEvent: (() => void) | undefined\n\nfunction storage(): Storage | undefined {\n try {\n return globalThis.localStorage ?? undefined\n } catch {\n return undefined\n }\n}\n\nfunction storageEvents(): StorageEventTarget | undefined {\n const target = (globalThis as { window?: Partial<StorageEventTarget> }).window\n return typeof target?.addEventListener === 'function' ? (target as StorageEventTarget) : undefined\n}\n\nfunction readStored(): BookmarkMap | undefined {\n try {\n const raw = storage()?.getItem(BOOKMARKS_STORAGE_KEY)\n if (raw == null) {\n return {}\n }\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return {}\n }\n const map: Record<string, readonly string[]> = {}\n for (const [key, value] of Object.entries(parsed)) {\n if (Array.isArray(value)) {\n map[key] = value.filter((id): id is string => typeof id === 'string')\n }\n }\n return map\n } catch {\n return undefined\n }\n}\n\nfunction sameIds(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((id, index) => id === b[index])\n}\n\n// Unchanged lists keep their identity, so a write to one session never re-renders another.\nfunction adopt(next: BookmarkMap): void {\n const previous = loaded ?? {}\n const merged: Record<string, readonly string[]> = {}\n for (const [key, ids] of Object.entries(next)) {\n const held = previous[key]\n merged[key] = held && sameIds(held, ids) ? held : ids\n }\n loaded = merged\n}\n\nfunction current(): BookmarkMap {\n if (loaded === undefined) {\n adopt(readStored() ?? {})\n }\n return loaded ?? {}\n}\n\nfunction notify(): void {\n for (const listener of listeners) {\n listener()\n }\n}\n\nexport function bookmarksFor(sessionKey: string): readonly string[] {\n return current()[sessionKey] ?? EMPTY\n}\n\n// Read-modify-write against storage as it stands now, so a second tab's toggles survive this one's.\nexport function toggleBookmark(sessionKey: string, itemId: string): void {\n const base = readStored() ?? current()\n const held = base[sessionKey] ?? EMPTY\n const ids = held.includes(itemId) ? held.filter((id) => id !== itemId) : [...held, itemId]\n const next: Record<string, readonly string[]> = { ...base, [sessionKey]: ids }\n if (ids.length === 0) {\n delete next[sessionKey]\n }\n try {\n storage()?.setItem(BOOKMARKS_STORAGE_KEY, JSON.stringify(next))\n } catch {}\n adopt(next)\n notify()\n}\n\nfunction onStorage(event: { key: string | null }): void {\n if (event.key !== null && event.key !== BOOKMARKS_STORAGE_KEY) {\n return\n }\n const stored = readStored()\n if (stored) {\n adopt(stored)\n notify()\n }\n}\n\nexport function subscribeBookmarks(listener: () => void): () => void {\n listeners.add(listener)\n const target = storageEvents()\n if (listeners.size === 1 && target) {\n target.addEventListener('storage', onStorage)\n detachStorageEvent = () => target.removeEventListener('storage', onStorage)\n }\n return () => {\n listeners.delete(listener)\n if (listeners.size === 0) {\n detachStorageEvent?.()\n detachStorageEvent = undefined\n }\n }\n}\n\nexport function resetBookmarkStore(): void {\n loaded = undefined\n}\n","import { useCallback, useMemo, useSyncExternalStore } from 'react'\nimport { bookmarksFor, subscribeBookmarks, toggleBookmark } from '../lib/bookmark-store.ts'\n\nexport type UseBookmarksResult = {\n bookmarks: readonly string[]\n toggle: (itemId: string) => void\n}\n\nconst NONE: readonly string[] = Object.freeze([])\n\nexport function useBookmarks(sessionKey: string | undefined): UseBookmarksResult {\n const read = useCallback(() => (sessionKey ? bookmarksFor(sessionKey) : NONE), [sessionKey])\n const bookmarks = useSyncExternalStore(subscribeBookmarks, read, () => NONE)\n const toggle = useCallback(\n (itemId: string) => {\n if (sessionKey) {\n toggleBookmark(sessionKey, itemId)\n }\n },\n [sessionKey],\n )\n return useMemo(() => ({ bookmarks, toggle }), [bookmarks, toggle])\n}\n","import { useCallback, useMemo } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { draftKey, readDraft, writeDraft } from '../lib/draft-store.ts'\n\nexport type UseDraftResult = {\n // What was left unsent last time, read once so it can seed the composer on mount.\n initialText: string\n save: (text: string) => void\n clear: () => void\n}\n\n// Remember unsent composer text for a session. Purely local: it never reaches the gateway and never syncs between\n// clients, because a half-written prompt is not something anyone asked to publish.\nexport function useDraft(client: WorkerDeckClient, sessionId: string | undefined): UseDraftResult {\n const key = sessionId ? draftKey(client, sessionId) : undefined\n // Read once per key: re-reading on render would fight whatever is being typed.\n const initialText = useMemo(() => (key ? readDraft(key) : ''), [key])\n const save = useCallback(\n (text: string) => {\n if (key) {\n writeDraft(key, text)\n }\n },\n [key],\n )\n const clear = useCallback(() => {\n if (key) {\n writeDraft(key, '')\n }\n }, [key])\n return { initialText, save, clear }\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\nimport { profileUsageCacheKey, readProfileUsageCache, writeProfileUsageCache } from '../lib/profile-usage-cache.ts'\nimport type { ProfileSpend, ProfileUsage } from '@workerdeck/protocol'\n\nexport type UseProfileUsageOptions = {\n intervalMs?: number\n enabled?: boolean\n}\n\nexport type UseProfileUsageResult = {\n usage: ProfileUsage | undefined\n spend: ProfileSpend | undefined\n refresh: () => void\n}\n\nexport function useProfileUsage(\n client: WorkerDeckClient,\n profile: string | undefined,\n options: UseProfileUsageOptions = {},\n): UseProfileUsageResult {\n const { intervalMs = 60_000, enabled = true } = options\n const cacheKey = profile ? profileUsageCacheKey(client, profile) : undefined\n const [usage, setUsage] = useState<ProfileUsage | undefined>(() => (cacheKey ? readProfileUsageCache(cacheKey) : undefined))\n const [spend, setSpend] = useState<ProfileSpend | undefined>(undefined)\n const [unsupported, setUnsupported] = useState(false)\n const [nonce, setNonce] = useState(0)\n const refresh = useCallback(() => setNonce((n) => n + 1), [])\n\n // A previous profile's reading is another account's plan, not a stale view of this one - so switch to what we last\n // knew about *this* profile rather than to nothing. Blanking here is what made a session switch fall back on the\n // newly-attached session's own replayed numbers, which is the usage-reverts report.\n useEffect(() => {\n setUsage(cacheKey ? readProfileUsageCache(cacheKey) : undefined)\n setSpend(undefined)\n }, [cacheKey])\n\n const alive = useAliveRef()\n\n useEffect(() => {\n if (!profile || !enabled || unsupported) {\n return\n }\n let cancelled = false\n const load = () => {\n // `document` through globalThis: the extras project typechecks this source with no DOM lib.\n if ((globalThis as { document?: { hidden?: boolean } }).document?.hidden) {\n return\n }\n client\n .listProfiles()\n .then((res) => {\n if (cancelled || !alive.current) {\n return\n }\n const found = res.profiles.find((p) => p.name === profile)\n const next = found?.usage\n if (cacheKey) {\n writeProfileUsageCache(cacheKey, next)\n }\n setUsage(next)\n setSpend(found?.spend)\n })\n .catch((e: unknown) => {\n if (cancelled || !alive.current) {\n return\n }\n if (isRouteUnsupported(e)) {\n setUnsupported(true)\n }\n })\n }\n load()\n const timer = setInterval(load, intervalMs)\n return () => {\n cancelled = true\n clearInterval(timer)\n }\n }, [client, profile, enabled, unsupported, intervalMs, nonce, cacheKey])\n\n return { usage, spend, refresh }\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\nimport { errorMessage, type SessionInfo } from '@workerdeck/protocol'\nimport { useAsync } from '../lib/async-guards.ts'\n\nexport type UseSessionInfoResult = {\n info: SessionInfo | undefined\n loading: boolean\n error: string | undefined\n}\n\nexport function useSessionInfo(client: WorkerDeckClient, sessionId: string | undefined): UseSessionInfoResult {\n const { data, error, loading } = useAsync(() => client.getSession(sessionId!), [client, sessionId], { enabled: !!sessionId })\n return { info: data, loading, error: error === undefined ? undefined : errorMessage(error, 'Session not found') }\n}\n","export type OpenFile = {\n path: string\n name: string\n status: 'loading' | 'ready' | 'binary' | 'error'\n content?: string\n draft?: string\n bytes?: number\n hash?: string\n modifiedAt?: number\n error?: string\n saving?: boolean\n saveError?: string\n conflict?: boolean\n}\n\nexport function isDirty(file: OpenFile): boolean {\n return file.draft !== undefined && file.draft !== file.content\n}\n\nexport function currentText(file: OpenFile): string {\n return file.draft ?? file.content ?? ''\n}\n\nexport type OpenFilesState = {\n files: OpenFile[]\n activePath?: string\n}\n\nexport type OpenFilesAction =\n | { type: 'open'; path: string }\n | { type: 'close'; path: string }\n | { type: 'closeAll' }\n | { type: 'activate'; path: string }\n | {\n type: 'loaded'\n path: string\n content: string\n encoding: 'utf8' | 'base64'\n bytes: number\n hash: string\n modifiedAt: number\n }\n | { type: 'failed'; path: string; error: string }\n | { type: 'edit'; path: string; content: string }\n | { type: 'revert'; path: string }\n | { type: 'saveStart'; path: string }\n | { type: 'saved'; path: string; content: string; bytes: number; hash: string; modifiedAt: number }\n | { type: 'saveFailed'; path: string; error: string; conflict?: boolean }\n | { type: 'dismissConflict'; path: string }\n\nexport const initialOpenFilesState: OpenFilesState = { files: [] }\n\nexport function openFilesReducer(state: OpenFilesState, action: OpenFilesAction): OpenFilesState {\n switch (action.type) {\n case 'open': {\n if (state.files.some((f) => f.path === action.path)) {\n return state.activePath === action.path ? state : { ...state, activePath: action.path }\n }\n const file: OpenFile = { path: action.path, name: baseName(action.path), status: 'loading' }\n return { files: [...state.files, file], activePath: action.path }\n }\n\n case 'close': {\n const index = state.files.findIndex((f) => f.path === action.path)\n if (index === -1) {\n return state\n }\n const files = state.files.filter((f) => f.path !== action.path)\n if (state.activePath !== action.path) {\n return { ...state, files }\n }\n // The right-hand neighbour has slid into this index; a closed last tab has nothing there.\n const next = files[index] ?? files[index - 1]\n return { files, activePath: next?.path }\n }\n\n case 'closeAll': {\n return initialOpenFilesState\n }\n\n case 'activate': {\n if (!state.files.some((f) => f.path === action.path)) {\n return state\n }\n return state.activePath === action.path ? state : { ...state, activePath: action.path }\n }\n\n case 'loaded': {\n return patch(state, action.path, () => ({\n path: action.path,\n name: baseName(action.path),\n status: action.encoding === 'utf8' ? 'ready' : 'binary',\n content: action.encoding === 'utf8' ? action.content : undefined,\n bytes: action.bytes,\n hash: action.hash,\n modifiedAt: action.modifiedAt,\n }))\n }\n\n case 'failed': {\n return patch(state, action.path, (file) => ({ ...file, status: 'error', error: action.error }))\n }\n\n case 'edit': {\n return patch(state, action.path, (file) => (file.status === 'ready' ? { ...file, draft: action.content } : file))\n }\n\n case 'revert': {\n return patch(state, action.path, (file) => ({\n ...file,\n draft: undefined,\n saveError: undefined,\n conflict: false,\n }))\n }\n\n case 'saveStart': {\n return patch(state, action.path, (file) => ({\n ...file,\n saving: true,\n saveError: undefined,\n conflict: false,\n }))\n }\n\n case 'saved': {\n return patch(state, action.path, (file) => ({\n ...file,\n saving: false,\n saveError: undefined,\n conflict: false,\n content: action.content,\n bytes: action.bytes,\n hash: action.hash,\n modifiedAt: action.modifiedAt,\n draft: file.draft === action.content ? undefined : file.draft,\n }))\n }\n\n case 'saveFailed': {\n return patch(state, action.path, (file) => ({\n ...file,\n saving: false,\n saveError: action.error,\n conflict: action.conflict ?? false,\n }))\n }\n\n case 'dismissConflict': {\n return patch(state, action.path, (file) => ({\n ...file,\n conflict: false,\n saveError: undefined,\n }))\n }\n }\n}\n\nfunction patch(state: OpenFilesState, path: string, next: (file: OpenFile) => OpenFile): OpenFilesState {\n const index = state.files.findIndex((f) => f.path === path)\n if (index === -1) {\n return state\n }\n const current = state.files[index]!\n const updated = next(current)\n if (updated === current) {\n return state\n }\n const files = state.files.slice()\n files[index] = updated\n return { ...state, files }\n}\n\nfunction baseName(path: string): string {\n const trimmed = path.endsWith('/') ? path.slice(0, -1) : path\n return trimmed.slice(trimmed.lastIndexOf('/') + 1) || trimmed || path\n}\n","import { errorMessage } from '@workerdeck/protocol'\nimport { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'\nimport { WorkerDeckError, type WorkerDeckClient } from '@workerdeck/client'\nimport { currentText, initialOpenFilesState, isDirty, openFilesReducer, type OpenFile, type OpenFilesState } from '../lib/open-files.ts'\n\nexport type UseOpenFilesResult = OpenFilesState & {\n active: OpenFile | undefined\n hasUnsaved: boolean\n open: (path: string) => void\n close: (path: string) => void\n closeAll: () => void\n activate: (path: string) => void\n edit: (path: string, content: string) => void\n save: (path: string) => Promise<void>\n revert: (path: string) => void\n reload: (path: string) => void\n overwrite: (path: string) => Promise<void>\n dismissConflict: (path: string) => void\n}\n\nexport function useOpenFiles(client: WorkerDeckClient): UseOpenFilesResult {\n const [state, dispatch] = useReducer(openFilesReducer, initialOpenFilesState)\n\n const requested = useRef(new Set<string>())\n const alive = useRef(true)\n useEffect(() => {\n alive.current = true\n return () => {\n alive.current = false\n }\n }, [])\n\n const latest = useRef(state)\n useEffect(() => {\n latest.current = state\n }, [state])\n\n const loading = state.files.filter((f) => f.status === 'loading')\n // Joined so the effect's identity is the set of pending reads, not the array the reducer rebuilds.\n const pending = loading.map((f) => f.path).join('\\n')\n\n const read = useCallback(\n (path: string) =>\n client.readHostFile(path).then((response) => {\n if (!alive.current) {\n return undefined\n }\n dispatch({\n type: 'loaded',\n // The tab is keyed on the path asked for, never the canonical one the gateway answers with.\n path,\n content: response.content,\n encoding: response.encoding,\n bytes: response.bytes,\n hash: response.hash,\n modifiedAt: response.modifiedAt,\n })\n return response\n }),\n [client],\n )\n\n useEffect(() => {\n for (const path of pending ? pending.split('\\n') : []) {\n if (requested.current.has(path)) {\n continue\n }\n requested.current.add(path)\n read(path).catch((e: unknown) => {\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'failed',\n path,\n error: errorMessage(e, 'Could not read that file'),\n })\n })\n }\n }, [read, pending])\n\n const open = useCallback((path: string) => dispatch({ type: 'open', path }), [])\n const close = useCallback((path: string) => {\n requested.current.delete(path)\n dispatch({ type: 'close', path })\n }, [])\n const closeAll = useCallback(() => {\n requested.current.clear()\n dispatch({ type: 'closeAll' })\n }, [])\n const activate = useCallback((path: string) => dispatch({ type: 'activate', path }), [])\n const edit = useCallback((path: string, content: string) => dispatch({ type: 'edit', path, content }), [])\n const revert = useCallback((path: string) => dispatch({ type: 'revert', path }), [])\n const dismissConflict = useCallback((path: string) => dispatch({ type: 'dismissConflict', path }), [])\n\n const reload = useCallback(\n (path: string) => {\n requested.current.add(path)\n read(path).catch((e: unknown) => {\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'failed',\n path,\n error: errorMessage(e, 'Could not re-read that file'),\n })\n })\n },\n [read],\n )\n\n const write = useCallback(\n async (path: string, text: string, expectedHash: string | undefined) => {\n try {\n const response = await client.writeHostFile({ path, content: text, expectedHash })\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'saved',\n path,\n content: text,\n bytes: response.bytes,\n hash: response.hash,\n modifiedAt: response.modifiedAt,\n })\n } catch (e) {\n if (!alive.current) {\n return\n }\n const conflict = e instanceof WorkerDeckError && e.status === 409\n dispatch({\n type: 'saveFailed',\n path,\n conflict,\n error: conflict ? 'This file changed on disk since you opened it.' : errorMessage(e, 'Could not save that file'),\n })\n }\n },\n [client],\n )\n\n const save = useCallback(\n async (path: string) => {\n const file = latest.current.files.find((f) => f.path === path)\n if (!file || file.saving || !isDirty(file)) {\n return\n }\n dispatch({ type: 'saveStart', path })\n await write(path, currentText(file), file.hash)\n },\n [write],\n )\n\n const overwrite = useCallback(\n async (path: string) => {\n const file = latest.current.files.find((f) => f.path === path)\n if (!file || file.saving) {\n return\n }\n // Captured before the re-read, whose `loaded` clears the draft - the one thing \"take mine\" must not do.\n const mine = currentText(file)\n dispatch({ type: 'saveStart', path })\n try {\n const fresh = await client.readHostFile(path)\n if (!alive.current) {\n return\n }\n await write(path, mine, fresh.hash)\n } catch (e) {\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'saveFailed',\n path,\n error: errorMessage(e, 'Could not save that file'),\n })\n }\n },\n [client, write],\n )\n\n const active = useMemo(() => state.files.find((f) => f.path === state.activePath), [state.files, state.activePath])\n const hasUnsaved = useMemo(() => state.files.some(isDirty), [state.files])\n\n return {\n ...state,\n active,\n hasUnsaved,\n open,\n close,\n closeAll,\n activate,\n edit,\n save,\n revert,\n reload,\n overwrite,\n dismissConflict,\n }\n}\n","import type { SessionHandle } from '@workerdeck/client'\nimport { errorMessage, type ToolCallRequestFrame } from '@workerdeck/protocol'\nimport type { RunScriptResult, SandboxEngine, SandboxVfs } from '@workerdeck/sandbox'\n\nexport type ToolHostExecution = {\n executionId: string\n toolName: string\n status: 'running' | 'settled' | 'failed' | 'canceled'\n reason?: string\n startedAt: number\n endedAt?: number\n}\n\nexport type ToolHostRunner = (request: {\n script: string\n vfs: SandboxVfs\n timeoutMs: number\n memoryLimitBytes: number\n signal: AbortSignal\n}) => Promise<RunScriptResult>\n\nexport type ClientToolResult = { value: unknown } | { error: string; reason?: string }\n\nexport type ClientToolHandler = (\n input: unknown,\n context: { executionId: string; signal: AbortSignal },\n) => ClientToolResult | Promise<ClientToolResult>\n\nexport type ToolCallHostOptions = {\n tools?: string[]\n clientTools?: Record<string, ClientToolHandler>\n timeoutMs?: number\n memoryLimitBytes?: number\n loadEngine?: () => Promise<SandboxEngine>\n // The guest deadline preempts the interpreter only on the thread it runs on; a Web Worker is the way off this one.\n execute?: ToolHostRunner\n fetchText?: (url: string) => Promise<string>\n onExecution?: (execution: ToolHostExecution) => void\n}\n\ntype Work = (signal: AbortSignal) => Promise<Outcome>\n\ntype Outcome = { ok: true; value: unknown; logs?: string[] } | { ok: false; reason: string; error: string; logs?: string[] }\n\nexport function createToolCallHost(handle: SessionHandle, options: ToolCallHostOptions = {}): { dispose: () => void } {\n const inFlight = new Map<string, AbortController>()\n let enginePromise: Promise<SandboxEngine> | undefined\n let disposed = false\n\n const track = (execution: ToolHostExecution) => options.onExecution?.(execution)\n\n const settle = (frame: ToolCallRequestFrame, startedAt: number, outcome: Outcome) => {\n const { executionId, toolName } = frame\n if (outcome.ok) {\n handle.sendToolCallResult(executionId, { type: 'json', value: outcome.value }, outcome.logs)\n track({ executionId, toolName, status: 'settled', startedAt, endedAt: Date.now() })\n } else {\n handle.sendToolCallError(executionId, outcome.reason, outcome.error, outcome.logs)\n track({ executionId, toolName, status: 'failed', reason: outcome.reason, startedAt, endedAt: Date.now() })\n }\n }\n\n const execute = async (frame: ToolCallRequestFrame, startedAt: number, work: Work): Promise<void> => {\n const controller = new AbortController()\n inFlight.set(frame.executionId, controller)\n track({ executionId: frame.executionId, toolName: frame.toolName, status: 'running', startedAt })\n let outcome: Outcome\n try {\n outcome = await work(controller.signal)\n } catch (error) {\n outcome = { ok: false, reason: 'host_error', error: errorMessage(error) }\n }\n try {\n if (!disposed && inFlight.has(frame.executionId)) {\n settle(frame, startedAt, outcome)\n }\n } finally {\n inFlight.delete(frame.executionId)\n }\n }\n\n const runClientTool = (frame: ToolCallRequestFrame, handler: ClientToolHandler, startedAt: number): Promise<void> =>\n execute(frame, startedAt, async (signal) => {\n const result = await handler(frame.input, { executionId: frame.executionId, signal })\n return 'error' in result\n ? { ok: false, reason: result.reason ?? 'client_error', error: result.error }\n : { ok: true, value: result.value }\n })\n\n const runScript = (frame: ToolCallRequestFrame, script: string, startedAt: number): Promise<void> =>\n execute(frame, startedAt, async (signal) => {\n const sandbox = await import('@workerdeck/sandbox')\n const vfs = sandbox.createVfs(frame.vfsSeed)\n // Never above what the server asked for: it owns the deadline it gives up at.\n const timeoutMs = Math.min(frame.limits?.timeoutMs ?? Number.POSITIVE_INFINITY, options.timeoutMs ?? 5000)\n const memoryLimitBytes = Math.min(\n frame.limits?.memoryLimitBytes ?? Number.POSITIVE_INFINITY,\n options.memoryLimitBytes ?? 64 * 1024 * 1024,\n )\n let result: RunScriptResult\n if (options.execute) {\n result = await options.execute({ script, vfs, timeoutMs, memoryLimitBytes, signal })\n } else {\n enginePromise ??= (options.loadEngine ?? defaultLoadEngine)()\n result = await sandbox.runScript(await enginePromise, {\n script,\n vfs,\n timeoutMs,\n memoryLimitBytes,\n signal,\n fetchText: options.fetchText,\n })\n }\n const logs = result.logs.map((l) => `[${l.level}] ${l.text}`)\n return result.ok ? { ok: true, value: result.value, logs } : { ok: false, reason: result.reason, error: result.error, logs }\n })\n\n const run = async (frame: ToolCallRequestFrame): Promise<void> => {\n const startedAt = Date.now()\n const clientHandler = options.clientTools?.[frame.toolName]\n if (clientHandler) {\n return runClientTool(frame, clientHandler, startedAt)\n }\n const allowed = options.tools ?? ['eval_script']\n if (!allowed.includes(frame.toolName)) {\n settle(frame, startedAt, { ok: false, reason: 'unsupported_tool', error: `this client does not execute '${frame.toolName}'` })\n return\n }\n const script = (frame.input as { script?: unknown } | undefined)?.script\n if (typeof script !== 'string') {\n settle(frame, startedAt, { ok: false, reason: 'invalid_input', error: 'expected a string `script` input' })\n return\n }\n return runScript(frame, script, startedAt)\n }\n\n const offRequest = handle.on('toolCallRequest', (frame) => void run(frame))\n const offCancel = handle.on('toolCallCanceled', ({ executionId, reason }) => {\n const controller = inFlight.get(executionId)\n if (!controller) {\n return\n }\n controller.abort()\n inFlight.delete(executionId)\n track({\n executionId,\n toolName: '',\n status: 'canceled',\n reason,\n startedAt: Date.now(),\n endedAt: Date.now(),\n })\n })\n\n return {\n dispose: () => {\n disposed = true\n offRequest()\n offCancel()\n for (const controller of inFlight.values()) {\n controller.abort()\n }\n inFlight.clear()\n },\n }\n}\n\nasync function defaultLoadEngine(): Promise<SandboxEngine> {\n const [sandbox, variant] = await Promise.all([import('@workerdeck/sandbox'), import('@jitl/quickjs-singlefile-browser-release-asyncify')])\n return sandbox.loadEngine(variant as never)\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { SessionHandle } from '@workerdeck/client'\nimport { createToolCallHost, type ToolCallHostOptions, type ToolHostExecution } from '../lib/tool-host.ts'\n\nexport type UseToolCallHostOptions = ToolCallHostOptions & {\n enabled?: boolean\n historyLimit?: number\n}\n\nexport function useToolCallHost(\n handle: SessionHandle | undefined,\n options: UseToolCallHostOptions = {},\n): { executions: ToolHostExecution[] } {\n const [executions, setExecutions] = useState<ToolHostExecution[]>([])\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n useEffect(() => {\n if (!handle || options.enabled === false) {\n return\n }\n const host = createToolCallHost(handle, {\n // Getters read the ref at call time, so inline objects and closures never resubscribe.\n get tools() {\n const base = optionsRef.current.tools\n const client = optionsRef.current.clientTools\n if (!client) {\n return base\n }\n const clientNames = Object.keys(client)\n return base ? [...new Set([...base, ...clientNames])] : clientNames\n },\n get clientTools() {\n return optionsRef.current.clientTools\n },\n get timeoutMs() {\n return optionsRef.current.timeoutMs\n },\n get memoryLimitBytes() {\n return optionsRef.current.memoryLimitBytes\n },\n get loadEngine() {\n return optionsRef.current.loadEngine\n },\n get execute() {\n return optionsRef.current.execute\n },\n get fetchText() {\n return optionsRef.current.fetchText\n },\n onExecution: (execution) => {\n optionsRef.current.onExecution?.(execution)\n const limit = optionsRef.current.historyLimit ?? 50\n setExecutions((prev) => [...prev.filter((e) => e.executionId !== execution.executionId), execution].slice(-limit))\n },\n })\n return () => host.dispose()\n }, [handle, options.enabled])\n\n return { executions }\n}\n","import type { TranscriptItem } from './transcript.ts'\n\nexport type RecapSummary = {\n turns: number\n replies: number\n tools: number\n toolNames: string[]\n files: number\n errors: number\n pending: number\n any: boolean\n}\n\nexport type RecapInput = {\n items: readonly TranscriptItem[]\n pendingApprovals?: readonly unknown[]\n}\n\n// The boundary is clamped, never rejected: a transcript can shrink (a `/clear`, a compaction).\nexport function summarizeSince(state: RecapInput, fromIndex: number): RecapSummary {\n const start = Math.max(0, Math.min(fromIndex, state.items.length))\n const fresh = state.items.slice(start)\n const toolCounts = new Map<string, number>()\n let turns = 0\n let replies = 0\n let tools = 0\n let files = 0\n let errors = 0\n\n for (const item of fresh) {\n switch (item.kind) {\n case 'turn_result': {\n turns += 1\n if (item.isError) {\n errors += 1\n }\n break\n }\n case 'assistant_text': {\n replies += 1\n break\n }\n case 'tool_call': {\n tools += 1\n toolCounts.set(item.name, (toolCounts.get(item.name) ?? 0) + 1)\n if (item.status === 'failed' || item.result?.isError) {\n errors += 1\n }\n break\n }\n case 'file_delivered': {\n files += 1\n break\n }\n case 'notice': {\n if (item.level === 'error') {\n errors += 1\n }\n break\n }\n default: {\n break\n }\n }\n }\n\n const toolNames = [...toolCounts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([name]) => name)\n const pending = state.pendingApprovals?.length ?? 0\n return {\n turns,\n replies,\n tools,\n toolNames,\n files,\n errors,\n pending,\n any: turns + replies + tools + files + errors + pending > 0,\n }\n}\n\nexport function recapLine(summary: RecapSummary): string | undefined {\n if (!summary.any) {\n return undefined\n }\n const parts: string[] = []\n if (summary.turns > 0) {\n parts.push(plural(summary.turns, 'turn'))\n } else if (summary.replies > 0) {\n parts.push(plural(summary.replies, 'reply', 'replies'))\n }\n if (summary.tools > 0) {\n const named = summary.toolNames.slice(0, 3).join(', ')\n const rest = summary.toolNames.length - 3\n parts.push(`${plural(summary.tools, 'tool call')}${named ? ` (${named}${rest > 0 ? `, +${rest}` : ''})` : ''}`)\n }\n if (summary.files > 0) {\n parts.push(plural(summary.files, 'file'))\n }\n if (summary.errors > 0) {\n parts.push(plural(summary.errors, 'error'))\n }\n if (summary.pending > 0) {\n parts.push(`${plural(summary.pending, 'approval')} waiting`)\n }\n return parts.join(' · ')\n}\n\nfunction plural(count: number, one: string, many = `${one}s`): string {\n return `${count} ${count === 1 ? one : many}`\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { SessionHandle } from '@workerdeck/client'\nimport type { ShellInfo } from '@workerdeck/protocol'\n\nexport type ShellTerminalSize = { cols: number; rows: number }\n\nexport type ShellTerminalStatus = 'idle' | 'attaching' | 'attached' | 'detached'\n\nexport type ShellAttachment = {\n shell: ShellInfo\n cols: number\n rows: number\n scrollback: string\n}\n\nexport type UseShellTerminalOptions = {\n onData: (data: string) => void\n onEnded?: (reason: string) => void\n onAttached?: (attachment: ShellAttachment) => void\n}\n\nexport type UseShellTerminalResult = {\n status: ShellTerminalStatus\n shell: ShellInfo | undefined\n reason: string | undefined\n attach: (size: ShellTerminalSize) => void\n write: (data: string) => void\n resize: (size: ShellTerminalSize) => void\n detach: () => void\n}\n\n// PTY bytes never enter React state, the transcript reducer or the transcript cache: they go\n// straight to the caller's renderer through a ref, so a noisy `npm run dev` re-renders nothing.\nexport function useShellTerminal(\n handle: SessionHandle | undefined,\n shellId: string | undefined,\n options: UseShellTerminalOptions,\n): UseShellTerminalResult {\n const [status, setStatus] = useState<ShellTerminalStatus>('idle')\n const [shell, setShell] = useState<ShellInfo | undefined>(undefined)\n const [reason, setReason] = useState<string | undefined>(undefined)\n const optionsRef = useRef(options)\n optionsRef.current = options\n const sizeRef = useRef<ShellTerminalSize>({ cols: 80, rows: 24 })\n const wantAttachRef = useRef(false)\n\n useEffect(() => {\n wantAttachRef.current = false\n setStatus('idle')\n setShell(undefined)\n setReason(undefined)\n }, [handle, shellId])\n\n useEffect(() => {\n if (!handle || shellId === undefined) {\n return\n }\n const offAttached = handle.on('shellAttached', (frame) => {\n if (frame.shellId !== shellId) {\n return\n }\n sizeRef.current = { cols: frame.cols, rows: frame.rows }\n setShell(frame.shell)\n setReason(undefined)\n setStatus('attached')\n const attachment: ShellAttachment = { shell: frame.shell, cols: frame.cols, rows: frame.rows, scrollback: frame.scrollback }\n if (optionsRef.current.onAttached) {\n optionsRef.current.onAttached(attachment)\n } else if (frame.scrollback) {\n optionsRef.current.onData(frame.scrollback)\n }\n })\n const offOutput = handle.on('shellOutput', (frame) => {\n if (frame.shellId === shellId) {\n optionsRef.current.onData(frame.data)\n }\n })\n const offDetached = handle.on('shellDetached', (frame) => {\n if (frame.shellId !== shellId) {\n return\n }\n wantAttachRef.current = false\n setReason(frame.reason)\n setStatus('detached')\n optionsRef.current.onEnded?.(frame.reason)\n })\n // A shell outlives the socket, so a reconnect re-attaches and the gateway replays the\n // scrollback into a reset screen rather than leaving a live pane frozen.\n const offConnection = handle.on('connectionChange', (connected) => {\n if (!wantAttachRef.current) {\n return\n }\n if (connected) {\n setStatus('attaching')\n handle.attachShell(shellId, sizeRef.current)\n } else {\n setStatus((current) => (current === 'attached' ? 'attaching' : current))\n }\n })\n return () => {\n offAttached()\n offOutput()\n offDetached()\n offConnection()\n if (wantAttachRef.current) {\n wantAttachRef.current = false\n handle.detachShell(shellId)\n }\n }\n }, [handle, shellId])\n\n const attach = useCallback(\n (size: ShellTerminalSize) => {\n if (!handle || shellId === undefined) {\n return\n }\n sizeRef.current = size\n wantAttachRef.current = true\n setReason(undefined)\n setStatus('attaching')\n handle.attachShell(shellId, size)\n },\n [handle, shellId],\n )\n\n const write = useCallback(\n (data: string) => {\n if (handle && shellId !== undefined) {\n handle.writeShell(shellId, data)\n }\n },\n [handle, shellId],\n )\n\n const resize = useCallback(\n (size: ShellTerminalSize) => {\n if (size.cols === sizeRef.current.cols && size.rows === sizeRef.current.rows) {\n return\n }\n sizeRef.current = size\n if (handle && shellId !== undefined && wantAttachRef.current) {\n handle.resizeShell(shellId, size)\n }\n },\n [handle, shellId],\n )\n\n const detach = useCallback(() => {\n if (handle && shellId !== undefined && wantAttachRef.current) {\n handle.detachShell(shellId)\n }\n wantAttachRef.current = false\n setStatus('idle')\n }, [handle, shellId])\n\n return useMemo(() => ({ status, shell, reason, attach, write, resize, detach }), [status, shell, reason, attach, write, resize, detach])\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["entries","storage","EMPTY"],"sources":["../src/lib/transcript.ts","../src/lib/transcript-cache.ts","../src/lib/attach-plan.ts","../src/hooks/use-session.ts","../src/lib/profile-usage-cache.ts","../src/lib/draft-store.ts","../src/hooks/use-attachments.ts","../src/lib/prompt-tokens.ts","../src/lib/async-guards.ts","../src/lib/host-tree.ts","../src/hooks/use-host-files.ts","../src/hooks/use-peer-sessions.ts","../src/hooks/use-project-icons.ts","../src/lib/bookmark-store.ts","../src/hooks/use-bookmarks.ts","../src/hooks/use-draft.ts","../src/hooks/use-profile-usage.ts","../src/hooks/use-session-info.ts","../src/lib/open-files.ts","../src/hooks/use-open-files.ts","../src/lib/tool-host.ts","../src/hooks/use-tool-host.ts","../src/lib/recap.ts","../src/hooks/use-shell-terminal.ts"],"sourcesContent":["import { ENGINE_CAPABILITIES, mergeUsage, orderUsageWindows } from '@workerdeck/protocol'\nimport type {\n ApiMessage,\n ByModel,\n ChecklistItem,\n ContentBlock,\n ContextUsage,\n EngineCapabilities,\n FilePatch,\n MessageAttachment,\n MessageOrigin,\n ModelOption,\n PermissionMode,\n PermissionRequest,\n ProfileEngine,\n RateLimitInfo,\n SessionEvent,\n SessionInfo,\n SessionStatus,\n ShellInfo,\n SkillInfo,\n SlashCommandInfo,\n ToolExecutionBackend,\n ToolExecutionOutput,\n ToolResultBlock,\n UsageWindowRow,\n} from '@workerdeck/protocol'\n\nexport type ToolResultImageRef = { partIndex: number; mediaType: string; bytes: number; sourceSeq: number }\n\nexport type TranscriptItem =\n | {\n kind: 'user'\n id: string\n text: string\n attachments?: MessageAttachment[]\n origin?: MessageOrigin\n // Optional, not `string | null` like the other kinds: there forgetting to stamp it must not typecheck; here almost every prompt has no parent.\n parentToolUseId?: string\n }\n | {\n kind: 'assistant_text'\n id: string\n text: string\n streaming: boolean\n parentToolUseId: string | null\n }\n | { kind: 'thinking'; id: string; text: string; parentToolUseId: string | null }\n | {\n kind: 'tool_call'\n id: string\n name: string\n input: unknown\n parentToolUseId: string | null\n // The event's own `ts`, never a receive time - replay-stable, stamped at creation only; absent reads as \"no elapsed\", never as the epoch.\n ts?: number\n status: 'running' | 'pending' | 'deferred' | 'settled' | 'failed'\n result?: {\n text: string\n isError: boolean\n truncated?: boolean\n totalChars?: number\n sourceSeq?: number\n images?: ReadonlyArray<ToolResultImageRef>\n }\n patch?: FilePatch\n executionId?: string\n backend?: ToolExecutionBackend\n logs?: string[]\n liveTail?: string\n }\n | {\n kind: 'turn_result'\n id: string\n subtype: string\n isError: boolean\n durationMs: number\n totalCostUsd: number\n costUsd?: number\n errors?: string[]\n }\n | { kind: 'notice'; id: string; level: 'info' | 'error'; text: string }\n | {\n kind: 'compaction'\n id: string\n parentToolUseId: string | null\n pending?: boolean\n trigger?: 'manual' | 'auto'\n preTokens?: number\n postTokens?: number\n error?: string\n }\n | { kind: 'file_delivered'; id: string; path: string; bytes: number; description?: string }\n | {\n kind: 'shell'\n id: string\n shell: ShellInfo\n text: string\n truncated: boolean\n expanded?: string\n // The record is gone from the gateway: swept past its TTL, or minted by a gateway this client is not talking to.\n missing?: boolean\n }\n\nexport type ProducedFileRef = {\n fileId: string\n mediaType?: string\n bytes?: number\n}\n\nexport type TranscriptState = {\n status: SessionStatus\n statusDetail?: string\n engineAsleep?: boolean\n model?: string\n effort?: string | null\n cwd?: string\n sdkSessionId?: string\n engine?: ProfileEngine\n capabilities: EngineCapabilities\n session?: SessionInfo\n models?: ModelOption[]\n commands?: SlashCommandInfo[]\n skills?: SkillInfo[]\n checklist?: ChecklistItem[]\n // Only what the client cannot derive: host- and MCP-declared titles. `toolTitle()` folds the\n // built-in table in on top of this.\n toolTitles?: Record<string, string>\n // Keyed by the absolute path the runner reported: a tool card looks up the `savedPath` in its input and resolves it via `client.producedFileUrl`.\n producedFiles?: Record<string, ProducedFileRef>\n\n defaultModel?: string\n permissionMode?: PermissionMode\n contextUsage?: ContextUsage\n rateLimits?: Record<string, RateLimitInfo>\n rateLimitsUpdatedAt?: number\n subscriptionType?: string\n items: TranscriptItem[]\n pendingApprovals: PermissionRequest[]\n totalCostUsd: number\n costUsd?: number\n usageByModel?: ByModel\n lastSeq: number\n}\n\nexport const initialTranscriptState: TranscriptState = {\n status: 'starting',\n capabilities: ENGINE_CAPABILITIES.claude,\n items: [],\n pendingApprovals: [],\n totalCostUsd: 0,\n lastSeq: 0,\n}\n\nconst STREAMING_ID = 'streaming'\nconst STREAMING_THINKING_ID = 'streaming-thinking'\n\nconst LOCAL_COMMAND_OUTPUT = /^<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>$/\nconst LOCAL_COMMAND_ELEMENT = /<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>/g\nconst LOCAL_COMMAND_CAVEAT = '<local-command-caveat>'\n\nconst SHELL_MORE_OUTPUT = /^\\[\\.\\.\\. more output \\.\\.\\.\\]$/\nconst SHELL_END_LINE = /^\\[(exit -?\\d+|killed|timed out|ended|failed to start)[^\\]]*\\]$/\n\nexport type ShellItem = Extract<TranscriptItem, { kind: 'shell' }>\n\n// The row's text is core's `shellInlineText`: one framed element whose first line is the command and whose\n// last is the end line, both of which the row draws from the record instead.\nexport function shellRowText(shell: ShellInfo, text: string): { text: string; truncated: boolean } {\n const body = LOCAL_COMMAND_OUTPUT.exec(text.trim())?.[2] ?? text\n const lines = body.split('\\n')\n if (lines[0]?.startsWith('$ ')) {\n lines.shift()\n }\n if (shell.status === 'exited' && lines.length > 0 && SHELL_END_LINE.test(lines[lines.length - 1]!)) {\n lines.pop()\n }\n let truncated = false\n const kept = lines.filter((line) => {\n if (!SHELL_MORE_OUTPUT.test(line)) {\n return true\n }\n truncated = true\n return false\n })\n return { text: kept.join('\\n').trimEnd(), truncated }\n}\n\nfunction shellItem(id: string, shell: ShellInfo, text: string, previous: ShellItem | undefined): ShellItem {\n const row = shellRowText(shell, text)\n return {\n kind: 'shell',\n id,\n shell,\n text: row.text,\n truncated: row.truncated,\n // Carried across the re-emit: a row the reader expanded must not collapse under them when the shell ticks.\n ...(previous?.expanded !== undefined && { expanded: previous.expanded }),\n }\n}\n\nfunction findShell(items: readonly TranscriptItem[], shellId: string): ShellItem | undefined {\n return items.find((item): item is ShellItem => item.kind === 'shell' && item.shell.id === shellId)\n}\n\nconst COMMAND_NAME = /<command-name>([\\s\\S]*?)<\\/command-name>/\nconst COMMAND_ARGS = /<command-args>([\\s\\S]*?)<\\/command-args>/\n// A message whose first text block is the deferred `!` flush is synthetic as a whole, but the block after it is\n// the person's own message. Only that shape earns the exemption - `<task-notification>` and the rest stay hidden.\nfunction carriesCaveat(content: ApiMessage['content']): boolean {\n return contentToBlocks(content).some(\n (block) => block.type === 'text' && (block as { text: string }).text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT),\n )\n}\n\nfunction streamingTextId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_ID : `${STREAMING_ID}:${parentToolUseId}`\n}\nfunction streamingThinkingId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_THINKING_ID : `${STREAMING_THINKING_ID}:${parentToolUseId}`\n}\nfunction isStreamingItem(item: TranscriptItem): boolean {\n return (\n (item.kind === 'assistant_text' && item.id.startsWith(STREAMING_ID)) ||\n (item.kind === 'thinking' && item.id.startsWith(STREAMING_THINKING_ID))\n )\n}\n\nexport function blockText(content: ToolResultBlock['content']): string {\n if (content === undefined) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n return content\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n}\n\nfunction imageRefsOf(content: ToolResultBlock['content'], seq: number): ReadonlyArray<ToolResultImageRef> | undefined {\n if (!Array.isArray(content)) {\n return undefined\n }\n const refs = content.flatMap((part) =>\n part.type === 'image_ref'\n ? [\n {\n partIndex: Number(part.part_index),\n mediaType: String(part.media_type ?? 'application/octet-stream'),\n bytes: Number(part.bytes ?? 0),\n sourceSeq: seq,\n },\n ]\n : [],\n )\n return refs.length > 0 ? refs : undefined\n}\n\nfunction contentToBlocks(content: string | ContentBlock[]): ContentBlock[] {\n return typeof content === 'string' ? [{ type: 'text', text: content }] : content\n}\n\nfunction outputText(output: ToolExecutionOutput): string {\n if (output.type === 'text') {\n return output.value\n }\n try {\n return JSON.stringify(output.value)\n } catch {\n return String(output.value)\n }\n}\n\nfunction slashCommandText(text: string): string | undefined {\n const name = COMMAND_NAME.exec(text)?.[1]?.trim()\n if (!name) {\n return undefined\n }\n const args = COMMAND_ARGS.exec(text)?.[1]?.trim()\n return args ? `${name} ${args}` : name\n}\n\n// Streaming ids are unique per agent and the in-flight row sits at the tail, so a token scans a few items, not the transcript.\nfunction findLastIndexOf(items: readonly TranscriptItem[], kind: TranscriptItem['kind'], id: string): number {\n for (let index = items.length - 1; index >= 0; index--) {\n const item = items[index]\n if (item?.id === id && item.kind === kind) {\n return index\n }\n }\n return -1\n}\n\nfunction replaceAt(items: TranscriptItem[], index: number, item: TranscriptItem): TranscriptItem[] {\n if (index === -1) {\n return [...items, item]\n }\n const next = [...items]\n next[index] = item\n return next\n}\n\nfunction upsert(items: TranscriptItem[], item: TranscriptItem): TranscriptItem[] {\n const index = items.findIndex((existing) => existing.id === item.id && existing.kind === item.kind)\n return replaceAt(items, index, item)\n}\n\nexport function seedFromSessionInfo(state: TranscriptState, info: SessionInfo): TranscriptState {\n // No event carries the engine - the snapshot is the only source.\n const engine = info.engine ?? state.engine\n return {\n ...state,\n // With held state (reconnect, warm cache seed) the held status stands: any change since is a `status_changed` in the replay span - events stay the one authority.\n status: state.lastSeq === 0 ? info.status : state.status,\n engineAsleep: state.lastSeq === 0 ? info.engineAsleep : state.engineAsleep,\n model: state.model ?? info.model,\n effort: state.effort !== undefined ? state.effort : info.effort,\n permissionMode: state.permissionMode ?? info.permissionMode,\n cwd: state.cwd ?? info.cwd,\n sdkSessionId: state.sdkSessionId ?? info.sdkSessionId,\n engine,\n capabilities: info.capabilities ?? ENGINE_CAPABILITIES[engine ?? 'claude'],\n // Spend outlives the log a replay is built from: a dormant wake starts a fresh log with no `turn_result` in it,\n // so the snapshot is the only thing that still knows what the session cost before it slept.\n totalCostUsd: state.totalCostUsd || (info.totalCostUsd ?? 0),\n costUsd: state.costUsd ?? info.costUsd,\n usageByModel: state.usageByModel ?? info.usageByModel,\n session: info,\n }\n}\n\nexport function rateLimitWindows(state: Pick<TranscriptState, 'rateLimits' | 'rateLimitsUpdatedAt'>): UsageWindowRow[] {\n return orderUsageWindows(mergeUsage({ rateLimits: state.rateLimits, updatedAt: state.rateLimitsUpdatedAt }, undefined))\n}\n\nexport function hydrateToolResult(state: TranscriptState, toolUseId: string, text: string): TranscriptState {\n let changed = false\n const items = state.items.map((item) => {\n if (item.kind !== 'tool_call' || item.id !== toolUseId || !item.result?.truncated) {\n return item\n }\n changed = true\n // `images` survives the text hydration: the refs carry their own `sourceSeq` because the result's clears here, and without them the row's pictures are unloadable.\n return {\n ...item,\n result: {\n text,\n isError: item.result.isError,\n ...(item.result.images && { images: item.result.images }),\n },\n }\n })\n return changed ? { ...state, items } : state\n}\n\n// `shell` absent is the 404: the record was swept or belongs to a gateway generation this one cannot answer for.\nexport function hydrateShellRow(state: TranscriptState, shellId: string, shell: ShellInfo | undefined): TranscriptState {\n const current = findShell(state.items, shellId)\n if (!current) {\n return state\n }\n const next: ShellItem = shell === undefined ? { ...current, missing: true } : { ...current, shell, missing: undefined }\n return { ...state, items: state.items.map((item) => (item === current ? next : item)) }\n}\n\nexport function hydrateShellOutput(state: TranscriptState, shellId: string, text: string): TranscriptState {\n const current = findShell(state.items, shellId)\n if (!current) {\n return state\n }\n return { ...state, items: state.items.map((item) => (item === current ? { ...current, expanded: text, missing: undefined } : item)) }\n}\n\nexport function applyEvent(state: TranscriptState, event: SessionEvent): TranscriptState {\n if (event.seq <= state.lastSeq) {\n return state\n }\n const base: TranscriptState = { ...state, lastSeq: event.seq }\n\n switch (event.type) {\n case 'system_init': {\n return {\n ...base,\n model: event.model,\n cwd: event.cwd,\n sdkSessionId: event.sdkSessionId,\n permissionMode: event.permissionMode,\n }\n }\n\n case 'status_changed': {\n return { ...base, status: event.status, statusDetail: event.detail }\n }\n\n case 'engine_sleep': {\n return { ...base, engineAsleep: event.asleep || undefined }\n }\n\n case 'capabilities': {\n return {\n ...base,\n models: event.models,\n commands: event.commands,\n defaultModel: event.defaultModel ?? base.defaultModel,\n }\n }\n\n case 'skills': {\n return { ...base, skills: event.skills }\n }\n\n case 'checklist': {\n return { ...base, checklist: event.items.length > 0 ? event.items : undefined }\n }\n\n case 'tool_titles': {\n return { ...base, toolTitles: { ...base.toolTitles, ...event.titles } }\n }\n\n case 'file_produced': {\n return {\n ...base,\n producedFiles: {\n ...base.producedFiles,\n [event.path]: {\n fileId: event.fileId,\n ...(event.mediaType ? { mediaType: event.mediaType } : {}),\n ...(event.bytes !== undefined ? { bytes: event.bytes } : {}),\n },\n },\n }\n }\n\n case 'model_changed': {\n return event.model === undefined ? base : { ...base, model: event.model }\n }\n\n case 'effort_changed': {\n return { ...base, effort: event.effort }\n }\n\n case 'permission_mode_changed': {\n return { ...base, permissionMode: event.mode }\n }\n\n case 'context_usage': {\n return { ...base, contextUsage: event.usage }\n }\n\n case 'rate_limit': {\n const key = event.info.rateLimitType\n if (!key) {\n return base\n }\n return {\n ...base,\n rateLimits: { ...base.rateLimits, [key]: event.info },\n rateLimitsUpdatedAt: event.ts,\n }\n }\n\n case 'plan_info': {\n return { ...base, subscriptionType: event.subscriptionType }\n }\n\n case 'conversation_reset': {\n return {\n ...base,\n items:\n event.agentReason === undefined\n ? []\n : [{ kind: 'notice', id: `reset-${event.seq}`, level: 'info', text: agentResetNotice(event.agentReason) }],\n contextUsage: undefined,\n checklist: undefined,\n sdkSessionId: event.sdkSessionId ?? base.sdkSessionId,\n }\n }\n\n // Appends where the reset above empties, and leaves `contextUsage` alone: the engine reports post-compaction occupancy itself.\n case 'context_compacted': {\n return {\n ...base,\n items: upsert(base.items, {\n kind: 'compaction',\n id: event.uuid,\n parentToolUseId: event.parentToolUseId ?? null,\n pending: event.pending,\n trigger: event.trigger,\n preTokens: event.preTokens,\n postTokens: event.postTokens,\n error: event.error,\n }),\n }\n }\n\n case 'user_message': {\n let items = base.items\n for (const block of contentToBlocks(event.message.content)) {\n if (block.type === 'tool_result') {\n const toolResult = block as ToolResultBlock\n const isError = toolResult.is_error === true\n items = items.map((item) =>\n item.kind === 'tool_call' && item.id === toolResult.tool_use_id\n ? {\n ...item,\n liveTail: undefined,\n status: isError ? 'failed' : 'settled',\n result: {\n text: blockText(toolResult.content),\n isError,\n ...(toolResult.truncated && {\n truncated: true as const,\n totalChars: toolResult.total_chars,\n sourceSeq: event.seq,\n }),\n ...(imageRefsOf(toolResult.content, event.seq) && {\n images: imageRefsOf(toolResult.content, event.seq),\n }),\n },\n ...(event.patch && { patch: event.patch }),\n }\n : item,\n )\n } else if (block.type === 'text') {\n const text = (block as { text: string }).text\n const rowId = event.uuid ?? `user-${event.seq}`\n // Both branches sit ahead of the synthetic guard on purpose. A `!` shell run is emitted synthetic so it\n // scores zero activity and zero prose, but it is the one synthetic message a person is meant to see; and\n // on resume the SDK hands back the shell output and the user's own text as one message, which\n // `isSyntheticUserText` then marks synthetic whole. Without this the user's own words vanish on reload.\n const localOutput = LOCAL_COMMAND_OUTPUT.exec(text.trim())\n if (event.shell) {\n const existing = items.find((item): item is ShellItem => item.kind === 'shell' && item.id === rowId)\n items = upsert(items, shellItem(rowId, event.shell, text, existing))\n } else if (localOutput) {\n items = upsert(items, {\n kind: 'notice',\n id: rowId,\n level: localOutput[1] === 'stderr' ? 'error' : 'info',\n text: localOutput[2].trim(),\n })\n } else if (text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT)) {\n let index = 0\n for (const match of text.matchAll(LOCAL_COMMAND_ELEMENT)) {\n items = upsert(items, {\n kind: 'notice',\n id: `${rowId}#${index++}`,\n level: match[1] === 'stderr' ? 'error' : 'info',\n text: match[2].trim(),\n })\n }\n } else if (!event.synthetic || carriesCaveat(event.message.content)) {\n items = upsert(items, {\n kind: 'user',\n id: event.uuid ?? `user-${event.seq}`,\n text: slashCommandText(text) ?? text,\n attachments: event.attachments,\n ...(event.origin && { origin: event.origin }),\n ...(event.parentToolUseId != null && {\n parentToolUseId: event.parentToolUseId,\n }),\n })\n }\n }\n }\n return { ...base, items }\n }\n\n case 'assistant_message': {\n const streamingText = streamingTextId(event.parentToolUseId)\n const streamingThought = streamingThinkingId(event.parentToolUseId)\n let streamedThinking =\n base.items.find(\n (item): item is Extract<TranscriptItem, { kind: 'thinking' }> => item.kind === 'thinking' && item.id === streamingThought,\n )?.text ?? ''\n let items = base.items.filter(\n (item) =>\n !(item.kind === 'assistant_text' && item.id === streamingText) && !(item.kind === 'thinking' && item.id === streamingThought),\n )\n const blocks = contentToBlocks(event.message.content)\n blocks.forEach((block, index) => {\n const id = `${event.uuid}-${index}`\n if (block.type === 'text') {\n items = upsert(items, {\n kind: 'assistant_text',\n id,\n text: (block as { text: string }).text,\n streaming: false,\n parentToolUseId: event.parentToolUseId,\n })\n } else if (block.type === 'thinking') {\n const text = (block as { thinking: string }).thinking || streamedThinking\n streamedThinking = ''\n if (text.trim() === '') {\n return\n }\n items = upsert(items, {\n kind: 'thinking',\n id,\n text,\n parentToolUseId: event.parentToolUseId,\n })\n } else if (block.type === 'tool_use') {\n const toolUse = block as { id: string; name: string; input: unknown }\n items = upsert(items, {\n kind: 'tool_call',\n id: toolUse.id,\n name: toolUse.name,\n input: toolUse.input,\n parentToolUseId: event.parentToolUseId,\n status: 'running',\n ts: event.ts,\n })\n }\n })\n return { ...base, items }\n }\n\n case 'stream_delta': {\n const delta = event.event as {\n type: string\n delta?: { type?: string; text?: string; thinking?: string }\n }\n if (delta.type !== 'content_block_delta') {\n return base\n }\n if (delta.delta?.type === 'text_delta') {\n const id = streamingTextId(event.parentToolUseId)\n const index = findLastIndexOf(base.items, 'assistant_text', id)\n const existing = index === -1 ? undefined : (base.items[index] as Extract<TranscriptItem, { kind: 'assistant_text' }>)\n const item: TranscriptItem = {\n kind: 'assistant_text',\n id,\n text: (existing?.text ?? '') + (delta.delta.text ?? ''),\n streaming: true,\n parentToolUseId: event.parentToolUseId,\n }\n return { ...base, items: replaceAt(base.items, index, item) }\n }\n if (delta.delta?.type === 'thinking_delta') {\n const id = streamingThinkingId(event.parentToolUseId)\n const index = findLastIndexOf(base.items, 'thinking', id)\n const existing = index === -1 ? undefined : (base.items[index] as Extract<TranscriptItem, { kind: 'thinking' }>)\n const text = (existing?.text ?? '') + (delta.delta.thinking ?? '')\n // Whitespace-only (encrypted) thinking creates no item - `turn_result` would finalize a permanent empty row; text rebuilds from `existing`, so skipping loses nothing.\n if (text.trim() === '') {\n return base\n }\n const item: TranscriptItem = {\n kind: 'thinking',\n id,\n text,\n parentToolUseId: event.parentToolUseId,\n }\n return { ...base, items: replaceAt(base.items, index, item) }\n }\n return base\n }\n\n case 'turn_result': {\n return {\n ...base,\n totalCostUsd: event.totalCostUsd,\n costUsd: event.costUsd ?? base.costUsd,\n usageByModel: event.usageByModel ?? base.usageByModel,\n items: [\n ...base.items.map((item) => {\n if (!isStreamingItem(item)) {\n return item\n }\n const agent = 'parentToolUseId' in item && item.parentToolUseId ? `-${item.parentToolUseId}` : ''\n return item.kind === 'assistant_text'\n ? { ...item, id: `text-${event.seq}${agent}`, streaming: false }\n : { ...item, id: `thinking-${event.seq}${agent}` }\n }),\n {\n kind: 'turn_result',\n id: `turn-${event.seq}`,\n subtype: event.subtype,\n isError: event.isError,\n durationMs: event.durationMs,\n totalCostUsd: event.totalCostUsd,\n costUsd: event.costUsd,\n errors: event.errors,\n },\n ],\n }\n }\n\n case 'permission_requested': {\n return { ...base, pendingApprovals: [...base.pendingApprovals, event.request] }\n }\n\n case 'permission_resolved': {\n return {\n ...base,\n pendingApprovals: base.pendingApprovals.filter((r) => r.id !== event.requestId),\n }\n }\n\n case 'tool_output': {\n const at = base.items.findIndex((item) => item.kind === 'tool_call' && item.id === event.toolUseId)\n const target = base.items[at]\n if (target?.kind !== 'tool_call' || (target.status !== 'running' && target.status !== 'pending') || target.liveTail === event.tail) {\n return base\n }\n const items = base.items.slice()\n items[at] = { ...target, liveTail: event.tail }\n return { ...base, items }\n }\n\n case 'execution_dispatched': {\n return {\n ...base,\n items: base.items.map((item) =>\n item.kind === 'tool_call' && item.id === event.executionId\n ? {\n ...item,\n status: event.deferred ? 'deferred' : 'pending',\n executionId: event.executionId,\n backend: event.backend,\n }\n : item,\n ),\n }\n }\n\n case 'execution_result': {\n return {\n ...base,\n items: base.items.map((item) =>\n item.kind === 'tool_call' && item.id === event.executionId\n ? {\n ...item,\n status: 'settled',\n executionId: event.executionId,\n result: { text: outputText(event.output), isError: false },\n logs: event.logs ?? item.logs,\n }\n : item,\n ),\n }\n }\n\n case 'execution_failed': {\n return {\n ...base,\n items: base.items.map((item) =>\n item.kind === 'tool_call' && item.id === event.executionId\n ? {\n ...item,\n status: 'failed',\n executionId: event.executionId,\n result: { text: `${event.reason}: ${event.error}`, isError: true },\n logs: event.logs ?? item.logs,\n }\n : item,\n ),\n }\n }\n\n case 'file_delivered': {\n return {\n ...base,\n items: [\n ...base.items,\n {\n kind: 'file_delivered',\n id: `file-${event.seq}`,\n path: event.path,\n bytes: event.bytes,\n description: event.description,\n },\n ],\n }\n }\n\n case 'session_error': {\n return {\n ...base,\n items: [...base.items, { kind: 'notice', id: `err-${event.seq}`, level: 'error', text: event.message }],\n }\n }\n\n case 'session_closed': {\n return {\n ...base,\n items: [\n ...base.items,\n {\n kind: 'notice',\n id: `closed-${event.seq}`,\n level: 'info',\n text: `Session closed (${event.reason})`,\n },\n ],\n }\n }\n\n case 'sdk_event':\n default: {\n return base\n }\n }\n}\n\nfunction agentResetNotice(reason: string): string {\n return `The agent cleared its context: ${reason}`\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\nimport type { TranscriptState } from './transcript.ts'\n\nconst MAX_ENTRIES = 5\n\nconst entries = new Map<string, TranscriptState>()\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function transcriptCacheKey(client: WorkerDeckClient, sessionId: string): string {\n return `${client.identityKey}\\u0000${sessionId}`\n}\n\nexport function readTranscriptCache(key: string): TranscriptState | undefined {\n return entries.get(key)\n}\n\nexport function writeTranscriptCache(key: string, state: TranscriptState): void {\n entries.delete(key)\n entries.set(key, state)\n if (entries.size > MAX_ENTRIES) {\n const oldest = entries.keys().next().value\n if (oldest !== undefined) {\n entries.delete(oldest)\n }\n }\n}\n\nexport function deleteTranscriptCache(key: string): void {\n entries.delete(key)\n}\n\nexport function clearTranscriptCache(): void {\n entries.clear()\n}\n","import { initialTranscriptState, type TranscriptState } from './transcript.ts'\n\nexport function attachSeedToken(resyncSeq: number, key: string): string {\n return `${resyncSeq}:${key}`\n}\n\nexport type AttachInputs = {\n resyncSeq: number\n key: string\n seededFor: string\n current: TranscriptState\n cacheEnabled: boolean\n skipCache: boolean\n warm: TranscriptState | undefined\n}\n\nexport type AttachPlan = {\n held: TranscriptState\n seed: boolean\n seedToken: string\n afterSeq?: number\n}\n\nexport function planAttach(input: AttachInputs): AttachPlan {\n const seedToken = attachSeedToken(input.resyncSeq, input.key)\n const warm = input.cacheEnabled && !input.skipCache ? input.warm : undefined\n const seed = input.seededFor !== seedToken\n const held = seed ? (warm ?? initialTranscriptState) : input.current\n // `afterSeq` derives from the state held and never from a second cache read, which a racing write could move.\n return { held, seed, seedToken, ...(held.lastSeq > 0 ? { afterSeq: held.lastSeq } : {}) }\n}\n\nexport function shouldWriteParting(input: { cacheEnabled: boolean; skipCache: boolean; parting: TranscriptState }): boolean {\n return input.cacheEnabled && !input.skipCache && input.parting.lastSeq > 0 && input.parting.session !== undefined\n}\n","import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'\nimport { WorkerDeckError } from '@workerdeck/client'\nimport type { WorkerDeckClient, SessionHandle } from '@workerdeck/client'\nimport { DEFAULT_PRICING, PROTOCOL_VERSION, mergePricing } from '@workerdeck/protocol'\nimport type { AttachedFrame, ModelOption, PermissionMode, PricingTable, SessionEvent, ShellInfo } from '@workerdeck/protocol'\nimport {\n applyEvent,\n blockText,\n initialTranscriptState,\n hydrateShellOutput,\n hydrateShellRow,\n hydrateToolResult,\n seedFromSessionInfo,\n type TranscriptState,\n} from '../lib/transcript.ts'\nimport { deleteTranscriptCache, readTranscriptCache, transcriptCacheKey, writeTranscriptCache } from '../lib/transcript-cache.ts'\nimport { attachSeedToken, planAttach, shouldWriteParting } from '../lib/attach-plan.ts'\n\ntype SeedAction = { type: 'transcript_seed'; state: TranscriptState }\ntype HydrateAction = { type: 'transcript_hydrate_result'; toolUseId: string; text: string }\ntype ShellRowAction = { type: 'transcript_hydrate_shell'; shellId: string; shell: ShellInfo | undefined }\ntype ShellOutputAction = { type: 'transcript_hydrate_shell_output'; shellId: string; text: string }\n\ntype TranscriptAction = SessionEvent | AttachedFrame | SeedAction | HydrateAction | ShellRowAction | ShellOutputAction\n\nfunction reduce(state: TranscriptState, action: TranscriptAction): TranscriptState {\n if (action.type === 'transcript_seed') {\n return action.state\n }\n if (action.type === 'transcript_hydrate_result') {\n return hydrateToolResult(state, action.toolUseId, action.text)\n }\n if (action.type === 'transcript_hydrate_shell') {\n return hydrateShellRow(state, action.shellId, action.shell)\n }\n if (action.type === 'transcript_hydrate_shell_output') {\n return hydrateShellOutput(state, action.shellId, action.text)\n }\n return action.type === 'attached' ? seedFromSessionInfo(state, action.session) : applyEvent(state, action)\n}\n\nexport type ConnectionState = 'live' | 'reconnecting' | 'offline'\n\n// Three failed attempts is ~3.5s of backoff - past a blip; the iOS client hardcodes the same threshold.\nconst OFFLINE_AFTER_ATTEMPTS = 3\n\nexport function initialReplayTarget(frame: AttachedFrame): number | undefined {\n return frame.replayingFrom === 0 && frame.session.lastSeq > 0 ? frame.session.lastSeq : undefined\n}\n\nexport function staleAttach(frame: AttachedFrame, held: TranscriptState): boolean {\n if (frame.replayingFrom === 0 || held.lastSeq === 0) {\n return false\n }\n if (frame.session.lastSeq < held.lastSeq) {\n return true\n }\n return held.session !== undefined && frame.session.createdAt !== held.session.createdAt\n}\n\nexport const REPLAY_HOLD_MAX_MS = 1500\n\nexport type UseClaudeSessionOptions = {\n onProtocolError?: (message: string) => void\n cacheTranscript?: boolean\n}\n\nexport type UseClaudeSessionResult = {\n state: TranscriptState\n connected: boolean\n connection: ConnectionState\n replaying: boolean\n protocolMismatch?: number\n // The gateway offers `$` shell mode to this principal on this session. Absent from an older gateway, so falsy by default.\n shell: boolean\n // The gateway's rate table, its own overrides merged over the bundled one, for every figure this client prices itself.\n pricing: PricingTable\n models: ModelOption[]\n effectiveModel?: string\n handle: SessionHandle | undefined\n send: (text: string, attachmentIds?: string[]) => void\n approve: (requestId: string, updatedInput?: Record<string, unknown>) => void\n deny: (requestId: string, message?: string, interrupt?: boolean) => void\n interrupt: () => void\n // Ctrl+B: the running tool call returns at once and its task keeps going. No id moves every foreground task.\n backgroundTask: (toolUseId?: string) => void\n clearContext: () => void\n runShell: (command: string) => void\n setPermissionMode: (mode: PermissionMode) => void\n setModel: (model?: string) => void\n setEffort: (effort?: string) => void\n closeSession: () => void\n reconnectNow: () => void\n loadFullResult: (toolUseId: string) => Promise<boolean>\n // The artifact's text view, fetched for one expanded row. It never reaches the model: the two budgets never touch.\n loadShellOutput: (shellId: string) => Promise<boolean>\n // A `running` row is a claim from the event log, which can be older than the process. Fetched once per shell id.\n verifyShell: (shellId: string) => Promise<boolean>\n killShell: (shellId: string) => Promise<boolean>\n setShellAgentWrite: (shellId: string, enabled: boolean) => Promise<boolean>\n}\n\nexport function useClaudeSession(\n client: WorkerDeckClient,\n sessionId: string | undefined,\n options?: UseClaudeSessionOptions,\n): UseClaudeSessionResult {\n const [state, dispatch] = useReducer(\n reduce,\n undefined,\n (): TranscriptState =>\n (options?.cacheTranscript !== false && sessionId !== undefined\n ? readTranscriptCache(transcriptCacheKey(client, sessionId))\n : undefined) ?? initialTranscriptState,\n )\n const [connection, setConnection] = useState<ConnectionState>('reconnecting')\n const [protocolMismatch, setProtocolMismatch] = useState<number | undefined>()\n const [shell, setShell] = useState(false)\n const [pricing, setPricing] = useState<PricingTable>(DEFAULT_PRICING)\n const [replayTarget, setReplayTarget] = useState<number | undefined>()\n const [resyncSeq, setResyncSeq] = useState(0)\n // Ref for the stable callbacks below; state so consumers of `handle` re-render when the socket opens or the session switches.\n const [handleState, setHandleState] = useState<SessionHandle | undefined>()\n const handleRef = useRef<SessionHandle | null>(null)\n const optionsRef = useRef(options)\n optionsRef.current = options\n const stateRef = useRef(state)\n stateRef.current = state\n const seededForRef = useRef(attachSeedToken(0, sessionId === undefined ? '' : transcriptCacheKey(client, sessionId)))\n const skipCacheRef = useRef(false)\n\n useEffect(() => {\n if (!sessionId) {\n return\n }\n const cache = optionsRef.current?.cacheTranscript !== false\n const key = transcriptCacheKey(client, sessionId)\n const plan = planAttach({\n resyncSeq,\n key,\n seededFor: seededForRef.current,\n current: stateRef.current,\n cacheEnabled: cache,\n skipCache: skipCacheRef.current,\n warm: readTranscriptCache(key),\n })\n skipCacheRef.current = false\n if (plan.seed) {\n dispatch({ type: 'transcript_seed', state: plan.held })\n seededForRef.current = plan.seedToken\n }\n const handle = client.attach(sessionId, {\n truncateResults: true,\n imageRefs: true,\n ...(plan.afterSeq === undefined ? {} : { afterSeq: plan.afterSeq }),\n })\n handleRef.current = handle\n setHandleState(handle)\n const offEvent = handle.on('event', (event: SessionEvent) => dispatch(event))\n const offAttached = handle.on('attached', (frame: AttachedFrame) => {\n if (staleAttach(frame, stateRef.current)) {\n offEvent()\n deleteTranscriptCache(key)\n skipCacheRef.current = true\n setResyncSeq((n) => n + 1)\n return\n }\n dispatch(frame)\n setReplayTarget(initialReplayTarget(frame))\n setProtocolMismatch(frame.protocolVersion === PROTOCOL_VERSION ? undefined : frame.protocolVersion)\n setShell(frame.shell === true)\n setPricing(mergePricing(frame.pricingOverrides).pricing)\n })\n const offConn = handle.on('connectionChange', (open: boolean) => setConnection(open ? 'live' : 'reconnecting'))\n const offRetry = handle.on('reconnectAttempt', (attempts: number) =>\n setConnection(attempts >= OFFLINE_AFTER_ATTEMPTS ? 'offline' : 'reconnecting'),\n )\n const offProtocolError = handle.on('protocolError', (message: string) => {\n optionsRef.current?.onProtocolError?.(message)\n })\n return () => {\n offEvent()\n offAttached()\n offConn()\n offRetry()\n offProtocolError()\n handle.detach()\n handleRef.current = null\n setHandleState(undefined)\n setConnection('reconnecting')\n setProtocolMismatch(undefined)\n setShell(false)\n setReplayTarget(undefined)\n const parting = stateRef.current\n if (shouldWriteParting({ cacheEnabled: cache, skipCache: skipCacheRef.current, parting })) {\n writeTranscriptCache(key, parting)\n }\n }\n }, [client, sessionId, resyncSeq])\n\n useEffect(() => {\n if (replayTarget === undefined) {\n return\n }\n const timer = setTimeout(() => setReplayTarget(undefined), REPLAY_HOLD_MAX_MS)\n return () => clearTimeout(timer)\n }, [replayTarget])\n useEffect(() => {\n if (replayTarget !== undefined && state.lastSeq >= replayTarget) {\n setReplayTarget(undefined)\n }\n }, [replayTarget, state.lastSeq])\n\n const models = useProfileModelFallback(client, sessionId, state)\n\n const connected = connection === 'live'\n // Derived at render, not in an effect, so the reveal lands in the same commit as the replay's final event - an effect is one visible frame late.\n const replaying = replayTarget !== undefined && state.lastSeq < replayTarget\n const reconnectNow = useCallback(() => handleRef.current?.reconnectNow(), [])\n\n const loadFullResult = useCallback(\n async (toolUseId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n const item = stateRef.current.items.find((candidate) => candidate.kind === 'tool_call' && candidate.id === toolUseId)\n const result = item?.kind === 'tool_call' ? item.result : undefined\n if (!result?.truncated || result.sourceSeq === undefined) {\n return false\n }\n try {\n const full = await client.toolResult(sessionId, result.sourceSeq, toolUseId)\n dispatch({ type: 'transcript_hydrate_result', toolUseId, text: blockText(full.content) })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n const verifiedRef = useRef(new Set<string>())\n useEffect(() => {\n verifiedRef.current = new Set<string>()\n }, [sessionId])\n\n const loadShellOutput = useCallback(\n async (shellId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n try {\n const text = await client.shellOutput(sessionId, shellId, { view: 'text' })\n dispatch({ type: 'transcript_hydrate_shell_output', shellId, text })\n return true\n } catch (error) {\n if (isNotFound(error)) {\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: undefined })\n }\n return false\n }\n },\n [client, sessionId],\n )\n\n const verifyShell = useCallback(\n async (shellId: string): Promise<boolean> => {\n const verified = verifiedRef.current\n if (!sessionId || verified.has(shellId)) {\n return false\n }\n verified.add(shellId)\n try {\n const record = await client.getShell(sessionId, shellId)\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: record })\n return true\n } catch (error) {\n if (isNotFound(error)) {\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: undefined })\n } else {\n verified.delete(shellId)\n }\n return false\n }\n },\n [client, sessionId],\n )\n\n const killShell = useCallback(\n async (shellId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n try {\n const record = await client.killShell(sessionId, shellId)\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: record })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n const setShellAgentWrite = useCallback(\n async (shellId: string, enabled: boolean): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n try {\n const record = await client.setShellAgentWrite(sessionId, shellId, enabled)\n dispatch({ type: 'transcript_hydrate_shell', shellId, shell: record })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n const actions = useMemo(\n () => ({\n send: (text: string, attachmentIds?: string[]) => handleRef.current?.send(text, attachmentIds),\n approve: (requestId: string, updatedInput?: Record<string, unknown>) => handleRef.current?.approve(requestId, updatedInput),\n deny: (requestId: string, message?: string, interrupt?: boolean) => handleRef.current?.deny(requestId, message, interrupt),\n interrupt: () => handleRef.current?.interrupt(),\n backgroundTask: (toolUseId?: string) => handleRef.current?.backgroundTask(toolUseId),\n clearContext: () => handleRef.current?.clearContext(),\n runShell: (command: string) => handleRef.current?.runShell(command),\n setPermissionMode: (mode: PermissionMode) => handleRef.current?.setPermissionMode(mode),\n setModel: (model?: string) => handleRef.current?.setModel(model),\n setEffort: (effort?: string) => handleRef.current?.setEffort(effort),\n closeSession: () => handleRef.current?.closeSession(),\n }),\n [],\n )\n\n return useMemo(\n () => ({\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n shell,\n pricing,\n models,\n effectiveModel: state.model ?? state.defaultModel,\n handle: handleState,\n ...actions,\n reconnectNow,\n loadFullResult,\n loadShellOutput,\n verifyShell,\n killShell,\n setShellAgentWrite,\n }),\n [\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n shell,\n pricing,\n models,\n handleState,\n actions,\n reconnectNow,\n loadFullResult,\n loadShellOutput,\n verifyShell,\n killShell,\n setShellAgentWrite,\n ],\n )\n}\n\nfunction isNotFound(error: unknown): boolean {\n return error instanceof WorkerDeckError && error.status === 404\n}\n\nfunction useProfileModelFallback(client: WorkerDeckClient, sessionId: string | undefined, state: TranscriptState): ModelOption[] {\n const [catalog, setCatalog] = useState<ModelOption[]>([])\n const profile = state.session?.profile\n const reported = state.models\n const hasReported = !!reported?.length\n\n useEffect(() => setCatalog([]), [sessionId])\n\n useEffect(() => {\n if (!profile || hasReported) {\n return\n }\n let cancelled = false\n client\n .listProfiles()\n .then((response) => {\n if (!cancelled) {\n setCatalog(response.profiles.find((p) => p.name === profile)?.models ?? [])\n }\n })\n .catch(() => {})\n return () => {\n cancelled = true\n }\n }, [client, profile, hasReported])\n\n return hasReported ? reported : catalog\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\nimport type { ProfileUsage } from '@workerdeck/protocol'\n\n// Last known profile usage, kept outside React so a session switch does not blank it.\n//\n// Usage belongs to the *account*, not the session, but it is fetched by a hook that lives inside the per-session\n// panel - so remounting that panel used to drop the authoritative reading to `undefined` for a whole round trip,\n// leaving only the newly-attached session's own replayed (and possibly days-old) numbers to render. That is the\n// \"switching sessions resets my weekly usage to 1%, then it catches up\" report.\n//\n// Keyed by client identity + profile because a different profile is a different account's plan, never a stale view\n// of this one. Same shape and reasoning as `transcript-cache.ts` next door.\nconst entries = new Map<string, ProfileUsage>()\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function profileUsageCacheKey(client: WorkerDeckClient, profile: string): string {\n return `${client.identityKey}\\u0000${profile}`\n}\n\nexport function readProfileUsageCache(key: string): ProfileUsage | undefined {\n return entries.get(key)\n}\n\nexport function writeProfileUsageCache(key: string, usage: ProfileUsage | undefined): void {\n if (usage === undefined) {\n return\n }\n entries.set(key, usage)\n}\n\nexport function clearProfileUsageCache(): void {\n entries.clear()\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\n\n// Unsent composer text, kept per session on the client that typed it.\n//\n// A draft is not session state: it never reaches the gateway and never syncs between clients. Two people looking at\n// one session are each mid-sentence in their own way, and a half-written prompt is not something either of them\n// asked to publish.\n//\n// It is persisted rather than merely held in memory because the two ways drafts got lost are different failures. A\n// session switch remounts the composer, which a module-scope map alone would survive; a Vite HMR reload or a VS Code\n// `dev:host` webview re-render replaces the whole document, which it would not.\nconst KEY = 'workerdeck.drafts.v1'\n\n// Drafts are a convenience, so the store stays small and drops the least recently touched first.\nconst MAX_DRAFTS = 20\n\ntype Draft = { text: string; savedAt: number }\n\nlet memory: Record<string, Draft> | undefined\n\nfunction storage(): Storage | undefined {\n try {\n // Through globalThis: this package is typechecked with no DOM lib, and a webview may deny storage outright.\n return (globalThis as { localStorage?: Storage }).localStorage\n } catch {\n return undefined\n }\n}\n\nfunction load(): Record<string, Draft> {\n if (memory) {\n return memory\n }\n memory = {}\n const raw = storage()?.getItem(KEY)\n if (raw) {\n try {\n const parsed = JSON.parse(raw) as Record<string, Draft>\n for (const [key, draft] of Object.entries(parsed)) {\n if (typeof draft?.text === 'string' && typeof draft.savedAt === 'number') {\n memory[key] = draft\n }\n }\n } catch {\n // A corrupt blob is not worth a broken composer; start over.\n }\n }\n return memory\n}\n\nfunction persist(drafts: Record<string, Draft>): void {\n const entries = Object.entries(drafts)\n if (entries.length > MAX_DRAFTS) {\n entries.sort((a, b) => b[1].savedAt - a[1].savedAt)\n for (const [key] of entries.slice(MAX_DRAFTS)) {\n delete drafts[key]\n }\n }\n try {\n storage()?.setItem(KEY, JSON.stringify(drafts))\n } catch {\n // Out of quota, or storage denied. The in-memory copy still carries the session switch.\n }\n}\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function draftKey(client: WorkerDeckClient, sessionId: string): string {\n return `${client.identityKey}\\u0000${sessionId}`\n}\n\nexport function readDraft(key: string): string {\n return load()[key]?.text ?? ''\n}\n\nexport function writeDraft(key: string, text: string, now = Date.now()): void {\n const drafts = load()\n // An empty draft is the absence of one: keeping it would evict a real draft under the cap.\n if (text.trim() === '') {\n if (drafts[key] === undefined) {\n return\n }\n delete drafts[key]\n } else {\n drafts[key] = { text, savedAt: now }\n }\n persist(drafts)\n}\n\nexport function clearDrafts(): void {\n memory = {}\n try {\n storage()?.removeItem(KEY)\n } catch {}\n}\n","import { errorMessage } from '@workerdeck/protocol'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport type { EngineCapabilities, ProfileEngine } from '@workerdeck/protocol'\n\nexport type StagedAttachment = {\n key: string\n name: string\n mediaType: string\n bytes: number\n previewUrl?: string\n status: 'uploading' | 'ready' | 'failed'\n id?: string\n error?: string\n}\n\nexport type AttachmentKind = 'image' | 'pdf' | 'text'\n\nconst TEXTUAL_TYPES = new Set([\n 'application/json',\n 'application/xml',\n 'application/yaml',\n 'application/x-yaml',\n 'application/toml',\n 'application/javascript',\n 'application/typescript',\n 'application/x-sh',\n 'application/sql',\n])\n\nconst MAX_IMAGE_EDGE = 1568\n\nexport function attachmentKind(mediaType: string): AttachmentKind | undefined {\n const type = mediaType.split(';')[0]!.trim().toLowerCase()\n if (type.startsWith('image/')) {\n return 'image'\n }\n if (type === 'application/pdf') {\n return 'pdf'\n }\n if (type.startsWith('text/')) {\n return 'text'\n }\n if (TEXTUAL_TYPES.has(type)) {\n return 'text'\n }\n return undefined\n}\n\nexport type UseAttachmentsOptions = {\n capabilities: EngineCapabilities\n engine?: ProfileEngine\n}\n\nexport type UseAttachmentsResult = {\n items: StagedAttachment[]\n readyIds: string[]\n uploading: boolean\n hasFailure: boolean\n accept: string\n disabled: boolean\n add: (files: Iterable<File>) => void\n retry: (key: string) => void\n remove: (key: string) => void\n clear: () => void\n error?: string\n dismissError: () => void\n}\n\nexport function useAttachments(\n client: WorkerDeckClient,\n sessionId: string | undefined,\n { capabilities, engine }: UseAttachmentsOptions,\n): UseAttachmentsResult {\n const [items, setItems] = useState<StagedAttachment[]>([])\n const [error, setError] = useState<string | undefined>()\n const counter = useRef(0)\n const fileByKey = useRef(new Map<string, File>())\n const previewUrls = useRef<string[]>([])\n previewUrls.current = items.flatMap((item) => (item.previewUrl ? [item.previewUrl] : []))\n const accepts = capabilities.attachments\n\n useEffect(\n () => () => {\n for (const url of previewUrls.current) {\n URL.revokeObjectURL(url)\n }\n },\n [],\n )\n\n const patch = useCallback((key: string, next: Partial<StagedAttachment>) => {\n setItems((current) => current.map((item) => (item.key === key ? { ...item, ...next } : item)))\n }, [])\n\n const upload = useCallback(\n (key: string, file: File) => {\n if (!sessionId) {\n return\n }\n patch(key, { status: 'uploading', error: undefined })\n void (async () => {\n try {\n const data = await prepare(file)\n const uploaded = await client.uploadAttachment(sessionId, {\n name: file.name,\n mediaType: data.mediaType,\n data: data.body,\n })\n patch(key, { status: 'ready', id: uploaded.id, bytes: uploaded.bytes ?? file.size })\n } catch (e) {\n patch(key, { status: 'failed', error: errorMessage(e, 'Upload failed') })\n }\n })()\n },\n [client, patch, sessionId],\n )\n\n const add = useCallback(\n (files: Iterable<File>) => {\n const staged: StagedAttachment[] = []\n const pending: Array<{ key: string; file: File }> = []\n for (const file of files) {\n const mediaType = file.type || 'application/octet-stream'\n const kind = attachmentKind(mediaType)\n // An unclassifiable type still goes: the gateway's vocabulary is the authoritative one.\n if (kind && !accepts.includes(kind)) {\n setError(`The ${engine ?? 'claude'} engine does not take ${kind} attachments.`)\n continue\n }\n const key = `att-${++counter.current}`\n staged.push({\n key,\n name: file.name,\n mediaType,\n bytes: file.size,\n previewUrl: kind === 'image' ? URL.createObjectURL(file) : undefined,\n status: 'uploading',\n })\n pending.push({ key, file })\n }\n if (staged.length === 0) {\n return\n }\n setItems((current) => [...current, ...staged])\n fileByKey.current = new Map([...fileByKey.current, ...pending.map(({ key, file }) => [key, file] as const)])\n for (const { key, file } of pending) {\n upload(key, file)\n }\n },\n [accepts, engine, upload],\n )\n\n const forget = useCallback((keys: string[]) => {\n setItems((current) => {\n for (const item of current) {\n if (keys.includes(item.key) && item.previewUrl) {\n URL.revokeObjectURL(item.previewUrl)\n }\n }\n return current.filter((item) => !keys.includes(item.key))\n })\n for (const key of keys) {\n fileByKey.current.delete(key)\n }\n }, [])\n\n const remove = useCallback((key: string) => forget([key]), [forget])\n\n const clear = useCallback(() => {\n setItems((current) => {\n for (const item of current) {\n if (item.previewUrl) {\n URL.revokeObjectURL(item.previewUrl)\n }\n }\n return []\n })\n fileByKey.current.clear()\n }, [])\n\n const retry = useCallback(\n (key: string) => {\n const file = fileByKey.current.get(key)\n if (file) {\n upload(key, file)\n }\n },\n [upload],\n )\n\n return useMemo(\n () => ({\n items,\n readyIds: items.flatMap((item) => (item.id ? [item.id] : [])),\n uploading: items.some((item) => item.status === 'uploading'),\n hasFailure: items.some((item) => item.status === 'failed'),\n accept: acceptAttribute(accepts),\n disabled: accepts.length === 0 || !sessionId,\n add,\n retry,\n remove,\n clear,\n error,\n dismissError: () => setError(undefined),\n }),\n [items, accepts, sessionId, add, retry, remove, clear, error],\n )\n}\n\nfunction acceptAttribute(kinds: readonly AttachmentKind[]): string {\n if (kinds.length === 0) {\n return ''\n }\n const parts: string[] = []\n if (kinds.includes('image')) {\n parts.push('image/*')\n }\n if (kinds.includes('pdf')) {\n parts.push('application/pdf')\n }\n if (kinds.includes('text')) {\n parts.push('text/*', '.md', '.json', '.yaml', '.yml', '.toml')\n }\n // All three kinds is no narrowing at all, and an empty accept leaves the picker open.\n return kinds.length === 3 ? '' : parts.join(',')\n}\n\n// Reached through globalThis, not named directly: smoke/ typechecks this source with no DOM lib.\ntype ImageBitmapLike = { width: number; height: number; close(): void }\ntype CanvasLike = {\n width: number\n height: number\n getContext(contextId: '2d'): {\n drawImage(image: ImageBitmapLike, dx: number, dy: number, dw: number, dh: number): void\n } | null\n toBlob(callback: (blob: Blob | null) => void, type?: string, quality?: number): void\n}\nconst imaging = globalThis as unknown as {\n createImageBitmap?: (source: Blob) => Promise<ImageBitmapLike>\n document?: { createElement(tagName: 'canvas'): CanvasLike }\n}\n\nasync function prepare(file: File): Promise<{ body: Blob; mediaType: string }> {\n const mediaType = file.type || 'application/octet-stream'\n const { createImageBitmap, document } = imaging\n if (!createImageBitmap || !document || !mediaType.startsWith('image/')) {\n return { body: file, mediaType }\n }\n // A redraw of an animation would keep one frame of it.\n if (mediaType === 'image/gif') {\n return { body: file, mediaType }\n }\n try {\n const bitmap = await createImageBitmap(file)\n const longest = Math.max(bitmap.width, bitmap.height)\n if (longest <= MAX_IMAGE_EDGE) {\n bitmap.close()\n return { body: file, mediaType }\n }\n const scale = MAX_IMAGE_EDGE / longest\n const canvas = document.createElement('canvas')\n canvas.width = Math.round(bitmap.width * scale)\n canvas.height = Math.round(bitmap.height * scale)\n const context = canvas.getContext('2d')\n if (!context) {\n bitmap.close()\n return { body: file, mediaType }\n }\n context.drawImage(bitmap, 0, 0, canvas.width, canvas.height)\n bitmap.close()\n const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, 'image/jpeg', 0.85))\n return blob ? { body: blob, mediaType: 'image/jpeg' } : { body: file, mediaType }\n } catch {\n return { body: file, mediaType }\n }\n}\n","import { PEER_MENTION_SIGIL, PROMPT_SENTENCE_TAIL, isPeerMentionBody, peerMentionKey } from '@workerdeck/protocol'\n\nexport type PromptToken = {\n kind: 'file' | 'command' | 'skill' | 'session'\n start: number\n end: number\n text: string\n}\n\n// `$name` is codex's skill mention and `#Name` is another session on the gateway; in both cases only\n// a name this client knows is a token, so a dollar amount and a colour literal never badge. The\n// session list is *live*, so a mention drawn today may draw plain once that peer is renamed - the\n// characters never change, only the colour, which is why this does not break the rule that a\n// transcript must read on replay as it did live (that rule binds substituting a name for an id).\nexport type PromptTokenOptions = {\n skills?: readonly string[]\n // Folded slugs (`peerMentionKey(peerMentionSlug(title, id))`), not display titles.\n sessions?: readonly string[]\n}\n\n// No `/`, so a pasted absolute path is not a command; `:` is in for namespaced skills (`dev:wrapup`).\nconst COMMAND_BODY = /^[A-Za-z0-9\\-_.:]+$/\n\n// The same set the gateway peels with, so one boundary answers for every sigil.\nconst SENTENCE_TAIL = PROMPT_SENTENCE_TAIL\n\nexport function scanPromptTokens(text: string, options?: PromptTokenOptions): PromptToken[] {\n const tokens: PromptToken[] = []\n const skills = options?.skills?.length ? new Set(options.skills) : undefined\n const sessions = options?.sessions?.length ? new Set(options.sessions) : undefined\n const words = /\\S+/g\n let match: RegExpExecArray | null\n while ((match = words.exec(text)) !== null) {\n const word = match[0]\n const kind =\n word[0] === '@'\n ? 'file'\n : word[0] === '/'\n ? 'command'\n : word[0] === '$' && skills\n ? 'skill'\n : word[0] === PEER_MENTION_SIGIL && sessions\n ? 'session'\n : undefined\n if (!kind) {\n continue\n }\n let end = match.index + word.length\n while (end > match.index && SENTENCE_TAIL.has(text[end - 1]!)) {\n end--\n }\n const body = text.slice(match.index + 1, end)\n if (!body) {\n continue\n }\n if (kind === 'command' && !COMMAND_BODY.test(body)) {\n continue\n }\n if (kind === 'skill' && !skills!.has(body)) {\n continue\n }\n if (kind === 'session' && !(isPeerMentionBody(body) && sessions!.has(peerMentionKey(body)))) {\n continue\n }\n tokens.push({ kind, start: match.index, end, text: text.slice(match.index, end) })\n }\n return tokens\n}\n","import { useCallback, useEffect, useRef, useState, type DependencyList, type Dispatch, type RefObject, type SetStateAction } from 'react'\nimport { WorkerDeckError } from '@workerdeck/client'\n\nexport type UseAsyncOptions = {\n enabled?: boolean\n pollMs?: number\n}\n\nexport type UseAsyncResult<T> = {\n data: T | undefined\n error: unknown\n loading: boolean\n reload: () => Promise<void>\n setData: Dispatch<SetStateAction<T | undefined>>\n}\n\n// Set in an effect, not at declaration: StrictMode remounts, and a once-initialised ref stays false.\nexport function useAliveRef(): RefObject<boolean> {\n const alive = useRef(true)\n useEffect(() => {\n alive.current = true\n return () => {\n alive.current = false\n }\n }, [])\n return alive\n}\n\nexport function isRouteUnsupported(e: unknown): boolean {\n return e instanceof WorkerDeckError && e.status === 404\n}\n\n// A change of `deps` drops the previous answer; `enabled` flipping on, a poll and `reload` keep it until the next one lands.\nexport function useAsync<T>(\n load: () => Promise<T>,\n deps: DependencyList,\n { enabled = true, pollMs }: UseAsyncOptions = {},\n): UseAsyncResult<T> {\n const [data, setData] = useState<T | undefined>()\n const [error, setError] = useState<unknown>()\n const [loading, setLoading] = useState(enabled)\n const generation = useRef(0)\n const loadRef = useRef(load)\n loadRef.current = load\n\n const run = useCallback(async () => {\n const id = ++generation.current\n setLoading(true)\n try {\n const next = await loadRef.current()\n if (id === generation.current) {\n setData(() => next)\n setError(undefined)\n }\n } catch (e) {\n if (id === generation.current) {\n setError(e)\n }\n } finally {\n if (id === generation.current) {\n setLoading(false)\n }\n }\n }, [])\n\n useEffect(() => {\n setData(undefined)\n setError(undefined)\n }, deps)\n\n useEffect(() => {\n if (!enabled) {\n generation.current++\n setLoading(false)\n return\n }\n void run()\n const timer = pollMs ? setInterval(() => void run(), pollMs) : undefined\n return () => {\n generation.current++\n clearInterval(timer)\n }\n }, [enabled, pollMs, run, ...deps])\n\n return { data, error, loading, reload: run, setData }\n}\n","import type { HostDirEntry } from '@workerdeck/protocol'\n\nexport type HostDirState = {\n entries: HostDirEntry[]\n truncated?: boolean\n}\n\nexport type HostTreeRow = {\n entry: HostDirEntry\n depth: number\n expanded?: boolean\n loading?: boolean\n truncated?: boolean\n}\n\nexport function flattenHostTree(root: string, dirs: ReadonlyMap<string, HostDirState>, expanded: ReadonlySet<string>): HostTreeRow[] {\n const rows: HostTreeRow[] = []\n const rootState = dirs.get(root)\n if (!rootState) {\n return rows\n }\n // An explicit stack rather than recursion. Depth is bounded by how many directories the user has\n // expanded, not by tree size, so this is a small risk - but it is the user's clicks that set the\n // bound, and an expanded chain deep enough to exhaust the call stack should still just render.\n const stack: { entries: readonly HostDirEntry[]; index: number; depth: number }[] = [{ entries: rootState.entries, index: 0, depth: 0 }]\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]\n const entry = frame.entries[frame.index]\n if (entry === undefined) {\n stack.pop()\n continue\n }\n frame.index += 1\n const depth = frame.depth\n if (entry.type !== 'dir') {\n rows.push({ entry, depth })\n continue\n }\n const isExpanded = expanded.has(entry.path)\n const childState = dirs.get(entry.path)\n rows.push({\n entry,\n depth,\n expanded: isExpanded,\n loading: isExpanded && !childState,\n truncated: isExpanded ? childState?.truncated : undefined,\n })\n if (isExpanded && childState) {\n stack.push({ entries: childState.entries, index: 0, depth: depth + 1 })\n }\n }\n return rows\n}\n\nexport function ancestorsWithin(root: string, path: string): string[] {\n const base = root.endsWith('/') ? root.slice(0, -1) : root\n if (path === base || !path.startsWith(`${base}/`)) {\n return []\n }\n const rest = path.slice(base.length + 1).split('/')\n const out: string[] = []\n let current = base\n for (const segment of rest.slice(0, -1)) {\n current = `${current}/${segment}`\n out.push(current)\n }\n return out\n}\n","import { errorMessage } from '@workerdeck/protocol'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\nimport type { HostFileMatch } from '@workerdeck/protocol'\nimport { ancestorsWithin, flattenHostTree, type HostDirState, type HostTreeRow } from '../lib/host-tree.ts'\n\nexport type UseHostFileSearchResult = {\n available: boolean\n search: (query: string, options?: { limit?: number; signal?: AbortSignal }) => Promise<HostFileMatch[]>\n}\n\nexport function useHostFileSearch(client: WorkerDeckClient, cwd: string | undefined): UseHostFileSearchResult {\n const [unsupported, setUnsupported] = useState(false)\n const lastCwd = useRef(cwd)\n useEffect(() => {\n if (lastCwd.current !== cwd) {\n lastCwd.current = cwd\n setUnsupported(false)\n }\n }, [cwd])\n\n const search = useCallback(\n async (query: string, options?: { limit?: number; signal?: AbortSignal }) => {\n if (!cwd || unsupported) {\n return []\n }\n try {\n const response = await client.findHostFiles(cwd, query, options?.limit ?? 8)\n return options?.signal?.aborted ? [] : response.matches\n } catch (e) {\n if (isRouteUnsupported(e)) {\n setUnsupported(true)\n }\n return []\n }\n },\n [client, cwd, unsupported],\n )\n\n return { available: !!cwd && !unsupported, search }\n}\n\nexport type UseHostFileRootsResult = {\n available: boolean\n canWrite: boolean\n}\n\nexport function useHostFileRoots(client: WorkerDeckClient): UseHostFileRootsResult {\n const [result, setResult] = useState<UseHostFileRootsResult>({\n available: false,\n canWrite: false,\n })\n useEffect(() => {\n let cancelled = false\n client\n .listHostRoots()\n .then((response) => {\n if (!cancelled) {\n setResult({ available: true, canWrite: response.canWrite })\n }\n })\n .catch(() => {\n if (!cancelled) {\n setResult({ available: false, canWrite: false })\n }\n })\n return () => {\n cancelled = true\n }\n }, [client])\n return result\n}\n\nexport type UseHostFileTreeResult = {\n available: boolean\n root: string | undefined\n rows: HostTreeRow[]\n loading: boolean\n error: string | undefined\n toggle: (path: string) => void\n reveal: (path: string) => void\n refresh: (path?: string) => void\n}\n\nexport function useHostFileTree(client: WorkerDeckClient, cwd: string | undefined): UseHostFileTreeResult {\n const [dirs, setDirs] = useState<Map<string, HostDirState>>(() => new Map())\n const [expanded, setExpanded] = useState<Set<string>>(() => new Set())\n const [unsupported, setUnsupported] = useState(false)\n const [error, setError] = useState<string | undefined>()\n\n const lastCwd = useRef(cwd)\n useEffect(() => {\n if (lastCwd.current === cwd) {\n return\n }\n lastCwd.current = cwd\n setDirs(new Map())\n setExpanded(new Set())\n setUnsupported(false)\n setError(undefined)\n }, [cwd])\n\n const alive = useAliveRef()\n\n const requested = useRef(new Set<string>())\n\n const list = useCallback(\n (target: string, { force = false } = {}) => {\n if (unsupported) {\n return\n }\n if (!force && requested.current.has(target)) {\n return\n }\n requested.current.add(target)\n client\n .listHostDir(target)\n .then((response) => {\n if (!alive.current) {\n return\n }\n setDirs((previous) => {\n const next = new Map(previous)\n // Keyed on the path asked for, never the canonical one answered: re-keying orphans the node that asked.\n next.set(target, { entries: response.entries, truncated: response.truncated })\n return next\n })\n })\n .catch((e: unknown) => {\n if (!alive.current) {\n return\n }\n requested.current.delete(target)\n if (isRouteUnsupported(e)) {\n setUnsupported(true)\n return\n }\n setError(errorMessage(e, 'Could not read that directory'))\n })\n },\n [client, unsupported],\n )\n\n useEffect(() => {\n if (cwd) {\n list(cwd)\n }\n }, [cwd, list])\n\n const toggle = useCallback(\n (path: string) => {\n setExpanded((previous) => {\n const next = new Set(previous)\n if (next.has(path)) {\n next.delete(path)\n } else {\n next.add(path)\n }\n return next\n })\n // Outside the updater, which React may run twice; `requested` makes this a no-op on the collapse.\n list(path)\n },\n [list],\n )\n\n const reveal = useCallback(\n (path: string) => {\n if (!cwd) {\n return\n }\n const ancestors = ancestorsWithin(cwd, path)\n if (ancestors.length === 0) {\n return\n }\n for (const dir of ancestors) {\n list(dir)\n }\n setExpanded((previous) => {\n const next = new Set(previous)\n for (const dir of ancestors) {\n next.add(dir)\n }\n return next\n })\n },\n [cwd, list],\n )\n\n const refresh = useCallback(\n (path?: string) => {\n const target = path ?? cwd\n if (!target) {\n return\n }\n setError(undefined)\n list(target, { force: true })\n },\n [cwd, list],\n )\n\n const rows = useMemo(() => (cwd ? flattenHostTree(cwd, dirs, expanded) : []), [cwd, dirs, expanded])\n\n return {\n available: !!cwd && !unsupported,\n root: cwd,\n rows,\n loading: !!cwd && !unsupported && !dirs.has(cwd) && !error,\n error,\n toggle,\n reveal,\n refresh,\n }\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { peerMentionKey, peerMentionSlug, type PeerSessionSummary, type SessionInfo } from '@workerdeck/protocol'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\n\nexport type PeerSessionOption = {\n id: string\n // What the composer writes after the `#`, and what the gateway folds to resolve it.\n slug: string\n label: string\n // Set for a session on another gateway, reached through the relay.\n gateway?: string\n engine?: SessionInfo['engine']\n status: SessionInfo['status']\n cwd: string\n project?: string\n lastActivityAt?: number\n}\n\nexport type UsePeerSessionsResult = {\n available: boolean\n peers: PeerSessionOption[]\n // Folded slugs, for `scanPromptTokens`'s `sessions` allowlist.\n names: string[]\n}\n\nexport function peerSessionOption(row: PeerSessionSummary): PeerSessionOption {\n const name = row.agent ?? row.title\n return {\n id: row.id,\n slug: peerMentionSlug(name, row.id),\n label: name ?? peerMentionSlug(undefined, row.id),\n gateway: row.gateway,\n engine: row.engine,\n status: row.status,\n cwd: row.cwd,\n project: row.project,\n lastActivityAt: row.lastActivityAt,\n }\n}\n\nconst EMPTY: UsePeerSessionsResult = { available: false, peers: [], names: [] }\n\nconst IDLE_MS = 20_000\n\n// The sessions this one may address, relay included, for the composer's `#` picker: the same\n// directory the gateway resolves a typed name against. Polled slowly on purpose: a name is not a\n// reading, and this list only has to be right when a menu opens, so a stale row costs nothing\n// worse than a mention that stays plain text.\nexport function usePeerSessions(client: WorkerDeckClient, sessionId: string | undefined, enabled = true): UsePeerSessionsResult {\n const [rows, setRows] = useState<PeerSessionSummary[] | undefined>(undefined)\n const [unsupported, setUnsupported] = useState(false)\n const alive = useAliveRef()\n\n useEffect(() => {\n setRows(undefined)\n if (!enabled || unsupported || !sessionId) {\n return\n }\n let timer: ReturnType<typeof setTimeout> | undefined\n const tick = () => {\n client\n .listPeers(sessionId)\n .then((peers) => {\n if (alive.current) {\n setRows(peers)\n }\n })\n .catch((e: unknown) => {\n if (alive.current && isRouteUnsupported(e)) {\n setUnsupported(true)\n }\n })\n .finally(() => {\n if (alive.current) {\n timer = setTimeout(tick, IDLE_MS)\n }\n })\n }\n tick()\n return () => {\n if (timer) {\n clearTimeout(timer)\n }\n }\n }, [client, enabled, sessionId, unsupported])\n\n return useMemo(() => {\n if (!enabled || unsupported || !rows) {\n return EMPTY\n }\n const peers = rows.map(peerSessionOption)\n return { available: peers.length > 0, peers, names: peers.map((peer) => peerMentionKey(peer.slug)) }\n }, [enabled, rows, unsupported])\n}\n","import { useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport type { SessionRow } from '@workerdeck/protocol'\n\nconst byHash = new Map<string, string>()\nconst inFlight = new Set<string>()\nconst failed = new Set<string>()\n\nexport type ClientForHost = (hostId: string) => WorkerDeckClient | undefined\n\nexport function useProjectIcons(rows: readonly SessionRow[], clientFor: ClientForHost): Record<string, string> {\n const [resolved, setResolved] = useState<Record<string, string>>(() => Object.fromEntries(byHash))\n\n useEffect(() => {\n let alive = true\n for (const row of rows) {\n const icon = row.info.project?.icon\n if (icon?.type !== 'image') {\n continue\n }\n const { hash } = icon\n if (byHash.has(hash) || inFlight.has(hash) || failed.has(hash)) {\n continue\n }\n const client = clientFor(row.hostId)\n // An unreachable gateway is not an iconless one: no failure recorded, so a later render retries.\n if (!client) {\n continue\n }\n inFlight.add(hash)\n void client\n .projectIcon(row.info.id)\n .then((blob) => {\n byHash.set(hash, URL.createObjectURL(blob))\n if (alive) {\n setResolved(Object.fromEntries(byHash))\n }\n })\n .catch(() => {\n failed.add(hash)\n })\n .finally(() => inFlight.delete(hash))\n }\n return () => {\n alive = false\n }\n }, [rows, clientFor])\n\n return resolved\n}\n","export const BOOKMARKS_STORAGE_KEY = 'workerdeck.bookmarks.v1'\n\ntype BookmarkMap = Record<string, readonly string[]>\ntype StorageListener = (event: { key: string | null }) => void\ntype StorageEventTarget = {\n addEventListener: (type: 'storage', listener: StorageListener) => void\n removeEventListener: (type: 'storage', listener: StorageListener) => void\n}\n\nconst EMPTY: readonly string[] = Object.freeze([])\nconst listeners = new Set<() => void>()\nlet loaded: BookmarkMap | undefined\nlet detachStorageEvent: (() => void) | undefined\n\nfunction storage(): Storage | undefined {\n try {\n return globalThis.localStorage ?? undefined\n } catch {\n return undefined\n }\n}\n\nfunction storageEvents(): StorageEventTarget | undefined {\n const target = (globalThis as { window?: Partial<StorageEventTarget> }).window\n return typeof target?.addEventListener === 'function' ? (target as StorageEventTarget) : undefined\n}\n\nfunction readStored(): BookmarkMap | undefined {\n try {\n const raw = storage()?.getItem(BOOKMARKS_STORAGE_KEY)\n if (raw == null) {\n return {}\n }\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return {}\n }\n const map: Record<string, readonly string[]> = {}\n for (const [key, value] of Object.entries(parsed)) {\n if (Array.isArray(value)) {\n map[key] = value.filter((id): id is string => typeof id === 'string')\n }\n }\n return map\n } catch {\n return undefined\n }\n}\n\nfunction sameIds(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((id, index) => id === b[index])\n}\n\n// Unchanged lists keep their identity, so a write to one session never re-renders another.\nfunction adopt(next: BookmarkMap): void {\n const previous = loaded ?? {}\n const merged: Record<string, readonly string[]> = {}\n for (const [key, ids] of Object.entries(next)) {\n const held = previous[key]\n merged[key] = held && sameIds(held, ids) ? held : ids\n }\n loaded = merged\n}\n\nfunction current(): BookmarkMap {\n if (loaded === undefined) {\n adopt(readStored() ?? {})\n }\n return loaded ?? {}\n}\n\nfunction notify(): void {\n for (const listener of listeners) {\n listener()\n }\n}\n\nexport function bookmarksFor(sessionKey: string): readonly string[] {\n return current()[sessionKey] ?? EMPTY\n}\n\n// Read-modify-write against storage as it stands now, so a second tab's toggles survive this one's.\nexport function toggleBookmark(sessionKey: string, itemId: string): void {\n const base = readStored() ?? current()\n const held = base[sessionKey] ?? EMPTY\n const ids = held.includes(itemId) ? held.filter((id) => id !== itemId) : [...held, itemId]\n const next: Record<string, readonly string[]> = { ...base, [sessionKey]: ids }\n if (ids.length === 0) {\n delete next[sessionKey]\n }\n try {\n storage()?.setItem(BOOKMARKS_STORAGE_KEY, JSON.stringify(next))\n } catch {}\n adopt(next)\n notify()\n}\n\nfunction onStorage(event: { key: string | null }): void {\n if (event.key !== null && event.key !== BOOKMARKS_STORAGE_KEY) {\n return\n }\n const stored = readStored()\n if (stored) {\n adopt(stored)\n notify()\n }\n}\n\nexport function subscribeBookmarks(listener: () => void): () => void {\n listeners.add(listener)\n const target = storageEvents()\n if (listeners.size === 1 && target) {\n target.addEventListener('storage', onStorage)\n detachStorageEvent = () => target.removeEventListener('storage', onStorage)\n }\n return () => {\n listeners.delete(listener)\n if (listeners.size === 0) {\n detachStorageEvent?.()\n detachStorageEvent = undefined\n }\n }\n}\n\nexport function resetBookmarkStore(): void {\n loaded = undefined\n}\n","import { useCallback, useMemo, useSyncExternalStore } from 'react'\nimport { bookmarksFor, subscribeBookmarks, toggleBookmark } from '../lib/bookmark-store.ts'\n\nexport type UseBookmarksResult = {\n bookmarks: readonly string[]\n toggle: (itemId: string) => void\n}\n\nconst NONE: readonly string[] = Object.freeze([])\n\nexport function useBookmarks(sessionKey: string | undefined): UseBookmarksResult {\n const read = useCallback(() => (sessionKey ? bookmarksFor(sessionKey) : NONE), [sessionKey])\n const bookmarks = useSyncExternalStore(subscribeBookmarks, read, () => NONE)\n const toggle = useCallback(\n (itemId: string) => {\n if (sessionKey) {\n toggleBookmark(sessionKey, itemId)\n }\n },\n [sessionKey],\n )\n return useMemo(() => ({ bookmarks, toggle }), [bookmarks, toggle])\n}\n","import { useCallback, useMemo } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { draftKey, readDraft, writeDraft } from '../lib/draft-store.ts'\n\nexport type UseDraftResult = {\n // What was left unsent last time, read once so it can seed the composer on mount.\n initialText: string\n save: (text: string) => void\n clear: () => void\n}\n\n// Remember unsent composer text for a session. Purely local: it never reaches the gateway and never syncs between\n// clients, because a half-written prompt is not something anyone asked to publish.\nexport function useDraft(client: WorkerDeckClient, sessionId: string | undefined): UseDraftResult {\n const key = sessionId ? draftKey(client, sessionId) : undefined\n // Read once per key: re-reading on render would fight whatever is being typed.\n const initialText = useMemo(() => (key ? readDraft(key) : ''), [key])\n const save = useCallback(\n (text: string) => {\n if (key) {\n writeDraft(key, text)\n }\n },\n [key],\n )\n const clear = useCallback(() => {\n if (key) {\n writeDraft(key, '')\n }\n }, [key])\n return { initialText, save, clear }\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\nimport { profileUsageCacheKey, readProfileUsageCache, writeProfileUsageCache } from '../lib/profile-usage-cache.ts'\nimport type { ProfileSpend, ProfileUsage } from '@workerdeck/protocol'\n\nexport type UseProfileUsageOptions = {\n intervalMs?: number\n enabled?: boolean\n}\n\nexport type UseProfileUsageResult = {\n usage: ProfileUsage | undefined\n spend: ProfileSpend | undefined\n refresh: () => void\n}\n\nexport function useProfileUsage(\n client: WorkerDeckClient,\n profile: string | undefined,\n options: UseProfileUsageOptions = {},\n): UseProfileUsageResult {\n const { intervalMs = 60_000, enabled = true } = options\n const cacheKey = profile ? profileUsageCacheKey(client, profile) : undefined\n const [usage, setUsage] = useState<ProfileUsage | undefined>(() => (cacheKey ? readProfileUsageCache(cacheKey) : undefined))\n const [spend, setSpend] = useState<ProfileSpend | undefined>(undefined)\n const [unsupported, setUnsupported] = useState(false)\n const [nonce, setNonce] = useState(0)\n const refresh = useCallback(() => setNonce((n) => n + 1), [])\n\n // A previous profile's reading is another account's plan, not a stale view of this one - so switch to what we last\n // knew about *this* profile rather than to nothing. Blanking here is what made a session switch fall back on the\n // newly-attached session's own replayed numbers, which is the usage-reverts report.\n useEffect(() => {\n setUsage(cacheKey ? readProfileUsageCache(cacheKey) : undefined)\n setSpend(undefined)\n }, [cacheKey])\n\n const alive = useAliveRef()\n\n useEffect(() => {\n if (!profile || !enabled || unsupported) {\n return\n }\n let cancelled = false\n const load = () => {\n // `document` through globalThis: the extras project typechecks this source with no DOM lib.\n if ((globalThis as { document?: { hidden?: boolean } }).document?.hidden) {\n return\n }\n client\n .listProfiles()\n .then((res) => {\n if (cancelled || !alive.current) {\n return\n }\n const found = res.profiles.find((p) => p.name === profile)\n const next = found?.usage\n if (cacheKey) {\n writeProfileUsageCache(cacheKey, next)\n }\n setUsage(next)\n setSpend(found?.spend)\n })\n .catch((e: unknown) => {\n if (cancelled || !alive.current) {\n return\n }\n if (isRouteUnsupported(e)) {\n setUnsupported(true)\n }\n })\n }\n load()\n const timer = setInterval(load, intervalMs)\n return () => {\n cancelled = true\n clearInterval(timer)\n }\n }, [client, profile, enabled, unsupported, intervalMs, nonce, cacheKey])\n\n return { usage, spend, refresh }\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\nimport { errorMessage, type SessionInfo } from '@workerdeck/protocol'\nimport { useAsync } from '../lib/async-guards.ts'\n\nexport type UseSessionInfoResult = {\n info: SessionInfo | undefined\n loading: boolean\n error: string | undefined\n}\n\nexport function useSessionInfo(client: WorkerDeckClient, sessionId: string | undefined): UseSessionInfoResult {\n const { data, error, loading } = useAsync(() => client.getSession(sessionId!), [client, sessionId], { enabled: !!sessionId })\n return { info: data, loading, error: error === undefined ? undefined : errorMessage(error, 'Session not found') }\n}\n","export type OpenFile = {\n path: string\n name: string\n status: 'loading' | 'ready' | 'binary' | 'error'\n content?: string\n draft?: string\n bytes?: number\n hash?: string\n modifiedAt?: number\n error?: string\n saving?: boolean\n saveError?: string\n conflict?: boolean\n}\n\nexport function isDirty(file: OpenFile): boolean {\n return file.draft !== undefined && file.draft !== file.content\n}\n\nexport function currentText(file: OpenFile): string {\n return file.draft ?? file.content ?? ''\n}\n\nexport type OpenFilesState = {\n files: OpenFile[]\n activePath?: string\n}\n\nexport type OpenFilesAction =\n | { type: 'open'; path: string }\n | { type: 'close'; path: string }\n | { type: 'closeAll' }\n | { type: 'activate'; path: string }\n | {\n type: 'loaded'\n path: string\n content: string\n encoding: 'utf8' | 'base64'\n bytes: number\n hash: string\n modifiedAt: number\n }\n | { type: 'failed'; path: string; error: string }\n | { type: 'edit'; path: string; content: string }\n | { type: 'revert'; path: string }\n | { type: 'saveStart'; path: string }\n | { type: 'saved'; path: string; content: string; bytes: number; hash: string; modifiedAt: number }\n | { type: 'saveFailed'; path: string; error: string; conflict?: boolean }\n | { type: 'dismissConflict'; path: string }\n\nexport const initialOpenFilesState: OpenFilesState = { files: [] }\n\nexport function openFilesReducer(state: OpenFilesState, action: OpenFilesAction): OpenFilesState {\n switch (action.type) {\n case 'open': {\n if (state.files.some((f) => f.path === action.path)) {\n return state.activePath === action.path ? state : { ...state, activePath: action.path }\n }\n const file: OpenFile = { path: action.path, name: baseName(action.path), status: 'loading' }\n return { files: [...state.files, file], activePath: action.path }\n }\n\n case 'close': {\n const index = state.files.findIndex((f) => f.path === action.path)\n if (index === -1) {\n return state\n }\n const files = state.files.filter((f) => f.path !== action.path)\n if (state.activePath !== action.path) {\n return { ...state, files }\n }\n // The right-hand neighbour has slid into this index; a closed last tab has nothing there.\n const next = files[index] ?? files[index - 1]\n return { files, activePath: next?.path }\n }\n\n case 'closeAll': {\n return initialOpenFilesState\n }\n\n case 'activate': {\n if (!state.files.some((f) => f.path === action.path)) {\n return state\n }\n return state.activePath === action.path ? state : { ...state, activePath: action.path }\n }\n\n case 'loaded': {\n return patch(state, action.path, () => ({\n path: action.path,\n name: baseName(action.path),\n status: action.encoding === 'utf8' ? 'ready' : 'binary',\n content: action.encoding === 'utf8' ? action.content : undefined,\n bytes: action.bytes,\n hash: action.hash,\n modifiedAt: action.modifiedAt,\n }))\n }\n\n case 'failed': {\n return patch(state, action.path, (file) => ({ ...file, status: 'error', error: action.error }))\n }\n\n case 'edit': {\n return patch(state, action.path, (file) => (file.status === 'ready' ? { ...file, draft: action.content } : file))\n }\n\n case 'revert': {\n return patch(state, action.path, (file) => ({\n ...file,\n draft: undefined,\n saveError: undefined,\n conflict: false,\n }))\n }\n\n case 'saveStart': {\n return patch(state, action.path, (file) => ({\n ...file,\n saving: true,\n saveError: undefined,\n conflict: false,\n }))\n }\n\n case 'saved': {\n return patch(state, action.path, (file) => ({\n ...file,\n saving: false,\n saveError: undefined,\n conflict: false,\n content: action.content,\n bytes: action.bytes,\n hash: action.hash,\n modifiedAt: action.modifiedAt,\n draft: file.draft === action.content ? undefined : file.draft,\n }))\n }\n\n case 'saveFailed': {\n return patch(state, action.path, (file) => ({\n ...file,\n saving: false,\n saveError: action.error,\n conflict: action.conflict ?? false,\n }))\n }\n\n case 'dismissConflict': {\n return patch(state, action.path, (file) => ({\n ...file,\n conflict: false,\n saveError: undefined,\n }))\n }\n }\n}\n\nfunction patch(state: OpenFilesState, path: string, next: (file: OpenFile) => OpenFile): OpenFilesState {\n const index = state.files.findIndex((f) => f.path === path)\n if (index === -1) {\n return state\n }\n const current = state.files[index]!\n const updated = next(current)\n if (updated === current) {\n return state\n }\n const files = state.files.slice()\n files[index] = updated\n return { ...state, files }\n}\n\nfunction baseName(path: string): string {\n const trimmed = path.endsWith('/') ? path.slice(0, -1) : path\n return trimmed.slice(trimmed.lastIndexOf('/') + 1) || trimmed || path\n}\n","import { errorMessage } from '@workerdeck/protocol'\nimport { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'\nimport { WorkerDeckError, type WorkerDeckClient } from '@workerdeck/client'\nimport { currentText, initialOpenFilesState, isDirty, openFilesReducer, type OpenFile, type OpenFilesState } from '../lib/open-files.ts'\n\nexport type UseOpenFilesResult = OpenFilesState & {\n active: OpenFile | undefined\n hasUnsaved: boolean\n open: (path: string) => void\n close: (path: string) => void\n closeAll: () => void\n activate: (path: string) => void\n edit: (path: string, content: string) => void\n save: (path: string) => Promise<void>\n revert: (path: string) => void\n reload: (path: string) => void\n overwrite: (path: string) => Promise<void>\n dismissConflict: (path: string) => void\n}\n\nexport function useOpenFiles(client: WorkerDeckClient): UseOpenFilesResult {\n const [state, dispatch] = useReducer(openFilesReducer, initialOpenFilesState)\n\n const requested = useRef(new Set<string>())\n const alive = useRef(true)\n useEffect(() => {\n alive.current = true\n return () => {\n alive.current = false\n }\n }, [])\n\n const latest = useRef(state)\n useEffect(() => {\n latest.current = state\n }, [state])\n\n const loading = state.files.filter((f) => f.status === 'loading')\n // Joined so the effect's identity is the set of pending reads, not the array the reducer rebuilds.\n const pending = loading.map((f) => f.path).join('\\n')\n\n const read = useCallback(\n (path: string) =>\n client.readHostFile(path).then((response) => {\n if (!alive.current) {\n return undefined\n }\n dispatch({\n type: 'loaded',\n // The tab is keyed on the path asked for, never the canonical one the gateway answers with.\n path,\n content: response.content,\n encoding: response.encoding,\n bytes: response.bytes,\n hash: response.hash,\n modifiedAt: response.modifiedAt,\n })\n return response\n }),\n [client],\n )\n\n useEffect(() => {\n for (const path of pending ? pending.split('\\n') : []) {\n if (requested.current.has(path)) {\n continue\n }\n requested.current.add(path)\n read(path).catch((e: unknown) => {\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'failed',\n path,\n error: errorMessage(e, 'Could not read that file'),\n })\n })\n }\n }, [read, pending])\n\n const open = useCallback((path: string) => dispatch({ type: 'open', path }), [])\n const close = useCallback((path: string) => {\n requested.current.delete(path)\n dispatch({ type: 'close', path })\n }, [])\n const closeAll = useCallback(() => {\n requested.current.clear()\n dispatch({ type: 'closeAll' })\n }, [])\n const activate = useCallback((path: string) => dispatch({ type: 'activate', path }), [])\n const edit = useCallback((path: string, content: string) => dispatch({ type: 'edit', path, content }), [])\n const revert = useCallback((path: string) => dispatch({ type: 'revert', path }), [])\n const dismissConflict = useCallback((path: string) => dispatch({ type: 'dismissConflict', path }), [])\n\n const reload = useCallback(\n (path: string) => {\n requested.current.add(path)\n read(path).catch((e: unknown) => {\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'failed',\n path,\n error: errorMessage(e, 'Could not re-read that file'),\n })\n })\n },\n [read],\n )\n\n const write = useCallback(\n async (path: string, text: string, expectedHash: string | undefined) => {\n try {\n const response = await client.writeHostFile({ path, content: text, expectedHash })\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'saved',\n path,\n content: text,\n bytes: response.bytes,\n hash: response.hash,\n modifiedAt: response.modifiedAt,\n })\n } catch (e) {\n if (!alive.current) {\n return\n }\n const conflict = e instanceof WorkerDeckError && e.status === 409\n dispatch({\n type: 'saveFailed',\n path,\n conflict,\n error: conflict ? 'This file changed on disk since you opened it.' : errorMessage(e, 'Could not save that file'),\n })\n }\n },\n [client],\n )\n\n const save = useCallback(\n async (path: string) => {\n const file = latest.current.files.find((f) => f.path === path)\n if (!file || file.saving || !isDirty(file)) {\n return\n }\n dispatch({ type: 'saveStart', path })\n await write(path, currentText(file), file.hash)\n },\n [write],\n )\n\n const overwrite = useCallback(\n async (path: string) => {\n const file = latest.current.files.find((f) => f.path === path)\n if (!file || file.saving) {\n return\n }\n // Captured before the re-read, whose `loaded` clears the draft - the one thing \"take mine\" must not do.\n const mine = currentText(file)\n dispatch({ type: 'saveStart', path })\n try {\n const fresh = await client.readHostFile(path)\n if (!alive.current) {\n return\n }\n await write(path, mine, fresh.hash)\n } catch (e) {\n if (!alive.current) {\n return\n }\n dispatch({\n type: 'saveFailed',\n path,\n error: errorMessage(e, 'Could not save that file'),\n })\n }\n },\n [client, write],\n )\n\n const active = useMemo(() => state.files.find((f) => f.path === state.activePath), [state.files, state.activePath])\n const hasUnsaved = useMemo(() => state.files.some(isDirty), [state.files])\n\n return {\n ...state,\n active,\n hasUnsaved,\n open,\n close,\n closeAll,\n activate,\n edit,\n save,\n revert,\n reload,\n overwrite,\n dismissConflict,\n }\n}\n","import type { SessionHandle } from '@workerdeck/client'\nimport { errorMessage, type ToolCallRequestFrame } from '@workerdeck/protocol'\nimport type { RunScriptResult, SandboxEngine, SandboxVfs } from '@workerdeck/sandbox'\n\nexport type ToolHostExecution = {\n executionId: string\n toolName: string\n status: 'running' | 'settled' | 'failed' | 'canceled'\n reason?: string\n startedAt: number\n endedAt?: number\n}\n\nexport type ToolHostRunner = (request: {\n script: string\n vfs: SandboxVfs\n timeoutMs: number\n memoryLimitBytes: number\n signal: AbortSignal\n}) => Promise<RunScriptResult>\n\nexport type ClientToolResult = { value: unknown } | { error: string; reason?: string }\n\nexport type ClientToolHandler = (\n input: unknown,\n context: { executionId: string; signal: AbortSignal },\n) => ClientToolResult | Promise<ClientToolResult>\n\nexport type ToolCallHostOptions = {\n tools?: string[]\n clientTools?: Record<string, ClientToolHandler>\n timeoutMs?: number\n memoryLimitBytes?: number\n loadEngine?: () => Promise<SandboxEngine>\n // The guest deadline preempts the interpreter only on the thread it runs on; a Web Worker is the way off this one.\n execute?: ToolHostRunner\n fetchText?: (url: string) => Promise<string>\n onExecution?: (execution: ToolHostExecution) => void\n}\n\ntype Work = (signal: AbortSignal) => Promise<Outcome>\n\ntype Outcome = { ok: true; value: unknown; logs?: string[] } | { ok: false; reason: string; error: string; logs?: string[] }\n\nexport function createToolCallHost(handle: SessionHandle, options: ToolCallHostOptions = {}): { dispose: () => void } {\n const inFlight = new Map<string, AbortController>()\n let enginePromise: Promise<SandboxEngine> | undefined\n let disposed = false\n\n const track = (execution: ToolHostExecution) => options.onExecution?.(execution)\n\n const settle = (frame: ToolCallRequestFrame, startedAt: number, outcome: Outcome) => {\n const { executionId, toolName } = frame\n if (outcome.ok) {\n handle.sendToolCallResult(executionId, { type: 'json', value: outcome.value }, outcome.logs)\n track({ executionId, toolName, status: 'settled', startedAt, endedAt: Date.now() })\n } else {\n handle.sendToolCallError(executionId, outcome.reason, outcome.error, outcome.logs)\n track({ executionId, toolName, status: 'failed', reason: outcome.reason, startedAt, endedAt: Date.now() })\n }\n }\n\n const execute = async (frame: ToolCallRequestFrame, startedAt: number, work: Work): Promise<void> => {\n const controller = new AbortController()\n inFlight.set(frame.executionId, controller)\n track({ executionId: frame.executionId, toolName: frame.toolName, status: 'running', startedAt })\n let outcome: Outcome\n try {\n outcome = await work(controller.signal)\n } catch (error) {\n outcome = { ok: false, reason: 'host_error', error: errorMessage(error) }\n }\n try {\n if (!disposed && inFlight.has(frame.executionId)) {\n settle(frame, startedAt, outcome)\n }\n } finally {\n inFlight.delete(frame.executionId)\n }\n }\n\n const runClientTool = (frame: ToolCallRequestFrame, handler: ClientToolHandler, startedAt: number): Promise<void> =>\n execute(frame, startedAt, async (signal) => {\n const result = await handler(frame.input, { executionId: frame.executionId, signal })\n return 'error' in result\n ? { ok: false, reason: result.reason ?? 'client_error', error: result.error }\n : { ok: true, value: result.value }\n })\n\n const runScript = (frame: ToolCallRequestFrame, script: string, startedAt: number): Promise<void> =>\n execute(frame, startedAt, async (signal) => {\n const sandbox = await import('@workerdeck/sandbox')\n const vfs = sandbox.createVfs(frame.vfsSeed)\n // Never above what the server asked for: it owns the deadline it gives up at.\n const timeoutMs = Math.min(frame.limits?.timeoutMs ?? Number.POSITIVE_INFINITY, options.timeoutMs ?? 5000)\n const memoryLimitBytes = Math.min(\n frame.limits?.memoryLimitBytes ?? Number.POSITIVE_INFINITY,\n options.memoryLimitBytes ?? 64 * 1024 * 1024,\n )\n let result: RunScriptResult\n if (options.execute) {\n result = await options.execute({ script, vfs, timeoutMs, memoryLimitBytes, signal })\n } else {\n enginePromise ??= (options.loadEngine ?? defaultLoadEngine)()\n result = await sandbox.runScript(await enginePromise, {\n script,\n vfs,\n timeoutMs,\n memoryLimitBytes,\n signal,\n fetchText: options.fetchText,\n })\n }\n const logs = result.logs.map((l) => `[${l.level}] ${l.text}`)\n return result.ok ? { ok: true, value: result.value, logs } : { ok: false, reason: result.reason, error: result.error, logs }\n })\n\n const run = async (frame: ToolCallRequestFrame): Promise<void> => {\n const startedAt = Date.now()\n const clientHandler = options.clientTools?.[frame.toolName]\n if (clientHandler) {\n return runClientTool(frame, clientHandler, startedAt)\n }\n const allowed = options.tools ?? ['eval_script']\n if (!allowed.includes(frame.toolName)) {\n settle(frame, startedAt, { ok: false, reason: 'unsupported_tool', error: `this client does not execute '${frame.toolName}'` })\n return\n }\n const script = (frame.input as { script?: unknown } | undefined)?.script\n if (typeof script !== 'string') {\n settle(frame, startedAt, { ok: false, reason: 'invalid_input', error: 'expected a string `script` input' })\n return\n }\n return runScript(frame, script, startedAt)\n }\n\n const offRequest = handle.on('toolCallRequest', (frame) => void run(frame))\n const offCancel = handle.on('toolCallCanceled', ({ executionId, reason }) => {\n const controller = inFlight.get(executionId)\n if (!controller) {\n return\n }\n controller.abort()\n inFlight.delete(executionId)\n track({\n executionId,\n toolName: '',\n status: 'canceled',\n reason,\n startedAt: Date.now(),\n endedAt: Date.now(),\n })\n })\n\n return {\n dispose: () => {\n disposed = true\n offRequest()\n offCancel()\n for (const controller of inFlight.values()) {\n controller.abort()\n }\n inFlight.clear()\n },\n }\n}\n\nasync function defaultLoadEngine(): Promise<SandboxEngine> {\n const [sandbox, variant] = await Promise.all([import('@workerdeck/sandbox'), import('@jitl/quickjs-singlefile-browser-release-asyncify')])\n return sandbox.loadEngine(variant as never)\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { SessionHandle } from '@workerdeck/client'\nimport { createToolCallHost, type ToolCallHostOptions, type ToolHostExecution } from '../lib/tool-host.ts'\n\nexport type UseToolCallHostOptions = ToolCallHostOptions & {\n enabled?: boolean\n historyLimit?: number\n}\n\nexport function useToolCallHost(\n handle: SessionHandle | undefined,\n options: UseToolCallHostOptions = {},\n): { executions: ToolHostExecution[] } {\n const [executions, setExecutions] = useState<ToolHostExecution[]>([])\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n useEffect(() => {\n if (!handle || options.enabled === false) {\n return\n }\n const host = createToolCallHost(handle, {\n // Getters read the ref at call time, so inline objects and closures never resubscribe.\n get tools() {\n const base = optionsRef.current.tools\n const client = optionsRef.current.clientTools\n if (!client) {\n return base\n }\n const clientNames = Object.keys(client)\n return base ? [...new Set([...base, ...clientNames])] : clientNames\n },\n get clientTools() {\n return optionsRef.current.clientTools\n },\n get timeoutMs() {\n return optionsRef.current.timeoutMs\n },\n get memoryLimitBytes() {\n return optionsRef.current.memoryLimitBytes\n },\n get loadEngine() {\n return optionsRef.current.loadEngine\n },\n get execute() {\n return optionsRef.current.execute\n },\n get fetchText() {\n return optionsRef.current.fetchText\n },\n onExecution: (execution) => {\n optionsRef.current.onExecution?.(execution)\n const limit = optionsRef.current.historyLimit ?? 50\n setExecutions((prev) => [...prev.filter((e) => e.executionId !== execution.executionId), execution].slice(-limit))\n },\n })\n return () => host.dispose()\n }, [handle, options.enabled])\n\n return { executions }\n}\n","import type { TranscriptItem } from './transcript.ts'\n\nexport type RecapSummary = {\n turns: number\n replies: number\n tools: number\n toolNames: string[]\n files: number\n errors: number\n pending: number\n any: boolean\n}\n\nexport type RecapInput = {\n items: readonly TranscriptItem[]\n pendingApprovals?: readonly unknown[]\n}\n\n// The boundary is clamped, never rejected: a transcript can shrink (a `/clear`, a compaction).\nexport function summarizeSince(state: RecapInput, fromIndex: number): RecapSummary {\n const start = Math.max(0, Math.min(fromIndex, state.items.length))\n const fresh = state.items.slice(start)\n const toolCounts = new Map<string, number>()\n let turns = 0\n let replies = 0\n let tools = 0\n let files = 0\n let errors = 0\n\n for (const item of fresh) {\n switch (item.kind) {\n case 'turn_result': {\n turns += 1\n if (item.isError) {\n errors += 1\n }\n break\n }\n case 'assistant_text': {\n replies += 1\n break\n }\n case 'tool_call': {\n tools += 1\n toolCounts.set(item.name, (toolCounts.get(item.name) ?? 0) + 1)\n if (item.status === 'failed' || item.result?.isError) {\n errors += 1\n }\n break\n }\n case 'file_delivered': {\n files += 1\n break\n }\n case 'notice': {\n if (item.level === 'error') {\n errors += 1\n }\n break\n }\n default: {\n break\n }\n }\n }\n\n const toolNames = [...toolCounts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([name]) => name)\n const pending = state.pendingApprovals?.length ?? 0\n return {\n turns,\n replies,\n tools,\n toolNames,\n files,\n errors,\n pending,\n any: turns + replies + tools + files + errors + pending > 0,\n }\n}\n\nexport function recapLine(summary: RecapSummary): string | undefined {\n if (!summary.any) {\n return undefined\n }\n const parts: string[] = []\n if (summary.turns > 0) {\n parts.push(plural(summary.turns, 'turn'))\n } else if (summary.replies > 0) {\n parts.push(plural(summary.replies, 'reply', 'replies'))\n }\n if (summary.tools > 0) {\n const named = summary.toolNames.slice(0, 3).join(', ')\n const rest = summary.toolNames.length - 3\n parts.push(`${plural(summary.tools, 'tool call')}${named ? ` (${named}${rest > 0 ? `, +${rest}` : ''})` : ''}`)\n }\n if (summary.files > 0) {\n parts.push(plural(summary.files, 'file'))\n }\n if (summary.errors > 0) {\n parts.push(plural(summary.errors, 'error'))\n }\n if (summary.pending > 0) {\n parts.push(`${plural(summary.pending, 'approval')} waiting`)\n }\n return parts.join(' · ')\n}\n\nfunction plural(count: number, one: string, many = `${one}s`): string {\n return `${count} ${count === 1 ? one : many}`\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { SessionHandle } from '@workerdeck/client'\nimport type { ShellInfo } from '@workerdeck/protocol'\n\nexport type ShellTerminalSize = { cols: number; rows: number }\n\nexport type ShellTerminalStatus = 'idle' | 'attaching' | 'attached' | 'detached'\n\nexport type ShellAttachment = {\n shell: ShellInfo\n cols: number\n rows: number\n scrollback: string\n}\n\nexport type UseShellTerminalOptions = {\n onData: (data: string) => void\n onEnded?: (reason: string) => void\n onAttached?: (attachment: ShellAttachment) => void\n}\n\nexport type UseShellTerminalResult = {\n status: ShellTerminalStatus\n shell: ShellInfo | undefined\n reason: string | undefined\n attach: (size: ShellTerminalSize) => void\n write: (data: string) => void\n resize: (size: ShellTerminalSize) => void\n detach: () => void\n}\n\n// PTY bytes never enter React state, the transcript reducer or the transcript cache: they go\n// straight to the caller's renderer through a ref, so a noisy `npm run dev` re-renders nothing.\nexport function useShellTerminal(\n handle: SessionHandle | undefined,\n shellId: string | undefined,\n options: UseShellTerminalOptions,\n): UseShellTerminalResult {\n const [status, setStatus] = useState<ShellTerminalStatus>('idle')\n const [shell, setShell] = useState<ShellInfo | undefined>(undefined)\n const [reason, setReason] = useState<string | undefined>(undefined)\n const optionsRef = useRef(options)\n optionsRef.current = options\n const sizeRef = useRef<ShellTerminalSize>({ cols: 80, rows: 24 })\n const wantAttachRef = useRef(false)\n\n useEffect(() => {\n wantAttachRef.current = false\n setStatus('idle')\n setShell(undefined)\n setReason(undefined)\n }, [handle, shellId])\n\n useEffect(() => {\n if (!handle || shellId === undefined) {\n return\n }\n const offAttached = handle.on('shellAttached', (frame) => {\n if (frame.shellId !== shellId) {\n return\n }\n sizeRef.current = { cols: frame.cols, rows: frame.rows }\n setShell(frame.shell)\n setReason(undefined)\n setStatus('attached')\n const attachment: ShellAttachment = { shell: frame.shell, cols: frame.cols, rows: frame.rows, scrollback: frame.scrollback }\n if (optionsRef.current.onAttached) {\n optionsRef.current.onAttached(attachment)\n } else if (frame.scrollback) {\n optionsRef.current.onData(frame.scrollback)\n }\n })\n const offOutput = handle.on('shellOutput', (frame) => {\n if (frame.shellId === shellId) {\n optionsRef.current.onData(frame.data)\n }\n })\n const offDetached = handle.on('shellDetached', (frame) => {\n if (frame.shellId !== shellId) {\n return\n }\n wantAttachRef.current = false\n setReason(frame.reason)\n setStatus('detached')\n optionsRef.current.onEnded?.(frame.reason)\n })\n // A shell outlives the socket, so a reconnect re-attaches and the gateway replays the\n // scrollback into a reset screen rather than leaving a live pane frozen.\n const offConnection = handle.on('connectionChange', (connected) => {\n if (!wantAttachRef.current) {\n return\n }\n if (connected) {\n setStatus('attaching')\n handle.attachShell(shellId, sizeRef.current)\n } else {\n setStatus((current) => (current === 'attached' ? 'attaching' : current))\n }\n })\n return () => {\n offAttached()\n offOutput()\n offDetached()\n offConnection()\n if (wantAttachRef.current) {\n wantAttachRef.current = false\n handle.detachShell(shellId)\n }\n }\n }, [handle, shellId])\n\n const attach = useCallback(\n (size: ShellTerminalSize) => {\n if (!handle || shellId === undefined) {\n return\n }\n sizeRef.current = size\n wantAttachRef.current = true\n setReason(undefined)\n setStatus('attaching')\n handle.attachShell(shellId, size)\n },\n [handle, shellId],\n )\n\n const write = useCallback(\n (data: string) => {\n if (handle && shellId !== undefined) {\n handle.writeShell(shellId, data)\n }\n },\n [handle, shellId],\n )\n\n const resize = useCallback(\n (size: ShellTerminalSize) => {\n if (size.cols === sizeRef.current.cols && size.rows === sizeRef.current.rows) {\n return\n }\n sizeRef.current = size\n if (handle && shellId !== undefined && wantAttachRef.current) {\n handle.resizeShell(shellId, size)\n }\n },\n [handle, shellId],\n )\n\n const detach = useCallback(() => {\n if (handle && shellId !== undefined && wantAttachRef.current) {\n handle.detachShell(shellId)\n }\n wantAttachRef.current = false\n setStatus('idle')\n }, [handle, shellId])\n\n return useMemo(() => ({ status, shell, reason, attach, write, resize, detach }), [status, shell, reason, attach, write, resize, detach])\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workerdeck/react",
3
- "version": "3.3.0",
3
+ "version": "3.5.0",
4
4
  "type": "module",
5
5
  "description": "Headless React layer for WorkerDeck: session hook + pure transcript and sessions-list reducers. No styling opinion - @workerdeck/ui is the styled layer on top.",
6
6
  "license": "MIT",
@@ -17,9 +17,9 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@workerdeck/client": "3.3.0",
21
- "@workerdeck/sandbox": "3.3.0",
22
- "@workerdeck/protocol": "3.3.0"
20
+ "@workerdeck/client": "3.5.0",
21
+ "@workerdeck/sandbox": "3.5.0",
22
+ "@workerdeck/protocol": "3.5.0"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "@jitl/quickjs-singlefile-browser-release-asyncify": "^0.31.0",
@@ -41,8 +41,8 @@
41
41
  "tsdown": "^0.22.14",
42
42
  "vitest": "^4.1.11",
43
43
  "ws": "^8.21.3",
44
- "@workerdeck/server": "3.3.0",
45
- "@workerdeck/core": "3.3.0"
44
+ "@workerdeck/server": "3.5.0",
45
+ "@workerdeck/core": "3.5.0"
46
46
  },
47
47
  "author": "Tobias Strebitzer",
48
48
  "repository": {