@workerdeck/react 2.7.1 → 2.8.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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @workerdeck/react
2
2
 
3
3
  Headless React layer for WorkerDeck: the `useClaudeSession` hook plus a pure transcript
4
- reducer. No styling opinion — bring your own rendering, or use
4
+ reducer. No styling opinion - bring your own rendering, or use
5
5
  [`@workerdeck/ui`](https://www.npmjs.com/package/@workerdeck/ui), the styled layer on top.
6
6
 
7
7
  Part of [WorkerDeck](https://github.com/workerdeck/workerdeck). It sits between
@@ -48,12 +48,12 @@ function Panel({ sessionId }: { sessionId: string }) {
48
48
  }
49
49
  ```
50
50
 
51
- The hook attaches on mount, detaches on unmount, and survives reconnects — the underlying handle
51
+ The hook attaches on mount, detaches on unmount, and survives reconnects - the underlying handle
52
52
  replays from the last seen seq, and the reducer ignores anything it has already applied.
53
53
 
54
54
  ### The transcript reducer, standalone
55
55
 
56
- The state machine is framework-free and exported directly — usable in tests, workers, or any
56
+ The state machine is framework-free and exported directly - usable in tests, workers, or any
57
57
  non-React consumer of the event stream:
58
58
 
59
59
  ```ts
@@ -71,23 +71,23 @@ stream doesn't carry yet; events stay authoritative once they arrive.
71
71
 
72
72
  `TranscriptState` is everything a session panel needs to render:
73
73
 
74
- - `items` — the ordered transcript: `user`, `assistant_text` (with a `streaming` flag),
74
+ - `items` - the ordered transcript: `user`, `assistant_text` (with a `streaming` flag),
75
75
  `thinking`, `tool_call` (input + eventual result), `turn_result`, and `notice` items.
76
76
  Streaming deltas accumulate in-place and are superseded by the full assistant message.
77
- - `pendingApprovals` — permission requests awaiting an approve/deny decision.
77
+ - `pendingApprovals` - permission requests awaiting an approve/deny decision.
78
78
  - `status` / `statusDetail`, `model`, `cwd`, `sdkSessionId`, `permissionMode`.
79
- - `models` and `commands` — what the session can switch to / accepts (from `capabilities`).
80
- - `capabilities` — **the engine's capability record**, always present: the runner-reported copy
79
+ - `models` and `commands` - what the session can switch to / accepts (from `capabilities`).
80
+ - `capabilities` - **the engine's capability record**, always present: the runner-reported copy
81
81
  from the attach snapshot, else the protocol's static default for the engine. Render affordances
82
82
  from this rather than switching on the engine name; an absent capability means the control is
83
83
  *hidden*, never one that silently does nothing.
84
- - `session` — the whole attach snapshot, for the facts no event carries (profile, `apiKeySource`,
84
+ - `session` - the whole attach snapshot, for the facts no event carries (profile, `apiKeySource`,
85
85
  `canBypassPermissions`, `createdAt`).
86
- - `contextUsage`, `rateLimits` (keyed by window; absent for API-key sessions — render nothing,
86
+ - `contextUsage`, `rateLimits` (keyed by window; absent for API-key sessions - render nothing,
87
87
  not 0%) with `rateLimitsUpdatedAt`, `totalCostUsd` (session-cumulative), and `lastSeq` for
88
88
  replay dedupe.
89
89
 
90
- The reducer is pure and immutable: same events in, same state out — which is also how it is
90
+ The reducer is pure and immutable: same events in, same state out - which is also how it is
91
91
  unit-tested. Keep rendering logic out of it. `rateLimitWindows(state)` and `scanPromptTokens(text)`
92
92
  are the other pure helpers here, for the same reason: ordered usage windows and `@file` /
93
93
  `/command` token recognition are string-and-shape work every client needs and every client should
@@ -106,7 +106,7 @@ const attachments = useAttachments(client, sessionId, {
106
106
  engine: state.engine,
107
107
  })
108
108
  // `@file` search rooted at the session's cwd. `available` is false when the
109
- // gateway serves no host files — don't advertise what isn't there.
109
+ // gateway serves no host files - don't advertise what isn't there.
110
110
  const files = useHostFileSearch(client, state.cwd)
111
111
 
112
112
  attachments.add(pickedFiles) // uploads start immediately
@@ -124,13 +124,13 @@ demand):
124
124
  ```tsx
125
125
  const { handle } = useClaudeSession(client, sessionId)
126
126
  const { executions } = useToolCallHost(handle, {
127
- tools: ['eval_script'], // allowlist — anything else the server asks for is refused
127
+ tools: ['eval_script'], // allowlist - anything else the server asks for is refused
128
128
  timeoutMs: 15_000,
129
129
  fetchText: (url) => myGatedFetch(url), // omit and the guest has no network at all
130
130
  })
131
131
  ```
132
132
 
133
- The host must ride **the hook's own `handle`** — the server bridges each call to the first attached
133
+ The host must ride **the hook's own `handle`** - the server bridges each call to the first attached
134
134
  client, so a second, separately-created handle would sit idle while the real one gets the requests.
135
135
  `createToolCallHost` is the same logic without React. Results returned from a tab are untrusted
136
136
  input by construction: fine for the user's own data, never a source of server-authoritative state.
@@ -146,12 +146,12 @@ input by construction: fine for the user's own data, never a source of server-au
146
146
 
147
147
  - **`result.images` is the same idea for pictures, and it is set only when there are any.** The
148
148
  hook also attaches with `imageRefs`, so a `tool_result`'s base64 images arrive as addresses and
149
- the reducer records `{ partIndex, mediaType, bytes, sourceSeq }` per picture — absent, never
149
+ the reducer records `{ partIndex, mediaType, bytes, sourceSeq }` per picture - absent, never
150
150
  empty, because an item that gained a field is an item every renderer re-measures (on iOS
151
151
  `ToolCallItem` is `Equatable` and half the row-plan cache key). Each entry carries its **own**
152
152
  `sourceSeq`: the result-level one is cleared by text hydration, and a reader who pressed "show
153
153
  everything" must still be able to load the screenshot. Raw base64 parts are still dropped on
154
- arrival, as they always were — folding them into state would pin megabytes inside the transcript
154
+ arrival, as they always were - folding them into state would pin megabytes inside the transcript
155
155
  cache.
156
156
 
157
157
  - **Companions must ride the hook's own `handle`.** The server's tool bridge asks the *first
@@ -159,12 +159,12 @@ input by construction: fine for the user's own data, never a source of server-au
159
159
  will never be asked anything. `useAttachments`, `useHostFileSearch` and `useToolCallHost` all
160
160
  take the handle you already have.
161
161
  - **`TranscriptState.capabilities` is always populated**, engine record or protocol default. Render
162
- every surface from it rather than branching on the engine name — that is what makes one component
162
+ every surface from it rather than branching on the engine name - that is what makes one component
163
163
  correct for all three engines.
164
164
  - **`useToolCallHost` refuses tool names outside its allow-list** (default `['eval_script']`). It is
165
165
  a grant, not a filter: every name you add is one this tab will execute on the gateway's say-so.
166
166
  - **`useOpenFiles` keeps `content` (disk) and `draft` (edits) apart, and `/fs/write` is conditional
167
- always.** A 409 is a *choice* to offer the user — reload, keep mine, dismiss — never a toast, and
167
+ always.** A 409 is a *choice* to offer the user - reload, keep mine, dismiss - never a toast, and
168
168
  nothing but `revert` or an explicit reload may discard a draft.
169
169
  - **The recap is counted, never written.** `summarizeSince` returns numbers because generating
170
170
  prose would spend a turn on a summary nobody asked for, and would be worst exactly where it
@@ -172,7 +172,7 @@ input by construction: fine for the user's own data, never a source of server-au
172
172
  - **Detached transcripts stay warm by default.** `useClaudeSession` keeps a bounded, module-scope
173
173
  cache of the last few transcripts it held, so switching back to a session paints in the mount
174
174
  frame and re-attaches with `afterSeq`, replaying only what it missed. Entries are keyed by the
175
- client's `identityKey` — gateway base URL plus auth headers — never the session id alone (a
175
+ client's `identityKey` - gateway base URL plus auth headers - never the session id alone (a
176
176
  session id is unique only within one gateway), and a cached `afterSeq` pointed at a log the
177
177
  server no longer has (a dormant rebuild, a restart) is detected off the attach frame
178
178
  (`staleAttach`) and discarded with a full resync, because that attach would otherwise deliver
@@ -182,5 +182,5 @@ input by construction: fine for the user's own data, never a source of server-au
182
182
 
183
183
  ## License
184
184
 
185
- MIT © Tobias Strebitzer — see
185
+ MIT © Tobias Strebitzer - see
186
186
  [LICENSE](https://github.com/workerdeck/workerdeck/blob/master/LICENSE).
@@ -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 ApiMessage,\n ChecklistItem,\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 kind: 'compaction'\n id: string\n parentToolUseId: string | null\n pending?: boolean\n trigger?: 'manual' | 'auto'\n preTokens?: number\n postTokens?: number\n error?: string\n }\n | { kind: 'file_delivered'; id: string; path: string; bytes: number; description?: string }\n\nexport type ProducedFileRef = {\n fileId: string\n mediaType?: string\n bytes?: number\n}\n\nexport type TranscriptState = {\n status: SessionStatus\n statusDetail?: string\n model?: string\n cwd?: string\n sdkSessionId?: string\n engine?: ProfileEngine\n capabilities: EngineCapabilities\n session?: SessionInfo\n models?: ModelOption[]\n commands?: SlashCommandInfo[]\n skills?: SkillInfo[]\n checklist?: ChecklistItem[]\n // Only what the client cannot derive: host- and MCP-declared titles. `toolTitle()` folds the\n // built-in table in on top of this.\n toolTitles?: Record<string, string>\n // Keyed by the absolute path the runner reported: a tool card looks up the `savedPath` in its input and resolves it via `client.producedFileUrl`.\n producedFiles?: Record<string, ProducedFileRef>\n\n defaultModel?: string\n permissionMode?: PermissionMode\n contextUsage?: ContextUsage\n rateLimits?: Record<string, RateLimitInfo>\n rateLimitsUpdatedAt?: number\n subscriptionType?: string\n items: TranscriptItem[]\n pendingApprovals: PermissionRequest[]\n totalCostUsd: number\n lastSeq: number\n}\n\nexport const initialTranscriptState: TranscriptState = {\n status: 'starting',\n capabilities: ENGINE_CAPABILITIES.claude,\n items: [],\n pendingApprovals: [],\n totalCostUsd: 0,\n lastSeq: 0,\n}\n\nconst STREAMING_ID = 'streaming'\nconst STREAMING_THINKING_ID = 'streaming-thinking'\n\nconst LOCAL_COMMAND_OUTPUT = /^<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>$/\nconst LOCAL_COMMAND_ELEMENT = /<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>/g\nconst LOCAL_COMMAND_CAVEAT = '<local-command-caveat>'\n\nconst COMMAND_NAME = /<command-name>([\\s\\S]*?)<\\/command-name>/\nconst COMMAND_ARGS = /<command-args>([\\s\\S]*?)<\\/command-args>/\n// A message whose first text block is the deferred `!` flush is synthetic as a whole, but the block after it is\n// the person's own message. Only that shape earns the exemption — `<task-notification>` and the rest stay hidden.\nfunction carriesCaveat(content: ApiMessage['content']): boolean {\n return contentToBlocks(content).some(\n (block) => block.type === 'text' && (block as { text: string }).text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT),\n )\n}\n\nfunction streamingTextId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_ID : `${STREAMING_ID}:${parentToolUseId}`\n}\nfunction streamingThinkingId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_THINKING_ID : `${STREAMING_THINKING_ID}:${parentToolUseId}`\n}\nfunction isStreamingItem(item: TranscriptItem): boolean {\n return (\n (item.kind === 'assistant_text' && item.id.startsWith(STREAMING_ID)) ||\n (item.kind === 'thinking' && item.id.startsWith(STREAMING_THINKING_ID))\n )\n}\n\nexport function blockText(content: ToolResultBlock['content']): string {\n if (content === undefined) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n return content\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n}\n\nfunction imageRefsOf(content: ToolResultBlock['content'], seq: number): ReadonlyArray<ToolResultImageRef> | undefined {\n if (!Array.isArray(content)) {\n return undefined\n }\n const refs = content.flatMap((part) =>\n part.type === 'image_ref'\n ? [\n {\n partIndex: Number(part.part_index),\n mediaType: String(part.media_type ?? 'application/octet-stream'),\n bytes: Number(part.bytes ?? 0),\n sourceSeq: seq,\n },\n ]\n : [],\n )\n return refs.length > 0 ? refs : undefined\n}\n\nfunction contentToBlocks(content: string | ContentBlock[]): ContentBlock[] {\n return typeof content === 'string' ? [{ type: 'text', text: content }] : content\n}\n\nfunction outputText(output: ToolExecutionOutput): string {\n if (output.type === 'text') {\n return output.value\n }\n try {\n return JSON.stringify(output.value)\n } catch {\n return String(output.value)\n }\n}\n\nfunction slashCommandText(text: string): string | undefined {\n const name = COMMAND_NAME.exec(text)?.[1]?.trim()\n if (!name) {\n return undefined\n }\n const args = COMMAND_ARGS.exec(text)?.[1]?.trim()\n return args ? `${name} ${args}` : name\n}\n\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 'checklist': {\n return { ...base, checklist: event.items.length > 0 ? event.items : undefined }\n }\n\n case 'tool_titles': {\n return { ...base, toolTitles: { ...base.toolTitles, ...event.titles } }\n }\n\n case 'file_produced': {\n return {\n ...base,\n producedFiles: {\n ...base.producedFiles,\n [event.path]: {\n fileId: event.fileId,\n ...(event.mediaType ? { mediaType: event.mediaType } : {}),\n ...(event.bytes !== undefined ? { bytes: event.bytes } : {}),\n },\n },\n }\n }\n\n case 'model_changed': {\n return event.model === undefined ? base : { ...base, model: event.model }\n }\n\n case 'permission_mode_changed': {\n return { ...base, permissionMode: event.mode }\n }\n\n case 'context_usage': {\n return { ...base, contextUsage: event.usage }\n }\n\n case 'rate_limit': {\n const key = event.info.rateLimitType\n if (!key) {\n return base\n }\n return {\n ...base,\n rateLimits: { ...base.rateLimits, [key]: event.info },\n rateLimitsUpdatedAt: event.ts,\n }\n }\n\n case 'plan_info': {\n return { ...base, subscriptionType: event.subscriptionType }\n }\n\n case 'conversation_reset': {\n return {\n ...base,\n items: [],\n contextUsage: undefined,\n checklist: undefined,\n sdkSessionId: event.sdkSessionId ?? base.sdkSessionId,\n }\n }\n\n // Appends where the reset above empties, and leaves `contextUsage` alone: the engine reports post-compaction occupancy itself.\n case 'context_compacted': {\n return {\n ...base,\n items: upsert(base.items, {\n kind: 'compaction',\n id: event.uuid,\n parentToolUseId: event.parentToolUseId ?? null,\n pending: event.pending,\n trigger: event.trigger,\n preTokens: event.preTokens,\n postTokens: event.postTokens,\n error: event.error,\n }),\n }\n }\n\n case 'user_message': {\n let items = base.items\n for (const block of contentToBlocks(event.message.content)) {\n if (block.type === 'tool_result') {\n const toolResult = block as ToolResultBlock\n const isError = toolResult.is_error === true\n items = items.map((item) =>\n item.kind === 'tool_call' && item.id === toolResult.tool_use_id\n ? {\n ...item,\n status: isError ? 'failed' : 'settled',\n result: {\n text: blockText(toolResult.content),\n isError,\n ...(toolResult.truncated && {\n truncated: true as const,\n totalChars: toolResult.total_chars,\n sourceSeq: event.seq,\n }),\n ...(imageRefsOf(toolResult.content, event.seq) && {\n images: imageRefsOf(toolResult.content, event.seq),\n }),\n },\n ...(event.patch && { patch: event.patch }),\n }\n : item,\n )\n } else if (block.type === 'text') {\n const text = (block as { text: string }).text\n const rowId = event.uuid ?? `user-${event.seq}`\n // Both branches sit ahead of the synthetic guard on purpose. A `!` shell run is emitted synthetic so it\n // scores zero activity and zero prose, but it is the one synthetic message a person is meant to see; and\n // on resume the SDK hands back the shell output and the user's own text as one message, which\n // `isSyntheticUserText` then marks synthetic whole. Without this the user's own words vanish on reload.\n const localOutput = LOCAL_COMMAND_OUTPUT.exec(text.trim())\n if (localOutput) {\n items = upsert(items, {\n kind: 'notice',\n id: rowId,\n level: localOutput[1] === 'stderr' ? 'error' : 'info',\n text: localOutput[2].trim(),\n })\n } else if (text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT)) {\n let index = 0\n for (const match of text.matchAll(LOCAL_COMMAND_ELEMENT)) {\n items = upsert(items, {\n kind: 'notice',\n id: `${rowId}#${index++}`,\n level: match[1] === 'stderr' ? 'error' : 'info',\n text: match[2].trim(),\n })\n }\n } else if (!event.synthetic || carriesCaveat(event.message.content)) {\n items = upsert(items, {\n kind: 'user',\n id: event.uuid ?? `user-${event.seq}`,\n text: slashCommandText(text) ?? text,\n attachments: event.attachments,\n ...(event.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 {\n applyEvent,\n blockText,\n initialTranscriptState,\n hydrateToolResult,\n seedFromSessionInfo,\n type TranscriptState,\n} from '../lib/transcript.ts'\nimport { deleteTranscriptCache, readTranscriptCache, transcriptCacheKey, writeTranscriptCache } from '../lib/transcript-cache.ts'\nimport { attachSeedToken, planAttach, shouldWriteParting } from '../lib/attach-plan.ts'\n\ntype SeedAction = { type: 'transcript_seed'; state: TranscriptState }\ntype HydrateAction = { type: 'transcript_hydrate_result'; toolUseId: string; text: string }\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 // The gateway offers `!` shell mode to this principal on this session. Absent from an older gateway, so falsy by default.\n shell: boolean\n models: ModelOption[]\n effectiveModel?: string\n handle: SessionHandle | undefined\n send: (text: string, attachmentIds?: string[]) => void\n approve: (requestId: string, updatedInput?: Record<string, unknown>) => void\n deny: (requestId: string, message?: string, interrupt?: boolean) => void\n interrupt: () => void\n clearContext: () => void\n runShell: (command: string) => void\n setPermissionMode: (mode: PermissionMode) => void\n setModel: (model?: string) => void\n closeSession: () => void\n reconnectNow: () => void\n loadFullResult: (toolUseId: string) => Promise<boolean>\n}\n\nexport function useClaudeSession(\n client: WorkerDeckClient,\n sessionId: string | undefined,\n options?: UseClaudeSessionOptions,\n): UseClaudeSessionResult {\n const [state, dispatch] = useReducer(\n reduce,\n undefined,\n (): TranscriptState =>\n (options?.cacheTranscript !== false && sessionId !== undefined\n ? readTranscriptCache(transcriptCacheKey(client, sessionId))\n : undefined) ?? initialTranscriptState,\n )\n const [connection, setConnection] = useState<ConnectionState>('reconnecting')\n const [protocolMismatch, setProtocolMismatch] = useState<number | undefined>()\n const [shell, setShell] = useState(false)\n const [replayTarget, setReplayTarget] = useState<number | undefined>()\n const [resyncSeq, setResyncSeq] = useState(0)\n // Ref for the stable callbacks below; state so consumers of `handle` re-render when the socket opens or the session switches.\n const [handleState, setHandleState] = useState<SessionHandle | undefined>()\n const handleRef = useRef<SessionHandle | null>(null)\n const optionsRef = useRef(options)\n optionsRef.current = options\n const stateRef = useRef(state)\n stateRef.current = state\n const seededForRef = useRef(attachSeedToken(0, sessionId === undefined ? '' : transcriptCacheKey(client, sessionId)))\n const skipCacheRef = useRef(false)\n\n useEffect(() => {\n if (!sessionId) {\n return\n }\n const cache = optionsRef.current?.cacheTranscript !== false\n const key = transcriptCacheKey(client, sessionId)\n const plan = planAttach({\n resyncSeq,\n key,\n seededFor: seededForRef.current,\n current: stateRef.current,\n cacheEnabled: cache,\n skipCache: skipCacheRef.current,\n warm: readTranscriptCache(key),\n })\n skipCacheRef.current = false\n if (plan.seed) {\n dispatch({ type: 'transcript_seed', state: plan.held })\n seededForRef.current = plan.seedToken\n }\n const handle = client.attach(sessionId, {\n truncateResults: true,\n imageRefs: true,\n ...(plan.afterSeq === undefined ? {} : { afterSeq: plan.afterSeq }),\n })\n handleRef.current = handle\n setHandleState(handle)\n const offEvent = handle.on('event', (event: SessionEvent) => dispatch(event))\n const offAttached = handle.on('attached', (frame: AttachedFrame) => {\n if (staleAttach(frame, stateRef.current)) {\n offEvent()\n deleteTranscriptCache(key)\n skipCacheRef.current = true\n setResyncSeq((n) => n + 1)\n return\n }\n dispatch(frame)\n setReplayTarget(initialReplayTarget(frame))\n setProtocolMismatch(frame.protocolVersion === PROTOCOL_VERSION ? undefined : frame.protocolVersion)\n setShell(frame.shell === true)\n })\n const offConn = handle.on('connectionChange', (open: boolean) => setConnection(open ? 'live' : 'reconnecting'))\n const offRetry = handle.on('reconnectAttempt', (attempts: number) =>\n setConnection(attempts >= OFFLINE_AFTER_ATTEMPTS ? 'offline' : 'reconnecting'),\n )\n const offProtocolError = handle.on('protocolError', (message: string) => {\n optionsRef.current?.onProtocolError?.(message)\n })\n return () => {\n offEvent()\n offAttached()\n offConn()\n offRetry()\n offProtocolError()\n handle.detach()\n handleRef.current = null\n setHandleState(undefined)\n setConnection('reconnecting')\n setProtocolMismatch(undefined)\n setShell(false)\n setReplayTarget(undefined)\n const parting = stateRef.current\n if (shouldWriteParting({ cacheEnabled: cache, skipCache: skipCacheRef.current, parting })) {\n writeTranscriptCache(key, parting)\n }\n }\n }, [client, sessionId, resyncSeq])\n\n useEffect(() => {\n if (replayTarget === undefined) {\n return\n }\n const timer = setTimeout(() => setReplayTarget(undefined), REPLAY_HOLD_MAX_MS)\n return () => clearTimeout(timer)\n }, [replayTarget])\n useEffect(() => {\n if (replayTarget !== undefined && state.lastSeq >= replayTarget) {\n setReplayTarget(undefined)\n }\n }, [replayTarget, state.lastSeq])\n\n const models = useProfileModelFallback(client, sessionId, state)\n\n const connected = connection === 'live'\n // Derived at render, not in an effect, so the reveal lands in the same commit as the replay's final event — an effect is one visible frame late.\n const replaying = replayTarget !== undefined && state.lastSeq < replayTarget\n const reconnectNow = useCallback(() => handleRef.current?.reconnectNow(), [])\n\n const loadFullResult = useCallback(\n async (toolUseId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n const item = stateRef.current.items.find((candidate) => candidate.kind === 'tool_call' && candidate.id === toolUseId)\n const result = item?.kind === 'tool_call' ? item.result : undefined\n if (!result?.truncated || result.sourceSeq === undefined) {\n return false\n }\n try {\n const full = await client.toolResult(sessionId, result.sourceSeq, toolUseId)\n dispatch({ type: 'transcript_hydrate_result', toolUseId, text: blockText(full.content) })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n return useMemo(\n () => ({\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n shell,\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 runShell: (command) => handleRef.current?.runShell(command),\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, shell, 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// Last known profile usage, kept outside React so a session switch does not blank it.\n//\n// Usage belongs to the *account*, not the session, but it is fetched by a hook that lives inside the per-session\n// panel — so remounting that panel used to drop the authoritative reading to `undefined` for a whole round trip,\n// leaving only the newly-attached session's own replayed (and possibly days-old) numbers to render. That is the\n// \"switching sessions resets my weekly usage to 1%, then it catches up\" report.\n//\n// Keyed by client identity + profile because a different profile is a different account's plan, never a stale view\n// of this one. Same shape and reasoning as `transcript-cache.ts` next door.\nconst entries = new Map<string, ProfileUsage>()\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function profileUsageCacheKey(client: WorkerDeckClient, profile: string): string {\n return `${client.identityKey}\\u0000${profile}`\n}\n\nexport function readProfileUsageCache(key: string): ProfileUsage | undefined {\n return entries.get(key)\n}\n\nexport function writeProfileUsageCache(key: string, usage: ProfileUsage | undefined): void {\n if (usage === undefined) {\n return\n }\n entries.set(key, usage)\n}\n\nexport function clearProfileUsageCache(): void {\n entries.clear()\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\n\n// Unsent composer text, kept per session on the client that typed it.\n//\n// A draft is not session state: it never reaches the gateway and never syncs between clients. Two people looking at\n// one session are each mid-sentence in their own way, and a half-written prompt is not something either of them\n// asked to publish.\n//\n// It is persisted rather than merely held in memory because the two ways drafts got lost are different failures. A\n// session switch remounts the composer, which a module-scope map alone would survive; a Vite HMR reload or a VS Code\n// `dev:host` webview re-render replaces the whole document, which it would not.\nconst KEY = 'workerdeck.drafts.v1'\n\n// Drafts are a convenience, so the store stays small and drops the least recently touched first.\nconst MAX_DRAFTS = 20\n\ntype Draft = { text: string; savedAt: number }\n\nlet memory: Record<string, Draft> | undefined\n\nfunction storage(): Storage | undefined {\n try {\n // Through globalThis: this package is typechecked with no DOM lib, and a webview may deny storage outright.\n return (globalThis as { localStorage?: Storage }).localStorage\n } catch {\n return undefined\n }\n}\n\nfunction load(): Record<string, Draft> {\n if (memory) {\n return memory\n }\n memory = {}\n const raw = storage()?.getItem(KEY)\n if (raw) {\n try {\n const parsed = JSON.parse(raw) as Record<string, Draft>\n for (const [key, draft] of Object.entries(parsed)) {\n if (typeof draft?.text === 'string' && typeof draft.savedAt === 'number') {\n memory[key] = draft\n }\n }\n } catch {\n // A corrupt blob is not worth a broken composer; start over.\n }\n }\n return memory\n}\n\nfunction persist(drafts: Record<string, Draft>): void {\n const entries = Object.entries(drafts)\n if (entries.length > MAX_DRAFTS) {\n entries.sort((a, b) => b[1].savedAt - a[1].savedAt)\n for (const [key] of entries.slice(MAX_DRAFTS)) {\n delete drafts[key]\n }\n }\n try {\n storage()?.setItem(KEY, JSON.stringify(drafts))\n } catch {\n // Out of quota, or storage denied. The in-memory copy still carries the session switch.\n }\n}\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function draftKey(client: WorkerDeckClient, sessionId: string): string {\n return `${client.identityKey}\\u0000${sessionId}`\n}\n\nexport function readDraft(key: string): string {\n return load()[key]?.text ?? ''\n}\n\nexport function writeDraft(key: string, text: string, now = Date.now()): void {\n const drafts = load()\n // An empty draft is the absence of one: keeping it would evict a real draft under the cap.\n if (text.trim() === '') {\n if (drafts[key] === undefined) {\n return\n }\n delete drafts[key]\n } else {\n drafts[key] = { text, savedAt: now }\n }\n persist(drafts)\n}\n\nexport function clearDrafts(): void {\n memory = {}\n try {\n storage()?.removeItem(KEY)\n } catch {}\n}\n","import { 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// Remember unsent composer text for a session. Purely local: it never reaches the gateway and never syncs between\n// clients, because a half-written prompt is not something anyone asked to publish.\nexport function useDraft(client: WorkerDeckClient, sessionId: string | undefined): UseDraftResult {\n const key = sessionId ? draftKey(client, sessionId) : undefined\n // Read once per key: re-reading on render would fight whatever is being typed.\n const initialText = useMemo(() => (key ? readDraft(key) : ''), [key])\n const save = useCallback(\n (text: string) => {\n if (key) {\n writeDraft(key, text)\n }\n },\n [key],\n )\n const clear = useCallback(() => {\n if (key) {\n writeDraft(key, '')\n }\n }, [key])\n return { initialText, save, clear }\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\nimport { profileUsageCacheKey, readProfileUsageCache, writeProfileUsageCache } from '../lib/profile-usage-cache.ts'\nimport type { 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":";;;;AA6HA,MAAa,yBAA0C;CACrD,QAAQ;CACR,cAAc,oBAAoB;CAClC,OAAO,CAAC;CACR,kBAAkB,CAAC;CACnB,cAAc;CACd,SAAS;AACX;AAEA,MAAM,eAAe;AACrB,MAAM,wBAAwB;AAE9B,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,uBAAuB;AAE7B,MAAM,eAAe;AACrB,MAAM,eAAe;AAGrB,SAAS,cAAc,SAAyC;CAC9D,OAAO,gBAAgB,OAAO,CAAC,CAAC,MAC7B,UAAU,MAAM,SAAS,UAAW,MAA2B,KAAK,UAAU,CAAC,CAAC,WAAW,oBAAoB,CAClH;AACF;AAEA,SAAS,gBAAgB,iBAAwC;CAC/D,OAAO,mBAAmB,OAAO,eAAe,GAAG,aAAa,GAAG;AACrE;AACA,SAAS,oBAAoB,iBAAwC;CACnE,OAAO,mBAAmB,OAAO,wBAAwB,GAAG,sBAAsB,GAAG;AACvF;AACA,SAAS,gBAAgB,MAA+B;CACtD,OACG,KAAK,SAAS,oBAAoB,KAAK,GAAG,WAAW,YAAY,KACjE,KAAK,SAAS,cAAc,KAAK,GAAG,WAAW,qBAAqB;AAEzE;AAEA,SAAgB,UAAU,SAA6C;CACrE,IAAI,YAAY,KAAA,GACd,OAAO;CAET,IAAI,OAAO,YAAY,UACrB,OAAO;CAET,OAAO,QACJ,KAAK,SAAU,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,EAAG,CAAC,CAC/D,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;AACd;AAEA,SAAS,YAAY,SAAqC,KAA4D;CACpH,IAAI,CAAC,MAAM,QAAQ,OAAO,GACxB;CAEF,MAAM,OAAO,QAAQ,SAAS,SAC5B,KAAK,SAAS,cACV,CACE;EACE,WAAW,OAAO,KAAK,UAAU;EACjC,WAAW,OAAO,KAAK,cAAc,0BAA0B;EAC/D,OAAO,OAAO,KAAK,SAAS,CAAC;EAC7B,WAAW;CACb,CACF,IACA,CAAC,CACP;CACA,OAAO,KAAK,SAAS,IAAI,OAAO,KAAA;AAClC;AAEA,SAAS,gBAAgB,SAAkD;CACzE,OAAO,OAAO,YAAY,WAAW,CAAC;EAAE,MAAM;EAAQ,MAAM;CAAQ,CAAC,IAAI;AAC3E;AAEA,SAAS,WAAW,QAAqC;CACvD,IAAI,OAAO,SAAS,QAClB,OAAO,OAAO;CAEhB,IAAI;EACF,OAAO,KAAK,UAAU,OAAO,KAAK;CACpC,QAAQ;EACN,OAAO,OAAO,OAAO,KAAK;CAC5B;AACF;AAEA,SAAS,iBAAiB,MAAkC;CAC1D,MAAM,OAAO,aAAa,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK;CAChD,IAAI,CAAC,MACH;CAEF,MAAM,OAAO,aAAa,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK;CAChD,OAAO,OAAO,GAAG,KAAK,GAAG,SAAS;AACpC;AAEA,SAAS,OAAO,OAAyB,MAAwC;CAC/E,MAAM,QAAQ,MAAM,WAAW,aAAa,SAAS,OAAO,KAAK,MAAM,SAAS,SAAS,KAAK,IAAI;CAClG,IAAI,UAAU,IACZ,OAAO,CAAC,GAAG,OAAO,IAAI;CAExB,MAAM,OAAO,CAAC,GAAG,KAAK;CACtB,KAAK,SAAS;CACd,OAAO;AACT;AAEA,SAAgB,oBAAoB,OAAwB,MAAoC;CAE9F,MAAM,SAAS,KAAK,UAAU,MAAM;CACpC,OAAO;EACL,GAAG;EAEH,QAAQ,MAAM,YAAY,IAAI,KAAK,SAAS,MAAM;EAClD,OAAO,MAAM,SAAS,KAAK;EAC3B,gBAAgB,MAAM,kBAAkB,KAAK;EAC7C,KAAK,MAAM,OAAO,KAAK;EACvB,cAAc,MAAM,gBAAgB,KAAK;EACzC;EACA,cAAc,KAAK,gBAAgB,oBAAoB,UAAU;EACjE,SAAS;CACX;AACF;AAEA,SAAgB,iBAAiB,OAA0C;CACzE,OAAO,kBAAkB,WAAW;EAAE,YAAY,MAAM;EAAY,WAAW,MAAM;CAAoB,GAAG,KAAA,CAAS,CAAC;AACxH;AAEA,SAAgB,kBAAkB,OAAwB,WAAmB,MAA+B;CAC1G,IAAI,UAAU;CACd,MAAM,QAAQ,MAAM,MAAM,KAAK,SAAS;EACtC,IAAI,KAAK,SAAS,eAAe,KAAK,OAAO,aAAa,CAAC,KAAK,QAAQ,WACtE,OAAO;EAET,UAAU;EAEV,OAAO;GACL,GAAG;GACH,QAAQ;IACN;IACA,SAAS,KAAK,OAAO;IACrB,GAAI,KAAK,OAAO,UAAU,EAAE,QAAQ,KAAK,OAAO,OAAO;GACzD;EACF;CACF,CAAC;CACD,OAAO,UAAU;EAAE,GAAG;EAAO;CAAM,IAAI;AACzC;AAEA,SAAgB,WAAW,OAAwB,OAAsC;CACvF,IAAI,MAAM,OAAO,MAAM,SACrB,OAAO;CAET,MAAM,OAAwB;EAAE,GAAG;EAAO,SAAS,MAAM;CAAI;CAE7D,QAAQ,MAAM,MAAd;EACE,KAAK,eACH,OAAO;GACL,GAAG;GACH,OAAO,MAAM;GACb,KAAK,MAAM;GACX,cAAc,MAAM;GACpB,gBAAgB,MAAM;EACxB;EAGF,KAAK,kBACH,OAAO;GAAE,GAAG;GAAM,QAAQ,MAAM;GAAQ,cAAc,MAAM;EAAO;EAGrE,KAAK,gBACH,OAAO;GACL,GAAG;GACH,QAAQ,MAAM;GACd,UAAU,MAAM;GAChB,cAAc,MAAM,gBAAgB,KAAK;EAC3C;EAGF,KAAK,UACH,OAAO;GAAE,GAAG;GAAM,QAAQ,MAAM;EAAO;EAGzC,KAAK,aACH,OAAO;GAAE,GAAG;GAAM,WAAW,MAAM,MAAM,SAAS,IAAI,MAAM,QAAQ,KAAA;EAAU;EAGhF,KAAK,eACH,OAAO;GAAE,GAAG;GAAM,YAAY;IAAE,GAAG,KAAK;IAAY,GAAG,MAAM;GAAO;EAAE;EAGxE,KAAK,iBACH,OAAO;GACL,GAAG;GACH,eAAe;IACb,GAAG,KAAK;KACP,MAAM,OAAO;KACZ,QAAQ,MAAM;KACd,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;KACxD,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;IAC5D;GACF;EACF;EAGF,KAAK,iBACH,OAAO,MAAM,UAAU,KAAA,IAAY,OAAO;GAAE,GAAG;GAAM,OAAO,MAAM;EAAM;EAG1E,KAAK,2BACH,OAAO;GAAE,GAAG;GAAM,gBAAgB,MAAM;EAAK;EAG/C,KAAK,iBACH,OAAO;GAAE,GAAG;GAAM,cAAc,MAAM;EAAM;EAG9C,KAAK,cAAc;GACjB,MAAM,MAAM,MAAM,KAAK;GACvB,IAAI,CAAC,KACH,OAAO;GAET,OAAO;IACL,GAAG;IACH,YAAY;KAAE,GAAG,KAAK;MAAa,MAAM,MAAM;IAAK;IACpD,qBAAqB,MAAM;GAC7B;EACF;EAEA,KAAK,aACH,OAAO;GAAE,GAAG;GAAM,kBAAkB,MAAM;EAAiB;EAG7D,KAAK,sBACH,OAAO;GACL,GAAG;GACH,OAAO,CAAC;GACR,cAAc,KAAA;GACd,WAAW,KAAA;GACX,cAAc,MAAM,gBAAgB,KAAK;EAC3C;EAIF,KAAK,qBACH,OAAO;GACL,GAAG;GACH,OAAO,OAAO,KAAK,OAAO;IACxB,MAAM;IACN,IAAI,MAAM;IACV,iBAAiB,MAAM,mBAAmB;IAC1C,SAAS,MAAM;IACf,SAAS,MAAM;IACf,WAAW,MAAM;IACjB,YAAY,MAAM;IAClB,OAAO,MAAM;GACf,CAAC;EACH;EAGF,KAAK,gBAAgB;GACnB,IAAI,QAAQ,KAAK;GACjB,KAAK,MAAM,SAAS,gBAAgB,MAAM,QAAQ,OAAO,GACvD,IAAI,MAAM,SAAS,eAAe;IAChC,MAAM,aAAa;IACnB,MAAM,UAAU,WAAW,aAAa;IACxC,QAAQ,MAAM,KAAK,SACjB,KAAK,SAAS,eAAe,KAAK,OAAO,WAAW,cAChD;KACE,GAAG;KACH,QAAQ,UAAU,WAAW;KAC7B,QAAQ;MACN,MAAM,UAAU,WAAW,OAAO;MAClC;MACA,GAAI,WAAW,aAAa;OAC1B,WAAW;OACX,YAAY,WAAW;OACvB,WAAW,MAAM;MACnB;MACA,GAAI,YAAY,WAAW,SAAS,MAAM,GAAG,KAAK,EAChD,QAAQ,YAAY,WAAW,SAAS,MAAM,GAAG,EACnD;KACF;KACA,GAAI,MAAM,SAAS,EAAE,OAAO,MAAM,MAAM;IAC1C,IACA,IACN;GACF,OAAO,IAAI,MAAM,SAAS,QAAQ;IAChC,MAAM,OAAQ,MAA2B;IACzC,MAAM,QAAQ,MAAM,QAAQ,QAAQ,MAAM;IAK1C,MAAM,cAAc,qBAAqB,KAAK,KAAK,KAAK,CAAC;IACzD,IAAI,aACF,QAAQ,OAAO,OAAO;KACpB,MAAM;KACN,IAAI;KACJ,OAAO,YAAY,OAAO,WAAW,UAAU;KAC/C,MAAM,YAAY,EAAE,CAAC,KAAK;IAC5B,CAAC;SACI,IAAI,KAAK,UAAU,CAAC,CAAC,WAAW,oBAAoB,GAAG;KAC5D,IAAI,QAAQ;KACZ,KAAK,MAAM,SAAS,KAAK,SAAS,qBAAqB,GACrD,QAAQ,OAAO,OAAO;MACpB,MAAM;MACN,IAAI,GAAG,MAAM,GAAG;MAChB,OAAO,MAAM,OAAO,WAAW,UAAU;MACzC,MAAM,MAAM,EAAE,CAAC,KAAK;KACtB,CAAC;IAEL,OAAO,IAAI,CAAC,MAAM,aAAa,cAAc,MAAM,QAAQ,OAAO,GAChE,QAAQ,OAAO,OAAO;KACpB,MAAM;KACN,IAAI,MAAM,QAAQ,QAAQ,MAAM;KAChC,MAAM,iBAAiB,IAAI,KAAK;KAChC,aAAa,MAAM;KACnB,GAAI,MAAM,mBAAmB,QAAQ,EACnC,iBAAiB,MAAM,gBACzB;IACF,CAAC;GAEL;GAEF,OAAO;IAAE,GAAG;IAAM;GAAM;EAC1B;EAEA,KAAK,qBAAqB;GACxB,MAAM,gBAAgB,gBAAgB,MAAM,eAAe;GAC3D,MAAM,mBAAmB,oBAAoB,MAAM,eAAe;GAClE,IAAI,mBACF,KAAK,MAAM,MACR,SAAgE,KAAK,SAAS,cAAc,KAAK,OAAO,gBAC3G,CAAC,EAAE,QAAQ;GACb,IAAI,QAAQ,KAAK,MAAM,QACpB,SACC,EAAE,KAAK,SAAS,oBAAoB,KAAK,OAAO,kBAAkB,EAAE,KAAK,SAAS,cAAc,KAAK,OAAO,iBAChH;GAEA,gBAD+B,MAAM,QAAQ,OACxC,CAAC,CAAC,SAAS,OAAO,UAAU;IAC/B,MAAM,KAAK,GAAG,MAAM,KAAK,GAAG;IAC5B,IAAI,MAAM,SAAS,QACjB,QAAQ,OAAO,OAAO;KACpB,MAAM;KACN;KACA,MAAO,MAA2B;KAClC,WAAW;KACX,iBAAiB,MAAM;IACzB,CAAC;SACI,IAAI,MAAM,SAAS,YAAY;KACpC,MAAM,OAAQ,MAA+B,YAAY;KACzD,mBAAmB;KACnB,IAAI,KAAK,KAAK,MAAM,IAClB;KAEF,QAAQ,OAAO,OAAO;MACpB,MAAM;MACN;MACA;MACA,iBAAiB,MAAM;KACzB,CAAC;IACH,OAAO,IAAI,MAAM,SAAS,YAAY;KACpC,MAAM,UAAU;KAChB,QAAQ,OAAO,OAAO;MACpB,MAAM;MACN,IAAI,QAAQ;MACZ,MAAM,QAAQ;MACd,OAAO,QAAQ;MACf,iBAAiB,MAAM;MACvB,QAAQ;MACR,IAAI,MAAM;KACZ,CAAC;IACH;GACF,CAAC;GACD,OAAO;IAAE,GAAG;IAAM;GAAM;EAC1B;EAEA,KAAK,gBAAgB;GACnB,MAAM,QAAQ,MAAM;GAIpB,IAAI,MAAM,SAAS,uBACjB,OAAO;GAET,IAAI,MAAM,OAAO,SAAS,cAAc;IACtC,MAAM,KAAK,gBAAgB,MAAM,eAAe;IAIhD,MAAM,OAAuB;KAC3B,MAAM;KACN;KACA,OANe,KAAK,MAAM,MACzB,SAAsE,KAAK,SAAS,oBAAoB,KAAK,OAAO,EAKvG,CAAC,EAAE,QAAQ,OAAO,MAAM,MAAM,QAAQ;KACpD,WAAW;KACX,iBAAiB,MAAM;IACzB;IACA,OAAO;KAAE,GAAG;KAAM,OAAO,OAAO,KAAK,OAAO,IAAI;IAAE;GACpD;GACA,IAAI,MAAM,OAAO,SAAS,kBAAkB;IAC1C,MAAM,KAAK,oBAAoB,MAAM,eAAe;IAIpD,MAAM,QAHW,KAAK,MAAM,MACzB,SAAgE,KAAK,SAAS,cAAc,KAAK,OAAO,EAEtF,CAAC,EAAE,QAAQ,OAAO,MAAM,MAAM,YAAY;IAE/D,IAAI,KAAK,KAAK,MAAM,IAClB,OAAO;IAET,MAAM,OAAuB;KAC3B,MAAM;KACN;KACA;KACA,iBAAiB,MAAM;IACzB;IACA,OAAO;KAAE,GAAG;KAAM,OAAO,OAAO,KAAK,OAAO,IAAI;IAAE;GACpD;GACA,OAAO;EACT;EAEA,KAAK,eACH,OAAO;GACL,GAAG;GACH,cAAc,MAAM;GACpB,OAAO,CACL,GAAG,KAAK,MAAM,KAAK,SAAS;IAC1B,IAAI,CAAC,gBAAgB,IAAI,GACvB,OAAO;IAET,MAAM,QAAQ,qBAAqB,QAAQ,KAAK,kBAAkB,IAAI,KAAK,oBAAoB;IAC/F,OAAO,KAAK,SAAS,mBACjB;KAAE,GAAG;KAAM,IAAI,QAAQ,MAAM,MAAM;KAAS,WAAW;IAAM,IAC7D;KAAE,GAAG;KAAM,IAAI,YAAY,MAAM,MAAM;IAAQ;GACrD,CAAC,GACD;IACE,MAAM;IACN,IAAI,QAAQ,MAAM;IAClB,SAAS,MAAM;IACf,SAAS,MAAM;IACf,YAAY,MAAM;IAClB,cAAc,MAAM;IACpB,QAAQ,MAAM;GAChB,CACF;EACF;EAGF,KAAK,wBACH,OAAO;GAAE,GAAG;GAAM,kBAAkB,CAAC,GAAG,KAAK,kBAAkB,MAAM,OAAO;EAAE;EAGhF,KAAK,uBACH,OAAO;GACL,GAAG;GACH,kBAAkB,KAAK,iBAAiB,QAAQ,MAAM,EAAE,OAAO,MAAM,SAAS;EAChF;EAGF,KAAK,wBACH,OAAO;GACL,GAAG;GACH,OAAO,KAAK,MAAM,KAAK,SACrB,KAAK,SAAS,eAAe,KAAK,OAAO,MAAM,cAC3C;IACE,GAAG;IACH,QAAQ,MAAM,WAAW,aAAa;IACtC,aAAa,MAAM;IACnB,SAAS,MAAM;GACjB,IACA,IACN;EACF;EAGF,KAAK,oBACH,OAAO;GACL,GAAG;GACH,OAAO,KAAK,MAAM,KAAK,SACrB,KAAK,SAAS,eAAe,KAAK,OAAO,MAAM,cAC3C;IACE,GAAG;IACH,QAAQ;IACR,aAAa,MAAM;IACnB,QAAQ;KAAE,MAAM,WAAW,MAAM,MAAM;KAAG,SAAS;IAAM;IACzD,MAAM,MAAM,QAAQ,KAAK;GAC3B,IACA,IACN;EACF;EAGF,KAAK,oBACH,OAAO;GACL,GAAG;GACH,OAAO,KAAK,MAAM,KAAK,SACrB,KAAK,SAAS,eAAe,KAAK,OAAO,MAAM,cAC3C;IACE,GAAG;IACH,QAAQ;IACR,aAAa,MAAM;IACnB,QAAQ;KAAE,MAAM,GAAG,MAAM,OAAO,IAAI,MAAM;KAAS,SAAS;IAAK;IACjE,MAAM,MAAM,QAAQ,KAAK;GAC3B,IACA,IACN;EACF;EAGF,KAAK,kBACH,OAAO;GACL,GAAG;GACH,OAAO,CACL,GAAG,KAAK,OACR;IACE,MAAM;IACN,IAAI,QAAQ,MAAM;IAClB,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,aAAa,MAAM;GACrB,CACF;EACF;EAGF,KAAK,iBACH,OAAO;GACL,GAAG;GACH,OAAO,CAAC,GAAG,KAAK,OAAO;IAAE,MAAM;IAAU,IAAI,OAAO,MAAM;IAAO,OAAO;IAAS,MAAM,MAAM;GAAQ,CAAC;EACxG;EAGF,KAAK,kBACH,OAAO;GACL,GAAG;GACH,OAAO,CACL,GAAG,KAAK,OACR;IACE,MAAM;IACN,IAAI,UAAU,MAAM;IACpB,OAAO;IACP,MAAM,mBAAmB,MAAM,OAAO;GACxC,CACF;EACF;EAIF,SACE,OAAO;CAEX;AACF;;;AC/pBA,MAAM,cAAc;AAEpB,MAAMA,4BAAU,IAAI,IAA6B;AAGjD,SAAgB,mBAAmB,QAA0B,WAA2B;CACtF,OAAO,GAAG,OAAO,YAAY,QAAQ;AACvC;AAEA,SAAgB,oBAAoB,KAA0C;CAC5E,OAAOA,UAAQ,IAAI,GAAG;AACxB;AAEA,SAAgB,qBAAqB,KAAa,OAA8B;CAC9E,UAAQ,OAAO,GAAG;CAClB,UAAQ,IAAI,KAAK,KAAK;CACtB,IAAIA,UAAQ,OAAO,aAAa;EAC9B,MAAM,SAASA,UAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;EACrC,IAAI,WAAW,KAAA,GACb,UAAQ,OAAO,MAAM;CAEzB;AACF;AAEA,SAAgB,sBAAsB,KAAmB;CACvD,UAAQ,OAAO,GAAG;AACpB;AAEA,SAAgB,uBAA6B;CAC3C,UAAQ,MAAM;AAChB;;;AC/BA,SAAgB,gBAAgB,WAAmB,KAAqB;CACtE,OAAO,GAAG,UAAU,GAAG;AACzB;AAmBA,SAAgB,WAAW,OAAiC;CAC1D,MAAM,YAAY,gBAAgB,MAAM,WAAW,MAAM,GAAG;CAC5D,MAAM,OAAO,MAAM,gBAAgB,CAAC,MAAM,YAAY,MAAM,OAAO,KAAA;CACnE,MAAM,OAAO,MAAM,cAAc;CACjC,MAAM,OAAO,OAAQ,QAAQ,yBAA0B,MAAM;CAE7D,OAAO;EAAE;EAAM;EAAM;EAAW,GAAI,KAAK,UAAU,IAAI,EAAE,UAAU,KAAK,QAAQ,IAAI,CAAC;CAAG;AAC1F;AAEA,SAAgB,mBAAmB,OAAyF;CAC1H,OAAO,MAAM,gBAAgB,CAAC,MAAM,aAAa,MAAM,QAAQ,UAAU,KAAK,MAAM,QAAQ,YAAY,KAAA;AAC1G;;;AChBA,SAAS,OAAO,OAAwB,QAAoF;CAC1H,IAAI,OAAO,SAAS,mBAClB,OAAO,OAAO;CAEhB,IAAI,OAAO,SAAS,6BAClB,OAAO,kBAAkB,OAAO,OAAO,WAAW,OAAO,IAAI;CAE/D,OAAO,OAAO,SAAS,aAAa,oBAAoB,OAAO,OAAO,OAAO,IAAI,WAAW,OAAO,MAAM;AAC3G;AAKA,MAAM,yBAAyB;AAE/B,SAAgB,oBAAoB,OAA0C;CAC5E,OAAO,MAAM,kBAAkB,KAAK,MAAM,QAAQ,UAAU,IAAI,MAAM,QAAQ,UAAU,KAAA;AAC1F;AAEA,SAAgB,YAAY,OAAsB,MAAgC;CAChF,IAAI,MAAM,kBAAkB,KAAK,KAAK,YAAY,GAChD,OAAO;CAET,IAAI,MAAM,QAAQ,UAAU,KAAK,SAC/B,OAAO;CAET,OAAO,KAAK,YAAY,KAAA,KAAa,MAAM,QAAQ,cAAc,KAAK,QAAQ;AAChF;AAEA,MAAa,qBAAqB;AA+BlC,SAAgB,iBACd,QACA,WACA,SACwB;CACxB,MAAM,CAAC,OAAO,YAAY,WACxB,QACA,KAAA,UAEG,SAAS,oBAAoB,SAAS,cAAc,KAAA,IACjD,oBAAoB,mBAAmB,QAAQ,SAAS,CAAC,IACzD,KAAA,MAAc,sBACtB;CACA,MAAM,CAAC,YAAY,iBAAiB,SAA0B,cAAc;CAC5E,MAAM,CAAC,kBAAkB,uBAAuB,SAA6B;CAC7E,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,cAAc,mBAAmB,SAA6B;CACrE,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC;CAE5C,MAAM,CAAC,aAAa,kBAAkB,SAAoC;CAC1E,MAAM,YAAY,OAA6B,IAAI;CACnD,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CACrB,MAAM,WAAW,OAAO,KAAK;CAC7B,SAAS,UAAU;CACnB,MAAM,eAAe,OAAO,gBAAgB,GAAG,cAAc,KAAA,IAAY,KAAK,mBAAmB,QAAQ,SAAS,CAAC,CAAC;CACpH,MAAM,eAAe,OAAO,KAAK;CAEjC,gBAAgB;EACd,IAAI,CAAC,WACH;EAEF,MAAM,QAAQ,WAAW,SAAS,oBAAoB;EACtD,MAAM,MAAM,mBAAmB,QAAQ,SAAS;EAChD,MAAM,OAAO,WAAW;GACtB;GACA;GACA,WAAW,aAAa;GACxB,SAAS,SAAS;GAClB,cAAc;GACd,WAAW,aAAa;GACxB,MAAM,oBAAoB,GAAG;EAC/B,CAAC;EACD,aAAa,UAAU;EACvB,IAAI,KAAK,MAAM;GACb,SAAS;IAAE,MAAM;IAAmB,OAAO,KAAK;GAAK,CAAC;GACtD,aAAa,UAAU,KAAK;EAC9B;EACA,MAAM,SAAS,OAAO,OAAO,WAAW;GACtC,iBAAiB;GACjB,WAAW;GACX,GAAI,KAAK,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;EACnE,CAAC;EACD,UAAU,UAAU;EACpB,eAAe,MAAM;EACrB,MAAM,WAAW,OAAO,GAAG,UAAU,UAAwB,SAAS,KAAK,CAAC;EAC5E,MAAM,cAAc,OAAO,GAAG,aAAa,UAAyB;GAClE,IAAI,YAAY,OAAO,SAAS,OAAO,GAAG;IACxC,SAAS;IACT,sBAAsB,GAAG;IACzB,aAAa,UAAU;IACvB,cAAc,MAAM,IAAI,CAAC;IACzB;GACF;GACA,SAAS,KAAK;GACd,gBAAgB,oBAAoB,KAAK,CAAC;GAC1C,oBAAoB,MAAM,oBAAoB,mBAAmB,KAAA,IAAY,MAAM,eAAe;GAClG,SAAS,MAAM,UAAU,IAAI;EAC/B,CAAC;EACD,MAAM,UAAU,OAAO,GAAG,qBAAqB,SAAkB,cAAc,OAAO,SAAS,cAAc,CAAC;EAC9G,MAAM,WAAW,OAAO,GAAG,qBAAqB,aAC9C,cAAc,YAAY,yBAAyB,YAAY,cAAc,CAC/E;EACA,MAAM,mBAAmB,OAAO,GAAG,kBAAkB,YAAoB;GACvE,WAAW,SAAS,kBAAkB,OAAO;EAC/C,CAAC;EACD,aAAa;GACX,SAAS;GACT,YAAY;GACZ,QAAQ;GACR,SAAS;GACT,iBAAiB;GACjB,OAAO,OAAO;GACd,UAAU,UAAU;GACpB,eAAe,KAAA,CAAS;GACxB,cAAc,cAAc;GAC5B,oBAAoB,KAAA,CAAS;GAC7B,SAAS,KAAK;GACd,gBAAgB,KAAA,CAAS;GACzB,MAAM,UAAU,SAAS;GACzB,IAAI,mBAAmB;IAAE,cAAc;IAAO,WAAW,aAAa;IAAS;GAAQ,CAAC,GACtF,qBAAqB,KAAK,OAAO;EAErC;CACF,GAAG;EAAC;EAAQ;EAAW;CAAS,CAAC;CAEjC,gBAAgB;EACd,IAAI,iBAAiB,KAAA,GACnB;EAEF,MAAM,QAAQ,iBAAiB,gBAAgB,KAAA,CAAS,GAAG,kBAAkB;EAC7E,aAAa,aAAa,KAAK;CACjC,GAAG,CAAC,YAAY,CAAC;CACjB,gBAAgB;EACd,IAAI,iBAAiB,KAAA,KAAa,MAAM,WAAW,cACjD,gBAAgB,KAAA,CAAS;CAE7B,GAAG,CAAC,cAAc,MAAM,OAAO,CAAC;CAEhC,MAAM,SAAS,wBAAwB,QAAQ,WAAW,KAAK;CAE/D,MAAM,YAAY,eAAe;CAEjC,MAAM,YAAY,iBAAiB,KAAA,KAAa,MAAM,UAAU;CAChE,MAAM,eAAe,kBAAkB,UAAU,SAAS,aAAa,GAAG,CAAC,CAAC;CAE5E,MAAM,iBAAiB,YACrB,OAAO,cAAwC;EAC7C,IAAI,CAAC,WACH,OAAO;EAET,MAAM,OAAO,SAAS,QAAQ,MAAM,MAAM,cAAc,UAAU,SAAS,eAAe,UAAU,OAAO,SAAS;EACpH,MAAM,SAAS,MAAM,SAAS,cAAc,KAAK,SAAS,KAAA;EAC1D,IAAI,CAAC,QAAQ,aAAa,OAAO,cAAc,KAAA,GAC7C,OAAO;EAET,IAAI;GACF,MAAM,OAAO,MAAM,OAAO,WAAW,WAAW,OAAO,WAAW,SAAS;GAC3E,SAAS;IAAE,MAAM;IAA6B;IAAW,MAAM,UAAU,KAAK,OAAO;GAAE,CAAC;GACxF,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF,GACA,CAAC,QAAQ,SAAS,CACpB;CAEA,OAAO,eACE;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA,gBAAgB,MAAM,SAAS,MAAM;EACrC,QAAQ;EACR,OAAO,MAAM,kBAAkB,UAAU,SAAS,KAAK,MAAM,aAAa;EAC1E,UAAU,WAAW,iBAAiB,UAAU,SAAS,QAAQ,WAAW,YAAY;EACxF,OAAO,WAAW,SAAS,cAAc,UAAU,SAAS,KAAK,WAAW,SAAS,SAAS;EAC9F,iBAAiB,UAAU,SAAS,UAAU;EAC9C,oBAAoB,UAAU,SAAS,aAAa;EACpD,WAAW,YAAY,UAAU,SAAS,SAAS,OAAO;EAC1D,oBAAoB,SAAS,UAAU,SAAS,kBAAkB,IAAI;EACtE,WAAW,UAAU,UAAU,SAAS,SAAS,KAAK;EACtD,oBAAoB,UAAU,SAAS,aAAa;EACpD;EACA;CACF,IACA;EAAC;EAAO;EAAW;EAAY;EAAW;EAAkB;EAAO;EAAQ;EAAa;EAAc;CAAc,CACtH;AACF;AAEA,SAAS,wBAAwB,QAA0B,WAA+B,OAAuC;CAC/H,MAAM,CAAC,SAAS,cAAc,SAAwB,CAAC,CAAC;CACxD,MAAM,UAAU,MAAM,SAAS;CAC/B,MAAM,WAAW,MAAM;CACvB,MAAM,cAAc,CAAC,CAAC,UAAU;CAEhC,gBAAgB,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;CAE3C,gBAAgB;EACd,IAAI,CAAC,WAAW,aACd;EAEF,IAAI,YAAY;EAChB,OACG,aAAa,CAAC,CACd,MAAM,aAAa;GAClB,IAAI,CAAC,WACH,WAAW,SAAS,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC;EAE9E,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;EACjB,aAAa;GACX,YAAY;EACd;CACF,GAAG;EAAC;EAAQ;EAAS;CAAW,CAAC;CAEjC,OAAO,cAAc,WAAW;AAClC;;;ACjQA,MAAM,0BAAU,IAAI,IAA0B;AAG9C,SAAgB,qBAAqB,QAA0B,SAAyB;CACtF,OAAO,GAAG,OAAO,YAAY,QAAQ;AACvC;AAEA,SAAgB,sBAAsB,KAAuC;CAC3E,OAAO,QAAQ,IAAI,GAAG;AACxB;AAEA,SAAgB,uBAAuB,KAAa,OAAuC;CACzF,IAAI,UAAU,KAAA,GACZ;CAEF,QAAQ,IAAI,KAAK,KAAK;AACxB;AAEA,SAAgB,yBAA+B;CAC7C,QAAQ,MAAM;AAChB;;;ACrBA,MAAM,MAAM;AAGZ,MAAM,aAAa;AAInB,IAAI;AAEJ,SAAS,UAA+B;CACtC,IAAI;EAEF,OAAQ,WAA0C;CACpD,QAAQ;EACN;CACF;AACF;AAEA,SAAS,OAA8B;CACrC,IAAI,QACF,OAAO;CAET,SAAS,CAAC;CACV,MAAM,MAAM,QAAQ,CAAC,EAAE,QAAQ,GAAG;CAClC,IAAI,KACF,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,OAAO,SAAS,YAAY,OAAO,MAAM,YAAY,UAC9D,OAAO,OAAO;CAGpB,QAAQ,CAER;CAEF,OAAO;AACT;AAEA,SAAS,QAAQ,QAAqC;CACpD,MAAM,UAAU,OAAO,QAAQ,MAAM;CACrC,IAAI,QAAQ,SAAS,YAAY;EAC/B,QAAQ,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO;EAClD,KAAK,MAAM,CAAC,QAAQ,QAAQ,MAAM,UAAU,GAC1C,OAAO,OAAO;CAElB;CACA,IAAI;EACF,QAAQ,CAAC,EAAE,QAAQ,KAAK,KAAK,UAAU,MAAM,CAAC;CAChD,QAAQ,CAER;AACF;AAGA,SAAgB,SAAS,QAA0B,WAA2B;CAC5E,OAAO,GAAG,OAAO,YAAY,QAAQ;AACvC;AAEA,SAAgB,UAAU,KAAqB;CAC7C,OAAO,KAAK,CAAC,CAAC,IAAI,EAAE,QAAQ;AAC9B;AAEA,SAAgB,WAAW,KAAa,MAAc,MAAM,KAAK,IAAI,GAAS;CAC5E,MAAM,SAAS,KAAK;CAEpB,IAAI,KAAK,KAAK,MAAM,IAAI;EACtB,IAAI,OAAO,SAAS,KAAA,GAClB;EAEF,OAAO,OAAO;CAChB,OACE,OAAO,OAAO;EAAE;EAAM,SAAS;CAAI;CAErC,QAAQ,MAAM;AAChB;AAEA,SAAgB,cAAoB;CAClC,SAAS,CAAC;CACV,IAAI;EACF,QAAQ,CAAC,EAAE,WAAW,GAAG;CAC3B,QAAQ,CAAC;AACX;;;AC5EA,MAAM,gCAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,iBAAiB;AAEvB,SAAgB,eAAe,WAA+C;CAC5E,MAAM,OAAO,UAAU,MAAM,GAAG,CAAC,CAAC,EAAE,CAAE,KAAK,CAAC,CAAC,YAAY;CACzD,IAAI,KAAK,WAAW,QAAQ,GAC1B,OAAO;CAET,IAAI,SAAS,mBACX,OAAO;CAET,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO;CAET,IAAI,cAAc,IAAI,IAAI,GACxB,OAAO;AAGX;AAsBA,SAAgB,eACd,QACA,WACA,EAAE,cAAc,UACM;CACtB,MAAM,CAAC,OAAO,YAAY,SAA6B,CAAC,CAAC;CACzD,MAAM,CAAC,OAAO,YAAY,SAA6B;CACvD,MAAM,UAAU,OAAO,CAAC;CACxB,MAAM,YAAY,uBAAO,IAAI,IAAkB,CAAC;CAChD,MAAM,cAAc,OAAiB,CAAC,CAAC;CACvC,YAAY,UAAU,MAAM,SAAS,SAAU,KAAK,aAAa,CAAC,KAAK,UAAU,IAAI,CAAC,CAAE;CACxF,MAAM,UAAU,aAAa;CAE7B,sBACc;EACV,KAAK,MAAM,OAAO,YAAY,SAC5B,IAAI,gBAAgB,GAAG;CAE3B,GACA,CAAC,CACH;CAEA,MAAM,QAAQ,aAAa,KAAa,SAAoC;EAC1E,UAAU,YAAY,QAAQ,KAAK,SAAU,KAAK,QAAQ,MAAM;GAAE,GAAG;GAAM,GAAG;EAAK,IAAI,IAAK,CAAC;CAC/F,GAAG,CAAC,CAAC;CAEL,MAAM,SAAS,aACZ,KAAa,SAAe;EAC3B,IAAI,CAAC,WACH;EAEF,MAAM,KAAK;GAAE,QAAQ;GAAa,OAAO,KAAA;EAAU,CAAC;EACpD,CAAM,YAAY;GAChB,IAAI;IACF,MAAM,OAAO,MAAM,QAAQ,IAAI;IAC/B,MAAM,WAAW,MAAM,OAAO,iBAAiB,WAAW;KACxD,MAAM,KAAK;KACX,WAAW,KAAK;KAChB,MAAM,KAAK;IACb,CAAC;IACD,MAAM,KAAK;KAAE,QAAQ;KAAS,IAAI,SAAS;KAAI,OAAO,SAAS,SAAS,KAAK;IAAK,CAAC;GACrF,SAAS,GAAG;IACV,MAAM,KAAK;KAAE,QAAQ;KAAU,OAAO,aAAa,QAAQ,EAAE,UAAU;IAAgB,CAAC;GAC1F;EACF,EAAA,CAAG;CACL,GACA;EAAC;EAAQ;EAAO;CAAS,CAC3B;CAEA,MAAM,MAAM,aACT,UAA0B;EACzB,MAAM,SAA6B,CAAC;EACpC,MAAM,UAA8C,CAAC;EACrD,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,YAAY,KAAK,QAAQ;GAC/B,MAAM,OAAO,eAAe,SAAS;GAErC,IAAI,QAAQ,CAAC,QAAQ,SAAS,IAAI,GAAG;IACnC,SAAS,OAAO,UAAU,SAAS,wBAAwB,KAAK,cAAc;IAC9E;GACF;GACA,MAAM,MAAM,OAAO,EAAE,QAAQ;GAC7B,OAAO,KAAK;IACV;IACA,MAAM,KAAK;IACX;IACA,OAAO,KAAK;IACZ,YAAY,SAAS,UAAU,IAAI,gBAAgB,IAAI,IAAI,KAAA;IAC3D,QAAQ;GACV,CAAC;GACD,QAAQ,KAAK;IAAE;IAAK;GAAK,CAAC;EAC5B;EACA,IAAI,OAAO,WAAW,GACpB;EAEF,UAAU,YAAY,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC;EAC7C,UAAU,UAAU,IAAI,IAAI,CAAC,GAAG,UAAU,SAAS,GAAG,QAAQ,KAAK,EAAE,KAAK,WAAW,CAAC,KAAK,IAAI,CAAU,CAAC,CAAC;EAC3G,KAAK,MAAM,EAAE,KAAK,UAAU,SAC1B,OAAO,KAAK,IAAI;CAEpB,GACA;EAAC;EAAS;EAAQ;CAAM,CAC1B;CAEA,MAAM,SAAS,aAAa,SAAmB;EAC7C,UAAU,YAAY;GACpB,KAAK,MAAM,QAAQ,SACjB,IAAI,KAAK,SAAS,KAAK,GAAG,KAAK,KAAK,YAClC,IAAI,gBAAgB,KAAK,UAAU;GAGvC,OAAO,QAAQ,QAAQ,SAAS,CAAC,KAAK,SAAS,KAAK,GAAG,CAAC;EAC1D,CAAC;EACD,KAAK,MAAM,OAAO,MAChB,UAAU,QAAQ,OAAO,GAAG;CAEhC,GAAG,CAAC,CAAC;CAEL,MAAM,SAAS,aAAa,QAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;CAEnE,MAAM,QAAQ,kBAAkB;EAC9B,UAAU,YAAY;GACpB,KAAK,MAAM,QAAQ,SACjB,IAAI,KAAK,YACP,IAAI,gBAAgB,KAAK,UAAU;GAGvC,OAAO,CAAC;EACV,CAAC;EACD,UAAU,QAAQ,MAAM;CAC1B,GAAG,CAAC,CAAC;CAEL,MAAM,QAAQ,aACX,QAAgB;EACf,MAAM,OAAO,UAAU,QAAQ,IAAI,GAAG;EACtC,IAAI,MACF,OAAO,KAAK,IAAI;CAEpB,GACA,CAAC,MAAM,CACT;CAEA,OAAO,eACE;EACL;EACA,UAAU,MAAM,SAAS,SAAU,KAAK,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAE;EAC5D,WAAW,MAAM,MAAM,SAAS,KAAK,WAAW,WAAW;EAC3D,YAAY,MAAM,MAAM,SAAS,KAAK,WAAW,QAAQ;EACzD,QAAQ,gBAAgB,OAAO;EAC/B,UAAU,QAAQ,WAAW,KAAK,CAAC;EACnC;EACA;EACA;EACA;EACA;EACA,oBAAoB,SAAS,KAAA,CAAS;CACxC,IACA;EAAC;EAAO;EAAS;EAAW;EAAK;EAAO;EAAQ;EAAO;CAAK,CAC9D;AACF;AAEA,SAAS,gBAAgB,OAA0C;CACjE,IAAI,MAAM,WAAW,GACnB,OAAO;CAET,MAAM,QAAkB,CAAC;CACzB,IAAI,MAAM,SAAS,OAAO,GACxB,MAAM,KAAK,SAAS;CAEtB,IAAI,MAAM,SAAS,KAAK,GACtB,MAAM,KAAK,iBAAiB;CAE9B,IAAI,MAAM,SAAS,MAAM,GACvB,MAAM,KAAK,UAAU,OAAO,SAAS,SAAS,QAAQ,OAAO;CAG/D,OAAO,MAAM,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG;AACjD;AAYA,MAAM,UAAU;AAKhB,eAAe,QAAQ,MAAwD;CAC7E,MAAM,YAAY,KAAK,QAAQ;CAC/B,MAAM,EAAE,mBAAmB,aAAa;CACxC,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC,UAAU,WAAW,QAAQ,GACnE,OAAO;EAAE,MAAM;EAAM;CAAU;CAGjC,IAAI,cAAc,aAChB,OAAO;EAAE,MAAM;EAAM;CAAU;CAEjC,IAAI;EACF,MAAM,SAAS,MAAM,kBAAkB,IAAI;EAC3C,MAAM,UAAU,KAAK,IAAI,OAAO,OAAO,OAAO,MAAM;EACpD,IAAI,WAAW,gBAAgB;GAC7B,OAAO,MAAM;GACb,OAAO;IAAE,MAAM;IAAM;GAAU;EACjC;EACA,MAAM,QAAQ,iBAAiB;EAC/B,MAAM,SAAS,SAAS,cAAc,QAAQ;EAC9C,OAAO,QAAQ,KAAK,MAAM,OAAO,QAAQ,KAAK;EAC9C,OAAO,SAAS,KAAK,MAAM,OAAO,SAAS,KAAK;EAChD,MAAM,UAAU,OAAO,WAAW,IAAI;EACtC,IAAI,CAAC,SAAS;GACZ,OAAO,MAAM;GACb,OAAO;IAAE,MAAM;IAAM;GAAU;EACjC;EACA,QAAQ,UAAU,QAAQ,GAAG,GAAG,OAAO,OAAO,OAAO,MAAM;EAC3D,OAAO,MAAM;EACb,MAAM,OAAO,MAAM,IAAI,SAAsB,YAAY,OAAO,OAAO,SAAS,cAAc,GAAI,CAAC;EACnG,OAAO,OAAO;GAAE,MAAM;GAAM,WAAW;EAAa,IAAI;GAAE,MAAM;GAAM;EAAU;CAClF,QAAQ;EACN,OAAO;GAAE,MAAM;GAAM;EAAU;CACjC;AACF;;;AC3QA,MAAM,eAAe;AAErB,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;AAAG,CAAC;AAErF,SAAgB,iBAAiB,MAA6B;CAC5D,MAAM,SAAwB,CAAC;CAC/B,MAAM,QAAQ;CACd,IAAI;CACJ,QAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;EAC1C,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,KAAK,OAAO,MAAM,SAAS,KAAK,OAAO,MAAM,YAAY,KAAA;EACtE,IAAI,CAAC,MACH;EAEF,IAAI,MAAM,MAAM,QAAQ,KAAK;EAC7B,OAAO,MAAM,MAAM,SAAS,cAAc,IAAI,KAAK,MAAM,EAAG,GAC1D;EAEF,MAAM,OAAO,KAAK,MAAM,MAAM,QAAQ,GAAG,GAAG;EAC5C,IAAI,CAAC,MACH;EAEF,IAAI,SAAS,aAAa,CAAC,aAAa,KAAK,IAAI,GAC/C;EAEF,OAAO,KAAK;GAAE;GAAM,OAAO,MAAM;GAAO;GAAK,MAAM,KAAK,MAAM,MAAM,OAAO,GAAG;EAAE,CAAC;CACnF;CACA,OAAO;AACT;;;AChCA,SAAgB,cAAkC;CAChD,MAAM,QAAQ,OAAO,IAAI;CACzB,gBAAgB;EACd,MAAM,UAAU;EAChB,aAAa;GACX,MAAM,UAAU;EAClB;CACF,GAAG,CAAC,CAAC;CACL,OAAO;AACT;AAEA,SAAgB,mBAAmB,GAAqB;CACtD,OAAO,aAAa,mBAAmB,EAAE,WAAW;AACtD;;;ACFA,SAAgB,gBAAgB,MAAc,MAAyC,UAA8C;CACnI,MAAM,OAAsB,CAAC;CAC7B,MAAM,YAAY,KAAK,IAAI,IAAI;CAC/B,IAAI,CAAC,WACH,OAAO;CAKT,MAAM,QAA8E,CAAC;EAAE,SAAS,UAAU;EAAS,OAAO;EAAG,OAAO;CAAE,CAAC;CACvI,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,QAAQ,MAAM,MAAM,SAAS;EACnC,MAAM,QAAQ,MAAM,QAAQ,MAAM;EAClC,IAAI,UAAU,KAAA,GAAW;GACvB,MAAM,IAAI;GACV;EACF;EACA,MAAM,SAAS;EACf,MAAM,QAAQ,MAAM;EACpB,IAAI,MAAM,SAAS,OAAO;GACxB,KAAK,KAAK;IAAE;IAAO;GAAM,CAAC;GAC1B;EACF;EACA,MAAM,aAAa,SAAS,IAAI,MAAM,IAAI;EAC1C,MAAM,aAAa,KAAK,IAAI,MAAM,IAAI;EACtC,KAAK,KAAK;GACR;GACA;GACA,UAAU;GACV,SAAS,cAAc,CAAC;GACxB,WAAW,aAAa,YAAY,YAAY,KAAA;EAClD,CAAC;EACD,IAAI,cAAc,YAChB,MAAM,KAAK;GAAE,SAAS,WAAW;GAAS,OAAO;GAAG,OAAO,QAAQ;EAAE,CAAC;CAE1E;CACA,OAAO;AACT;AAEA,SAAgB,gBAAgB,MAAc,MAAwB;CACpE,MAAM,OAAO,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI;CACtD,IAAI,SAAS,QAAQ,CAAC,KAAK,WAAW,GAAG,KAAK,EAAE,GAC9C,OAAO,CAAC;CAEV,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,GAAG;CAClD,MAAM,MAAgB,CAAC;CACvB,IAAI,UAAU;CACd,KAAK,MAAM,WAAW,KAAK,MAAM,GAAG,EAAE,GAAG;EACvC,UAAU,GAAG,QAAQ,GAAG;EACxB,IAAI,KAAK,OAAO;CAClB;CACA,OAAO;AACT;;;ACxDA,SAAgB,kBAAkB,QAA0B,KAAkD;CAC5G,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,UAAU,OAAO,GAAG;CAC1B,gBAAgB;EACd,IAAI,QAAQ,YAAY,KAAK;GAC3B,QAAQ,UAAU;GAClB,eAAe,KAAK;EACtB;CACF,GAAG,CAAC,GAAG,CAAC;CAER,MAAM,SAAS,YACb,OAAO,OAAe,YAAuD;EAC3E,IAAI,CAAC,OAAO,aACV,OAAO,CAAC;EAEV,IAAI;GACF,MAAM,WAAW,MAAM,OAAO,cAAc,KAAK,OAAO,SAAS,SAAS,CAAC;GAC3E,OAAO,SAAS,QAAQ,UAAU,CAAC,IAAI,SAAS;EAClD,SAAS,GAAG;GACV,IAAI,mBAAmB,CAAC,GACtB,eAAe,IAAI;GAErB,OAAO,CAAC;EACV;CACF,GACA;EAAC;EAAQ;EAAK;CAAW,CAC3B;CAEA,OAAO;EAAE,WAAW,CAAC,CAAC,OAAO,CAAC;EAAa;CAAO;AACpD;AAOA,SAAgB,iBAAiB,QAAkD;CACjF,MAAM,CAAC,QAAQ,aAAa,SAAiC;EAC3D,WAAW;EACX,UAAU;CACZ,CAAC;CACD,gBAAgB;EACd,IAAI,YAAY;EAChB,OACG,cAAc,CAAC,CACf,MAAM,aAAa;GAClB,IAAI,CAAC,WACH,UAAU;IAAE,WAAW;IAAM,UAAU,SAAS;GAAS,CAAC;EAE9D,CAAC,CAAC,CACD,YAAY;GACX,IAAI,CAAC,WACH,UAAU;IAAE,WAAW;IAAO,UAAU;GAAM,CAAC;EAEnD,CAAC;EACH,aAAa;GACX,YAAY;EACd;CACF,GAAG,CAAC,MAAM,CAAC;CACX,OAAO;AACT;AAaA,SAAgB,gBAAgB,QAA0B,KAAgD;CACxG,MAAM,CAAC,MAAM,WAAW,+BAA0C,IAAI,IAAI,CAAC;CAC3E,MAAM,CAAC,UAAU,eAAe,+BAA4B,IAAI,IAAI,CAAC;CACrE,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,OAAO,YAAY,SAA6B;CAEvD,MAAM,UAAU,OAAO,GAAG;CAC1B,gBAAgB;EACd,IAAI,QAAQ,YAAY,KACtB;EAEF,QAAQ,UAAU;EAClB,wBAAQ,IAAI,IAAI,CAAC;EACjB,4BAAY,IAAI,IAAI,CAAC;EACrB,eAAe,KAAK;EACpB,SAAS,KAAA,CAAS;CACpB,GAAG,CAAC,GAAG,CAAC;CAER,MAAM,QAAQ,YAAY;CAE1B,MAAM,YAAY,uBAAO,IAAI,IAAY,CAAC;CAE1C,MAAM,OAAO,aACV,QAAgB,EAAE,QAAQ,UAAU,CAAC,MAAM;EAC1C,IAAI,aACF;EAEF,IAAI,CAAC,SAAS,UAAU,QAAQ,IAAI,MAAM,GACxC;EAEF,UAAU,QAAQ,IAAI,MAAM;EAC5B,OACG,YAAY,MAAM,CAAC,CACnB,MAAM,aAAa;GAClB,IAAI,CAAC,MAAM,SACT;GAEF,SAAS,aAAa;IACpB,MAAM,OAAO,IAAI,IAAI,QAAQ;IAE7B,KAAK,IAAI,QAAQ;KAAE,SAAS,SAAS;KAAS,WAAW,SAAS;IAAU,CAAC;IAC7E,OAAO;GACT,CAAC;EACH,CAAC,CAAC,CACD,OAAO,MAAe;GACrB,IAAI,CAAC,MAAM,SACT;GAEF,UAAU,QAAQ,OAAO,MAAM;GAC/B,IAAI,mBAAmB,CAAC,GAAG;IACzB,eAAe,IAAI;IACnB;GACF;GACA,SAAS,aAAa,QAAQ,EAAE,UAAU,+BAA+B;EAC3E,CAAC;CACL,GACA,CAAC,QAAQ,WAAW,CACtB;CAEA,gBAAgB;EACd,IAAI,KACF,KAAK,GAAG;CAEZ,GAAG,CAAC,KAAK,IAAI,CAAC;CAEd,MAAM,SAAS,aACZ,SAAiB;EAChB,aAAa,aAAa;GACxB,MAAM,OAAO,IAAI,IAAI,QAAQ;GAC7B,IAAI,KAAK,IAAI,IAAI,GACf,KAAK,OAAO,IAAI;QAEhB,KAAK,IAAI,IAAI;GAEf,OAAO;EACT,CAAC;EAED,KAAK,IAAI;CACX,GACA,CAAC,IAAI,CACP;CAEA,MAAM,SAAS,aACZ,SAAiB;EAChB,IAAI,CAAC,KACH;EAEF,MAAM,YAAY,gBAAgB,KAAK,IAAI;EAC3C,IAAI,UAAU,WAAW,GACvB;EAEF,KAAK,MAAM,OAAO,WAChB,KAAK,GAAG;EAEV,aAAa,aAAa;GACxB,MAAM,OAAO,IAAI,IAAI,QAAQ;GAC7B,KAAK,MAAM,OAAO,WAChB,KAAK,IAAI,GAAG;GAEd,OAAO;EACT,CAAC;CACH,GACA,CAAC,KAAK,IAAI,CACZ;CAEA,MAAM,UAAU,aACb,SAAkB;EACjB,MAAM,SAAS,QAAQ;EACvB,IAAI,CAAC,QACH;EAEF,SAAS,KAAA,CAAS;EAClB,KAAK,QAAQ,EAAE,OAAO,KAAK,CAAC;CAC9B,GACA,CAAC,KAAK,IAAI,CACZ;CAEA,MAAM,OAAO,cAAe,MAAM,gBAAgB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAI;EAAC;EAAK;EAAM;CAAQ,CAAC;CAEnG,OAAO;EACL,WAAW,CAAC,CAAC,OAAO,CAAC;EACrB,MAAM;EACN;EACA,SAAS,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC;EACrD;EACA;EACA;EACA;CACF;AACF;;;ACjNA,MAAM,yBAAS,IAAI,IAAoB;AACvC,MAAM,2BAAW,IAAI,IAAY;AACjC,MAAM,yBAAS,IAAI,IAAY;AAI/B,SAAgB,gBAAgB,MAA6B,WAAkD;CAC7G,MAAM,CAAC,UAAU,eAAe,eAAuC,OAAO,YAAY,MAAM,CAAC;CAEjG,gBAAgB;EACd,IAAI,QAAQ;EACZ,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,OAAO,IAAI,KAAK,SAAS;GAC/B,IAAI,MAAM,SAAS,SACjB;GAEF,MAAM,EAAE,SAAS;GACjB,IAAI,OAAO,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,GAC3D;GAEF,MAAM,SAAS,UAAU,IAAI,MAAM;GAEnC,IAAI,CAAC,QACH;GAEF,SAAS,IAAI,IAAI;GACjB,OACG,YAAY,IAAI,KAAK,EAAE,CAAC,CACxB,MAAM,SAAS;IACd,OAAO,IAAI,MAAM,IAAI,gBAAgB,IAAI,CAAC;IAC1C,IAAI,OACF,YAAY,OAAO,YAAY,MAAM,CAAC;GAE1C,CAAC,CAAC,CACD,YAAY;IACX,OAAO,IAAI,IAAI;GACjB,CAAC,CAAC,CACD,cAAc,SAAS,OAAO,IAAI,CAAC;EACxC;EACA,aAAa;GACX,QAAQ;EACV;CACF,GAAG,CAAC,MAAM,SAAS,CAAC;CAEpB,OAAO;AACT;;;ACpCA,SAAgB,SAAS,QAA0B,WAA+C;CAChG,MAAM,MAAM,YAAY,SAAS,QAAQ,SAAS,IAAI,KAAA;CAgBtD,OAAO;EAAE,aAdW,cAAe,MAAM,UAAU,GAAG,IAAI,IAAK,CAAC,GAAG,CAchD;EAAG,MAbT,aACV,SAAiB;GAChB,IAAI,KACF,WAAW,KAAK,IAAI;EAExB,GACA,CAAC,GAAG,CAOmB;EAAG,OALd,kBAAkB;GAC9B,IAAI,KACF,WAAW,KAAK,EAAE;EAEtB,GAAG,CAAC,GAAG,CACyB;CAAE;AACpC;;;ACfA,SAAgB,gBACd,QACA,SACA,UAAkC,CAAC,GACZ;CACvB,MAAM,EAAE,aAAa,KAAQ,UAAU,SAAS;CAChD,MAAM,WAAW,UAAU,qBAAqB,QAAQ,OAAO,IAAI,KAAA;CACnE,MAAM,CAAC,OAAO,YAAY,eAA0C,WAAW,sBAAsB,QAAQ,IAAI,KAAA,CAAU;CAC3H,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,OAAO,YAAY,SAAS,CAAC;CACpC,MAAM,UAAU,kBAAkB,UAAU,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;CAK5D,gBAAgB,SAAS,WAAW,sBAAsB,QAAQ,IAAI,KAAA,CAAS,GAAG,CAAC,QAAQ,CAAC;CAE5F,MAAM,QAAQ,YAAY;CAE1B,gBAAgB;EACd,IAAI,CAAC,WAAW,CAAC,WAAW,aAC1B;EAEF,IAAI,YAAY;EAChB,MAAM,aAAa;GAEjB,IAAK,WAAmD,UAAU,QAChE;GAEF,OACG,aAAa,CAAC,CACd,MAAM,QAAQ;IACb,IAAI,aAAa,CAAC,MAAM,SACtB;IAEF,MAAM,OAAO,IAAI,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO,CAAC,EAAE;IAC3D,IAAI,UACF,uBAAuB,UAAU,IAAI;IAEvC,SAAS,IAAI;GACf,CAAC,CAAC,CACD,OAAO,MAAe;IACrB,IAAI,aAAa,CAAC,MAAM,SACtB;IAEF,IAAI,mBAAmB,CAAC,GACtB,eAAe,IAAI;GAEvB,CAAC;EACL;EACA,KAAK;EACL,MAAM,QAAQ,YAAY,MAAM,UAAU;EAC1C,aAAa;GACX,YAAY;GACZ,cAAc,KAAK;EACrB;CACF,GAAG;EAAC;EAAQ;EAAS;EAAS;EAAa;EAAY;EAAO;CAAQ,CAAC;CAEvE,OAAO;EAAE;EAAO;CAAQ;AAC1B;;;ACjEA,SAAgB,eAAe,QAA0B,WAAqD;CAC5G,MAAM,CAAC,MAAM,WAAW,SAAkC;CAC1D,MAAM,CAAC,SAAS,cAAc,SAAS,CAAC,CAAC,SAAS;CAClD,MAAM,CAAC,OAAO,YAAY,SAA6B;CAEvD,gBAAgB;EACd,IAAI,CAAC,WAAW;GACd,QAAQ,KAAA,CAAS;GACjB,WAAW,KAAK;GAChB,SAAS,KAAA,CAAS;GAClB;EACF;EACA,IAAI,YAAY;EAChB,WAAW,IAAI;EACf,SAAS,KAAA,CAAS;EAClB,QAAQ,KAAA,CAAS;EACjB,OACG,WAAW,SAAS,CAAC,CACrB,MAAM,SAAS;GACd,IAAI,WACF;GAEF,QAAQ,IAAI;GACZ,WAAW,KAAK;EAClB,CAAC,CAAC,CACD,OAAO,MAAe;GACrB,IAAI,WACF;GAEF,SAAS,aAAa,QAAQ,EAAE,UAAU,mBAAmB;GAC7D,WAAW,KAAK;EAClB,CAAC;EACH,aAAa;GACX,YAAY;EACd;CACF,GAAG,CAAC,QAAQ,SAAS,CAAC;CAEtB,OAAO;EAAE;EAAM;EAAS;CAAM;AAChC;;;ACjCA,SAAgB,QAAQ,MAAyB;CAC/C,OAAO,KAAK,UAAU,KAAA,KAAa,KAAK,UAAU,KAAK;AACzD;AAEA,SAAgB,YAAY,MAAwB;CAClD,OAAO,KAAK,SAAS,KAAK,WAAW;AACvC;AA6BA,MAAa,wBAAwC,EAAE,OAAO,CAAC,EAAE;AAEjE,SAAgB,iBAAiB,OAAuB,QAAyC;CAC/F,QAAQ,OAAO,MAAf;EACE,KAAK,QAAQ;GACX,IAAI,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,OAAO,IAAI,GAChD,OAAO,MAAM,eAAe,OAAO,OAAO,QAAQ;IAAE,GAAG;IAAO,YAAY,OAAO;GAAK;GAExF,MAAM,OAAiB;IAAE,MAAM,OAAO;IAAM,MAAM,SAAS,OAAO,IAAI;IAAG,QAAQ;GAAU;GAC3F,OAAO;IAAE,OAAO,CAAC,GAAG,MAAM,OAAO,IAAI;IAAG,YAAY,OAAO;GAAK;EAClE;EAEA,KAAK,SAAS;GACZ,MAAM,QAAQ,MAAM,MAAM,WAAW,MAAM,EAAE,SAAS,OAAO,IAAI;GACjE,IAAI,UAAU,IACZ,OAAO;GAET,MAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM,EAAE,SAAS,OAAO,IAAI;GAC9D,IAAI,MAAM,eAAe,OAAO,MAC9B,OAAO;IAAE,GAAG;IAAO;GAAM;GAI3B,OAAO;IAAE;IAAO,aADH,MAAM,UAAU,MAAM,QAAQ,GAAA,EACT;GAAK;EACzC;EAEA,KAAK,YACH,OAAO;EAGT,KAAK;GACH,IAAI,CAAC,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,OAAO,IAAI,GACjD,OAAO;GAET,OAAO,MAAM,eAAe,OAAO,OAAO,QAAQ;IAAE,GAAG;IAAO,YAAY,OAAO;GAAK;EAGxF,KAAK,UACH,OAAO,MAAM,OAAO,OAAO,aAAa;GACtC,MAAM,OAAO;GACb,MAAM,SAAS,OAAO,IAAI;GAC1B,QAAQ,OAAO,aAAa,SAAS,UAAU;GAC/C,SAAS,OAAO,aAAa,SAAS,OAAO,UAAU,KAAA;GACvD,OAAO,OAAO;GACd,MAAM,OAAO;GACb,YAAY,OAAO;EACrB,EAAE;EAGJ,KAAK,UACH,OAAO,MAAM,OAAO,OAAO,OAAO,UAAU;GAAE,GAAG;GAAM,QAAQ;GAAS,OAAO,OAAO;EAAM,EAAE;EAGhG,KAAK,QACH,OAAO,MAAM,OAAO,OAAO,OAAO,SAAU,KAAK,WAAW,UAAU;GAAE,GAAG;GAAM,OAAO,OAAO;EAAQ,IAAI,IAAK;EAGlH,KAAK,UACH,OAAO,MAAM,OAAO,OAAO,OAAO,UAAU;GAC1C,GAAG;GACH,OAAO,KAAA;GACP,WAAW,KAAA;GACX,UAAU;EACZ,EAAE;EAGJ,KAAK,aACH,OAAO,MAAM,OAAO,OAAO,OAAO,UAAU;GAC1C,GAAG;GACH,QAAQ;GACR,WAAW,KAAA;GACX,UAAU;EACZ,EAAE;EAGJ,KAAK,SACH,OAAO,MAAM,OAAO,OAAO,OAAO,UAAU;GAC1C,GAAG;GACH,QAAQ;GACR,WAAW,KAAA;GACX,UAAU;GACV,SAAS,OAAO;GAChB,OAAO,OAAO;GACd,MAAM,OAAO;GACb,YAAY,OAAO;GACnB,OAAO,KAAK,UAAU,OAAO,UAAU,KAAA,IAAY,KAAK;EAC1D,EAAE;EAGJ,KAAK,cACH,OAAO,MAAM,OAAO,OAAO,OAAO,UAAU;GAC1C,GAAG;GACH,QAAQ;GACR,WAAW,OAAO;GAClB,UAAU,OAAO,YAAY;EAC/B,EAAE;EAGJ,KAAK,mBACH,OAAO,MAAM,OAAO,OAAO,OAAO,UAAU;GAC1C,GAAG;GACH,UAAU;GACV,WAAW,KAAA;EACb,EAAE;CAEN;AACF;AAEA,SAAS,MAAM,OAAuB,MAAc,MAAoD;CACtG,MAAM,QAAQ,MAAM,MAAM,WAAW,MAAM,EAAE,SAAS,IAAI;CAC1D,IAAI,UAAU,IACZ,OAAO;CAET,MAAM,UAAU,MAAM,MAAM;CAC5B,MAAM,UAAU,KAAK,OAAO;CAC5B,IAAI,YAAY,SACd,OAAO;CAET,MAAM,QAAQ,MAAM,MAAM,MAAM;CAChC,MAAM,SAAS;CACf,OAAO;EAAE,GAAG;EAAO;CAAM;AAC3B;AAEA,SAAS,SAAS,MAAsB;CACtC,MAAM,UAAU,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI;CACzD,OAAO,QAAQ,MAAM,QAAQ,YAAY,GAAG,IAAI,CAAC,KAAK,WAAW;AACnE;;;AC7JA,SAAgB,aAAa,QAA8C;CACzE,MAAM,CAAC,OAAO,YAAY,WAAW,kBAAkB,qBAAqB;CAE5E,MAAM,YAAY,uBAAO,IAAI,IAAY,CAAC;CAC1C,MAAM,QAAQ,OAAO,IAAI;CACzB,gBAAgB;EACd,MAAM,UAAU;EAChB,aAAa;GACX,MAAM,UAAU;EAClB;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,SAAS,OAAO,KAAK;CAC3B,gBAAgB;EACd,OAAO,UAAU;CACnB,GAAG,CAAC,KAAK,CAAC;CAIV,MAAM,UAFU,MAAM,MAAM,QAAQ,MAAM,EAAE,WAAW,SAEjC,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI;CAEpD,MAAM,OAAO,aACV,SACC,OAAO,aAAa,IAAI,CAAC,CAAC,MAAM,aAAa;EAC3C,IAAI,CAAC,MAAM,SACT;EAEF,SAAS;GACP,MAAM;GAEN;GACA,SAAS,SAAS;GAClB,UAAU,SAAS;GACnB,OAAO,SAAS;GAChB,MAAM,SAAS;GACf,YAAY,SAAS;EACvB,CAAC;EACD,OAAO;CACT,CAAC,GACH,CAAC,MAAM,CACT;CAEA,gBAAgB;EACd,KAAK,MAAM,QAAQ,UAAU,QAAQ,MAAM,IAAI,IAAI,CAAC,GAAG;GACrD,IAAI,UAAU,QAAQ,IAAI,IAAI,GAC5B;GAEF,UAAU,QAAQ,IAAI,IAAI;GAC1B,KAAK,IAAI,CAAC,CAAC,OAAO,MAAe;IAC/B,IAAI,CAAC,MAAM,SACT;IAEF,SAAS;KACP,MAAM;KACN;KACA,OAAO,aAAa,QAAQ,EAAE,UAAU;IAC1C,CAAC;GACH,CAAC;EACH;CACF,GAAG,CAAC,MAAM,OAAO,CAAC;CAElB,MAAM,OAAO,aAAa,SAAiB,SAAS;EAAE,MAAM;EAAQ;CAAK,CAAC,GAAG,CAAC,CAAC;CAC/E,MAAM,QAAQ,aAAa,SAAiB;EAC1C,UAAU,QAAQ,OAAO,IAAI;EAC7B,SAAS;GAAE,MAAM;GAAS;EAAK,CAAC;CAClC,GAAG,CAAC,CAAC;CACL,MAAM,WAAW,kBAAkB;EACjC,UAAU,QAAQ,MAAM;EACxB,SAAS,EAAE,MAAM,WAAW,CAAC;CAC/B,GAAG,CAAC,CAAC;CACL,MAAM,WAAW,aAAa,SAAiB,SAAS;EAAE,MAAM;EAAY;CAAK,CAAC,GAAG,CAAC,CAAC;CACvF,MAAM,OAAO,aAAa,MAAc,YAAoB,SAAS;EAAE,MAAM;EAAQ;EAAM;CAAQ,CAAC,GAAG,CAAC,CAAC;CACzG,MAAM,SAAS,aAAa,SAAiB,SAAS;EAAE,MAAM;EAAU;CAAK,CAAC,GAAG,CAAC,CAAC;CACnF,MAAM,kBAAkB,aAAa,SAAiB,SAAS;EAAE,MAAM;EAAmB;CAAK,CAAC,GAAG,CAAC,CAAC;CAErG,MAAM,SAAS,aACZ,SAAiB;EAChB,UAAU,QAAQ,IAAI,IAAI;EAC1B,KAAK,IAAI,CAAC,CAAC,OAAO,MAAe;GAC/B,IAAI,CAAC,MAAM,SACT;GAEF,SAAS;IACP,MAAM;IACN;IACA,OAAO,aAAa,QAAQ,EAAE,UAAU;GAC1C,CAAC;EACH,CAAC;CACH,GACA,CAAC,IAAI,CACP;CAEA,MAAM,QAAQ,YACZ,OAAO,MAAc,MAAc,iBAAqC;EACtE,IAAI;GACF,MAAM,WAAW,MAAM,OAAO,cAAc;IAAE;IAAM,SAAS;IAAM;GAAa,CAAC;GACjF,IAAI,CAAC,MAAM,SACT;GAEF,SAAS;IACP,MAAM;IACN;IACA,SAAS;IACT,OAAO,SAAS;IAChB,MAAM,SAAS;IACf,YAAY,SAAS;GACvB,CAAC;EACH,SAAS,GAAG;GACV,IAAI,CAAC,MAAM,SACT;GAEF,MAAM,WAAW,aAAa,mBAAmB,EAAE,WAAW;GAC9D,SAAS;IACP,MAAM;IACN;IACA;IACA,OAAO,WAAW,mDAAmD,aAAa,QAAQ,EAAE,UAAU;GACxG,CAAC;EACH;CACF,GACA,CAAC,MAAM,CACT;CAEA,MAAM,OAAO,YACX,OAAO,SAAiB;EACtB,MAAM,OAAO,OAAO,QAAQ,MAAM,MAAM,MAAM,EAAE,SAAS,IAAI;EAC7D,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,IAAI,GACvC;EAEF,SAAS;GAAE,MAAM;GAAa;EAAK,CAAC;EACpC,MAAM,MAAM,MAAM,YAAY,IAAI,GAAG,KAAK,IAAI;CAChD,GACA,CAAC,KAAK,CACR;CAEA,MAAM,YAAY,YAChB,OAAO,SAAiB;EACtB,MAAM,OAAO,OAAO,QAAQ,MAAM,MAAM,MAAM,EAAE,SAAS,IAAI;EAC7D,IAAI,CAAC,QAAQ,KAAK,QAChB;EAGF,MAAM,OAAO,YAAY,IAAI;EAC7B,SAAS;GAAE,MAAM;GAAa;EAAK,CAAC;EACpC,IAAI;GACF,MAAM,QAAQ,MAAM,OAAO,aAAa,IAAI;GAC5C,IAAI,CAAC,MAAM,SACT;GAEF,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;EACpC,SAAS,GAAG;GACV,IAAI,CAAC,MAAM,SACT;GAEF,SAAS;IACP,MAAM;IACN;IACA,OAAO,aAAa,QAAQ,EAAE,UAAU;GAC1C,CAAC;EACH;CACF,GACA,CAAC,QAAQ,KAAK,CAChB;CAEA,MAAM,SAAS,cAAc,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,MAAM,UAAU,GAAG,CAAC,MAAM,OAAO,MAAM,UAAU,CAAC;CAClH,MAAM,aAAa,cAAc,MAAM,MAAM,KAAK,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC;CAEzE,OAAO;EACL,GAAG;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;ACjKA,SAAgB,mBAAmB,QAAuB,UAA+B,CAAC,GAA4B;CACpH,MAAM,2BAAW,IAAI,IAA6B;CAClD,IAAI;CACJ,IAAI,WAAW;CAEf,MAAM,SAAS,cAAiC,QAAQ,cAAc,SAAS;CAE/E,MAAM,UAAU,OAA6B,QAAgB,OAAe,cAAsB;EAChG,OAAO,kBAAkB,MAAM,aAAa,QAAQ,KAAK;EACzD,MAAM;GACJ,aAAa,MAAM;GACnB,UAAU,MAAM;GAChB,QAAQ;GACR;GACA;GACA,SAAS,KAAK,IAAI;EACpB,CAAC;CACH;CAEA,MAAM,gBAAgB,OAAO,OAA6B,YAA8C;EACtG,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,aAAa,IAAI,gBAAgB;EACvC,SAAS,IAAI,MAAM,aAAa,UAAU;EAC1C,MAAM;GAAE,aAAa,MAAM;GAAa,UAAU,MAAM;GAAU,QAAQ;GAAW;EAAU,CAAC;EAEhG,IAAI;GACF,MAAM,SAAS,MAAM,QAAQ,MAAM,OAAO;IACxC,aAAa,MAAM;IACnB,QAAQ,WAAW;GACrB,CAAC;GACD,IAAI,YAAY,CAAC,SAAS,IAAI,MAAM,WAAW,GAC7C;GAEF,IAAI,WAAW,QAAQ;IACrB,OAAO,kBAAkB,MAAM,aAAa,OAAO,UAAU,gBAAgB,OAAO,KAAK;IACzF,MAAM;KACJ,aAAa,MAAM;KACnB,UAAU,MAAM;KAChB,QAAQ;KACR,QAAQ,OAAO,UAAU;KACzB;KACA,SAAS,KAAK,IAAI;IACpB,CAAC;GACH,OAAO;IACL,OAAO,mBAAmB,MAAM,aAAa;KAAE,MAAM;KAAQ,OAAO,OAAO;IAAM,CAAC;IAClF,MAAM;KACJ,aAAa,MAAM;KACnB,UAAU,MAAM;KAChB,QAAQ;KACR;KACA,SAAS,KAAK,IAAI;IACpB,CAAC;GACH;EACF,SAAS,OAAO;GACd,IAAI,YAAY,CAAC,SAAS,IAAI,MAAM,WAAW,GAC7C;GAEF,OAAO,OAAO,cAAc,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,SAAS;EAC/F,UAAU;GACR,SAAS,OAAO,MAAM,WAAW;EACnC;CACF;CAEA,MAAM,MAAM,OAAO,UAA+C;EAChE,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,gBAAgB,QAAQ,cAAc,MAAM;EAClD,IAAI,eACF,OAAO,cAAc,OAAO,aAAa;EAG3C,IAAI,EADY,QAAQ,SAAS,CAAC,aAAa,EAAA,CAClC,SAAS,MAAM,QAAQ,GAAG;GACrC,OAAO,OAAO,oBAAoB,iCAAiC,MAAM,SAAS,IAAI,SAAS;GAC/F;EACF;EACA,MAAM,SAAU,MAAM,OAA4C;EAClE,IAAI,OAAO,WAAW,UAAU;GAC9B,OAAO,OAAO,iBAAiB,oCAAoC,SAAS;GAC5E;EACF;EAEA,MAAM,aAAa,IAAI,gBAAgB;EACvC,SAAS,IAAI,MAAM,aAAa,UAAU;EAC1C,MAAM;GAAE,aAAa,MAAM;GAAa,UAAU,MAAM;GAAU,QAAQ;GAAW;EAAU,CAAC;EAEhG,IAAI;GACF,MAAM,UAAU,MAAM,OAAO;GAC7B,MAAM,MAAM,QAAQ,UAAU,MAAM,OAAO;GAE3C,MAAM,YAAY,KAAK,IAAI,MAAM,QAAQ,aAAa,OAAO,mBAAmB,QAAQ,aAAa,GAAI;GACzG,MAAM,mBAAmB,KAAK,IAC5B,MAAM,QAAQ,oBAAoB,OAAO,mBACzC,QAAQ,oBAAoB,QAC9B;GAEA,MAAM,SAAS,QAAQ,UACnB,MAAM,QAAQ,QAAQ;IAAE;IAAQ;IAAK;IAAW;IAAkB,QAAQ,WAAW;GAAO,CAAC,IAC7F,OAAO,YAAY;IACjB,mBAAmB,QAAQ,cAAc,kBAAA,CAAmB;IAC5D,OAAO,QAAQ,UAAU,MAAM,eAAe;KAC5C;KACA;KACA;KACA;KACA,QAAQ,WAAW;KACnB,WAAW,QAAQ;IACrB,CAAC;GACH,EAAA,CAAG;GAEP,IAAI,YAAY,CAAC,SAAS,IAAI,MAAM,WAAW,GAC7C;GAEF,MAAM,OAAO,OAAO,KAAK,KAAK,MAAM,IAAI,EAAE,MAAM,IAAI,EAAE,MAAM;GAC5D,IAAI,OAAO,IAAI;IACb,OAAO,mBAAmB,MAAM,aAAa;KAAE,MAAM;KAAQ,OAAO,OAAO;IAAM,GAAG,IAAI;IACxF,MAAM;KACJ,aAAa,MAAM;KACnB,UAAU,MAAM;KAChB,QAAQ;KACR;KACA,SAAS,KAAK,IAAI;IACpB,CAAC;GACH,OAAO;IACL,OAAO,kBAAkB,MAAM,aAAa,OAAO,QAAQ,OAAO,OAAO,IAAI;IAC7E,MAAM;KACJ,aAAa,MAAM;KACnB,UAAU,MAAM;KAChB,QAAQ;KACR,QAAQ,OAAO;KACf;KACA,SAAS,KAAK,IAAI;IACpB,CAAC;GACH;EACF,SAAS,OAAO;GACd,IAAI,YAAY,CAAC,SAAS,IAAI,MAAM,WAAW,GAC7C;GAEF,OAAO,OAAO,cAAc,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,SAAS;EAC/F,UAAU;GACR,SAAS,OAAO,MAAM,WAAW;EACnC;CACF;CAEA,MAAM,aAAa,OAAO,GAAG,oBAAoB,UAAU,KAAK,IAAI,KAAK,CAAC;CAC1E,MAAM,YAAY,OAAO,GAAG,qBAAqB,EAAE,aAAa,aAAa;EAC3E,MAAM,aAAa,SAAS,IAAI,WAAW;EAC3C,IAAI,CAAC,YACH;EAEF,WAAW,MAAM;EACjB,SAAS,OAAO,WAAW;EAC3B,MAAM;GACJ;GACA,UAAU;GACV,QAAQ;GACR;GACA,WAAW,KAAK,IAAI;GACpB,SAAS,KAAK,IAAI;EACpB,CAAC;CACH,CAAC;CAED,OAAO,EACL,eAAe;EACb,WAAW;EACX,WAAW;EACX,UAAU;EACV,KAAK,MAAM,cAAc,SAAS,OAAO,GACvC,WAAW,MAAM;EAEnB,SAAS,MAAM;CACjB,EACF;AACF;AAEA,eAAe,oBAA4C;CACzD,MAAM,CAAC,SAAS,WAAW,MAAM,QAAQ,IAAI,CAAC,OAAO,wBAAwB,OAAO,oDAAoD,CAAC;CACzI,OAAO,QAAQ,WAAW,OAAgB;AAC5C;;;AC/MA,SAAgB,gBACd,QACA,UAAkC,CAAC,GACE;CACrC,MAAM,CAAC,YAAY,iBAAiB,SAA8B,CAAC,CAAC;CACpE,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CAErB,gBAAgB;EACd,IAAI,CAAC,UAAU,QAAQ,YAAY,OACjC;EAEF,MAAM,OAAO,mBAAmB,QAAQ;GAEtC,IAAI,QAAQ;IACV,MAAM,OAAO,WAAW,QAAQ;IAChC,MAAM,SAAS,WAAW,QAAQ;IAClC,IAAI,CAAC,QACH,OAAO;IAET,MAAM,cAAc,OAAO,KAAK,MAAM;IACtC,OAAO,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,IAAI;GAC1D;GACA,IAAI,cAAc;IAChB,OAAO,WAAW,QAAQ;GAC5B;GACA,IAAI,YAAY;IACd,OAAO,WAAW,QAAQ;GAC5B;GACA,IAAI,mBAAmB;IACrB,OAAO,WAAW,QAAQ;GAC5B;GACA,IAAI,aAAa;IACf,OAAO,WAAW,QAAQ;GAC5B;GACA,IAAI,UAAU;IACZ,OAAO,WAAW,QAAQ;GAC5B;GACA,IAAI,YAAY;IACd,OAAO,WAAW,QAAQ;GAC5B;GACA,cAAc,cAAc;IAC1B,WAAW,QAAQ,cAAc,SAAS;IAC1C,MAAM,QAAQ,WAAW,QAAQ,gBAAgB;IACjD,eAAe,SAAS,CAAC,GAAG,KAAK,QAAQ,MAAM,EAAE,gBAAgB,UAAU,WAAW,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;GACnH;EACF,CAAC;EACD,aAAa,KAAK,QAAQ;CAC5B,GAAG,CAAC,QAAQ,QAAQ,OAAO,CAAC;CAE5B,OAAO,EAAE,WAAW;AACtB;;;ACzCA,SAAgB,eAAe,OAAmB,WAAiC;CACjF,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,MAAM,MAAM,MAAM,CAAC;CACjE,MAAM,QAAQ,MAAM,MAAM,MAAM,KAAK;CACrC,MAAM,6BAAa,IAAI,IAAoB;CAC3C,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,IAAI,QAAQ;CACZ,IAAI,SAAS;CAEb,KAAK,MAAM,QAAQ,OACjB,QAAQ,KAAK,MAAb;EACE,KAAK;GACH,SAAS;GACT,IAAI,KAAK,SACP,UAAU;GAEZ;EAEF,KAAK;GACH,WAAW;GACX;EAEF,KAAK;GACH,SAAS;GACT,WAAW,IAAI,KAAK,OAAO,WAAW,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;GAC9D,IAAI,KAAK,WAAW,YAAY,KAAK,QAAQ,SAC3C,UAAU;GAEZ;EAEF,KAAK;GACH,SAAS;GACT;EAEF,KAAK,UACH,IAAI,KAAK,UAAU,SACjB,UAAU;CAOhB;CAGF,MAAM,YAAY,CAAC,GAAG,WAAW,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,IAAI;CACxH,MAAM,UAAU,MAAM,kBAAkB,UAAU;CAClD,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA,KAAK,QAAQ,UAAU,QAAQ,QAAQ,SAAS,UAAU;CAC5D;AACF;AAEA,SAAgB,UAAU,SAA2C;CACnE,IAAI,CAAC,QAAQ,KACX;CAEF,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ,QAAQ,GAClB,MAAM,KAAK,OAAO,QAAQ,OAAO,MAAM,CAAC;MACnC,IAAI,QAAQ,UAAU,GAC3B,MAAM,KAAK,OAAO,QAAQ,SAAS,SAAS,SAAS,CAAC;CAExD,IAAI,QAAQ,QAAQ,GAAG;EACrB,MAAM,QAAQ,QAAQ,UAAU,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI;EACrD,MAAM,OAAO,QAAQ,UAAU,SAAS;EACxC,MAAM,KAAK,GAAG,OAAO,QAAQ,OAAO,WAAW,IAAI,QAAQ,KAAK,QAAQ,OAAO,IAAI,MAAM,SAAS,GAAG,KAAK,IAAI;CAChH;CACA,IAAI,QAAQ,QAAQ,GAClB,MAAM,KAAK,OAAO,QAAQ,OAAO,MAAM,CAAC;CAE1C,IAAI,QAAQ,SAAS,GACnB,MAAM,KAAK,OAAO,QAAQ,QAAQ,OAAO,CAAC;CAE5C,IAAI,QAAQ,UAAU,GACpB,MAAM,KAAK,GAAG,OAAO,QAAQ,SAAS,UAAU,EAAE,SAAS;CAE7D,OAAO,MAAM,KAAK,KAAK;AACzB;AAEA,SAAS,OAAO,OAAe,KAAa,OAAO,GAAG,IAAI,IAAY;CACpE,OAAO,GAAG,MAAM,GAAG,UAAU,IAAI,MAAM;AACzC"}
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 ApiMessage,\n ChecklistItem,\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 kind: 'compaction'\n id: string\n parentToolUseId: string | null\n pending?: boolean\n trigger?: 'manual' | 'auto'\n preTokens?: number\n postTokens?: number\n error?: string\n }\n | { kind: 'file_delivered'; id: string; path: string; bytes: number; description?: string }\n\nexport type ProducedFileRef = {\n fileId: string\n mediaType?: string\n bytes?: number\n}\n\nexport type TranscriptState = {\n status: SessionStatus\n statusDetail?: string\n model?: string\n cwd?: string\n sdkSessionId?: string\n engine?: ProfileEngine\n capabilities: EngineCapabilities\n session?: SessionInfo\n models?: ModelOption[]\n commands?: SlashCommandInfo[]\n skills?: SkillInfo[]\n checklist?: ChecklistItem[]\n // Only what the client cannot derive: host- and MCP-declared titles. `toolTitle()` folds the\n // built-in table in on top of this.\n toolTitles?: Record<string, string>\n // Keyed by the absolute path the runner reported: a tool card looks up the `savedPath` in its input and resolves it via `client.producedFileUrl`.\n producedFiles?: Record<string, ProducedFileRef>\n\n defaultModel?: string\n permissionMode?: PermissionMode\n contextUsage?: ContextUsage\n rateLimits?: Record<string, RateLimitInfo>\n rateLimitsUpdatedAt?: number\n subscriptionType?: string\n items: TranscriptItem[]\n pendingApprovals: PermissionRequest[]\n totalCostUsd: number\n lastSeq: number\n}\n\nexport const initialTranscriptState: TranscriptState = {\n status: 'starting',\n capabilities: ENGINE_CAPABILITIES.claude,\n items: [],\n pendingApprovals: [],\n totalCostUsd: 0,\n lastSeq: 0,\n}\n\nconst STREAMING_ID = 'streaming'\nconst STREAMING_THINKING_ID = 'streaming-thinking'\n\nconst LOCAL_COMMAND_OUTPUT = /^<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>$/\nconst LOCAL_COMMAND_ELEMENT = /<local-command-(stdout|stderr)>([\\s\\S]*?)<\\/local-command-\\1>/g\nconst LOCAL_COMMAND_CAVEAT = '<local-command-caveat>'\n\nconst COMMAND_NAME = /<command-name>([\\s\\S]*?)<\\/command-name>/\nconst COMMAND_ARGS = /<command-args>([\\s\\S]*?)<\\/command-args>/\n// A message whose first text block is the deferred `!` flush is synthetic as a whole, but the block after it is\n// the person's own message. Only that shape earns the exemption - `<task-notification>` and the rest stay hidden.\nfunction carriesCaveat(content: ApiMessage['content']): boolean {\n return contentToBlocks(content).some(\n (block) => block.type === 'text' && (block as { text: string }).text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT),\n )\n}\n\nfunction streamingTextId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_ID : `${STREAMING_ID}:${parentToolUseId}`\n}\nfunction streamingThinkingId(parentToolUseId: string | null): string {\n return parentToolUseId == null ? STREAMING_THINKING_ID : `${STREAMING_THINKING_ID}:${parentToolUseId}`\n}\nfunction isStreamingItem(item: TranscriptItem): boolean {\n return (\n (item.kind === 'assistant_text' && item.id.startsWith(STREAMING_ID)) ||\n (item.kind === 'thinking' && item.id.startsWith(STREAMING_THINKING_ID))\n )\n}\n\nexport function blockText(content: ToolResultBlock['content']): string {\n if (content === undefined) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n return content\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n')\n}\n\nfunction imageRefsOf(content: ToolResultBlock['content'], seq: number): ReadonlyArray<ToolResultImageRef> | undefined {\n if (!Array.isArray(content)) {\n return undefined\n }\n const refs = content.flatMap((part) =>\n part.type === 'image_ref'\n ? [\n {\n partIndex: Number(part.part_index),\n mediaType: String(part.media_type ?? 'application/octet-stream'),\n bytes: Number(part.bytes ?? 0),\n sourceSeq: seq,\n },\n ]\n : [],\n )\n return refs.length > 0 ? refs : undefined\n}\n\nfunction contentToBlocks(content: string | ContentBlock[]): ContentBlock[] {\n return typeof content === 'string' ? [{ type: 'text', text: content }] : content\n}\n\nfunction outputText(output: ToolExecutionOutput): string {\n if (output.type === 'text') {\n return output.value\n }\n try {\n return JSON.stringify(output.value)\n } catch {\n return String(output.value)\n }\n}\n\nfunction slashCommandText(text: string): string | undefined {\n const name = COMMAND_NAME.exec(text)?.[1]?.trim()\n if (!name) {\n return undefined\n }\n const args = COMMAND_ARGS.exec(text)?.[1]?.trim()\n return args ? `${name} ${args}` : name\n}\n\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 'checklist': {\n return { ...base, checklist: event.items.length > 0 ? event.items : undefined }\n }\n\n case 'tool_titles': {\n return { ...base, toolTitles: { ...base.toolTitles, ...event.titles } }\n }\n\n case 'file_produced': {\n return {\n ...base,\n producedFiles: {\n ...base.producedFiles,\n [event.path]: {\n fileId: event.fileId,\n ...(event.mediaType ? { mediaType: event.mediaType } : {}),\n ...(event.bytes !== undefined ? { bytes: event.bytes } : {}),\n },\n },\n }\n }\n\n case 'model_changed': {\n return event.model === undefined ? base : { ...base, model: event.model }\n }\n\n case 'permission_mode_changed': {\n return { ...base, permissionMode: event.mode }\n }\n\n case 'context_usage': {\n return { ...base, contextUsage: event.usage }\n }\n\n case 'rate_limit': {\n const key = event.info.rateLimitType\n if (!key) {\n return base\n }\n return {\n ...base,\n rateLimits: { ...base.rateLimits, [key]: event.info },\n rateLimitsUpdatedAt: event.ts,\n }\n }\n\n case 'plan_info': {\n return { ...base, subscriptionType: event.subscriptionType }\n }\n\n case 'conversation_reset': {\n return {\n ...base,\n items: [],\n contextUsage: undefined,\n checklist: undefined,\n sdkSessionId: event.sdkSessionId ?? base.sdkSessionId,\n }\n }\n\n // Appends where the reset above empties, and leaves `contextUsage` alone: the engine reports post-compaction occupancy itself.\n case 'context_compacted': {\n return {\n ...base,\n items: upsert(base.items, {\n kind: 'compaction',\n id: event.uuid,\n parentToolUseId: event.parentToolUseId ?? null,\n pending: event.pending,\n trigger: event.trigger,\n preTokens: event.preTokens,\n postTokens: event.postTokens,\n error: event.error,\n }),\n }\n }\n\n case 'user_message': {\n let items = base.items\n for (const block of contentToBlocks(event.message.content)) {\n if (block.type === 'tool_result') {\n const toolResult = block as ToolResultBlock\n const isError = toolResult.is_error === true\n items = items.map((item) =>\n item.kind === 'tool_call' && item.id === toolResult.tool_use_id\n ? {\n ...item,\n status: isError ? 'failed' : 'settled',\n result: {\n text: blockText(toolResult.content),\n isError,\n ...(toolResult.truncated && {\n truncated: true as const,\n totalChars: toolResult.total_chars,\n sourceSeq: event.seq,\n }),\n ...(imageRefsOf(toolResult.content, event.seq) && {\n images: imageRefsOf(toolResult.content, event.seq),\n }),\n },\n ...(event.patch && { patch: event.patch }),\n }\n : item,\n )\n } else if (block.type === 'text') {\n const text = (block as { text: string }).text\n const rowId = event.uuid ?? `user-${event.seq}`\n // Both branches sit ahead of the synthetic guard on purpose. A `!` shell run is emitted synthetic so it\n // scores zero activity and zero prose, but it is the one synthetic message a person is meant to see; and\n // on resume the SDK hands back the shell output and the user's own text as one message, which\n // `isSyntheticUserText` then marks synthetic whole. Without this the user's own words vanish on reload.\n const localOutput = LOCAL_COMMAND_OUTPUT.exec(text.trim())\n if (localOutput) {\n items = upsert(items, {\n kind: 'notice',\n id: rowId,\n level: localOutput[1] === 'stderr' ? 'error' : 'info',\n text: localOutput[2].trim(),\n })\n } else if (text.trimStart().startsWith(LOCAL_COMMAND_CAVEAT)) {\n let index = 0\n for (const match of text.matchAll(LOCAL_COMMAND_ELEMENT)) {\n items = upsert(items, {\n kind: 'notice',\n id: `${rowId}#${index++}`,\n level: match[1] === 'stderr' ? 'error' : 'info',\n text: match[2].trim(),\n })\n }\n } else if (!event.synthetic || carriesCaveat(event.message.content)) {\n items = upsert(items, {\n kind: 'user',\n id: event.uuid ?? `user-${event.seq}`,\n text: slashCommandText(text) ?? text,\n attachments: event.attachments,\n ...(event.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 {\n applyEvent,\n blockText,\n initialTranscriptState,\n hydrateToolResult,\n seedFromSessionInfo,\n type TranscriptState,\n} from '../lib/transcript.ts'\nimport { deleteTranscriptCache, readTranscriptCache, transcriptCacheKey, writeTranscriptCache } from '../lib/transcript-cache.ts'\nimport { attachSeedToken, planAttach, shouldWriteParting } from '../lib/attach-plan.ts'\n\ntype SeedAction = { type: 'transcript_seed'; state: TranscriptState }\ntype HydrateAction = { type: 'transcript_hydrate_result'; toolUseId: string; text: string }\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 // The gateway offers `!` shell mode to this principal on this session. Absent from an older gateway, so falsy by default.\n shell: boolean\n models: ModelOption[]\n effectiveModel?: string\n handle: SessionHandle | undefined\n send: (text: string, attachmentIds?: string[]) => void\n approve: (requestId: string, updatedInput?: Record<string, unknown>) => void\n deny: (requestId: string, message?: string, interrupt?: boolean) => void\n interrupt: () => void\n clearContext: () => void\n runShell: (command: string) => void\n setPermissionMode: (mode: PermissionMode) => void\n setModel: (model?: string) => void\n closeSession: () => void\n reconnectNow: () => void\n loadFullResult: (toolUseId: string) => Promise<boolean>\n}\n\nexport function useClaudeSession(\n client: WorkerDeckClient,\n sessionId: string | undefined,\n options?: UseClaudeSessionOptions,\n): UseClaudeSessionResult {\n const [state, dispatch] = useReducer(\n reduce,\n undefined,\n (): TranscriptState =>\n (options?.cacheTranscript !== false && sessionId !== undefined\n ? readTranscriptCache(transcriptCacheKey(client, sessionId))\n : undefined) ?? initialTranscriptState,\n )\n const [connection, setConnection] = useState<ConnectionState>('reconnecting')\n const [protocolMismatch, setProtocolMismatch] = useState<number | undefined>()\n const [shell, setShell] = useState(false)\n const [replayTarget, setReplayTarget] = useState<number | undefined>()\n const [resyncSeq, setResyncSeq] = useState(0)\n // Ref for the stable callbacks below; state so consumers of `handle` re-render when the socket opens or the session switches.\n const [handleState, setHandleState] = useState<SessionHandle | undefined>()\n const handleRef = useRef<SessionHandle | null>(null)\n const optionsRef = useRef(options)\n optionsRef.current = options\n const stateRef = useRef(state)\n stateRef.current = state\n const seededForRef = useRef(attachSeedToken(0, sessionId === undefined ? '' : transcriptCacheKey(client, sessionId)))\n const skipCacheRef = useRef(false)\n\n useEffect(() => {\n if (!sessionId) {\n return\n }\n const cache = optionsRef.current?.cacheTranscript !== false\n const key = transcriptCacheKey(client, sessionId)\n const plan = planAttach({\n resyncSeq,\n key,\n seededFor: seededForRef.current,\n current: stateRef.current,\n cacheEnabled: cache,\n skipCache: skipCacheRef.current,\n warm: readTranscriptCache(key),\n })\n skipCacheRef.current = false\n if (plan.seed) {\n dispatch({ type: 'transcript_seed', state: plan.held })\n seededForRef.current = plan.seedToken\n }\n const handle = client.attach(sessionId, {\n truncateResults: true,\n imageRefs: true,\n ...(plan.afterSeq === undefined ? {} : { afterSeq: plan.afterSeq }),\n })\n handleRef.current = handle\n setHandleState(handle)\n const offEvent = handle.on('event', (event: SessionEvent) => dispatch(event))\n const offAttached = handle.on('attached', (frame: AttachedFrame) => {\n if (staleAttach(frame, stateRef.current)) {\n offEvent()\n deleteTranscriptCache(key)\n skipCacheRef.current = true\n setResyncSeq((n) => n + 1)\n return\n }\n dispatch(frame)\n setReplayTarget(initialReplayTarget(frame))\n setProtocolMismatch(frame.protocolVersion === PROTOCOL_VERSION ? undefined : frame.protocolVersion)\n setShell(frame.shell === true)\n })\n const offConn = handle.on('connectionChange', (open: boolean) => setConnection(open ? 'live' : 'reconnecting'))\n const offRetry = handle.on('reconnectAttempt', (attempts: number) =>\n setConnection(attempts >= OFFLINE_AFTER_ATTEMPTS ? 'offline' : 'reconnecting'),\n )\n const offProtocolError = handle.on('protocolError', (message: string) => {\n optionsRef.current?.onProtocolError?.(message)\n })\n return () => {\n offEvent()\n offAttached()\n offConn()\n offRetry()\n offProtocolError()\n handle.detach()\n handleRef.current = null\n setHandleState(undefined)\n setConnection('reconnecting')\n setProtocolMismatch(undefined)\n setShell(false)\n setReplayTarget(undefined)\n const parting = stateRef.current\n if (shouldWriteParting({ cacheEnabled: cache, skipCache: skipCacheRef.current, parting })) {\n writeTranscriptCache(key, parting)\n }\n }\n }, [client, sessionId, resyncSeq])\n\n useEffect(() => {\n if (replayTarget === undefined) {\n return\n }\n const timer = setTimeout(() => setReplayTarget(undefined), REPLAY_HOLD_MAX_MS)\n return () => clearTimeout(timer)\n }, [replayTarget])\n useEffect(() => {\n if (replayTarget !== undefined && state.lastSeq >= replayTarget) {\n setReplayTarget(undefined)\n }\n }, [replayTarget, state.lastSeq])\n\n const models = useProfileModelFallback(client, sessionId, state)\n\n const connected = connection === 'live'\n // Derived at render, not in an effect, so the reveal lands in the same commit as the replay's final event - an effect is one visible frame late.\n const replaying = replayTarget !== undefined && state.lastSeq < replayTarget\n const reconnectNow = useCallback(() => handleRef.current?.reconnectNow(), [])\n\n const loadFullResult = useCallback(\n async (toolUseId: string): Promise<boolean> => {\n if (!sessionId) {\n return false\n }\n const item = stateRef.current.items.find((candidate) => candidate.kind === 'tool_call' && candidate.id === toolUseId)\n const result = item?.kind === 'tool_call' ? item.result : undefined\n if (!result?.truncated || result.sourceSeq === undefined) {\n return false\n }\n try {\n const full = await client.toolResult(sessionId, result.sourceSeq, toolUseId)\n dispatch({ type: 'transcript_hydrate_result', toolUseId, text: blockText(full.content) })\n return true\n } catch {\n return false\n }\n },\n [client, sessionId],\n )\n\n return useMemo(\n () => ({\n state,\n connected,\n connection,\n replaying,\n protocolMismatch,\n shell,\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 runShell: (command) => handleRef.current?.runShell(command),\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, shell, 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// Last known profile usage, kept outside React so a session switch does not blank it.\n//\n// Usage belongs to the *account*, not the session, but it is fetched by a hook that lives inside the per-session\n// panel - so remounting that panel used to drop the authoritative reading to `undefined` for a whole round trip,\n// leaving only the newly-attached session's own replayed (and possibly days-old) numbers to render. That is the\n// \"switching sessions resets my weekly usage to 1%, then it catches up\" report.\n//\n// Keyed by client identity + profile because a different profile is a different account's plan, never a stale view\n// of this one. Same shape and reasoning as `transcript-cache.ts` next door.\nconst entries = new Map<string, ProfileUsage>()\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function profileUsageCacheKey(client: WorkerDeckClient, profile: string): string {\n return `${client.identityKey}\\u0000${profile}`\n}\n\nexport function readProfileUsageCache(key: string): ProfileUsage | undefined {\n return entries.get(key)\n}\n\nexport function writeProfileUsageCache(key: string, usage: ProfileUsage | undefined): void {\n if (usage === undefined) {\n return\n }\n entries.set(key, usage)\n}\n\nexport function clearProfileUsageCache(): void {\n entries.clear()\n}\n","import type { WorkerDeckClient } from '@workerdeck/client'\n\n// Unsent composer text, kept per session on the client that typed it.\n//\n// A draft is not session state: it never reaches the gateway and never syncs between clients. Two people looking at\n// one session are each mid-sentence in their own way, and a half-written prompt is not something either of them\n// asked to publish.\n//\n// It is persisted rather than merely held in memory because the two ways drafts got lost are different failures. A\n// session switch remounts the composer, which a module-scope map alone would survive; a Vite HMR reload or a VS Code\n// `dev:host` webview re-render replaces the whole document, which it would not.\nconst KEY = 'workerdeck.drafts.v1'\n\n// Drafts are a convenience, so the store stays small and drops the least recently touched first.\nconst MAX_DRAFTS = 20\n\ntype Draft = { text: string; savedAt: number }\n\nlet memory: Record<string, Draft> | undefined\n\nfunction storage(): Storage | undefined {\n try {\n // Through globalThis: this package is typechecked with no DOM lib, and a webview may deny storage outright.\n return (globalThis as { localStorage?: Storage }).localStorage\n } catch {\n return undefined\n }\n}\n\nfunction load(): Record<string, Draft> {\n if (memory) {\n return memory\n }\n memory = {}\n const raw = storage()?.getItem(KEY)\n if (raw) {\n try {\n const parsed = JSON.parse(raw) as Record<string, Draft>\n for (const [key, draft] of Object.entries(parsed)) {\n if (typeof draft?.text === 'string' && typeof draft.savedAt === 'number') {\n memory[key] = draft\n }\n }\n } catch {\n // A corrupt blob is not worth a broken composer; start over.\n }\n }\n return memory\n}\n\nfunction persist(drafts: Record<string, Draft>): void {\n const entries = Object.entries(drafts)\n if (entries.length > MAX_DRAFTS) {\n entries.sort((a, b) => b[1].savedAt - a[1].savedAt)\n for (const [key] of entries.slice(MAX_DRAFTS)) {\n delete drafts[key]\n }\n }\n try {\n storage()?.setItem(KEY, JSON.stringify(drafts))\n } catch {\n // Out of quota, or storage denied. The in-memory copy still carries the session switch.\n }\n}\n\n// NUL separates unambiguously: `identityKey` is JSON.stringify output, so no two pairs spell one key.\nexport function draftKey(client: WorkerDeckClient, sessionId: string): string {\n return `${client.identityKey}\\u0000${sessionId}`\n}\n\nexport function readDraft(key: string): string {\n return load()[key]?.text ?? ''\n}\n\nexport function writeDraft(key: string, text: string, now = Date.now()): void {\n const drafts = load()\n // An empty draft is the absence of one: keeping it would evict a real draft under the cap.\n if (text.trim() === '') {\n if (drafts[key] === undefined) {\n return\n }\n delete drafts[key]\n } else {\n drafts[key] = { text, savedAt: now }\n }\n persist(drafts)\n}\n\nexport function clearDrafts(): void {\n memory = {}\n try {\n storage()?.removeItem(KEY)\n } catch {}\n}\n","import { 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// Remember unsent composer text for a session. Purely local: it never reaches the gateway and never syncs between\n// clients, because a half-written prompt is not something anyone asked to publish.\nexport function useDraft(client: WorkerDeckClient, sessionId: string | undefined): UseDraftResult {\n const key = sessionId ? draftKey(client, sessionId) : undefined\n // Read once per key: re-reading on render would fight whatever is being typed.\n const initialText = useMemo(() => (key ? readDraft(key) : ''), [key])\n const save = useCallback(\n (text: string) => {\n if (key) {\n writeDraft(key, text)\n }\n },\n [key],\n )\n const clear = useCallback(() => {\n if (key) {\n writeDraft(key, '')\n }\n }, [key])\n return { initialText, save, clear }\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport type { WorkerDeckClient } from '@workerdeck/client'\nimport { isRouteUnsupported, useAliveRef } from '../lib/async-guards.ts'\nimport { profileUsageCacheKey, readProfileUsageCache, writeProfileUsageCache } from '../lib/profile-usage-cache.ts'\nimport type { 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,8 +1,8 @@
1
1
  {
2
2
  "name": "@workerdeck/react",
3
- "version": "2.7.1",
3
+ "version": "2.8.0",
4
4
  "type": "module",
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.",
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",
7
7
  "main": "./build/index.mjs",
8
8
  "types": "./build/index.d.mts",
@@ -17,9 +17,9 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@workerdeck/sandbox": "2.7.1",
21
- "@workerdeck/client": "2.7.1",
22
- "@workerdeck/protocol": "2.7.1"
20
+ "@workerdeck/client": "2.8.0",
21
+ "@workerdeck/protocol": "2.8.0",
22
+ "@workerdeck/sandbox": "2.8.0"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "@jitl/quickjs-singlefile-browser-release-asyncify": "^0.31.0",
@@ -33,16 +33,16 @@
33
33
  "devDependencies": {
34
34
  "@jitl/quickjs-ng-wasmfile-release-asyncify": "^0.31.0",
35
35
  "@jitl/quickjs-singlefile-browser-release-asyncify": "^0.31.0",
36
- "@types/node": "^26.4.0",
37
- "@types/react": "^19.2.18",
36
+ "@types/node": "^26.6.1",
37
+ "@types/react": "^19.3.0",
38
38
  "@types/ws": "^8.18.1",
39
- "react": "^19.2.8",
39
+ "react": "^19.3.0",
40
40
  "rimraf": "^6.1.3",
41
41
  "tsdown": "^0.22.14",
42
42
  "vitest": "^4.1.11",
43
43
  "ws": "^8.21.3",
44
- "@workerdeck/core": "2.7.1",
45
- "@workerdeck/server": "2.7.1"
44
+ "@workerdeck/core": "2.8.0",
45
+ "@workerdeck/server": "2.8.0"
46
46
  },
47
47
  "author": "Tobias Strebitzer",
48
48
  "repository": {