@workerdeck/react 1.1.0 → 1.2.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
@@ -58,6 +58,17 @@ type TranscriptItem = {
58
58
  id: string;
59
59
  level: 'info' | 'error';
60
60
  text: string;
61
+ } |
62
+ /**
63
+ * The engine summarised the conversation in place to fit its context window. A boundary, not a
64
+ * message: nothing above it is retracted (that is `conversation_reset`, which empties `items`),
65
+ * and it carries no text of its own because the wire event carries none — codex's
66
+ * `contextCompaction` item is `{id, type}` and nothing more.
67
+ */
68
+ {
69
+ kind: 'compaction';
70
+ id: string;
71
+ parentToolUseId: string | null;
61
72
  } | {
62
73
  kind: 'file_delivered';
63
74
  id: string;
package/build/index.mjs CHANGED
@@ -179,6 +179,14 @@ function applyEvent(state, event) {
179
179
  contextUsage: void 0,
180
180
  sdkSessionId: event.sdkSessionId ?? base.sdkSessionId
181
181
  };
182
+ case "context_compacted": return {
183
+ ...base,
184
+ items: upsert(base.items, {
185
+ kind: "compaction",
186
+ id: event.uuid,
187
+ parentToolUseId: event.parentToolUseId ?? null
188
+ })
189
+ };
182
190
  case "user_message": {
183
191
  let items = base.items;
184
192
  for (const block of contentToBlocks(event.message.content)) if (block.type === "tool_result") {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["entries"],"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-project-icons.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"],"sourcesContent":["import { ENGINE_CAPABILITIES, mergeUsage, orderUsageWindows } from '@workerdeck/protocol'\nimport type {\n ContentBlock,\n ContextUsage,\n EngineCapabilities,\n FilePatch,\n MessageAttachment,\n ModelOption,\n PermissionMode,\n PermissionRequest,\n ProfileEngine,\n RateLimitInfo,\n SessionEvent,\n SessionInfo,\n SessionStatus,\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 // 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 errors?: string[]\n }\n | { kind: 'notice'; id: string; level: 'info' | 'error'; text: string }\n | { kind: 'file_delivered'; id: string; path: string; bytes: number; description?: string }\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 // 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 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>$/\n\nconst COMMAND_NAME = /<command-name>([\\s\\S]*?)<\\/command-name>/\nconst COMMAND_ARGS = /<command-args>([\\s\\S]*?)<\\/command-args>/\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\nfunction 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\nfunction upsert(items: TranscriptItem[], item: TranscriptItem): TranscriptItem[] {\n const index = items.findIndex((existing) => existing.id === item.id && existing.kind === item.kind)\n if (index === -1) {\n return [...items, item]\n }\n const next = [...items]\n next[index] = item\n return next\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 session: info,\n }\n}\n\nexport function rateLimitWindows(state: TranscriptState): 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\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 '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 sdkSessionId: event.sdkSessionId ?? base.sdkSessionId,\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' && !event.synthetic) {\n const text = (block as { text: string }).text\n const localOutput = LOCAL_COMMAND_OUTPUT.exec(text.trim())\n if (localOutput) {\n items = upsert(items, {\n kind: 'notice',\n id: event.uuid ?? `user-${event.seq}`,\n level: localOutput[1] === 'stderr' ? 'error' : 'info',\n text: localOutput[2].trim(),\n })\n } else {\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.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 existing = base.items.find(\n (item): item is Extract<TranscriptItem, { kind: 'assistant_text' }> => item.kind === 'assistant_text' && item.id === id,\n )\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: upsert(base.items, item) }\n }\n if (delta.delta?.type === 'thinking_delta') {\n const id = streamingThinkingId(event.parentToolUseId)\n const existing = base.items.find(\n (item): item is Extract<TranscriptItem, { kind: 'thinking' }> => item.kind === 'thinking' && item.id === id,\n )\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: upsert(base.items, item) }\n }\n return base\n }\n\n case 'turn_result': {\n return {\n ...base,\n totalCostUsd: event.totalCostUsd,\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 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 type { WorkerDeckClient, SessionHandle } from '@workerdeck/client'\nimport { PROTOCOL_VERSION } from '@workerdeck/protocol'\nimport type { AttachedFrame, ModelOption, PermissionMode, SessionEvent } from '@workerdeck/protocol'\nimport { applyEvent, initialTranscriptState, hydrateToolResult, seedFromSessionInfo, type TranscriptState } 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 }\n\nfunction reduce(state: TranscriptState, action: SessionEvent | AttachedFrame | SeedAction | HydrateAction): 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 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 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 setPermissionMode: (mode: PermissionMode) => void\n setModel: (model?: string) => void\n closeSession: () => void\n reconnectNow: () => void\n loadFullResult: (toolUseId: string) => 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 [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 })\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 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 const text =\n typeof full.content === 'string'\n ? full.content\n : (full.content ?? [])\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n dispatch({ type: 'transcript_hydrate_result', toolUseId, text })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n return useMemo(\n () => ({\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n models,\n effectiveModel: state.model ?? state.defaultModel,\n handle: handleState,\n send: (text, attachmentIds) => handleRef.current?.send(text, attachmentIds),\n approve: (requestId, updatedInput) => handleRef.current?.approve(requestId, updatedInput),\n deny: (requestId, message, interrupt) => handleRef.current?.deny(requestId, message, interrupt),\n interrupt: () => handleRef.current?.interrupt(),\n clearContext: () => handleRef.current?.clearContext(),\n setPermissionMode: (mode) => handleRef.current?.setPermissionMode(mode),\n setModel: (model) => handleRef.current?.setModel(model),\n closeSession: () => handleRef.current?.closeSession(),\n reconnectNow,\n loadFullResult,\n }),\n [state, connected, connection, replaying, protocolMismatch, models, handleState, reconnectNow, loadFullResult],\n )\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/**\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.\n */\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/**\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.\n */\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 { 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: e instanceof Error ? e.message : '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","export type PromptToken = {\n kind: 'file' | 'command'\n start: number\n end: number\n text: 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\nconst SENTENCE_TAIL = new Set(['.', ',', ';', ':', '!', '?', ')', ']', '}', '\"', \"'\"])\n\nexport function scanPromptTokens(text: string): PromptToken[] {\n const tokens: PromptToken[] = []\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 = word[0] === '@' ? 'file' : word[0] === '/' ? 'command' : 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 tokens.push({ kind, start: match.index, end, text: text.slice(match.index, end) })\n }\n return tokens\n}\n","import { useEffect, useRef, type RefObject } from 'react'\nimport { WorkerDeckError } from '@workerdeck/client'\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","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 { 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(e instanceof Error ? e.message : '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, 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","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/**\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.\n */\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 { ProfileUsage } from '@workerdeck/protocol'\n\nexport type UseProfileUsageOptions = {\n intervalMs?: number\n enabled?: boolean\n}\n\nexport type UseProfileUsageResult = {\n usage: ProfileUsage | 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 [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(() => setUsage(cacheKey ? readProfileUsageCache(cacheKey) : undefined), [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 next = res.profiles.find((p) => p.name === profile)?.usage\n if (cacheKey) {\n writeProfileUsageCache(cacheKey, next)\n }\n setUsage(next)\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, refresh }\n}\n","import { useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport type { SessionInfo } from '@workerdeck/protocol'\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 [info, setInfo] = useState<SessionInfo | undefined>()\n const [loading, setLoading] = useState(!!sessionId)\n const [error, setError] = useState<string | undefined>()\n\n useEffect(() => {\n if (!sessionId) {\n setInfo(undefined)\n setLoading(false)\n setError(undefined)\n return\n }\n let cancelled = false\n setLoading(true)\n setError(undefined)\n setInfo(undefined)\n client\n .getSession(sessionId)\n .then((next) => {\n if (cancelled) {\n return\n }\n setInfo(next)\n setLoading(false)\n })\n .catch((e: unknown) => {\n if (cancelled) {\n return\n }\n setError(e instanceof Error ? e.message : 'Session not found')\n setLoading(false)\n })\n return () => {\n cancelled = true\n }\n }, [client, sessionId])\n\n return { info, loading, error }\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 { 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: e instanceof Error ? e.message : '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: e instanceof Error ? e.message : '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.' : e instanceof Error ? e.message : '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: e instanceof Error ? e.message : '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 type { RunScriptResult, SandboxEngine, SandboxVfs } from '@workerdeck/sandbox'\nimport type { ToolCallRequestFrame } from '@workerdeck/protocol'\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\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 refuse = (frame: ToolCallRequestFrame, reason: string, error: string, startedAt: number) => {\n handle.sendToolCallError(frame.executionId, reason, error)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'failed',\n reason,\n startedAt,\n endedAt: Date.now(),\n })\n }\n\n const runClientTool = async (frame: ToolCallRequestFrame, handler: ClientToolHandler): Promise<void> => {\n const startedAt = Date.now()\n const controller = new AbortController()\n inFlight.set(frame.executionId, controller)\n track({ executionId: frame.executionId, toolName: frame.toolName, status: 'running', startedAt })\n\n try {\n const result = await handler(frame.input, {\n executionId: frame.executionId,\n signal: controller.signal,\n })\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n if ('error' in result) {\n handle.sendToolCallError(frame.executionId, result.reason ?? 'client_error', result.error)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'failed',\n reason: result.reason ?? 'client_error',\n startedAt,\n endedAt: Date.now(),\n })\n } else {\n handle.sendToolCallResult(frame.executionId, { type: 'json', value: result.value })\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'settled',\n startedAt,\n endedAt: Date.now(),\n })\n }\n } catch (error) {\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n refuse(frame, 'host_error', error instanceof Error ? error.message : String(error), startedAt)\n } finally {\n inFlight.delete(frame.executionId)\n }\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)\n }\n const allowed = options.tools ?? ['eval_script']\n if (!allowed.includes(frame.toolName)) {\n refuse(frame, 'unsupported_tool', `this client does not execute '${frame.toolName}'`, startedAt)\n return\n }\n const script = (frame.input as { script?: unknown } | undefined)?.script\n if (typeof script !== 'string') {\n refuse(frame, 'invalid_input', 'expected a string `script` input', startedAt)\n return\n }\n\n const controller = new AbortController()\n inFlight.set(frame.executionId, controller)\n track({ executionId: frame.executionId, toolName: frame.toolName, status: 'running', startedAt })\n\n try {\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\n const result = options.execute\n ? await options.execute({ script, vfs, timeoutMs, memoryLimitBytes, signal: controller.signal })\n : await (async () => {\n enginePromise ??= (options.loadEngine ?? defaultLoadEngine)()\n return sandbox.runScript(await enginePromise, {\n script,\n vfs,\n timeoutMs,\n memoryLimitBytes,\n signal: controller.signal,\n fetchText: options.fetchText,\n })\n })()\n\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n const logs = result.logs.map((l) => `[${l.level}] ${l.text}`)\n if (result.ok) {\n handle.sendToolCallResult(frame.executionId, { type: 'json', value: result.value }, logs)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'settled',\n startedAt,\n endedAt: Date.now(),\n })\n } else {\n handle.sendToolCallError(frame.executionId, result.reason, result.error, logs)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'failed',\n reason: result.reason,\n startedAt,\n endedAt: Date.now(),\n })\n }\n } catch (error) {\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n refuse(frame, 'host_error', error instanceof Error ? error.message : String(error), startedAt)\n } finally {\n inFlight.delete(frame.executionId)\n }\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"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["entries"],"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-project-icons.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"],"sourcesContent":["import { ENGINE_CAPABILITIES, mergeUsage, orderUsageWindows } from '@workerdeck/protocol'\nimport type {\n ContentBlock,\n ContextUsage,\n EngineCapabilities,\n FilePatch,\n MessageAttachment,\n ModelOption,\n PermissionMode,\n PermissionRequest,\n ProfileEngine,\n RateLimitInfo,\n SessionEvent,\n SessionInfo,\n SessionStatus,\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 // 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 errors?: string[]\n }\n | { kind: 'notice'; id: string; level: 'info' | 'error'; text: string }\n /**\n * The engine summarised the conversation in place to fit its context window. A boundary, not a\n * message: nothing above it is retracted (that is `conversation_reset`, which empties `items`),\n * and it carries no text of its own because the wire event carries none — codex's\n * `contextCompaction` item is `{id, type}` and nothing more.\n */\n | { kind: 'compaction'; id: string; parentToolUseId: string | null }\n | { kind: 'file_delivered'; id: string; path: string; bytes: number; description?: string }\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 // 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 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>$/\n\nconst COMMAND_NAME = /<command-name>([\\s\\S]*?)<\\/command-name>/\nconst COMMAND_ARGS = /<command-args>([\\s\\S]*?)<\\/command-args>/\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\nfunction 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\nfunction upsert(items: TranscriptItem[], item: TranscriptItem): TranscriptItem[] {\n const index = items.findIndex((existing) => existing.id === item.id && existing.kind === item.kind)\n if (index === -1) {\n return [...items, item]\n }\n const next = [...items]\n next[index] = item\n return next\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 session: info,\n }\n}\n\nexport function rateLimitWindows(state: TranscriptState): 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\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 '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 sdkSessionId: event.sdkSessionId ?? base.sdkSessionId,\n }\n }\n\n // Deliberately unlike the reset above: it appends rather than empties. `contextUsage` is left\n // alone too — the engine reports the post-compaction occupancy itself, and guessing here would\n // put a number on the ring that no `context_usage` event ever said.\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 }),\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' && !event.synthetic) {\n const text = (block as { text: string }).text\n const localOutput = LOCAL_COMMAND_OUTPUT.exec(text.trim())\n if (localOutput) {\n items = upsert(items, {\n kind: 'notice',\n id: event.uuid ?? `user-${event.seq}`,\n level: localOutput[1] === 'stderr' ? 'error' : 'info',\n text: localOutput[2].trim(),\n })\n } else {\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.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 existing = base.items.find(\n (item): item is Extract<TranscriptItem, { kind: 'assistant_text' }> => item.kind === 'assistant_text' && item.id === id,\n )\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: upsert(base.items, item) }\n }\n if (delta.delta?.type === 'thinking_delta') {\n const id = streamingThinkingId(event.parentToolUseId)\n const existing = base.items.find(\n (item): item is Extract<TranscriptItem, { kind: 'thinking' }> => item.kind === 'thinking' && item.id === id,\n )\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: upsert(base.items, item) }\n }\n return base\n }\n\n case 'turn_result': {\n return {\n ...base,\n totalCostUsd: event.totalCostUsd,\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 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 type { WorkerDeckClient, SessionHandle } from '@workerdeck/client'\nimport { PROTOCOL_VERSION } from '@workerdeck/protocol'\nimport type { AttachedFrame, ModelOption, PermissionMode, SessionEvent } from '@workerdeck/protocol'\nimport { applyEvent, initialTranscriptState, hydrateToolResult, seedFromSessionInfo, type TranscriptState } 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 }\n\nfunction reduce(state: TranscriptState, action: SessionEvent | AttachedFrame | SeedAction | HydrateAction): 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 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 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 setPermissionMode: (mode: PermissionMode) => void\n setModel: (model?: string) => void\n closeSession: () => void\n reconnectNow: () => void\n loadFullResult: (toolUseId: string) => 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 [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 })\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 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 const text =\n typeof full.content === 'string'\n ? full.content\n : (full.content ?? [])\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n dispatch({ type: 'transcript_hydrate_result', toolUseId, text })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n return useMemo(\n () => ({\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n models,\n effectiveModel: state.model ?? state.defaultModel,\n handle: handleState,\n send: (text, attachmentIds) => handleRef.current?.send(text, attachmentIds),\n approve: (requestId, updatedInput) => handleRef.current?.approve(requestId, updatedInput),\n deny: (requestId, message, interrupt) => handleRef.current?.deny(requestId, message, interrupt),\n interrupt: () => handleRef.current?.interrupt(),\n clearContext: () => handleRef.current?.clearContext(),\n setPermissionMode: (mode) => handleRef.current?.setPermissionMode(mode),\n setModel: (model) => handleRef.current?.setModel(model),\n closeSession: () => handleRef.current?.closeSession(),\n reconnectNow,\n loadFullResult,\n }),\n [state, connected, connection, replaying, protocolMismatch, models, handleState, reconnectNow, loadFullResult],\n )\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/**\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.\n */\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/**\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.\n */\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 { 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: e instanceof Error ? e.message : '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","export type PromptToken = {\n kind: 'file' | 'command'\n start: number\n end: number\n text: 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\nconst SENTENCE_TAIL = new Set(['.', ',', ';', ':', '!', '?', ')', ']', '}', '\"', \"'\"])\n\nexport function scanPromptTokens(text: string): PromptToken[] {\n const tokens: PromptToken[] = []\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 = word[0] === '@' ? 'file' : word[0] === '/' ? 'command' : 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 tokens.push({ kind, start: match.index, end, text: text.slice(match.index, end) })\n }\n return tokens\n}\n","import { useEffect, useRef, type RefObject } from 'react'\nimport { WorkerDeckError } from '@workerdeck/client'\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","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 { 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(e instanceof Error ? e.message : '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, 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","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/**\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.\n */\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 { ProfileUsage } from '@workerdeck/protocol'\n\nexport type UseProfileUsageOptions = {\n intervalMs?: number\n enabled?: boolean\n}\n\nexport type UseProfileUsageResult = {\n usage: ProfileUsage | 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 [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(() => setUsage(cacheKey ? readProfileUsageCache(cacheKey) : undefined), [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 next = res.profiles.find((p) => p.name === profile)?.usage\n if (cacheKey) {\n writeProfileUsageCache(cacheKey, next)\n }\n setUsage(next)\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, refresh }\n}\n","import { useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport type { SessionInfo } from '@workerdeck/protocol'\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 [info, setInfo] = useState<SessionInfo | undefined>()\n const [loading, setLoading] = useState(!!sessionId)\n const [error, setError] = useState<string | undefined>()\n\n useEffect(() => {\n if (!sessionId) {\n setInfo(undefined)\n setLoading(false)\n setError(undefined)\n return\n }\n let cancelled = false\n setLoading(true)\n setError(undefined)\n setInfo(undefined)\n client\n .getSession(sessionId)\n .then((next) => {\n if (cancelled) {\n return\n }\n setInfo(next)\n setLoading(false)\n })\n .catch((e: unknown) => {\n if (cancelled) {\n return\n }\n setError(e instanceof Error ? e.message : 'Session not found')\n setLoading(false)\n })\n return () => {\n cancelled = true\n }\n }, [client, sessionId])\n\n return { info, loading, error }\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 { 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: e instanceof Error ? e.message : '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: e instanceof Error ? e.message : '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.' : e instanceof Error ? e.message : '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: e instanceof Error ? e.message : '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 type { RunScriptResult, SandboxEngine, SandboxVfs } from '@workerdeck/sandbox'\nimport type { ToolCallRequestFrame } from '@workerdeck/protocol'\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\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 refuse = (frame: ToolCallRequestFrame, reason: string, error: string, startedAt: number) => {\n handle.sendToolCallError(frame.executionId, reason, error)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'failed',\n reason,\n startedAt,\n endedAt: Date.now(),\n })\n }\n\n const runClientTool = async (frame: ToolCallRequestFrame, handler: ClientToolHandler): Promise<void> => {\n const startedAt = Date.now()\n const controller = new AbortController()\n inFlight.set(frame.executionId, controller)\n track({ executionId: frame.executionId, toolName: frame.toolName, status: 'running', startedAt })\n\n try {\n const result = await handler(frame.input, {\n executionId: frame.executionId,\n signal: controller.signal,\n })\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n if ('error' in result) {\n handle.sendToolCallError(frame.executionId, result.reason ?? 'client_error', result.error)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'failed',\n reason: result.reason ?? 'client_error',\n startedAt,\n endedAt: Date.now(),\n })\n } else {\n handle.sendToolCallResult(frame.executionId, { type: 'json', value: result.value })\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'settled',\n startedAt,\n endedAt: Date.now(),\n })\n }\n } catch (error) {\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n refuse(frame, 'host_error', error instanceof Error ? error.message : String(error), startedAt)\n } finally {\n inFlight.delete(frame.executionId)\n }\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)\n }\n const allowed = options.tools ?? ['eval_script']\n if (!allowed.includes(frame.toolName)) {\n refuse(frame, 'unsupported_tool', `this client does not execute '${frame.toolName}'`, startedAt)\n return\n }\n const script = (frame.input as { script?: unknown } | undefined)?.script\n if (typeof script !== 'string') {\n refuse(frame, 'invalid_input', 'expected a string `script` input', startedAt)\n return\n }\n\n const controller = new AbortController()\n inFlight.set(frame.executionId, controller)\n track({ executionId: frame.executionId, toolName: frame.toolName, status: 'running', startedAt })\n\n try {\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\n const result = options.execute\n ? await options.execute({ script, vfs, timeoutMs, memoryLimitBytes, signal: controller.signal })\n : await (async () => {\n enginePromise ??= (options.loadEngine ?? defaultLoadEngine)()\n return sandbox.runScript(await enginePromise, {\n script,\n vfs,\n timeoutMs,\n memoryLimitBytes,\n signal: controller.signal,\n fetchText: options.fetchText,\n })\n })()\n\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n const logs = result.logs.map((l) => `[${l.level}] ${l.text}`)\n if (result.ok) {\n handle.sendToolCallResult(frame.executionId, { type: 'json', value: result.value }, logs)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'settled',\n startedAt,\n endedAt: Date.now(),\n })\n } else {\n handle.sendToolCallError(frame.executionId, result.reason, result.error, logs)\n track({\n executionId: frame.executionId,\n toolName: frame.toolName,\n status: 'failed',\n reason: result.reason,\n startedAt,\n endedAt: Date.now(),\n })\n }\n } catch (error) {\n if (disposed || !inFlight.has(frame.executionId)) {\n return\n }\n refuse(frame, 'host_error', error instanceof Error ? error.message : String(error), startedAt)\n } finally {\n inFlight.delete(frame.executionId)\n }\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"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workerdeck/react",
3
- "version": "1.1.0",
3
+ "version": "1.2.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": "1.1.0",
21
- "@workerdeck/protocol": "1.1.0",
22
- "@workerdeck/sandbox": "1.1.0"
20
+ "@workerdeck/client": "1.2.0",
21
+ "@workerdeck/protocol": "1.2.0",
22
+ "@workerdeck/sandbox": "1.2.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/core": "1.1.0",
45
- "@workerdeck/server": "1.1.0"
44
+ "@workerdeck/server": "1.2.0",
45
+ "@workerdeck/core": "1.2.0"
46
46
  },
47
47
  "author": "Tobias Strebitzer",
48
48
  "repository": {