@av-pi-studio/web-client 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/web/assets/{BinaryFallbackViewer-D45LvgRU.js → BinaryFallbackViewer-HicqzbWd.js} +2 -2
  3. package/dist/web/assets/{BinaryFallbackViewer-D45LvgRU.js.map → BinaryFallbackViewer-HicqzbWd.js.map} +1 -1
  4. package/dist/web/assets/ChatPanel-CTnpkb2U.css +1 -0
  5. package/dist/web/assets/ChatPanel-XI36Imum.js +3 -0
  6. package/dist/web/assets/ChatPanel-XI36Imum.js.map +1 -0
  7. package/dist/web/assets/{CodeView-DKjlpq-m.js → CodeView-z3x4ATgx.js} +2 -2
  8. package/dist/web/assets/{CodeView-DKjlpq-m.js.map → CodeView-z3x4ATgx.js.map} +1 -1
  9. package/dist/web/assets/{FilePanel-CGmR13VT.js → FilePanel-VOhIehHw.js} +3 -3
  10. package/dist/web/assets/{FilePanel-CGmR13VT.js.map → FilePanel-VOhIehHw.js.map} +1 -1
  11. package/dist/web/assets/{ImageViewer-g8uyibCK.js → ImageViewer-BivcSG2D.js} +2 -2
  12. package/dist/web/assets/{ImageViewer-g8uyibCK.js.map → ImageViewer-BivcSG2D.js.map} +1 -1
  13. package/dist/web/assets/{MarkdownFileViewer-Cjch4tHP.js → MarkdownFileViewer-CcfSk7Qc.js} +2 -2
  14. package/dist/web/assets/{MarkdownFileViewer-Cjch4tHP.js.map → MarkdownFileViewer-CcfSk7Qc.js.map} +1 -1
  15. package/dist/web/assets/{TerminalPanel-D21QoVnF.js → TerminalPanel-KNfHGYYL.js} +2 -2
  16. package/dist/web/assets/{TerminalPanel-D21QoVnF.js.map → TerminalPanel-KNfHGYYL.js.map} +1 -1
  17. package/dist/web/assets/{TextViewer-BVDA29H4.js → TextViewer-DlvdoBEv.js} +2 -2
  18. package/dist/web/assets/{TextViewer-BVDA29H4.js.map → TextViewer-DlvdoBEv.js.map} +1 -1
  19. package/dist/web/assets/{VideoViewer-Bj8wu5hl.js → VideoViewer-BmTmnaOQ.js} +2 -2
  20. package/dist/web/assets/{VideoViewer-Bj8wu5hl.js.map → VideoViewer-BmTmnaOQ.js.map} +1 -1
  21. package/dist/web/assets/index-C5SpA_B-.js +3 -0
  22. package/dist/web/assets/index-C5SpA_B-.js.map +1 -0
  23. package/dist/web/assets/{index-ZP_-GPM5.css → index-D_2xgUa4.css} +1 -1
  24. package/dist/web/assets/{use-file-download-B8_UiD_5.js → use-file-download-t12JJGKT.js} +2 -2
  25. package/dist/web/assets/{use-file-download-B8_UiD_5.js.map → use-file-download-t12JJGKT.js.map} +1 -1
  26. package/dist/web/assets/{vendor-icons-DwowToH7.js → vendor-icons-BouiMPVM.js} +72 -37
  27. package/dist/web/assets/vendor-icons-BouiMPVM.js.map +1 -0
  28. package/dist/web/index.html +3 -3
  29. package/package.json +3 -3
  30. package/dist/web/assets/ChatPanel-CG_Yz_QI.js +0 -3
  31. package/dist/web/assets/ChatPanel-CG_Yz_QI.js.map +0 -1
  32. package/dist/web/assets/ChatPanel-Cz7YoXXW.css +0 -1
  33. package/dist/web/assets/index-CM7PrEq0.js +0 -3
  34. package/dist/web/assets/index-CM7PrEq0.js.map +0 -1
  35. package/dist/web/assets/vendor-icons-DwowToH7.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TerminalPanel-D21QoVnF.js","sources":["../../../../client/src/terminal-stream-router.ts","../../../src/features/terminal/TerminalPanel.tsx"],"sourcesContent":["import { encodeTerminalFrame, type TerminalFrame } from \"@av-pi-studio/protocol\";\n\nimport type { DaemonClient } from \"./daemon-client.js\";\n\n/**\n * Client-side demux of binary terminal frames to per-slot subscribers, plus outbound input/resize\n * encoding (architecture/client-app-runtime.md § Router; features/terminals.md § Binary stream\n * protocol).\n *\n * Inbound `Output`/`Snapshot`/`Restore` frames are dispatched to the subscriber registered for that\n * `slot`. Outbound `Input`/`Resize` are encoded with the right opcode + slot and sent on the data\n * path.\n */\n\nexport interface TerminalSlotSubscriber {\n /** Live terminal output bytes. */\n onOutput?: (data: Uint8Array) => void;\n /** Full-screen snapshot bytes (sent on (re)subscribe). */\n onSnapshot?: (data: Uint8Array) => void;\n /** Restore snapshot bytes (reflowable/mode-gated). */\n onRestore?: (data: Uint8Array) => void;\n}\n\nexport class TerminalStreamRouter {\n private readonly subscribers = new Map<number, TerminalSlotSubscriber>();\n private detach: (() => void) | null = null;\n\n constructor(private readonly daemon: DaemonClient) {}\n\n /** Begin routing inbound terminal frames. Idempotent. */\n start(): void {\n if (this.detach) return;\n this.detach = this.daemon.onTerminalFrame((frame) => this.dispatch(frame));\n }\n\n /** Stop routing inbound frames (subscribers retained). */\n stop(): void {\n this.detach?.();\n this.detach = null;\n }\n\n /** Register (or replace) the subscriber for a slot. Returns an unsubscribe fn. */\n subscribeSlot(slot: number, subscriber: TerminalSlotSubscriber): () => void {\n this.subscribers.set(slot, subscriber);\n return () => {\n if (this.subscribers.get(slot) === subscriber) this.subscribers.delete(slot);\n };\n }\n\n /** True iff a subscriber is registered for the slot. */\n hasSlot(slot: number): boolean {\n return this.subscribers.has(slot);\n }\n\n // ─── Outbound ─────────────────────────────────────────────────────────────\n\n /** Send raw input bytes to a slot's PTY (opcode `Input = 0x02`). */\n sendInput(slot: number, data: Uint8Array): void {\n this.daemon.sendBinary(encodeTerminalFrame({ opcode: \"Input\", slot, data }));\n }\n\n /** Send a resize (opcode `Resize = 0x03`, JSON `{ rows, cols }` payload). */\n sendResize(slot: number, rows: number, cols: number): void {\n this.daemon.sendBinary(encodeTerminalFrame({ opcode: \"Resize\", slot, rows, cols }));\n }\n\n // ─── Inbound dispatch ───────────────────────────────────────────────────────\n\n private dispatch(frame: TerminalFrame): void {\n const subscriber = this.subscribers.get(frame.slot);\n if (!subscriber) return; // no subscriber for this slot — drop\n switch (frame.opcode) {\n case \"Output\":\n subscriber.onOutput?.(frame.data);\n return;\n case \"Snapshot\":\n subscriber.onSnapshot?.(frame.data);\n return;\n case \"Restore\":\n subscriber.onRestore?.(frame.data);\n return;\n default:\n // Input/Resize are outbound-only; ignore if echoed back.\n return;\n }\n }\n}\n","/**\n * TerminalPanel — @xterm/xterm mount + binary-frame streaming via `TerminalStreamRouter`\n * (POC `initTerminalPanel`, POC_TO_APP_PLAN_UI.md §4.6). Strict upgrade over the POC's 800ms\n * `capture_terminal_request` poll: the daemon pushes `Output`/`Snapshot`/`Restore` binary frames\n * directly over the one shared `DaemonClient` connection, demuxed by slot.\n *\n * Slot lifecycle: created once via `create_terminal_request`, then persisted onto the tab's\n * `TerminalTabData.slot` via `useTabStore.getState().updateData` so switching away and back to\n * this tab (kept mounted-but-hidden by `TabPanelHost`) never recreates the terminal. `TabPanelHost`\n * only unmounts a tab's panel when the tab leaves the store's `tabs[]` (i.e. real tab close, never\n * a tab switch) — this component's true-unmount effect below relies on exactly that invariant to\n * send `kill_terminal_request`, terminating the PTY server-side instead of leaking it forever.\n */\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Terminal } from \"@xterm/xterm\";\nimport { FitAddon } from \"@xterm/addon-fit\";\nimport \"@xterm/xterm/css/xterm.css\";\nimport type { DaemonClient } from \"@av-pi-studio/client\";\nimport { TerminalStreamRouter } from \"@av-pi-studio/client\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\nimport { useTabStore } from \"@pi-studio-ui/stores/tab-store.js\";\nimport type { Tab, TerminalTabData } from \"@pi-studio-ui/stores/tab-store.js\";\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport styles from \"./TerminalPanel.module.css\";\n\nexport interface TerminalPanelProps {\n tab: Tab;\n}\n\ninterface CreateTerminalResponse {\n terminal: { slot: number };\n}\n\n// One TerminalStreamRouter per daemon connection — multiple terminal tabs share it rather than\n// each opening its own frame demuxer over the same socket.\nconst routerByDaemon = new WeakMap<DaemonClient, TerminalStreamRouter>();\n\nfunction routerFor(daemon: DaemonClient): TerminalStreamRouter {\n let router = routerByDaemon.get(daemon);\n if (!router) {\n router = new TerminalStreamRouter(daemon);\n router.start();\n routerByDaemon.set(daemon, router);\n }\n return router;\n}\n\n/** Dark palette matching the app's github-dark-ish default theme (theme/variants.ts \"dark\"). */\nconst TERMINAL_THEME = {\n background: \"#181b1a\",\n foreground: \"#fafafa\",\n cursor: \"#a2b4d7\",\n cursorAccent: \"#181b1a\",\n selectionBackground: \"rgba(255,255,255,0.18)\",\n black: \"#18181b\",\n red: \"#ef4444\",\n green: \"#22c55e\",\n yellow: \"#f59e0b\",\n blue: \"#3b82f6\",\n magenta: \"#a855f7\",\n cyan: \"#14b8a6\",\n white: \"#d4d4d8\",\n brightBlack: \"#52525b\",\n brightRed: \"#f87171\",\n brightGreen: \"#4ade80\",\n brightYellow: \"#fbbf24\",\n brightBlue: \"#60a5fa\",\n brightMagenta: \"#c084fc\",\n brightCyan: \"#2dd4bf\",\n brightWhite: \"#fafafa\",\n};\n\nexport function TerminalPanel({ tab }: TerminalPanelProps) {\n const data = tab.data as TerminalTabData;\n const client = useConnectionStore((s) => s.client);\n const activeTabId = useTabStore((s) => s.activeTabId);\n const isActive = activeTabId === tab.id;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const terminalRef = useRef<Terminal | null>(null);\n const fitAddonRef = useRef<FitAddon | null>(null);\n const slotRef = useRef<number | null>(data.slot);\n // Mirrors `use-checkout-status.ts`'s convention: kept in sync every render so the unmount-only\n // kill effect below always sends the CURRENT client, never a stale mount-time closure (e.g.\n // after a reconnect swaps in a new `PiStudioClient` instance).\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const [slot, setSlot] = useState<number | null>(data.slot);\n const [error, setError] = useState<string | null>(null);\n\n // ─── Slot lifecycle: create once, persist onto the tab so re-opening reuses it ─────────────\n // React StrictMode double-invokes effects in dev: mount → cleanup → remount, synchronously,\n // on the SAME component instance (refs/state persist across all three phases — this is not\n // three separate mounts). Two things must hold across that: (1) the request fires exactly\n // once, and (2) whether to APPLY the eventual response is decided by whether the component is\n // mounted at RESPONSE time, not by a flag captured at REQUEST time.\n //\n // `requestStartedRef` gives (1): set the instant the request fires and never reset, so the\n // phantom-mount's cleanup-then-remount sees it's already in flight and never fires a second\n // `create_terminal_request` (this is what previously spawned two real PTYs from one Ctrl+T).\n //\n // `isMountedRef` gives (2): flipped true at the START of every effect invocation and false in\n // every cleanup, so it always reflects the LATEST phase. StrictMode's remount happens\n // synchronously, before the request's promise can possibly settle, so by response time\n // `isMountedRef.current` is back to `true` for a StrictMode phantom (correctly applies the\n // slot) — but stays `false` for a genuine fast real close (correctly kills the orphaned PTY\n // instead of leaking it or, as the previous buggy version did, killing a terminal that was\n // never actually torn down).\n const isMountedRef = useRef(false);\n const requestStartedRef = useRef(false);\n useEffect(() => {\n isMountedRef.current = true;\n if (!client || slotRef.current !== null || requestStartedRef.current) {\n return () => {\n isMountedRef.current = false;\n };\n }\n requestStartedRef.current = true;\n\n const cwd = data.cwd || \"~\";\n\n void client.connection\n .request<CreateTerminalResponse>(\"create_terminal_request\", { workspaceId: \"\", cwd })\n .then((res) => {\n const created = res.terminal.slot;\n if (!isMountedRef.current) {\n // A real close happened with no remount after it — kill the PTY that finished\n // spawning after the tab was already gone, instead of leaking it.\n void client.connection.request(\"kill_terminal_request\", { slot: created }).catch(() => {});\n return;\n }\n slotRef.current = created;\n setSlot(created);\n useTabStore.getState().updateData(tab.id, { slot: created });\n })\n .catch((err: unknown) => {\n if (!isMountedRef.current) return;\n setError(err instanceof Error ? err.message : String(err));\n })\n .finally(() => {\n // Reset only after the promise settles — by then StrictMode's synchronous\n // mount→cleanup→remount window has long passed, so this can never reopen the\n // double-fire race. It DOES allow a legitimate retry (e.g. `client` changed because of\n // a reconnect after the first attempt failed) instead of leaving the tab stuck forever.\n requestStartedRef.current = false;\n });\n\n return () => {\n isMountedRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, tab.id]);\n\n // ─── True unmount only: kill the PTY server-side ───────────────────────────────────────────\n // Runs its cleanup exactly once, when this component itself unmounts (real tab close, per\n // `TabPanelHost`'s \"hidden but alive\" model — a tab switch never unmounts). An empty deps array\n // means React never re-runs the effect body itself; only the cleanup fires, and only on\n // unmount, so this never races the slot-creation effect above or double-kills on a client\n // change. Without this, every closed terminal tab leaked its PTY process forever.\n //\n // For a REATTACH (this tab opened with a non-null `data.slot` from the very first render —\n // `use-terminal-restore.ts`, or the create-effect above once it has resolved) `slotRef.current`\n // is non-null from the start, so StrictMode's synchronous mount→cleanup→remount phantom cycle\n // would fire this cleanup and kill the PTY immediately on mount — unlike a freshly created\n // terminal, where `slotRef.current` is still `null` during that same phantom window (see the\n // create-effect's own comment) and so never hits this path. Deferred via `setTimeout`, exactly\n // like the create-effect's response handler: by the time it fires, StrictMode's remount has\n // already flipped `isMountedRef` back to `true` if this was a phantom unmount, so the kill is\n // skipped; a genuine close never remounts, so `isMountedRef` stays `false` and the kill proceeds.\n useEffect(() => {\n return () => {\n const currentSlot = slotRef.current;\n if (currentSlot === null) return;\n setTimeout(() => {\n if (isMountedRef.current) return; // StrictMode remounted synchronously — not a real close\n void clientRef.current?.connection\n .request(\"kill_terminal_request\", { slot: currentSlot })\n .catch(() => {});\n }, 0);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ─── xterm mount (once slot + container are ready) ─────────────────────────────────────────\n useEffect(() => {\n if (!client || slot === null || !containerRef.current) return;\n\n const terminal = new Terminal({\n cursorBlink: true,\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',\n fontSize: 13,\n scrollback: 5000,\n theme: TERMINAL_THEME,\n allowProposedApi: true,\n });\n const fitAddon = new FitAddon();\n terminal.loadAddon(fitAddon);\n terminal.open(containerRef.current);\n fitAddon.fit();\n\n terminalRef.current = terminal;\n fitAddonRef.current = fitAddon;\n\n const router = routerFor(client.connection);\n const unsubscribeSlot = router.subscribeSlot(slot, {\n onOutput: (chunk) => terminal.write(chunk),\n onSnapshot: (chunk) => {\n terminal.clear();\n terminal.write(chunk);\n },\n onRestore: (chunk) => terminal.write(chunk),\n });\n\n void client.connection.request(\"subscribe_terminal_request\", { slot }).catch((err: unknown) => {\n setError(err instanceof Error ? err.message : String(err));\n });\n\n const dataDisposable = terminal.onData((chunk) => {\n router.sendInput(slot, new TextEncoder().encode(chunk));\n });\n const resizeDisposable = terminal.onResize(({ cols, rows }) => {\n router.sendResize(slot, rows, cols);\n });\n\n const resizeObserver = new ResizeObserver(() => {\n fitAddon.fit();\n });\n resizeObserver.observe(containerRef.current);\n\n return () => {\n resizeObserver.disconnect();\n dataDisposable.dispose();\n resizeDisposable.dispose();\n unsubscribeSlot();\n void client.connection.request(\"unsubscribe_terminal_request\", { slot }).catch(() => {});\n terminal.dispose();\n terminalRef.current = null;\n fitAddonRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slot]);\n\n // ─── Re-fit whenever this tab becomes the active (visible) one ────────────────────────────\n useEffect(() => {\n if (!isActive) return;\n fitAddonRef.current?.fit();\n }, [isActive]);\n\n if (error) {\n return (\n <div className={styles.wrap}>\n <div className={styles.status}>Terminal error: {error}</div>\n </div>\n );\n }\n\n if (slot === null) {\n return (\n <div className={styles.wrap}>\n <div className={styles.status}>\n <Spinner size=\"sm\" /> Starting terminal…\n </div>\n </div>\n );\n }\n\n return (\n <div className={styles.wrap}>\n <div ref={containerRef} className={styles.terminal} />\n </div>\n );\n}\n"],"names":["TerminalStreamRouter","daemon","__publicField","frame","_a","slot","subscriber","data","encodeTerminalFrame","rows","cols","_b","_c","routerByDaemon","routerFor","router","TERMINAL_THEME","TerminalPanel","tab","client","useConnectionStore","s","isActive","useTabStore","containerRef","useRef","terminalRef","fitAddonRef","slotRef","clientRef","setSlot","useState","error","setError","isMountedRef","requestStartedRef","useEffect","cwd","res","created","err","currentSlot","terminal","Terminal","fitAddon","FitAddon","unsubscribeSlot","chunk","dataDisposable","resizeDisposable","resizeObserver","jsx","styles","jsxs","Spinner"],"mappings":"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"}
1
+ {"version":3,"file":"TerminalPanel-KNfHGYYL.js","sources":["../../../../client/src/terminal-stream-router.ts","../../../src/features/terminal/TerminalPanel.tsx"],"sourcesContent":["import { encodeTerminalFrame, type TerminalFrame } from \"@av-pi-studio/protocol\";\n\nimport type { DaemonClient } from \"./daemon-client.js\";\n\n/**\n * Client-side demux of binary terminal frames to per-slot subscribers, plus outbound input/resize\n * encoding (architecture/client-app-runtime.md § Router; features/terminals.md § Binary stream\n * protocol).\n *\n * Inbound `Output`/`Snapshot`/`Restore` frames are dispatched to the subscriber registered for that\n * `slot`. Outbound `Input`/`Resize` are encoded with the right opcode + slot and sent on the data\n * path.\n */\n\nexport interface TerminalSlotSubscriber {\n /** Live terminal output bytes. */\n onOutput?: (data: Uint8Array) => void;\n /** Full-screen snapshot bytes (sent on (re)subscribe). */\n onSnapshot?: (data: Uint8Array) => void;\n /** Restore snapshot bytes (reflowable/mode-gated). */\n onRestore?: (data: Uint8Array) => void;\n}\n\nexport class TerminalStreamRouter {\n private readonly subscribers = new Map<number, TerminalSlotSubscriber>();\n private detach: (() => void) | null = null;\n\n constructor(private readonly daemon: DaemonClient) {}\n\n /** Begin routing inbound terminal frames. Idempotent. */\n start(): void {\n if (this.detach) return;\n this.detach = this.daemon.onTerminalFrame((frame) => this.dispatch(frame));\n }\n\n /** Stop routing inbound frames (subscribers retained). */\n stop(): void {\n this.detach?.();\n this.detach = null;\n }\n\n /** Register (or replace) the subscriber for a slot. Returns an unsubscribe fn. */\n subscribeSlot(slot: number, subscriber: TerminalSlotSubscriber): () => void {\n this.subscribers.set(slot, subscriber);\n return () => {\n if (this.subscribers.get(slot) === subscriber) this.subscribers.delete(slot);\n };\n }\n\n /** True iff a subscriber is registered for the slot. */\n hasSlot(slot: number): boolean {\n return this.subscribers.has(slot);\n }\n\n // ─── Outbound ─────────────────────────────────────────────────────────────\n\n /** Send raw input bytes to a slot's PTY (opcode `Input = 0x02`). */\n sendInput(slot: number, data: Uint8Array): void {\n this.daemon.sendBinary(encodeTerminalFrame({ opcode: \"Input\", slot, data }));\n }\n\n /** Send a resize (opcode `Resize = 0x03`, JSON `{ rows, cols }` payload). */\n sendResize(slot: number, rows: number, cols: number): void {\n this.daemon.sendBinary(encodeTerminalFrame({ opcode: \"Resize\", slot, rows, cols }));\n }\n\n // ─── Inbound dispatch ───────────────────────────────────────────────────────\n\n private dispatch(frame: TerminalFrame): void {\n const subscriber = this.subscribers.get(frame.slot);\n if (!subscriber) return; // no subscriber for this slot — drop\n switch (frame.opcode) {\n case \"Output\":\n subscriber.onOutput?.(frame.data);\n return;\n case \"Snapshot\":\n subscriber.onSnapshot?.(frame.data);\n return;\n case \"Restore\":\n subscriber.onRestore?.(frame.data);\n return;\n default:\n // Input/Resize are outbound-only; ignore if echoed back.\n return;\n }\n }\n}\n","/**\n * TerminalPanel — @xterm/xterm mount + binary-frame streaming via `TerminalStreamRouter`\n * (POC `initTerminalPanel`, POC_TO_APP_PLAN_UI.md §4.6). Strict upgrade over the POC's 800ms\n * `capture_terminal_request` poll: the daemon pushes `Output`/`Snapshot`/`Restore` binary frames\n * directly over the one shared `DaemonClient` connection, demuxed by slot.\n *\n * Slot lifecycle: created once via `create_terminal_request`, then persisted onto the tab's\n * `TerminalTabData.slot` via `useTabStore.getState().updateData` so switching away and back to\n * this tab (kept mounted-but-hidden by `TabPanelHost`) never recreates the terminal. `TabPanelHost`\n * only unmounts a tab's panel when the tab leaves the store's `tabs[]` (i.e. real tab close, never\n * a tab switch) — this component's true-unmount effect below relies on exactly that invariant to\n * send `kill_terminal_request`, terminating the PTY server-side instead of leaking it forever.\n */\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Terminal } from \"@xterm/xterm\";\nimport { FitAddon } from \"@xterm/addon-fit\";\nimport \"@xterm/xterm/css/xterm.css\";\nimport type { DaemonClient } from \"@av-pi-studio/client\";\nimport { TerminalStreamRouter } from \"@av-pi-studio/client\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\nimport { useTabStore } from \"@pi-studio-ui/stores/tab-store.js\";\nimport type { Tab, TerminalTabData } from \"@pi-studio-ui/stores/tab-store.js\";\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport styles from \"./TerminalPanel.module.css\";\n\nexport interface TerminalPanelProps {\n tab: Tab;\n}\n\ninterface CreateTerminalResponse {\n terminal: { slot: number };\n}\n\n// One TerminalStreamRouter per daemon connection — multiple terminal tabs share it rather than\n// each opening its own frame demuxer over the same socket.\nconst routerByDaemon = new WeakMap<DaemonClient, TerminalStreamRouter>();\n\nfunction routerFor(daemon: DaemonClient): TerminalStreamRouter {\n let router = routerByDaemon.get(daemon);\n if (!router) {\n router = new TerminalStreamRouter(daemon);\n router.start();\n routerByDaemon.set(daemon, router);\n }\n return router;\n}\n\n/** Dark palette matching the app's github-dark-ish default theme (theme/variants.ts \"dark\"). */\nconst TERMINAL_THEME = {\n background: \"#181b1a\",\n foreground: \"#fafafa\",\n cursor: \"#a2b4d7\",\n cursorAccent: \"#181b1a\",\n selectionBackground: \"rgba(255,255,255,0.18)\",\n black: \"#18181b\",\n red: \"#ef4444\",\n green: \"#22c55e\",\n yellow: \"#f59e0b\",\n blue: \"#3b82f6\",\n magenta: \"#a855f7\",\n cyan: \"#14b8a6\",\n white: \"#d4d4d8\",\n brightBlack: \"#52525b\",\n brightRed: \"#f87171\",\n brightGreen: \"#4ade80\",\n brightYellow: \"#fbbf24\",\n brightBlue: \"#60a5fa\",\n brightMagenta: \"#c084fc\",\n brightCyan: \"#2dd4bf\",\n brightWhite: \"#fafafa\",\n};\n\nexport function TerminalPanel({ tab }: TerminalPanelProps) {\n const data = tab.data as TerminalTabData;\n const client = useConnectionStore((s) => s.client);\n const activeTabId = useTabStore((s) => s.activeTabId);\n const isActive = activeTabId === tab.id;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const terminalRef = useRef<Terminal | null>(null);\n const fitAddonRef = useRef<FitAddon | null>(null);\n const slotRef = useRef<number | null>(data.slot);\n // Mirrors `use-checkout-status.ts`'s convention: kept in sync every render so the unmount-only\n // kill effect below always sends the CURRENT client, never a stale mount-time closure (e.g.\n // after a reconnect swaps in a new `PiStudioClient` instance).\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const [slot, setSlot] = useState<number | null>(data.slot);\n const [error, setError] = useState<string | null>(null);\n\n // ─── Slot lifecycle: create once, persist onto the tab so re-opening reuses it ─────────────\n // React StrictMode double-invokes effects in dev: mount → cleanup → remount, synchronously,\n // on the SAME component instance (refs/state persist across all three phases — this is not\n // three separate mounts). Two things must hold across that: (1) the request fires exactly\n // once, and (2) whether to APPLY the eventual response is decided by whether the component is\n // mounted at RESPONSE time, not by a flag captured at REQUEST time.\n //\n // `requestStartedRef` gives (1): set the instant the request fires and never reset, so the\n // phantom-mount's cleanup-then-remount sees it's already in flight and never fires a second\n // `create_terminal_request` (this is what previously spawned two real PTYs from one Ctrl+T).\n //\n // `isMountedRef` gives (2): flipped true at the START of every effect invocation and false in\n // every cleanup, so it always reflects the LATEST phase. StrictMode's remount happens\n // synchronously, before the request's promise can possibly settle, so by response time\n // `isMountedRef.current` is back to `true` for a StrictMode phantom (correctly applies the\n // slot) — but stays `false` for a genuine fast real close (correctly kills the orphaned PTY\n // instead of leaking it or, as the previous buggy version did, killing a terminal that was\n // never actually torn down).\n const isMountedRef = useRef(false);\n const requestStartedRef = useRef(false);\n useEffect(() => {\n isMountedRef.current = true;\n if (!client || slotRef.current !== null || requestStartedRef.current) {\n return () => {\n isMountedRef.current = false;\n };\n }\n requestStartedRef.current = true;\n\n const cwd = data.cwd || \"~\";\n\n void client.connection\n .request<CreateTerminalResponse>(\"create_terminal_request\", { workspaceId: \"\", cwd })\n .then((res) => {\n const created = res.terminal.slot;\n if (!isMountedRef.current) {\n // A real close happened with no remount after it — kill the PTY that finished\n // spawning after the tab was already gone, instead of leaking it.\n void client.connection.request(\"kill_terminal_request\", { slot: created }).catch(() => {});\n return;\n }\n slotRef.current = created;\n setSlot(created);\n useTabStore.getState().updateData(tab.id, { slot: created });\n })\n .catch((err: unknown) => {\n if (!isMountedRef.current) return;\n setError(err instanceof Error ? err.message : String(err));\n })\n .finally(() => {\n // Reset only after the promise settles — by then StrictMode's synchronous\n // mount→cleanup→remount window has long passed, so this can never reopen the\n // double-fire race. It DOES allow a legitimate retry (e.g. `client` changed because of\n // a reconnect after the first attempt failed) instead of leaving the tab stuck forever.\n requestStartedRef.current = false;\n });\n\n return () => {\n isMountedRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, tab.id]);\n\n // ─── True unmount only: kill the PTY server-side ───────────────────────────────────────────\n // Runs its cleanup exactly once, when this component itself unmounts (real tab close, per\n // `TabPanelHost`'s \"hidden but alive\" model — a tab switch never unmounts). An empty deps array\n // means React never re-runs the effect body itself; only the cleanup fires, and only on\n // unmount, so this never races the slot-creation effect above or double-kills on a client\n // change. Without this, every closed terminal tab leaked its PTY process forever.\n //\n // For a REATTACH (this tab opened with a non-null `data.slot` from the very first render —\n // `use-terminal-restore.ts`, or the create-effect above once it has resolved) `slotRef.current`\n // is non-null from the start, so StrictMode's synchronous mount→cleanup→remount phantom cycle\n // would fire this cleanup and kill the PTY immediately on mount — unlike a freshly created\n // terminal, where `slotRef.current` is still `null` during that same phantom window (see the\n // create-effect's own comment) and so never hits this path. Deferred via `setTimeout`, exactly\n // like the create-effect's response handler: by the time it fires, StrictMode's remount has\n // already flipped `isMountedRef` back to `true` if this was a phantom unmount, so the kill is\n // skipped; a genuine close never remounts, so `isMountedRef` stays `false` and the kill proceeds.\n useEffect(() => {\n return () => {\n const currentSlot = slotRef.current;\n if (currentSlot === null) return;\n setTimeout(() => {\n if (isMountedRef.current) return; // StrictMode remounted synchronously — not a real close\n void clientRef.current?.connection\n .request(\"kill_terminal_request\", { slot: currentSlot })\n .catch(() => {});\n }, 0);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ─── xterm mount (once slot + container are ready) ─────────────────────────────────────────\n useEffect(() => {\n if (!client || slot === null || !containerRef.current) return;\n\n const terminal = new Terminal({\n cursorBlink: true,\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',\n fontSize: 13,\n scrollback: 5000,\n theme: TERMINAL_THEME,\n allowProposedApi: true,\n });\n const fitAddon = new FitAddon();\n terminal.loadAddon(fitAddon);\n terminal.open(containerRef.current);\n fitAddon.fit();\n\n terminalRef.current = terminal;\n fitAddonRef.current = fitAddon;\n\n const router = routerFor(client.connection);\n const unsubscribeSlot = router.subscribeSlot(slot, {\n onOutput: (chunk) => terminal.write(chunk),\n onSnapshot: (chunk) => {\n terminal.clear();\n terminal.write(chunk);\n },\n onRestore: (chunk) => terminal.write(chunk),\n });\n\n void client.connection.request(\"subscribe_terminal_request\", { slot }).catch((err: unknown) => {\n setError(err instanceof Error ? err.message : String(err));\n });\n\n const dataDisposable = terminal.onData((chunk) => {\n router.sendInput(slot, new TextEncoder().encode(chunk));\n });\n const resizeDisposable = terminal.onResize(({ cols, rows }) => {\n router.sendResize(slot, rows, cols);\n });\n\n const resizeObserver = new ResizeObserver(() => {\n fitAddon.fit();\n });\n resizeObserver.observe(containerRef.current);\n\n return () => {\n resizeObserver.disconnect();\n dataDisposable.dispose();\n resizeDisposable.dispose();\n unsubscribeSlot();\n void client.connection.request(\"unsubscribe_terminal_request\", { slot }).catch(() => {});\n terminal.dispose();\n terminalRef.current = null;\n fitAddonRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slot]);\n\n // ─── Re-fit whenever this tab becomes the active (visible) one ────────────────────────────\n useEffect(() => {\n if (!isActive) return;\n fitAddonRef.current?.fit();\n }, [isActive]);\n\n if (error) {\n return (\n <div className={styles.wrap}>\n <div className={styles.status}>Terminal error: {error}</div>\n </div>\n );\n }\n\n if (slot === null) {\n return (\n <div className={styles.wrap}>\n <div className={styles.status}>\n <Spinner size=\"sm\" /> Starting terminal…\n </div>\n </div>\n );\n }\n\n return (\n <div className={styles.wrap}>\n <div ref={containerRef} className={styles.terminal} />\n </div>\n );\n}\n"],"names":["TerminalStreamRouter","daemon","__publicField","frame","_a","slot","subscriber","data","encodeTerminalFrame","rows","cols","_b","_c","routerByDaemon","routerFor","router","TERMINAL_THEME","TerminalPanel","tab","client","useConnectionStore","s","isActive","useTabStore","containerRef","useRef","terminalRef","fitAddonRef","slotRef","clientRef","setSlot","useState","error","setError","isMountedRef","requestStartedRef","useEffect","cwd","res","created","err","currentSlot","terminal","Terminal","fitAddon","FitAddon","unsubscribeSlot","chunk","dataDisposable","resizeDisposable","resizeObserver","jsx","styles","jsxs","Spinner"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{j as e}from"./vendor-react-BoIQBqDW.js";import{S as i}from"./index-CM7PrEq0.js";import{u as s,C as n}from"./CodeView-DKjlpq-m.js";import{p as o}from"./FilePanel-CGmR13VT.js";import"./vendor-query-AtKBh_Yt.js";import"./vendor--os7hw7d.js";import"./vendor-markdown-B8HSIhaA.js";import"./vendor-highlight-DCzuSv8g.js";import"./vendor-icons-DwowToH7.js";import"./vendor-overlays-UwLNGk04.js";import"./vendor-dnd-D9kA7FgH.js";import"./DiffView-DlVCPvLc.js";function E({path:t}){const r=s(t);return r.isLoading?e.jsxs("div",{className:o.emptyState,children:[e.jsx(i,{size:"sm"})," Loading..."]}):r.isError?e.jsxs("div",{className:o.emptyState,children:["Error: ",r.error instanceof Error?r.error.message:"unknown error"]}):r.data?e.jsx(n,{path:t,content:r.data.content}):null}export{E as TextViewer};
2
- //# sourceMappingURL=TextViewer-BVDA29H4.js.map
1
+ import{j as e}from"./vendor-react-BoIQBqDW.js";import{S as i}from"./index-C5SpA_B-.js";import{u as s,C as n}from"./CodeView-z3x4ATgx.js";import{p as o}from"./FilePanel-VOhIehHw.js";import"./vendor-query-AtKBh_Yt.js";import"./vendor--os7hw7d.js";import"./vendor-markdown-B8HSIhaA.js";import"./vendor-highlight-DCzuSv8g.js";import"./vendor-icons-BouiMPVM.js";import"./vendor-overlays-UwLNGk04.js";import"./vendor-dnd-D9kA7FgH.js";import"./DiffView-DlVCPvLc.js";function E({path:t}){const r=s(t);return r.isLoading?e.jsxs("div",{className:o.emptyState,children:[e.jsx(i,{size:"sm"})," Loading..."]}):r.isError?e.jsxs("div",{className:o.emptyState,children:["Error: ",r.error instanceof Error?r.error.message:"unknown error"]}):r.data?e.jsx(n,{path:t,content:r.data.content}):null}export{E as TextViewer};
2
+ //# sourceMappingURL=TextViewer-DlvdoBEv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextViewer-BVDA29H4.js","sources":["../../../src/features/files/TextViewer.tsx"],"sourcesContent":["/**\n * TextViewer — the default viewer for source/text files: fetches the UTF-8 preview via\n * `useFileRead` and renders it through `CodeView` (line gutter + Shiki highlighting). Registered\n * in `viewer-registry.ts` as the fallback for any file not claimed by a more specific viewer.\n */\n\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport { useFileRead } from \"@pi-studio-ui/hooks/use-file-read.js\";\nimport { CodeView } from \"./CodeView.js\";\nimport type { ViewerProps } from \"./viewer-registry.js\";\nimport styles from \"./FilePanel.module.css\";\n\nexport function TextViewer({ path }: ViewerProps) {\n const query = useFileRead(path);\n\n if (query.isLoading) {\n return (\n <div className={styles.emptyState}>\n <Spinner size=\"sm\" /> Loading...\n </div>\n );\n }\n if (query.isError) {\n return (\n <div className={styles.emptyState}>\n Error: {query.error instanceof Error ? query.error.message : \"unknown error\"}\n </div>\n );\n }\n if (!query.data) return null;\n return <CodeView path={path} content={query.data.content} />;\n}\n"],"names":["TextViewer","path","query","useFileRead","jsxs","styles","jsx","Spinner","CodeView"],"mappings":"2cAYO,SAASA,EAAW,CAAE,KAAAC,GAAqB,CAChD,MAAMC,EAAQC,EAAYF,CAAI,EAE9B,OAAIC,EAAM,UAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAO,WACrB,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAQ,KAAK,IAAA,CAAK,EAAE,aAAA,EACvB,EAGAL,EAAM,QAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAO,WAAY,SAAA,CAAA,UACzBH,EAAM,iBAAiB,MAAQA,EAAM,MAAM,QAAU,eAAA,EAC/D,EAGCA,EAAM,WACHM,EAAA,CAAS,KAAAP,EAAY,QAASC,EAAM,KAAK,QAAS,EADlC,IAE1B"}
1
+ {"version":3,"file":"TextViewer-DlvdoBEv.js","sources":["../../../src/features/files/TextViewer.tsx"],"sourcesContent":["/**\n * TextViewer — the default viewer for source/text files: fetches the UTF-8 preview via\n * `useFileRead` and renders it through `CodeView` (line gutter + Shiki highlighting). Registered\n * in `viewer-registry.ts` as the fallback for any file not claimed by a more specific viewer.\n */\n\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport { useFileRead } from \"@pi-studio-ui/hooks/use-file-read.js\";\nimport { CodeView } from \"./CodeView.js\";\nimport type { ViewerProps } from \"./viewer-registry.js\";\nimport styles from \"./FilePanel.module.css\";\n\nexport function TextViewer({ path }: ViewerProps) {\n const query = useFileRead(path);\n\n if (query.isLoading) {\n return (\n <div className={styles.emptyState}>\n <Spinner size=\"sm\" /> Loading...\n </div>\n );\n }\n if (query.isError) {\n return (\n <div className={styles.emptyState}>\n Error: {query.error instanceof Error ? query.error.message : \"unknown error\"}\n </div>\n );\n }\n if (!query.data) return null;\n return <CodeView path={path} content={query.data.content} />;\n}\n"],"names":["TextViewer","path","query","useFileRead","jsxs","styles","jsx","Spinner","CodeView"],"mappings":"2cAYO,SAASA,EAAW,CAAE,KAAAC,GAAqB,CAChD,MAAMC,EAAQC,EAAYF,CAAI,EAE9B,OAAIC,EAAM,UAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAO,WACrB,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAQ,KAAK,IAAA,CAAK,EAAE,aAAA,EACvB,EAGAL,EAAM,QAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAO,WAAY,SAAA,CAAA,UACzBH,EAAM,iBAAiB,MAAQA,EAAM,MAAM,QAAU,eAAA,EAC/D,EAGCA,EAAM,WACHM,EAAA,CAAS,KAAAP,EAAY,QAASC,EAAM,KAAK,QAAS,EADlC,IAE1B"}
@@ -1,2 +1,2 @@
1
- import{j as o}from"./vendor-react-BoIQBqDW.js";import{S as t}from"./index-CM7PrEq0.js";import{u as a}from"./use-file-download-B8_UiD_5.js";import{p as e}from"./FilePanel-CGmR13VT.js";import"./vendor-query-AtKBh_Yt.js";import"./vendor--os7hw7d.js";import"./vendor-markdown-B8HSIhaA.js";import"./vendor-highlight-DCzuSv8g.js";import"./vendor-icons-DwowToH7.js";import"./vendor-overlays-UwLNGk04.js";import"./vendor-dnd-D9kA7FgH.js";import"./DiffView-DlVCPvLc.js";const n="_wrap_1c9y4_1",m="_video_1c9y4_10",i={wrap:n,video:m};function S({path:s}){const r=a(s);return r.isLoading?o.jsxs("div",{className:e.emptyState,children:[o.jsx(t,{size:"sm"})," Loading video..."]}):r.isError?o.jsxs("div",{className:e.emptyState,children:["Error: ",r.error instanceof Error?r.error.message:"unknown error"]}):r.data?o.jsx("div",{className:i.wrap,children:o.jsx("video",{className:i.video,src:r.data.objectUrl,controls:!0})}):null}export{S as VideoViewer};
2
- //# sourceMappingURL=VideoViewer-Bj8wu5hl.js.map
1
+ import{j as o}from"./vendor-react-BoIQBqDW.js";import{S as t}from"./index-C5SpA_B-.js";import{u as a}from"./use-file-download-t12JJGKT.js";import{p as e}from"./FilePanel-VOhIehHw.js";import"./vendor-query-AtKBh_Yt.js";import"./vendor--os7hw7d.js";import"./vendor-markdown-B8HSIhaA.js";import"./vendor-highlight-DCzuSv8g.js";import"./vendor-icons-BouiMPVM.js";import"./vendor-overlays-UwLNGk04.js";import"./vendor-dnd-D9kA7FgH.js";import"./DiffView-DlVCPvLc.js";const n="_wrap_1c9y4_1",m="_video_1c9y4_10",i={wrap:n,video:m};function S({path:s}){const r=a(s);return r.isLoading?o.jsxs("div",{className:e.emptyState,children:[o.jsx(t,{size:"sm"})," Loading video..."]}):r.isError?o.jsxs("div",{className:e.emptyState,children:["Error: ",r.error instanceof Error?r.error.message:"unknown error"]}):r.data?o.jsx("div",{className:i.wrap,children:o.jsx("video",{className:i.video,src:r.data.objectUrl,controls:!0})}):null}export{S as VideoViewer};
2
+ //# sourceMappingURL=VideoViewer-BmTmnaOQ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VideoViewer-Bj8wu5hl.js","sources":["../../../src/features/files/VideoViewer.tsx"],"sourcesContent":["/**\n * VideoViewer — renders a binary video file via the file-transfer binary download\n * (`useFileDownload`) into a native `<video>` element (POC_TO_APP_PLAN_UI.md §4.5 follow-up:\n * modular file preview).\n */\n\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport { useFileDownload } from \"@pi-studio-ui/hooks/use-file-download.js\";\nimport type { ViewerProps } from \"./viewer-registry.js\";\nimport panelStyles from \"./FilePanel.module.css\";\nimport styles from \"./VideoViewer.module.css\";\n\nexport function VideoViewer({ path }: ViewerProps) {\n const query = useFileDownload(path);\n\n if (query.isLoading) {\n return (\n <div className={panelStyles.emptyState}>\n <Spinner size=\"sm\" /> Loading video...\n </div>\n );\n }\n if (query.isError) {\n return (\n <div className={panelStyles.emptyState}>\n Error: {query.error instanceof Error ? query.error.message : \"unknown error\"}\n </div>\n );\n }\n if (!query.data) return null;\n\n return (\n <div className={styles.wrap}>\n {/* eslint-disable-next-line jsx-a11y/media-has-caption -- arbitrary local file, no caption track available */}\n <video className={styles.video} src={query.data.objectUrl} controls />\n </div>\n );\n}\n"],"names":["VideoViewer","path","query","useFileDownload","jsxs","panelStyles","jsx","Spinner","styles"],"mappings":"4gBAYO,SAASA,EAAY,CAAE,KAAAC,GAAqB,CACjD,MAAMC,EAAQC,EAAgBF,CAAI,EAElC,OAAIC,EAAM,UAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAY,WAC1B,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAQ,KAAK,IAAA,CAAK,EAAE,mBAAA,EACvB,EAGAL,EAAM,QAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAY,WAAY,SAAA,CAAA,UAC9BH,EAAM,iBAAiB,MAAQA,EAAM,MAAM,QAAU,eAAA,EAC/D,EAGCA,EAAM,WAGR,MAAA,CAAI,UAAWM,EAAO,KAErB,eAAC,QAAA,CAAM,UAAWA,EAAO,MAAO,IAAKN,EAAM,KAAK,UAAW,SAAQ,GAAC,EACtE,EANsB,IAQ1B"}
1
+ {"version":3,"file":"VideoViewer-BmTmnaOQ.js","sources":["../../../src/features/files/VideoViewer.tsx"],"sourcesContent":["/**\n * VideoViewer — renders a binary video file via the file-transfer binary download\n * (`useFileDownload`) into a native `<video>` element (POC_TO_APP_PLAN_UI.md §4.5 follow-up:\n * modular file preview).\n */\n\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport { useFileDownload } from \"@pi-studio-ui/hooks/use-file-download.js\";\nimport type { ViewerProps } from \"./viewer-registry.js\";\nimport panelStyles from \"./FilePanel.module.css\";\nimport styles from \"./VideoViewer.module.css\";\n\nexport function VideoViewer({ path }: ViewerProps) {\n const query = useFileDownload(path);\n\n if (query.isLoading) {\n return (\n <div className={panelStyles.emptyState}>\n <Spinner size=\"sm\" /> Loading video...\n </div>\n );\n }\n if (query.isError) {\n return (\n <div className={panelStyles.emptyState}>\n Error: {query.error instanceof Error ? query.error.message : \"unknown error\"}\n </div>\n );\n }\n if (!query.data) return null;\n\n return (\n <div className={styles.wrap}>\n {/* eslint-disable-next-line jsx-a11y/media-has-caption -- arbitrary local file, no caption track available */}\n <video className={styles.video} src={query.data.objectUrl} controls />\n </div>\n );\n}\n"],"names":["VideoViewer","path","query","useFileDownload","jsxs","panelStyles","jsx","Spinner","styles"],"mappings":"4gBAYO,SAASA,EAAY,CAAE,KAAAC,GAAqB,CACjD,MAAMC,EAAQC,EAAgBF,CAAI,EAElC,OAAIC,EAAM,UAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAY,WAC1B,SAAA,CAAAC,EAAAA,IAACC,EAAA,CAAQ,KAAK,IAAA,CAAK,EAAE,mBAAA,EACvB,EAGAL,EAAM,QAENE,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAY,WAAY,SAAA,CAAA,UAC9BH,EAAM,iBAAiB,MAAQA,EAAM,MAAM,QAAU,eAAA,EAC/D,EAGCA,EAAM,WAGR,MAAA,CAAI,UAAWM,EAAO,KAErB,eAAC,QAAA,CAAM,UAAWA,EAAO,MAAO,IAAKN,EAAM,KAAK,UAAW,SAAQ,GAAC,EACtE,EANsB,IAQ1B"}
@@ -0,0 +1,3 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ChatPanel-XI36Imum.js","assets/vendor-react-BoIQBqDW.js","assets/vendor-query-AtKBh_Yt.js","assets/vendor-icons-BouiMPVM.js","assets/markdown-D9FuaV1m.js","assets/vendor-highlight-DCzuSv8g.js","assets/vendor-markdown-B8HSIhaA.js","assets/vendor--os7hw7d.js","assets/markdown-BQwXm0MF.css","assets/DiffView-DlVCPvLc.js","assets/DiffView-CRbeRztO.css","assets/vendor-overlays-UwLNGk04.js","assets/vendor-dnd-D9kA7FgH.js","assets/ChatPanel-CTnpkb2U.css","assets/FilePanel-VOhIehHw.js","assets/FilePanel-DIInFr3h.css","assets/TerminalPanel-KNfHGYYL.js","assets/vendor-terminal-BhzX2_ts.js","assets/vendor-terminal-DYP7pi_n.css","assets/TerminalPanel-BQj62G6N.css"])))=>i.map(i=>d[i]);
2
+ var dn=Object.defineProperty;var un=(t,e,n)=>e in t?dn(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var I=(t,e,n)=>un(t,typeof e!="symbol"?e+"":e,n);import{r as S,j as i,d as pn}from"./vendor-react-BoIQBqDW.js";import{Q as fn,a as hn,u as gn,b as mn,c as Ge,d as _n}from"./vendor-query-AtKBh_Yt.js";import{A as c,B as p,C as M,D as It,E as C,F as Se,G,H as E,I as _,J as $,K as D,L as Ne,M as de,N as se}from"./vendor--os7hw7d.js";import{L as yn,P as bn,a as wn,b as Sn,c as xn,E as Ct,C as Ve,d as vn,F as kn,e as Tt,f as In,S as jt,G as Cn,g as Tn,M as Et,X as Fe,h as Je,i as jn,U as En,R as Nn,j as Rn,k as qn,l as Bn,m as Mn,D as An,n as $n,A as Dn}from"./vendor-icons-BouiMPVM.js";import{R as Ye,T as Xe,P as Qe,C as Ze,I as Y,S as Nt,D as On,a as Fn,b as Pn,c as Hn,d as it,e as Pe}from"./vendor-overlays-UwLNGk04.js";import{u as zn,a as Wn,D as Ln,c as Un,S as Kn,h as Gn,P as Vn,b as Jn,C as Yn}from"./vendor-dnd-D9kA7FgH.js";import{_ as et}from"./vendor-highlight-DCzuSv8g.js";import"./vendor-markdown-B8HSIhaA.js";(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))s(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const a of r.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&s(a)}).observe(document,{childList:!0,subtree:!0});function n(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function s(o){if(o.ep)return;o.ep=!0;const r=n(o);fetch(o.href,r)}})();const Xn=new fn;function Rt(t){const e=t.trim().replace(/^#/,""),n=e.length===3?e.split("").map(s=>s+s).join(""):e;if(n.length!==6||/[^0-9a-fA-F]/.test(n))throw new Error(`Invalid hex color: ${t}`);return{r:parseInt(n.slice(0,2),16),g:parseInt(n.slice(2,4),16),b:parseInt(n.slice(4,6),16)}}function Qn(t){return Math.max(0,Math.min(255,Math.round(t)))}function Zn({r:t,g:e,b:n}){const s=o=>Qn(o).toString(16).padStart(2,"0");return`#${s(t)}${s(e)}${s(n)}`}function es(t){const{r:e,g:n,b:s}=Rt(t),o=r=>{const a=r/255;return a<=.03928?a/12.92:((a+.055)/1.055)**2.4};return .2126*o(e)+.7152*o(n)+.0722*o(s)}function tt(t,e="#18181b",n="#ffffff"){return es(t)>.45?e:n}function ts(t,e){const{r:n,g:s,b:o}=Rt(t),r=Math.max(0,Math.min(1,e));return Zn({r:n+(255-n)*r,g:s+(255-s)*r,b:o+(255-o)*r})}function ve(t){const e=t.trim().replace(/^#/,"");return(e.length===3||e.length===6)&&!/[^0-9a-fA-F]/.test(e)}const H=(t,e,n,s,o,r,a,l,d,u,m)=>({50:t,100:e,200:n,300:s,400:o,500:r,600:a,700:l,800:d,900:u,950:m}),y={zinc:H("#fafafa","#f4f4f5","#e4e4e7","#d4d4d8","#a1a1aa","#71717a","#52525b","#3f3f46","#27272a","#18181b","#09090b"),gray:H("#f9fafb","#f3f4f6","#e5e7eb","#d1d5db","#9ca3af","#6b7280","#4b5563","#374151","#1f2937","#111827","#030712"),slate:H("#f8fafc","#f1f5f9","#e2e8f0","#cbd5e1","#94a3b8","#64748b","#475569","#334155","#1e293b","#0f172a","#020617"),blue:H("#eff6ff","#dbeafe","#bfdbfe","#93c5fd","#60a5fa","#3b82f6","#2563eb","#1d4ed8","#1e40af","#1e3a8a","#172554"),green:H("#f0fdf4","#dcfce7","#bbf7d0","#86efac","#4ade80","#22c55e","#16a34a","#15803d","#166534","#14532d","#052e16"),red:H("#fef2f2","#fee2e2","#fecaca","#fca5a5","#f87171","#ef4444","#dc2626","#b91c1c","#991b1b","#7f1d1d","#450a0a"),teal:H("#f0fdfa","#ccfbf1","#99f6e4","#5eead4","#2dd4bf","#14b8a6","#0d9488","#0f766e","#115e59","#134e4a","#042f2e"),amber:H("#fffbeb","#fef3c7","#fde68a","#fcd34d","#fbbf24","#f59e0b","#d97706","#b45309","#92400e","#78350f","#451a03"),yellow:H("#fefce8","#fef9c3","#fef08a","#fde047","#facc15","#eab308","#ca8a04","#a16207","#854d0e","#713f12","#422006"),purple:H("#faf5ff","#f3e8ff","#e9d5ff","#d8b4fe","#c084fc","#a855f7","#9333ea","#7e22ce","#6b21a8","#581c87","#3b0764"),orange:H("#fff7ed","#ffedd5","#fed7aa","#fdba74","#fb923c","#f97316","#ea580c","#c2410c","#9a3412","#7c2d12","#431407"),white:"#ffffff",black:"#000000"},ns={statusSuccess:"#16a34a",statusDanger:"#dc2626",statusWarning:"#f59e0b",statusMerged:"#9333ea"},ss={statusSuccess:"#15803d",statusDanger:"#b91c1c",statusWarning:"#d97706",statusMerged:"#7c3aed"};function os(){return{keyword:y.purple[300],string:y.green[300],number:y.orange[300],boolean:y.orange[300],comment:y.zinc[500],function:y.blue[300],variable:y.zinc[200],type:y.teal[300],class:y.amber[300],constant:y.orange[300],operator:y.zinc[400],punctuation:y.zinc[400],tag:y.red[300],attribute:y.amber[300],property:y.blue[200],regexp:y.teal[300],escape:y.orange[200],heading:y.blue[300],link:y.blue[400],deleted:y.red[400],inserted:y.green[400]}}function rs(){return{keyword:y.purple[700],string:y.green[700],number:y.orange[700],boolean:y.orange[700],comment:y.zinc[500],function:y.blue[700],variable:y.zinc[800],type:y.teal[700],class:y.amber[700],constant:y.orange[700],operator:y.zinc[600],punctuation:y.zinc[600],tag:y.red[700],attribute:y.amber[700],property:y.blue[700],regexp:y.teal[700],escape:y.orange[700],heading:y.blue[700],link:y.blue[600],deleted:y.red[700],inserted:y.green[700]}}function qt(t,e,n){return{background:t,foreground:e,cursor:n,cursorAccent:t,selectionBackground:"rgba(255,255,255,0.18)",black:y.zinc[900],red:y.red[500],green:y.green[500],yellow:y.amber[500],blue:y.blue[500],magenta:y.purple[500],cyan:y.teal[500],white:y.zinc[300],brightBlack:y.zinc[600],brightRed:y.red[400],brightGreen:y.green[400],brightYellow:y.amber[400],brightBlue:y.blue[400],brightMagenta:y.purple[400],brightCyan:y.teal[400],brightWhite:y.zinc[50]}}function pe(t){const e=y.zinc[50],n=tt(t.accent);return{surface0:t.surface0,surface1:t.surface1,surface2:t.surface2,surface3:t.surface3,surface4:t.surface4,surfaceDiffEmpty:t.surfaceDiffEmpty,surfaceSidebar:t.surfaceSidebar,surfaceSidebarHover:t.surfaceSidebarHover,surfaceWorkspace:t.surface1,foreground:e,foregroundMuted:t.mutedForeground,accent:t.accent,accentBright:t.accentBright,accentForeground:n,destructive:t.destructive,destructiveForeground:y.white,success:t.accent,successForeground:y.white,border:t.border,borderAccent:t.borderAccent,...ns,diffAddition:y.green[400],diffDeletion:y.red[500],scrollbarHandle:t.scrollbarHandle,background:t.surface0,popover:t.surface2,popoverForeground:e,primary:t.accent,secondary:t.surface2,muted:t.surface2,mutedForeground:t.mutedForeground,input:t.surface2,ring:t.accent,palette:y,syntax:os(),terminal:qt(t.surface0,e,t.accent)}}function as(){const t="#1a1a1e",e="#253e6f";return{surface0:"#ffffff",surface1:"#fafafa",surface2:"#f4f4f5",surface3:"#e4e4e7",surface4:"#d4d4d8",surfaceDiffEmpty:"#f6f6f6",surfaceSidebar:"#f4f4f5",surfaceSidebarHover:"#e9e9ec",surfaceWorkspace:"#ffffff",foreground:t,foregroundMuted:"#71717a",accent:e,accentBright:"#2f4f8e",accentForeground:tt(e),destructive:"#b04138",destructiveForeground:"#ffffff",success:e,successForeground:"#ffffff",border:"#e4e4e7",borderAccent:"#ececf1",...ss,diffAddition:"#15803d",diffDeletion:"#b91c1c",scrollbarHandle:"#3f3f46",background:"#ffffff",popover:"#ffffff",popoverForeground:t,primary:e,secondary:"#f4f4f5",muted:"#f4f4f5",mutedForeground:"#71717a",input:"#f4f4f5",ring:e,palette:y,syntax:rs(),terminal:{...qt("#ffffff",t,e),selectionBackground:"rgba(0,0,0,0.15)",white:"#ffffff",brightWhite:"#fafafa"}}}const is={light:"#ffffff",dark:"#3b62b0",zinc:"#808080",midnight:"#4A6BA8",claude:"#D97757",ghostty:"#8caaee"},Bt=["light","dark","zinc","midnight","claude","ghostty"];function cs(t){if(t==="light")return as();switch(t){case"dark":return pe({surface0:"#181B1A",surface1:"#1E2120",surface2:"#272A29",surface3:"#434645",surface4:"#595B5B",surfaceDiffEmpty:"#252827",surfaceSidebar:"#141716",surfaceSidebarHover:"#1c1f1e",mutedForeground:"#A1A5A4",scrollbarHandle:"#717574",border:"#252B2A",borderAccent:"#2f3135",accent:"#2e5cb8",accentBright:"#a2b4d7",destructive:"#c64f43"});case"zinc":return pe({surface0:"#18181b",surface1:"#1f1f22",surface2:"#27272a",surface3:"#3f3f46",surface4:"#52525b",surfaceDiffEmpty:"#242427",surfaceSidebar:"#131316",surfaceSidebarHover:"#1b1b1e",mutedForeground:"#a1a1aa",scrollbarHandle:"#71717a",border:"#27272a",borderAccent:"#303036",accent:"#e4e4e7",accentBright:"#fafafa",destructive:"#c44a4a"});case"midnight":return pe({surface0:"#161820",surface1:"#1c1e27",surface2:"#252731",surface3:"#3c3e4c",surface4:"#535564",surfaceDiffEmpty:"#222430",surfaceSidebar:"#121420",surfaceSidebarHover:"#1a1c28",mutedForeground:"#9a9db0",scrollbarHandle:"#6b6e82",border:"#242636",borderAccent:"#2e3040",accent:"#3b6fcf",accentBright:"#7eaaeb",destructive:"#c44a52"});case"claude":return pe({surface0:"#1f1f1e",surface1:"#262523",surface2:"#2f2d2b",surface3:"#4a4745",surface4:"#605d5b",surfaceDiffEmpty:"#2a2826",surfaceSidebar:"#1a1918",surfaceSidebarHover:"#222120",mutedForeground:"#ada9a5",scrollbarHandle:"#78746f",border:"#2c2a27",borderAccent:"#36332f",accent:"#d97757",accentBright:"#e89a7f",destructive:"#cf513e"});case"ghostty":return pe({surface0:"#282c34",surface1:"#2f333d",surface2:"#383c48",surface3:"#4a4f5e",surface4:"#5b6175",surfaceDiffEmpty:"#323643",surfaceSidebar:"#21252d",surfaceSidebarHover:"#292d36",mutedForeground:"#c8ccd8",scrollbarHandle:"#a0a4b2",border:"#353a47",borderAccent:"#3f4454",accent:"#89b4fa",accentBright:"#b4d0fc",destructive:"#c44a55"})}}const Mt={};for(const t of Bt){const e=t==="light"?"light":"dark";Mt[t]={name:t,colorScheme:e,colors:cs(t),swatch:is[t]}}const ls=Mt,ds={0:0,1:4,"1.5":6,2:8,3:12,4:16,6:24,8:32,12:48,16:64,20:80,24:96,32:128},At={xs:12,code:12,sm:14,base:16,lg:18,xl:20,"2xl":22,"3xl":26,"4xl":34},us={normal:"400",medium:"500",semibold:"600",bold:"700"},ps={none:0,sm:2,base:4,md:6,lg:8,xl:12,"2xl":16,full:9999},fs={0:0,1:1,2:2},hs={0:0,50:.5,100:1},gs={xs:12,sm:14,md:16,lg:20},ms={diff:22},$t='system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',Dt='ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace';function _s(t){const e=t==="dark"?"rgba(0,0,0,0.55)":"rgba(24,24,27,0.12)";return{sm:{color:e,offsetX:0,offsetY:1,radius:2,elevation:1},md:{color:e,offsetX:0,offsetY:3,radius:8,elevation:4},lg:{color:e,offsetX:0,offsetY:10,radius:24,elevation:12}}}function Ot(t){const e=ls[t];return{name:t,colorScheme:e.colorScheme,colors:e.colors,spacing:ds,fontSize:{...At},fontFamily:{ui:$t,mono:Dt},lineHeight:{...ms},iconSize:gs,fontWeight:us,borderRadius:ps,borderWidth:fs,opacity:hs,shadow:_s(e.colorScheme),swatch:e.swatch}}const ys=16,bs=10,ws=24;function Ss(t,e){const n=e.themeName??t.name,s=Ot(n),o=e.uiFont&&e.uiFont.trim()!==""?e.uiFont:$t,r=e.monoFont&&e.monoFont.trim()!==""?e.monoFont:Dt;let a={...s.fontSize};if(e.fontSize!=null){const d=Math.max(bs,Math.min(ws,e.fontSize))/ys,u=["xs","code","sm","base","lg","xl","2xl","3xl","4xl"];for(const m of u){const h=At[m];a[m]=Math.round(h*d)}}return{...s,fontSize:a,fontFamily:{ui:o,mono:r}}}function xs(t){return Ot(t)}const vs="dark";function ks(t){const e={};Is(t.colors,e);for(const[n,s]of Object.entries(t.spacing))e[`--pi-spacing-${n}`]=`${s}px`;for(const[n,s]of Object.entries(t.fontSize))e[`--pi-font-size-${n}`]=`${s}px`;e["--pi-font-ui"]=t.fontFamily.ui,e["--pi-font-mono"]=t.fontFamily.mono,e["--pi-line-height-diff"]=`${t.lineHeight.diff}px`;for(const[n,s]of Object.entries(t.iconSize))e[`--pi-icon-size-${n}`]=`${s}px`;for(const[n,s]of Object.entries(t.fontWeight))e[`--pi-font-weight-${n}`]=String(s);for(const[n,s]of Object.entries(t.borderRadius))e[`--pi-radius-${n}`]=s===9999?"9999px":`${s}px`;for(const[n,s]of Object.entries(t.borderWidth))e[`--pi-border-width-${n}`]=`${s}px`;for(const[n,s]of Object.entries(t.opacity))e[`--pi-opacity-${n}`]=String(s);for(const[n,s]of Object.entries(t.shadow))if(typeof s=="string")e[`--pi-shadow-${n}`]=s;else if(s&&typeof s=="object"){const o=s;e[`--pi-shadow-${n}`]=`${o.offsetX}px ${o.offsetY}px ${o.radius}px ${o.color}`}return e["--pi-color-scheme"]=t.colorScheme,e}function Is(t,e){const{palette:n,syntax:s,terminal:o,...r}=t;for(const[a,l]of Object.entries(r))typeof l=="string"&&(e[`--pi-color-${a}`]=l);s&&Cs(s,e),o&&(e["--pi-terminal-bg"]=o.background,e["--pi-terminal-fg"]=o.foreground)}function Cs(t,e){for(const[n,s]of Object.entries(t))typeof s=="string"&&(e[`--syntax-${Ts(n)}`]=s)}function Ts(t){return t.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function js(t){if(typeof document>"u")return;const e=document.documentElement.style;for(const[s,o]of Object.entries(t))e.setProperty(s,o);const n=t["--pi-color-scheme"];n&&document.documentElement.style.setProperty("color-scheme",n)}function Es(t){const e=ks(t);js(e)}const fe=c().min(1,"Asset path must not be empty"),Ns=p({accent:c().refine(ve,{message:"accent must be a valid #rrggbb hex color"}),accentBright:c().refine(ve,{message:"accentBright must be a valid #rrggbb hex color"}).optional(),accentForeground:c().refine(ve,{message:"accentForeground must be a valid #rrggbb hex color"}).optional(),swatch:c().refine(ve,{message:"swatch must be a valid #rrggbb hex color"}).optional()}),Rs=p({logoLight:fe,logoDark:fe,logoMark:fe.optional(),icon:fe,splash:fe.optional()}),qs=p({docs:c().url().optional(),support:c().url().optional(),issues:c().url().optional(),website:c().url().optional()}).optional(),Bs=p({copyright:c().optional(),companyName:c().optional()}).optional();p({productName:c().min(1,"productName is required"),shortName:c().optional(),tagline:c().optional(),colors:Ns,assets:Rs,links:qs,legal:Bs});function Ms(t){const e=t.accent,n=t.accentBright??ts(e,.35),s=t.accentForeground??tt(e),o=t.swatch??e;return{accent:e,accentBright:n,accentForeground:s,swatch:o}}function As(t,e){return{...t,colors:{...t.colors,accent:e.accent,accentBright:e.accentBright,accentForeground:e.accentForeground,primary:e.accent,ring:e.accent},swatch:e.swatch}}const ct="pi-studio-appearance";function $s(t,e){let n=l(t),s=null;function o(m){return m==="system"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":m}function r(m,h){const f=o(m),g=xs(f);let w=Ss(g,{...h,themeName:f});if(e!=null&&e.colors){const b=Ms(e.colors);w=As(w,b)}return w}function a(){const m=JSON.stringify({mode:n.mode,settings:n.settings});t.set(ct,m)}function l(m){const h=m.get(ct);let f=vs,g={};if(h)try{const b=JSON.parse(h);b.mode&&(Bt.includes(b.mode)||b.mode==="system")&&(f=b.mode),b.settings&&typeof b.settings=="object"&&(g=b.settings)}catch{}const w=r(f,g);return{mode:f,settings:g,resolvedTheme:w}}function d(){n={...n,resolvedTheme:r(n.mode,n.settings)},a()}const u={getState(){return n},setMode(m){n={...n,mode:m},d(),u.apply()},updateSettings(m){n={...n,settings:{...n.settings,...m}},d(),u.apply()},apply(){Es(n.resolvedTheme)},listen(){if(typeof window>"u")return()=>{};const m=window.matchMedia("(prefers-color-scheme: dark)"),h=()=>{n.mode==="system"&&(d(),u.apply())};return m.addEventListener("change",h),s=()=>m.removeEventListener("change",h),s}};return u}function Ds({store:t,brandConfig:e,children:n}){const s=S.useRef(null);return s.current||(s.current=$s(t,e),s.current.apply()),S.useEffect(()=>s.current.listen(),[]),i.jsx(i.Fragment,{children:n})}const Os={get(t){var e;try{return((e=globalThis.localStorage)==null?void 0:e.getItem(t))??null}catch{return null}},set(t,e){var n;try{(n=globalThis.localStorage)==null||n.setItem(t,e)}catch{}}};function Fs({children:t}){return i.jsx(Ds,{store:Os,children:i.jsx(hn,{client:Xn,children:t})})}const Ps="_btn_1chbg_4",Hs="_secondary_1chbg_44",zs="_outline_1chbg_53",Ws="_ghost_1chbg_62",Ls="_destructive_1chbg_72",Us="_iconOnly_1chbg_82",Ks="_loadingSpinner_1chbg_89",Gs="_piSpin_1chbg_1",ke={btn:Ps,default:"_default_1chbg_35",secondary:Hs,outline:zs,ghost:Ws,destructive:Ls,iconOnly:Us,loadingSpinner:Ks,piSpin:Gs},lt={xs:28,sm:32,md:36,lg:40},Vs={xs:12,sm:14,md:16,lg:20},dt={xs:8,sm:10,md:12,lg:16},Js={xs:12,sm:13,md:14,lg:15};function Ys(t){const{disabled:e,loading:n}=t;return e||n?{opacity:.5,isGhostHover:!1}:{opacity:1,isGhostHover:!1}}function z({variant:t="default",size:e="md",loading:n=!1,disabled:s=!1,leftIcon:o,trailing:r,iconOnly:a=!1,children:l,style:d,className:u,...m}){const{opacity:h}=Ys({disabled:s??!1,loading:n}),f=s||n,g=Vs[e];return i.jsxs("button",{className:M(ke.btn,ke[t],a&&ke.iconOnly,u),disabled:f,"aria-busy":n||void 0,style:{minHeight:lt[e],paddingLeft:a?void 0:dt[e],paddingRight:a?void 0:dt[e],fontSize:Js[e],opacity:h,...a?{width:lt[e]}:{},...d},...m,children:[n?i.jsx(yn,{className:ke.loadingSpinner,size:g,"aria-hidden":!0}):o?i.jsx("span",{"aria-hidden":!0,style:{display:"flex",alignItems:"center",flexShrink:0},children:o}):null,l,r&&!n&&i.jsx("span",{"aria-hidden":!0,style:{display:"flex",alignItems:"center",flexShrink:0},children:r})]})}const Xs="_input_a7qyq_3",Qs="_textarea_a7qyq_32",He={input:Xs,textarea:Qs},ze=S.forwardRef(function({className:e,...n},s){return i.jsx("input",{ref:s,className:M(He.input,e),...n})}),ed=S.forwardRef(function({className:e,...n},s){return i.jsx("textarea",{ref:s,className:M(He.input,He.textarea,e),...n})}),Ft=c().datetime({offset:!0});c().uuid();c().regex(/^[A-Za-z0-9_-]+$/,"expected base64url");const we=It([C(),Ft]),Zs=Se(["mobile","browser","cli","mcp"]),eo=p({type:_("hello"),clientId:c(),clientType:Zs,protocolVersion:C(),appVersion:c().optional(),capabilities:G(c(),E()).optional()}),to=p({status:_("server_info"),serverId:c(),hostname:c().optional(),version:c().optional(),capabilities:G(c(),$()),features:G(c(),$())}),no=p({type:_("status"),payload:to}),so=p({type:_("ping"),requestId:c(),clientSentAt:we.optional()}),oo=p({type:_("pong"),requestId:c(),clientSentAt:we.optional(),serverReceivedAt:we,serverSentAt:we}),Pt=Se(["initializing","idle","running","error","closed"]),Re=p({mimeType:c().optional(),data:c().optional()}).passthrough(),ro=p({prs:D($()).optional(),issues:D($()).optional()}).passthrough(),ao=p({provider:c(),cwd:c(),modeId:c().optional(),model:c().optional(),thinkingOptionId:c().optional(),featureValues:G(c(),$()).optional(),title:c().nullable().optional(),approvalPolicy:c().optional(),sandboxMode:c().optional(),networkAccess:E().optional(),webSearch:E().optional(),extra:p({pi:$().optional()}).passthrough().optional(),systemPrompt:c().optional(),mcpServers:G(c(),$()).optional()}),io=p({type:_("create_agent_request"),requestId:c(),config:ao,env:G(c(),c()).optional(),workspaceId:c().optional(),worktreeName:c().optional(),initialPrompt:c().optional(),clientMessageId:c().optional(),outputSchema:G(c(),$()).optional(),images:D(Re).optional(),attachments:ro.optional(),git:$().optional(),worktree:$().optional(),autoArchive:E().optional(),labels:G(c(),c()).default({})}),co=p({type:_("create_agent_response"),requestId:c(),payload:p({agentId:c()}).passthrough()}),lo=p({type:_("agent_update"),agentId:c(),status:Pt.optional(),title:c().nullable().optional(),labels:G(c(),c()).optional()}),uo=p({type:_("agent_status"),agentId:c(),status:Pt}),po=p({type:_("agent_list"),agents:D(p({id:c()}).passthrough())}),fo=p({type:_("agent_deleted"),agentId:c()}),ho=p({type:_("agent_archived"),agentId:c(),archivedAt:Ft.optional()}),Ht=Ne("kind",[p({kind:_("shell"),command:c().optional(),output:c().optional()}),p({kind:_("read"),path:c().optional(),output:c().optional()}),p({kind:_("edit"),path:c().optional(),diff:c().optional(),output:c().optional()}),p({kind:_("write"),path:c().optional(),output:c().optional()}),p({kind:_("search"),query:c().optional(),output:c().optional()}),p({kind:_("fetch"),url:c().optional(),output:c().optional()}),p({kind:_("task"),description:c().optional(),output:c().optional()})]),go=Ne("kind",[p({kind:_("user_message"),messageId:c().optional(),text:c().optional(),images:D(Re).optional()}),p({kind:_("assistant_message"),messageId:c().optional(),text:c().optional()}),p({kind:_("reasoning"),text:c().optional()}),p({kind:_("tool_call"),callId:c().optional(),tool:Ht,status:c().optional()}),p({kind:_("turn_started"),turnId:c().optional()}),p({kind:_("turn_completed"),turnId:c().optional()}),p({kind:_("turn_failed"),turnId:c().optional(),error:c().optional()}),p({kind:_("turn_canceled"),turnId:c().optional()}),p({kind:_("error"),message:c().optional()}),p({kind:_("queue_update"),steering:D(c()).optional(),followUp:D(c()).optional()})]),mo=p({type:_("agent_stream"),agentId:c(),seq:C().optional(),timestamp:we.optional(),event:go}),_o=Se(["before","after"]),yo=p({start:C(),end:C()}),bo=p({type:_("fetch_agent_timeline_request"),requestId:c(),agentId:c(),cursor:c().nullable().optional(),direction:_o,limit:C().optional()}),wo=p({type:_("fetch_agent_timeline_response"),requestId:c(),agentId:c().optional(),items:D($()),seqStart:C(),seqEnd:C(),sourceSeqRanges:D(yo),collapsed:E(),hasNewer:E(),startCursor:c().nullable().optional(),endCursor:c().nullable().optional()}),So=p({type:_("agent_permission_request"),requestId:c(),agentId:c(),toolName:c().optional(),tool:Ht.optional(),action:$().optional(),responses:D(c()).optional()}),xo=p({type:_("agent_permission_resolved"),requestId:c(),agentId:c(),decision:c().optional()}),vo=p({type:_("agent.permission.respond.request"),requestId:c(),permissionRequestId:c(),response:$()}),ko=p({type:_("agent.permission.respond.response"),requestId:c(),payload:p({resolved:E()}).passthrough()}),Io=p({type:_("respond_to_permission"),requestId:c(),permissionRequestId:c(),response:$()}),zt=Se(["conversation","files","both"]),Co=p({type:_("agent.rewind.request"),requestId:c(),agentId:c(),messageId:c(),mode:zt}).passthrough(),To=p({type:_("agent.rewind.response"),requestId:c(),payload:p({agentId:c(),messageId:c(),mode:zt,truncatedAt:c().optional()}).passthrough()}).passthrough(),jo=p({input:C().optional(),output:C().optional(),cacheRead:C().optional(),cacheWrite:C().optional(),total:C().optional()}).passthrough(),Eo=p({tokens:C().nullable().optional(),contextWindow:C().optional(),percent:C().nullable().optional()}).passthrough(),No=p({type:_("agent_session_stats_request"),requestId:c(),agentId:c()}).passthrough(),Ro=p({type:_("agent_session_stats_response"),requestId:c(),payload:p({sessionId:c().optional(),sessionFile:c().optional(),userMessages:C().optional(),assistantMessages:C().optional(),toolCalls:C().optional(),toolResults:C().optional(),totalMessages:C().optional(),tokens:jo.optional(),cost:C().optional(),contextUsage:Eo.optional(),model:c().optional()}).passthrough()}).passthrough(),qo=p({type:_("agent_compact_request"),requestId:c(),agentId:c(),customInstructions:c().optional()}).passthrough(),Bo=p({type:_("agent_compact_response"),requestId:c(),payload:p({summary:c().optional(),firstKeptEntryId:c().optional(),tokensBefore:C().optional(),details:$().optional()}).passthrough()}).passthrough(),Mo=p({type:_("agent_new_session_request"),requestId:c(),agentId:c()}).passthrough(),Ao=p({type:_("agent_new_session_response"),requestId:c(),payload:p({cancelled:E()}).passthrough()}).passthrough(),$o=p({type:_("agent_switch_session_request"),requestId:c(),agentId:c(),sessionPath:c()}).passthrough(),Do=p({type:_("agent_switch_session_response"),requestId:c(),payload:p({cancelled:E()}).passthrough()}).passthrough(),Oo=p({type:_("agent_fork_request"),requestId:c(),agentId:c(),entryId:c()}).passthrough(),Fo=p({type:_("agent_fork_response"),requestId:c(),payload:p({text:c(),cancelled:E()}).passthrough()}).passthrough(),Po=p({type:_("agent_fork_messages_request"),requestId:c(),agentId:c()}).passthrough(),Ho=p({type:_("agent_fork_messages_response"),requestId:c(),payload:p({messages:D(p({entryId:c(),text:c()}).passthrough())}).passthrough()}).passthrough(),zo=p({type:_("agent_clone_request"),requestId:c(),agentId:c()}).passthrough(),Wo=p({type:_("agent_clone_response"),requestId:c(),payload:p({cancelled:E()}).passthrough()}).passthrough(),Lo=p({type:_("agent_set_session_name_request"),requestId:c(),agentId:c(),name:c()}).passthrough(),Uo=p({type:_("agent_set_session_name_response"),requestId:c(),payload:p({}).passthrough().optional()}).passthrough(),Ko=p({type:_("agent_export_html_request"),requestId:c(),agentId:c(),outputPath:c().optional()}).passthrough(),Go=p({type:_("agent_export_html_response"),requestId:c(),payload:p({path:c()}).passthrough()}).passthrough(),Vo=p({type:_("agent_set_model_request"),requestId:c(),agentId:c(),provider:c(),modelId:c()}).passthrough(),Jo=p({type:_("agent_set_model_response"),requestId:c(),payload:p({}).passthrough()}).passthrough(),Yo=p({type:_("agent_cycle_model_request"),requestId:c(),agentId:c()}).passthrough(),Xo=p({type:_("agent_cycle_model_response"),requestId:c(),payload:p({model:$().nullable().optional(),thinkingLevel:c().optional(),isScoped:E().optional()}).passthrough()}).passthrough(),Qo=p({type:_("agent_last_assistant_text_request"),requestId:c(),agentId:c()}).passthrough(),Zo=p({type:_("agent_last_assistant_text_response"),requestId:c(),payload:p({text:c().nullable()}).passthrough()}).passthrough(),er=p({type:_("steer_agent_request"),requestId:c(),agentId:c(),message:c(),images:D(Re).optional(),clientMessageId:c().optional()}).passthrough(),tr=p({type:_("steer_agent_response"),requestId:c(),agentId:c(),ok:E()}).passthrough(),nr=p({type:_("follow_up_agent_request"),requestId:c(),agentId:c(),message:c(),images:D(Re).optional(),clientMessageId:c().optional()}).passthrough(),sr=p({type:_("follow_up_agent_response"),requestId:c(),agentId:c(),ok:E()}).passthrough(),or=p({type:_("rpc_error"),requestId:c(),code:c().optional(),message:c().optional(),error:c().optional()}),rr=Ne("type",[io,co,lo,uo,po,fo,ho,mo,bo,wo,So,xo,vo,ko,Io,Co,To,No,Ro,qo,Bo,Mo,Ao,$o,Do,Oo,Fo,Po,Ho,zo,Wo,Lo,Uo,Ko,Go,Vo,Jo,Yo,Xo,Qo,Zo,er,tr,nr,sr,or]),ar=p({type:c()}).passthrough(),ir=p({type:_("session"),message:It([rr,ar])});Ne("type",[eo,no,so,oo,ir]);const ie={Output:1,Input:2,Resize:3,Snapshot:4,Restore:5},cr=Object.fromEntries(Object.entries(ie).map(([t,e])=>[e,t])),Wt=p({rows:C().int().nonnegative(),cols:C().int().nonnegative()});class _e extends Error{constructor(e){super(e),this.name="TerminalFrameError"}}const lr=new TextEncoder,dr=new TextDecoder;function ur(t){if(!Number.isInteger(t)||t<0||t>255)throw new _e(`slot must be an integer 0–255, got ${t}`)}function he(t,e,n){const s=new Uint8Array(2+n.length);return s[0]=t,s[1]=e,s.set(n,2),s}function td(t){switch(ur(t.slot),t.opcode){case"Output":return he(ie.Output,t.slot,t.data);case"Input":return he(ie.Input,t.slot,t.data);case"Snapshot":return he(ie.Snapshot,t.slot,t.data);case"Restore":return he(ie.Restore,t.slot,t.data);case"Resize":{const e=JSON.stringify(Wt.parse({rows:t.rows,cols:t.cols}));return he(ie.Resize,t.slot,lr.encode(e))}}}function pr(t){if(t.length<2)throw new _e(`frame too short: ${t.length} bytes (need ≥ 2)`);const e=t[0],n=t[1],s=cr[e];if(!s)throw new _e(`unknown terminal opcode 0x${e.toString(16)}`);const o=t.subarray(2);if(s==="Resize"){let r;try{r=JSON.parse(dr.decode(o))}catch{throw new _e("resize payload is not valid JSON")}const a=Wt.safeParse(r);if(!a.success)throw new _e("resize payload is not { rows, cols }");return{opcode:"Resize",slot:n,rows:a.data.rows,cols:a.data.cols}}return{opcode:s,slot:n,data:o.slice()}}const le={Begin:16,Chunk:17,End:18,Error:19},fr=Object.fromEntries(Object.entries(le).map(([t,e])=>[e,t])),Lt=p({transferId:c(),fileName:c().optional(),mimeType:c().optional(),totalBytes:C().int().nonnegative().optional()});class ye extends Error{constructor(e){super(e),this.name="FileTransferFrameError"}}const ut=new TextEncoder,pt=new TextDecoder;function hr(t){if(!Number.isInteger(t)||t<0||t>255)throw new ye(`stream must be an integer 0–255, got ${t}`)}function Ie(t,e,n){const s=new Uint8Array(2+n.length);return s[0]=t,s[1]=e,s.set(n,2),s}function Ae(t){switch(hr(t.stream),t.opcode){case"Begin":return Ie(le.Begin,t.stream,ut.encode(JSON.stringify(Lt.parse(t.meta))));case"Chunk":return Ie(le.Chunk,t.stream,t.data);case"End":return Ie(le.End,t.stream,new Uint8Array([t.ok?1:0]));case"Error":return Ie(le.Error,t.stream,ut.encode(t.message))}}function gr(t){if(t.length<2)throw new ye(`frame too short: ${t.length} bytes (need ≥ 2)`);const e=t[0],n=t[1],s=fr[e];if(!s)throw new ye(`unknown file-transfer opcode 0x${e.toString(16)}`);const o=t.subarray(2);switch(s){case"Begin":{let r;try{r=JSON.parse(pt.decode(o))}catch{throw new ye("begin payload is not valid JSON")}const a=Lt.safeParse(r);if(!a.success)throw new ye("begin payload is not a valid transfer header");return{opcode:"Begin",stream:n,meta:a.data}}case"Chunk":return{opcode:"Chunk",stream:n,data:o.slice()};case"End":return{opcode:"End",stream:n,ok:(o[0]??1)!==0};case"Error":return{opcode:"Error",stream:n,message:pt.decode(o)}}}function mr(t){try{return gr(t)}catch{return null}}const _r=c().regex(/^[a-z][a-z0-9-]*$/,"invalid provider id"),yr=Se(["safe","moderate","dangerous","planning"]),br=p({supportsStreaming:E(),supportsSessionPersistence:E(),supportsDynamicModes:E(),supportsMcpServers:E(),supportsReasoningStream:E(),supportsToolInvocations:E(),supportsRewindConversation:E().optional(),supportsRewindFiles:E().optional(),supportsRewindBoth:E().optional(),supportsSteering:E().optional()}).passthrough(),wr=p({id:c(),label:c().optional(),description:c().optional(),icon:c().optional(),colorTier:yr});p({id:_r,label:c(),description:c().optional(),extends:c().optional(),modes:D(wr),capabilities:br});function We(t){return typeof t=="string"?t:t instanceof Uint8Array||Buffer.isBuffer(t)?t.toString("utf8"):String(t??"")}function Ut(t){let e=null;const n={onMessage:null,onClose:null,onError:null,get isOpen(){return e!==null&&e.readyState===1},connect(s){return new Promise((o,r)=>{const a=t??(()=>new WebSocket(s));try{e=t?a(s):new WebSocket(s)}catch(l){r(l);return}e.onopen=()=>o(),e.onerror=l=>{var d;(e==null?void 0:e.readyState)!==1&&r(l),(d=n.onError)==null||d.call(n,l)},e.onclose=l=>{var d;(d=n.onClose)==null||d.call(n,l.code,We(l.reason))},e.onmessage=l=>{var u,m,h,f;const{data:d}=l;d instanceof ArrayBuffer||d instanceof Uint8Array?(u=n.onMessage)==null||u.call(n,d):typeof d=="string"?(m=n.onMessage)==null||m.call(n,d):typeof Blob<"u"&&d instanceof Blob?(h=n.onMessage)==null||h.call(n,d):Buffer.isBuffer(d)&&((f=n.onMessage)==null||f.call(n,d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)))}})},sendText(s){e==null||e.send(s)},sendBinary(s){e==null||e.send(s)},close(s=1e3,o=""){e==null||e.close(s,o),e=null}};return n}const be="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function Kt(t){let e="";for(let n=0;n<t.length;n+=3){const s=t[n],o=n+1<t.length,r=n+2<t.length,a=o?t[n+1]:0,l=r?t[n+2]:0;e+=be[s>>2],e+=be[(s&3)<<4|a>>4],e+=o?be[(a&15)<<2|l>>6]:"=",e+=r?be[l&63]:"="}return e}function Gt(t){const e=t.replace(/=+$/,""),n=[];let s=0,o=0;for(const r of e){const a=be.indexOf(r);if(a===-1)throw new Error(`invalid base64 character: ${JSON.stringify(r)}`);s=s<<6|a,o+=6,o>=8&&(o-=8,n.push(s>>o&255))}return new Uint8Array(n)}function Sr(t){try{const e=JSON.parse(t);return!e||typeof e.type!="string"?null:e}catch{return null}}const Ee=24;function Vt(t,e){const n=de.randomBytes(Ee),s=de.box.after(t,n,e),o=new Uint8Array(n.length+s.length);return o.set(n,0),o.set(s,n.length),Kt(o)}function Jt(t,e){let n;try{n=Gt(t)}catch{return null}if(n.length<Ee)return null;const s=n.slice(0,Ee),o=n.slice(Ee);return de.box.open.after(o,s,e)}function xr(t,e){return Vt(new TextEncoder().encode(t),e)}function vr(t,e){const n=Jt(t,e);return n?new TextDecoder().decode(n):null}function kr(t,e,n,s,o,r){let a=!1;return n.onClose(l=>{var d;a=!0,(d=s.onClose)==null||d.call(s,l)}),{handleAppFrame(l){var m,h;if(a)return;const d=o();if(!r()||!d)return;const u=vr(l.frame,d);if(u===null){(m=s.onAuthError)==null||m.call(s,new Error(`relay ${t} channel: message failed authentication`));return}(h=s.onMessage)==null||h.call(s,u)},handleBinaryFrame(l){var m,h;if(a)return;const d=o();if(!r()||!d)return;const u=Jt(l.frame,d);if(u===null){(m=s.onAuthError)==null||m.call(s,new Error(`relay ${t} channel: binary message failed authentication`));return}(h=s.onBinaryMessage)==null||h.call(s,u)},send(l){if(a)throw new Error(`relay ${t} channel: cannot send after close()`);const d=o();if(!r()||!d)throw new Error(`relay ${t} channel: cannot send before the E2EE handshake completes`);n.send(JSON.stringify({type:"e2ee_app",frame:xr(l,d)}))},sendBinary(l){if(a)throw new Error(`relay ${t} channel: cannot send after close()`);const d=o();if(!r()||!d)throw new Error(`relay ${t} channel: cannot send before the E2EE handshake completes`);n.send(JSON.stringify({type:"e2ee_bin",frame:Vt(l,d)}))},close(){a||(a=!0,n.close())}}}function Ir(t){const{transport:e,attachment:n,daemonPublicKey:s}=t,o=t.events??{},r=de.box.keyPair(),a=de.box.before(s,r.secretKey);let l=!1;const d=kr("client",n,e,o,()=>a,()=>l);return e.onMessage(u=>{var h;const m=Sr(u);if(m){if(m.type==="e2ee_ready"){if(l)return;l=!0,(h=o.onReady)==null||h.call(o);return}if(m.type==="e2ee_app"){d.handleAppFrame(m);return}m.type==="e2ee_bin"&&d.handleBinaryFrame(m)}}),e.send(JSON.stringify({type:"e2ee_hello",ephemeralPublicKey:Kt(r.publicKey)})),{role:"client",attachment:n,get ready(){return l},send:d.send,sendBinary:d.sendBinary,close:d.close}}const Cr=16;function Tr(t){const e=de.hash(t);let n="";for(let s=0;s<Cr;s++)n+=e[s].toString(16).padStart(2,"0");return n}function jr(t){const e=t.useTls?"wss":"ws",n=t.endpoint.replace(/^(?:https?|wss?):\/\//,"").replace(/\/+$/,"");return`${e}://${n}`}function Er(t){let e=null,n=null;const s=t.sessionId??Tr(t.daemonPublicKey),o={onMessage:null,onClose:null,onError:null,get isOpen(){return e!==null&&e.readyState===1&&n!==null&&n.ready},connect(r){return new Promise((a,l)=>{const d=t.factory??(()=>new WebSocket(r));try{e=t.factory?d(r):new WebSocket(r)}catch(f){l(f);return}const u=e,m=[],h=[];u.onopen=()=>{u.send(JSON.stringify({type:"relay_register",sessionId:s})),n=Ir({transport:{send:f=>u.send(f),onMessage:f=>m.push(f),onClose:f=>h.push(f),close:()=>u.close()},attachment:{sessionId:s},daemonPublicKey:t.daemonPublicKey,events:{onReady:()=>a(),onMessage:f=>{var g;return(g=o.onMessage)==null?void 0:g.call(o,f)},onBinaryMessage:f=>{var g;return(g=o.onMessage)==null?void 0:g.call(o,f.slice().buffer)},onAuthError:f=>{var g;return(g=o.onError)==null?void 0:g.call(o,f)}}})},u.onerror=f=>{var g;u.readyState!==1&&l(f),(g=o.onError)==null||g.call(o,f)},u.onclose=f=>{var g;for(const w of h)w(We(f.reason));(g=o.onClose)==null||g.call(o,f.code,We(f.reason))},u.onmessage=f=>{const{data:g}=f;if(typeof g=="string")for(const w of m)w(g)}})},sendText(r){if(!n||!n.ready)throw new Error("relay transport: cannot send before the E2EE handshake completes");n.send(r)},sendBinary(r){if(!n||!n.ready)throw new Error("relay transport: cannot send before the E2EE handshake completes");n.sendBinary(r)},close(r=1e3,a=""){n==null||n.close(),n=null,e==null||e.close(r,a),e=null}};return o}function Nr(t){const e=t.indexOf("#"),n=e===-1?t:t.slice(e+1),s=new URLSearchParams(n),o=s.get("offer");if(!o)return null;let r;try{r=Gt(o)}catch{return null}const a=s.get("relay");if(a){const d={endpoint:a,useTls:s.get("relayTls")==="1"};return{publicKeyB64:o,publicKey:r,relay:d}}const l=s.get("host")??void 0;return{publicKeyB64:o,publicKey:r,...l?{host:l}:{}}}const Rr=1;function Le(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`id-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}class qr extends Error{constructor(e,n,s){super(e),this.requestId=n,this.code=s,this.name="RpcError"}}class ft extends Error{constructor(e){super(`RPC ${e} timed out`),this.requestId=e,this.name="RpcTimeoutError"}}class Br{constructor(e){I(this,"transport");I(this,"rpcTimeoutMs");I(this,"now");I(this,"_state","idle");I(this,"_serverId",null);I(this,"_features",{});I(this,"_serverCapabilities",{});I(this,"pending",new Map);I(this,"sessionHandlers",new Set);I(this,"terminalHandlers",new Set);I(this,"fileTransferHandlers",new Set);I(this,"stateHandlers",new Set);I(this,"helloResolve",null);I(this,"helloReject",null);this.options=e,this.transport=e.transport??Ut(),this.rpcTimeoutMs=e.rpcTimeoutMs??3e4,this.now=e.now??(()=>Date.now()),this.transport.onMessage=n=>this.handleIncoming(n),this.transport.onClose=(n,s)=>this.handleClose(n,s),this.transport.onError=()=>{}}get state(){return this._state}get serverId(){return this._serverId}get features(){return this._features}get serverCapabilities(){return this._serverCapabilities}hasFeature(e){return!!this._features[e]}async connect(){this.setState("connecting"),await this.transport.connect(this.options.url);const e=new Promise((s,o)=>{this.helloResolve=s,this.helloReject=o});this.transport.sendText(JSON.stringify({type:"hello",clientId:this.options.clientId,clientType:this.options.clientType,protocolVersion:this.options.protocolVersion??Rr,appVersion:this.options.appVersion,capabilities:this.options.capabilities}));const n=await e;return this._serverId=n.serverId,this._features=n.features,this._serverCapabilities=n.capabilities,this.setState("open"),n}close(e=1e3,n=""){this.setState("closing"),this.transport.close(e,n)}request(e,n={},s){const o=n.requestId??Le();return new Promise((r,a)=>{const l=s??this.rpcTimeoutMs,d=l>0?setTimeout(()=>{this.pending.delete(o),a(new ft(o))},l):null;this.pending.set(o,{resolve:u=>r(u),reject:a,timer:d}),this.sendSession({type:e,...n,requestId:o})})}sendSession(e){this.transport.sendText(JSON.stringify({type:"session",message:e}))}sendBinary(e){this.transport.sendBinary(e)}ping(e=1e4){const n=Le();return new Promise((s,o)=>{const r=e>0?setTimeout(()=>{this.pending.delete(n),o(new ft(n))},e):null;this.pending.set(n,{resolve:()=>s(),reject:o,timer:r}),this.transport.sendText(JSON.stringify({type:"ping",requestId:n,clientSentAt:this.now()}))})}onSessionMessage(e){return this.sessionHandlers.add(e),()=>this.sessionHandlers.delete(e)}onTerminalFrame(e){return this.terminalHandlers.add(e),()=>this.terminalHandlers.delete(e)}onFileTransferFrame(e){return this.fileTransferHandlers.add(e),()=>this.fileTransferHandlers.delete(e)}onStateChange(e){return this.stateHandlers.add(e),()=>this.stateHandlers.delete(e)}setState(e){if(this._state!==e){this._state=e;for(const n of this.stateHandlers)n(e)}}handleClose(e,n){this.helloReject&&(this.helloReject(new Error(`socket closed during handshake: ${n}`)),this.helloResolve=null,this.helloReject=null);for(const[,s]of this.pending)s.timer&&clearTimeout(s.timer),s.reject(new Error(`socket closed: ${n}`));this.pending.clear(),this.setState("closed")}handleIncoming(e){if(typeof e=="string"){this.handleTextFrame(e);return}if(e instanceof ArrayBuffer){this.handleBinaryFrame(new Uint8Array(e));return}typeof e.arrayBuffer=="function"&&e.arrayBuffer().then(n=>this.handleBinaryFrame(new Uint8Array(n)))}handleBinaryFrame(e){const n=e[0];if(n!==void 0&&Object.values(le).includes(n)){const r=mr(e);if(!r)return;for(const a of this.fileTransferHandlers)a(r);return}const o=pr(e);for(const r of this.terminalHandlers)r(o)}handleTextFrame(e){let n;try{n=JSON.parse(e)}catch{return}const s=n;switch(s.type){case"status":this.handleStatus(s);return;case"pong":this.resolvePending(s.requestId,void 0);return;case"ping":this.transport.sendText(JSON.stringify({type:"pong",requestId:s.requestId,serverReceivedAt:this.now(),serverSentAt:this.now()}));return;case"session":this.handleSession(s.message);return;default:return}}handleStatus(e){const n=e.payload;(n==null?void 0:n.status)==="server_info"&&this.helloResolve&&(this.helloResolve(n),this.helloResolve=null,this.helloReject=null)}handleSession(e){if(!e||typeof e!="object")return;const n=e;if(n.type==="rpc_error"&&typeof n.requestId=="string"){const s=this.pending.get(n.requestId);s&&(s.timer&&clearTimeout(s.timer),this.pending.delete(n.requestId),s.reject(new qr(n.message??n.error??"RPC failed",n.requestId,n.code)));return}if(typeof n.requestId=="string"&&this.pending.has(n.requestId)){const s="payload"in n?n.payload:n;this.resolvePending(n.requestId,s)}for(const s of this.sessionHandlers)s(e)}resolvePending(e,n){const s=this.pending.get(e);s&&(s.timer&&clearTimeout(s.timer),this.pending.delete(e),s.resolve(n))}}class Mr{constructor(e){this.daemon=e}get connection(){return this.daemon}async createAgent(e){return await this.daemon.request("create_agent_request",{...e})}agent(e){return new $r(this.daemon,e)}workspace(e){return new Dr(this.daemon,e)}get providers(){return new Or(this.daemon)}onAgentUpdate(e){return this.daemon.onSessionMessage(n=>{n.type==="agent_update"&&e(n)})}onWorkspaceUpdate(e){return this.daemon.onSessionMessage(n=>{n.type==="workspace_update"&&e(n)})}}class Ar{constructor(e,n){this.daemon=e,this.agentId=n}fetch(e={}){return this.daemon.request("fetch_agent_timeline_request",{agentId:this.agentId,cursor:e.cursor,direction:e.direction,limit:e.limit})}subscribe(e){return this.daemon.onSessionMessage(n=>{const s=n;s.type==="agent_stream"&&s.agentId===this.agentId&&s.event&&e(s.event)})}}class $r{constructor(e,n){I(this,"timeline");this.daemon=e,this.agentId=n,this.timeline=new Ar(e,n)}send(e,n={}){return this.daemon.request("send_agent_prompt",{agentId:this.agentId,prompt:e,clientMessageId:n.clientMessageId,images:n.images})}run(e,n){return this.send(e,n)}interrupt(){return this.daemon.request("interrupt_agent",{agentId:this.agentId})}steer(e,n={}){return this.daemon.request("steer_agent_request",{agentId:this.agentId,message:e,clientMessageId:n.clientMessageId,images:n.images})}followUp(e,n={}){return this.daemon.request("follow_up_agent_request",{agentId:this.agentId,message:e,clientMessageId:n.clientMessageId,images:n.images})}update(e){return this.daemon.request("update_agent",{agentId:this.agentId,...e})}resume(){return this.daemon.request("resume_agent",{agentId:this.agentId})}archive(){return this.daemon.request("archive_agent",{agentId:this.agentId})}delete(){return this.daemon.request("delete_agent",{agentId:this.agentId})}onUpdate(e){return this.daemon.onSessionMessage(n=>{const s=n;s.type==="agent_update"&&s.agentId===this.agentId&&e(s)})}sessionStats(){return this.daemon.request("agent_session_stats_request",{agentId:this.agentId})}compact(e){return this.daemon.request("agent_compact_request",{agentId:this.agentId,customInstructions:e})}newSession(){return this.daemon.request("agent_new_session_request",{agentId:this.agentId})}switchSession(e){return this.daemon.request("agent_switch_session_request",{agentId:this.agentId,sessionPath:e})}fork(e){return this.daemon.request("agent_fork_request",{agentId:this.agentId,entryId:e})}forkMessages(){return this.daemon.request("agent_fork_messages_request",{agentId:this.agentId})}clone(){return this.daemon.request("agent_clone_request",{agentId:this.agentId})}setSessionName(e){return this.daemon.request("agent_set_session_name_request",{agentId:this.agentId,name:e})}exportHtml(e){return this.daemon.request("agent_export_html_request",{agentId:this.agentId,outputPath:e})}setModel(e,n){return this.daemon.request("agent_set_model_request",{agentId:this.agentId,provider:e,modelId:n})}cycleModel(){return this.daemon.request("agent_cycle_model_request",{agentId:this.agentId})}lastAssistantText(){return this.daemon.request("agent_last_assistant_text_request",{agentId:this.agentId})}}class Dr{constructor(e,n){this.daemon=e,this.workspaceId=n}onUpdate(e){return this.daemon.onSessionMessage(n=>{const s=n;s.type==="workspace_update"&&s.workspaceId===this.workspaceId&&e(s)})}}class Or{constructor(e){this.daemon=e}listProviders(){return this.daemon.request("list_providers",{})}listModels(e){return this.daemon.request("list_provider_models",{provider:e})}listModes(e){return this.daemon.request("list_provider_modes",{provider:e})}refreshSnapshot(){return this.daemon.request("providers.snapshot.refresh.request",{})}}const ht=32*1024;function Fr(t){const e=t.reduce((o,r)=>o+r.length,0),n=new Uint8Array(e);let s=0;for(const o of t)n.set(o,s),s+=o.length;return n}class Pr{constructor(e){I(this,"pending",new Map);I(this,"nextStream",1);I(this,"detach",null);this.daemon=e}start(){this.detach||(this.detach=this.daemon.onFileTransferFrame(e=>this.dispatch(e)))}stop(){var e;(e=this.detach)==null||e.call(this),this.detach=null;for(const[n,s]of this.pending)s.reject(new Error("file transfer router stopped")),this.pending.delete(n)}async download(e){const n=await this.daemon.request("file_download_token_request",{path:e});if(!n.ok||!n.token)throw new Error(n.error??"failed to issue download token");const s=this.nextStream++,o=new Promise((a,l)=>{this.pending.set(s,{chunks:[],meta:{},resolve:a,reject:l})}),r=await this.daemon.request("file_download_request",{token:n.token,stream:s});if(!r.ok)throw this.pending.delete(s),new Error(r.error??"download request failed");return o}async upload(e,n){const s=Le(),o=await this.daemon.request("file_upload_request",{path:e,transferId:s});if(!o.ok||o.stream===void 0)throw new Error(o.error??"upload request failed");const r=o.stream;this.daemon.sendBinary(Ae({opcode:"Begin",stream:r,meta:{transferId:s}}));for(let a=0;a<n.length;a+=ht){const l=n.subarray(a,a+ht);this.daemon.sendBinary(Ae({opcode:"Chunk",stream:r,data:l}))}this.daemon.sendBinary(Ae({opcode:"End",stream:r,ok:!0}))}dispatch(e){const n=this.pending.get(e.stream);if(n)switch(e.opcode){case"Begin":n.meta.fileName=e.meta.fileName,n.meta.mimeType=e.meta.mimeType;return;case"Chunk":n.chunks.push(e.data);return;case"End":this.pending.delete(e.stream),e.ok?n.resolve({bytes:Fr(n.chunks),...n.meta}):n.reject(new Error("download failed"));return;case"Error":this.pending.delete(e.stream),n.reject(new Error(e.message));return}}}class Hr{constructor(e,n={}){I(this,"initialDelayMs");I(this,"maxDelayMs");I(this,"factor");I(this,"jitter");I(this,"maxAttempts");I(this,"setTimer");I(this,"clearTimer");I(this,"random");I(this,"attempt",0);I(this,"timer",null);I(this,"active",!1);I(this,"detachState",null);I(this,"reconnectedHandlers",new Set);I(this,"failedHandlers",new Set);this.daemon=e,this.initialDelayMs=n.initialDelayMs??500,this.maxDelayMs=n.maxDelayMs??3e4,this.factor=n.factor??2,this.jitter=n.jitter??.2,this.maxAttempts=n.maxAttempts??Number.POSITIVE_INFINITY,this.setTimer=n.setTimer??((s,o)=>setTimeout(s,o)),this.clearTimer=n.clearTimer??(s=>clearTimeout(s)),this.random=n.random??Math.random}delayForAttempt(e){const n=Math.min(this.maxDelayMs,this.initialDelayMs*this.factor**(e-1)),s=n*this.jitter*(this.random()*2-1);return Math.max(0,Math.round(n+s))}onReconnected(e){return this.reconnectedHandlers.add(e),()=>this.reconnectedHandlers.delete(e)}onReconnectFailed(e){return this.failedHandlers.add(e),()=>this.failedHandlers.delete(e)}start(){this.active||(this.active=!0,this.detachState=this.daemon.onStateChange(e=>{e==="closed"&&this.active&&this.scheduleReconnect(),e==="open"&&(this.attempt=0)}))}stop(){var e;this.active=!1,this.timer&&this.clearTimer(this.timer),this.timer=null,(e=this.detachState)==null||e.call(this),this.detachState=null}get attemptCount(){return this.attempt}scheduleReconnect(){if(!this.active||this.attempt>=this.maxAttempts)return;this.attempt+=1;const e=this.delayForAttempt(this.attempt);this.timer=this.setTimer(()=>{this.timer=null,this.tryReconnect()},e)}async tryReconnect(){if(!this.active)return;const e=this.attempt;try{await this.daemon.connect();for(const n of this.reconnectedHandlers)n({attempt:e,serverId:this.daemon.serverId})}catch(n){for(const s of this.failedHandlers)s(n,e);this.scheduleReconnect()}}}function gt(t){const e=t.trim();if(e==="")return e;const n=e.match(/^([a-z][a-z0-9+.-]*):\/\//i);if(!n)return`ws://${e.replace(/\/+$/,"")}`;const s=n[1].toLowerCase(),o=e.slice(n[0].length).replace(/\/+$/,"");switch(s){case"http":return`ws://${o}`;case"https":return`wss://${o}`;case"ws":case"wss":return`${s}://${o}`;default:return e}}function zr(t){const e=Nr(t);return e!=null&&e.relay?{mode:"relay",url:jr(e.relay),daemonPublicKey:e.publicKey}:e!=null&&e.host?{mode:"direct",url:gt(e.host)}:{mode:"direct",url:gt(t)}}function Wr(){return"web-"+Math.random().toString(36).slice(2,10)}const T=se()((t,e)=>({status:"idle",serverInfo:null,error:null,daemon:null,client:null,reconnection:null,async connect(n){e().disconnect();const s=zr(n.url);let o;s.mode==="relay"?o=Er({daemonPublicKey:s.daemonPublicKey}):n.password&&(o=Ut(d=>new WebSocket(d,[`pi-studio.bearer.${n.password}`])));const r=new Br({url:s.url,clientId:n.clientId??Wr(),clientType:"browser",capabilities:{},transport:o,rpcTimeoutMs:1800*1e3}),a=new Mr(r),l=new Hr(r);r.onStateChange(d=>t({status:d})),l.onReconnected(()=>t({error:null})),l.onReconnectFailed(d=>{t({error:d instanceof Error?d.message:String(d)})}),t({daemon:r,client:a,reconnection:l,error:null,status:"connecting"});try{const d=await r.connect();t({serverInfo:d}),l.start()}catch(d){throw t({error:d instanceof Error?d.message:String(d)}),d}},disconnect(){const{daemon:n,reconnection:s}=e();s==null||s.stop(),n==null||n.close(),t({status:"idle",serverInfo:null,daemon:null,client:null,reconnection:null})}})),Lr=100,Ur=480,Kr=220,Gr=280;function Ce(t){return Math.min(Ur,Math.max(Lr,t))}const v=se()(t=>({host:"ws://127.0.0.1:6767",password:"",cwd:"~",cwdPickerOpen:!1,sessionMenu:null,fileMenu:null,rightSidebarTab:"files",collapsedWorkspaces:new Set,leftSidebarCollapsed:!1,rightSidebarCollapsed:!1,leftSidebarWidth:Kr,rightSidebarWidth:Gr,setHost:e=>t({host:e}),setPassword:e=>t({password:e}),setCwd:e=>t({cwd:e}),openCwdPicker:()=>t({cwdPickerOpen:!0}),closeCwdPicker:()=>t({cwdPickerOpen:!1}),openSessionMenu:(e,n,s)=>t({sessionMenu:{sessionId:e,x:n,y:s}}),closeSessionMenu:()=>t({sessionMenu:null}),openFileMenu:(e,n,s,o)=>t({fileMenu:{path:e,isDirectory:n,x:s,y:o}}),closeFileMenu:()=>t({fileMenu:null}),setRightSidebarTab:e=>t({rightSidebarTab:e}),toggleWorkspaceCollapsed:e=>t(n=>{const s=new Set(n.collapsedWorkspaces);return s.has(e)?s.delete(e):s.add(e),{collapsedWorkspaces:s}}),toggleLeftSidebar:()=>t(e=>({leftSidebarCollapsed:!e.leftSidebarCollapsed})),toggleRightSidebar:()=>t(e=>({rightSidebarCollapsed:!e.rightSidebarCollapsed})),setLeftSidebarWidth:e=>t({leftSidebarWidth:Ce(e)}),setRightSidebarWidth:e=>t({rightSidebarWidth:Ce(e)}),resizeLeftSidebar:e=>t(n=>({leftSidebarWidth:Ce(n.leftSidebarWidth+e)})),resizeRightSidebar:e=>t(n=>({rightSidebarWidth:Ce(n.rightSidebarWidth+e)}))})),Vr="_wrap_emmus_1",Jr="_dot_emmus_8",Yr="_open_emmus_15",Xr="_connecting_emmus_18",Qr="_closed_emmus_21",Zr="_idle_emmus_22",ea="_closing_emmus_23",$e={wrap:Vr,dot:Jr,open:Yr,connecting:Xr,closed:Qr,idle:Zr,closing:ea},ta={idle:"disconnected",connecting:"connecting…",open:"connected",closing:"disconnecting…",closed:"disconnected"};function na(){const t=T(n=>n.status),e=T(n=>n.error);return i.jsxs("span",{className:$e.wrap,title:e??void 0,children:[i.jsx("span",{className:M($e.dot,$e[t])}),ta[t]??t]})}const sa="_toolbar_i9hmh_1",oa="_brand_i9hmh_10",ra="_version_i9hmh_16",aa="_sep_i9hmh_22",ia="_host_i9hmh_28",ca="_password_i9hmh_31",la="_sidebarToggles_i9hmh_34",Z={toolbar:sa,brand:oa,version:ra,sep:aa,host:ia,password:ca,sidebarToggles:la};function da(){const t=T(f=>f.status),e=T(f=>f.connect),n=T(f=>f.disconnect),s=v(f=>f.host),o=v(f=>f.setHost),r=v(f=>f.password),a=v(f=>f.setPassword),l=v(f=>f.leftSidebarCollapsed),d=v(f=>f.toggleLeftSidebar),u=v(f=>f.rightSidebarCollapsed),m=v(f=>f.toggleRightSidebar),h=t==="open"||t==="connecting";return i.jsxs("div",{className:Z.toolbar,children:[i.jsx("span",{className:Z.brand,children:"Pi-Studio"}),i.jsxs("span",{className:Z.version,children:["v","0.0.34"]}),i.jsx(na,{}),i.jsx("div",{className:Z.sep}),i.jsx(ze,{className:Z.host,value:s,onChange:f=>o(f.target.value),placeholder:"host:port, ws://…/http://…, or a pasted pairing link",disabled:h}),i.jsx(ze,{className:Z.password,type:"password",value:r,onChange:f=>a(f.target.value),placeholder:"password",disabled:h}),t==="open"||t==="connecting"||t==="closing"?i.jsx(z,{size:"sm",onClick:()=>n(),children:"Disconnect"}):i.jsx(z,{size:"sm",variant:"default",onClick:()=>void e({url:s,password:r||void 0}),children:"Connect"}),i.jsxs("div",{className:Z.sidebarToggles,children:[i.jsx(z,{size:"sm",variant:"ghost",iconOnly:!0,title:l?"Show sessions sidebar":"Hide sessions sidebar",onClick:()=>d(),children:l?i.jsx(bn,{size:16}):i.jsx(wn,{size:16})}),i.jsx(z,{size:"sm",variant:"ghost",iconOnly:!0,title:u?"Show files/changes sidebar":"Hide files/changes sidebar",onClick:()=>m(),children:u?i.jsx(Sn,{size:16}):i.jsx(xn,{size:16})})]})]})}const Ue={rows:[],streamingAssistantIndex:null,streamingReasoningIndex:null,toolIndexByCallId:{}};let mt=0;function X(){return mt+=1,`row-${mt}`}function ua(t){switch(t.kind){case"shell":return t.command??"";case"read":case"write":return t.path??"";case"edit":return t.path??"";case"search":return t.query??"";case"fetch":return t.url??"";case"task":return t.description??"";default:return""}}function pa(t,e){return t??`${e.kind}:${ua(e)}`}function fa(t){return{...t,streamingAssistantIndex:null,streamingReasoningIndex:null}}function ha(t,e){var r;const n=t.rows.slice();let s=t.streamingAssistantIndex;if(s===null||((r=n[s])==null?void 0:r.kind)!=="assistant"){const a={kind:"assistant",id:X(),text:"",streaming:!0};n.push(a),s=n.length-1}const o=n[s];return!o||o.kind!=="assistant"?t:(n[s]={...o,text:o.text+e},{...t,rows:n,streamingAssistantIndex:s,streamingReasoningIndex:null})}function ga(t,e){var r;const n=t.rows.slice();let s=t.streamingReasoningIndex;if(s===null||((r=n[s])==null?void 0:r.kind)!=="reasoning"){const a={kind:"reasoning",id:X(),text:"",streaming:!0};n.push(a),s=n.length-1}const o=n[s];return!o||o.kind!=="reasoning"?t:(n[s]={...o,text:o.text+e},{...t,rows:n,streamingReasoningIndex:s,streamingAssistantIndex:null})}function ma(t,e){if(t.kind!==e.kind)return e;const n={...t};for(const[s,o]of Object.entries(e))o!==void 0&&o!==""&&(n[s]=o);return n}function _a(t,e){var l;const n=pa(e.callId,e.tool),s=e.status==="completed"||e.status==="error"?e.status:"running",o=t.toolIndexByCallId[n],r=t.rows.slice();if(o!==void 0&&((l=r[o])==null?void 0:l.kind)==="tool"){const d=r[o];return d.kind!=="tool"?t:(r[o]={...d,tool:ma(d.tool,e.tool),status:s},{...t,rows:r,streamingAssistantIndex:null,streamingReasoningIndex:null})}const a={kind:"tool",id:X(),callId:n,tool:e.tool,status:s};return r.push(a),{...t,rows:r,toolIndexByCallId:{...t.toolIndexByCallId,[n]:r.length-1},streamingAssistantIndex:null,streamingReasoningIndex:null}}function nt(t){const e=t.rows.slice();if(t.streamingAssistantIndex!==null){const n=e[t.streamingAssistantIndex];(n==null?void 0:n.kind)==="assistant"&&(e[t.streamingAssistantIndex]={...n,streaming:!1})}if(t.streamingReasoningIndex!==null){const n=e[t.streamingReasoningIndex];(n==null?void 0:n.kind)==="reasoning"&&(e[t.streamingReasoningIndex]={...n,streaming:!1})}return{...t,rows:e,streamingAssistantIndex:null,streamingReasoningIndex:null}}function ya(t,e){const n=nt(t),s={kind:"error",id:X(),text:e||"turn failed"};return{...n,rows:[...n.rows,s]}}function ba(t){const e=nt(t),n={kind:"system",id:X(),text:"(canceled)"};return{...e,rows:[...e.rows,n]}}function wa(t,e){const n={kind:"error",id:X(),text:e||"error"};return{...t,rows:[...t.rows,n]}}function Sa(t,e,n,s){if(s!==void 0){const r=t.rows.findIndex(a=>a.kind==="user"&&a.pending&&a.clientMessageId===s);if(r!==-1){const a=t.rows.slice(),l=a[r];if((l==null?void 0:l.kind)==="user")return a[r]={...l,text:e,images:n,pending:!1},{...t,rows:a}}}const o={kind:"user",id:X(),text:e,images:n,clientMessageId:s};return{...t,rows:[...t.rows,o]}}function xa(t,e){let n=!1;const s=t.rows.map(o=>o.kind!=="user"||!o.queued||e.includes(o.text)?o:(n=!0,{...o,queued:!1}));return n?{...t,rows:s}:t}function Yt(t,e){switch(e.kind){case"turn_started":return fa(t);case"user_message":return Sa(t,e.text??"",e.images,e.messageId);case"assistant_message":return ha(t,e.text??"");case"reasoning":return ga(t,e.text??"");case"tool_call":return _a(t,e);case"turn_completed":return nt(t);case"turn_failed":return ya(t,e.error);case"turn_canceled":return ba(t);case"error":return wa(t,e.message);case"queue_update":return xa(t,e.steering??[]);default:return t}}function va(t,e,n,s,o){const r={kind:"user",id:X(),text:n,images:s,clientMessageId:e,pending:!0,queued:o};return{...t,rows:[...t.rows,r]}}function ka(t,e){const n=t.rows.findIndex(r=>r.kind==="user"&&r.pending&&r.clientMessageId===e);if(n===-1)return t;const s=t.rows.slice(),o=s[n];return(o==null?void 0:o.kind)!=="user"?t:(s[n]={...o,pending:!1,failed:!0},{...t,rows:s})}let _t=0;function Ia(){return _t+=1,`s-${Date.now().toString(36)}-${_t}`}const q=se()((t,e)=>({sessions:{},order:[],activeSessionId:null,createSession(n){const s=Ia(),o={id:s,agentId:null,title:"New chat",status:"idle",cwd:n,timeline:Ue,userMessageCount:0};return t(r=>({sessions:{...r.sessions,[s]:o},order:[s,...r.order],activeSessionId:s})),s},hydrate(n){t(s=>s.sessions[n.id]?s:{sessions:{...s.sessions,[n.id]:n},order:[...s.order,n.id]})},bindAgent(n,s){t(o=>{const r=o.sessions[n];return r?{sessions:{...o.sessions,[n]:{...r,agentId:s}}}:o})},setStatus(n,s){t(o=>{const r=o.sessions[n];return r?{sessions:{...o.sessions,[n]:{...r,status:s}}}:o})},setStatusByAgentId(n,s){const o=e().findByAgentId(n);o&&e().setStatus(o.id,s)},setModel(n,s){t(o=>{const r=o.sessions[n];return r?{sessions:{...o.sessions,[n]:{...r,model:s}}}:o})},setModelByAgentId(n,s){const o=e().findByAgentId(n);o&&e().setModel(o.id,s)},setTitle(n,s){t(o=>{const r=o.sessions[n];return r?{sessions:{...o.sessions,[n]:{...r,title:s}}}:o})},setCwd(n,s){t(o=>{const r=o.sessions[n];return r?{sessions:{...o.sessions,[n]:{...r,cwd:s}}}:o})},applyStreamEvent(n,s){t(o=>{const r=o.sessions[n];if(!r)return o;const a=Yt(r.timeline,s);let l=r.title;if(s.kind==="turn_completed"&&l==="New chat"){const d=a.rows.slice().reverse().find(u=>u.kind==="assistant");d&&d.kind==="assistant"&&d.text&&(l=d.text.slice(0,40)+(d.text.length>40?"…":""))}return{sessions:{...o.sessions,[n]:{...r,timeline:a,title:l}}}})},addOptimisticUserMessage(n,s,o,r,a){t(l=>{const d=l.sessions[n];if(!d)return l;const u=va(d.timeline,s,o,r,a);return{sessions:{...l.sessions,[n]:{...d,timeline:u,userMessageCount:d.userMessageCount+1}}}})},markUserMessageFailed(n,s){t(o=>{const r=o.sessions[n];if(!r)return o;const a=ka(r.timeline,s);return{sessions:{...o.sessions,[n]:{...r,timeline:a}}}})},activate(n){t({activeSessionId:n})},remove(n){t(s=>{const{[n]:o,...r}=s.sessions,a=s.order.filter(d=>d!==n),l=s.activeSessionId===n?a[0]??null:s.activeSessionId;return{sessions:r,order:a,activeSessionId:l}})},findByAgentId(n){return Object.values(e().sessions).find(s=>s.agentId===n)}}));function De(t,e){return t.filter(n=>n.workspaceCwd===e)}const j=se()((t,e)=>({tabs:[],activeTabId:null,activeWorkspaceCwd:null,lastActiveTabByWorkspace:{},open(n){const s=e().tabs.find(o=>o.id===n.id);if(s){e().activate(s.id);return}t(o=>({tabs:[...o.tabs,n],activeTabId:n.id,activeWorkspaceCwd:n.workspaceCwd,lastActiveTabByWorkspace:{...o.lastActiveTabByWorkspace,[n.workspaceCwd]:n.id}}))},close(n){t(s=>{const o=s.tabs.find(u=>u.id===n);if(!o)return s;const r=s.tabs.findIndex(u=>u.id===n),a=s.tabs.filter(u=>u.id!==n);let l=s.activeTabId;const d={...s.lastActiveTabByWorkspace};if(l===n){const u=De(a,o.workspaceCwd),m=Math.min(r,u.length-1),h=u[m];l=(h==null?void 0:h.id)??null}if(d[o.workspaceCwd]===n){const u=De(a,o.workspaceCwd)[0];u?d[o.workspaceCwd]=u.id:delete d[o.workspaceCwd]}return{tabs:a,activeTabId:l,lastActiveTabByWorkspace:d}})},activate(n){t(s=>{const o=s.tabs.find(r=>r.id===n);return o?{activeTabId:n,activeWorkspaceCwd:o.workspaceCwd,lastActiveTabByWorkspace:{...s.lastActiveTabByWorkspace,[o.workspaceCwd]:n}}:s})},switchWorkspace(n){t(s=>{var d;const o=De(s.tabs,n),r=s.lastActiveTabByWorkspace[n],l=r&&o.some(u=>u.id===r)?r:((d=o[0])==null?void 0:d.id)??null;return{activeWorkspaceCwd:n,activeTabId:l,lastActiveTabByWorkspace:l?{...s.lastActiveTabByWorkspace,[n]:l}:s.lastActiveTabByWorkspace}})},reorder(n,s){t(o=>{const r=o.tabs.findIndex(u=>u.id===n),a=o.tabs.findIndex(u=>u.id===s);if(r===-1||a===-1||r===a)return o;const l=o.tabs.slice(),[d]=l.splice(r,1);return d?(l.splice(a,0,d),{tabs:l}):o})},updateLabel(n,s){t(o=>({tabs:o.tabs.map(r=>r.id===n?{...r,label:s}:r)}))},updateData(n,s){t(o=>({tabs:o.tabs.map(r=>r.id===n?{...r,data:{...r.data,...s}}:r)}))}})),U={chat:t=>`chat-${t}`,file:t=>`file-${t}`,diff:(t,e)=>`diff-${t}${e?"-staged":""}`,terminal:t=>`term-${t}`};let Oe=0;function Xt(t){Oe+=1,j.getState().open({id:U.terminal(`new-${Oe}`),kind:"terminal",label:`Terminal ${Oe}`,closable:!0,data:{slot:null,cwd:t},workspaceCwd:t})}function qe(t){const e=q.getState().createSession(t);j.getState().open({id:U.chat(e),kind:"chat",label:"New chat",closable:!0,data:{sessionId:e},workspaceCwd:t})}const Te=se()(t=>({rootPath:"",expanded:new Set,expandedByRoot:new Map,setRoot:e=>t(n=>{const s=new Map(n.expandedByRoot);n.rootPath&&s.set(n.rootPath,n.expanded);const o=s.get(e),r=new Set(o);return r.add(e),{rootPath:e,expanded:r,expandedByRoot:s}}),toggle:e=>t(n=>{if(e===n.rootPath)return n;const s=new Set(n.expanded);s.has(e)?s.delete(e):s.add(e);const o=new Map(n.expandedByRoot);return o.set(n.rootPath,s),{expanded:s,expandedByRoot:o}})}));let ce=null;const Ke=new Set;function Ca(t){return Ke.add(t),()=>Ke.delete(t)}async function Be(t){var e;if(ce)return ce;try{const n=await t.connection.request("file_explorer_request",{path:"/home"}),o=(((e=n.result)==null?void 0:e.entries)??n.entries??[]).find(r=>r.kind==="directory"||r.type==="directory");ce="/home/"+((o==null?void 0:o.name)||"user")}catch{return"/tmp"}for(const n of Ke)n(ce);return ce}function Ta(){return ce}async function ja(t,e){return e==="~"||e.startsWith("~/")?await Be(t)+e.slice(1):e}function st(){const t=T(o=>o.client),e=T(o=>o.status),[n,s]=S.useState(Ta());return S.useEffect(()=>Ca(s),[]),S.useEffect(()=>{!t||e!=="open"||n||Be(t)},[t,e,n]),n}const Ea="_dot_202py_3",Na={dot:Ea};function Ra(t){const{status:e,requiresAttention:n,attentionReason:s,showInactive:o}=t;if(!e)return null;if(n)switch(s){case"permission":return"statusWarning";case"error":return"statusDanger";case"finished":default:return"statusSuccess"}switch(e){case"running":case"queued":return"accent";case"waiting":return"statusWarning";case"finished":return"statusSuccess";case"error":return"statusDanger";case"idle":case"archived":return o?"foregroundMuted":null}}const yt=8,qa={accent:"var(--pi-color-accent)",statusSuccess:"var(--pi-color-statusSuccess)",statusDanger:"var(--pi-color-statusDanger)",statusWarning:"var(--pi-color-statusWarning)",foregroundMuted:"var(--pi-color-foregroundMuted)"};function Ba({className:t,...e}){const n=Ra(e);return n?i.jsx("span",{className:`${Na.dot}${t?` ${t}`:""}`,style:{width:yt,height:yt,backgroundColor:qa[n]??"currentColor"},role:"presentation"}):null}const Ma={initializing:"queued",idle:"idle",running:"running",error:"error",closed:"finished"};function Aa(t){return Ma[t]??"idle"}const $a="_wrap_sqws5_1",Da="_header_sqws5_7",Oa="_list_sqws5_23",Fa="_item_sqws5_28",Pa="_active_sqws5_37",Ha="_title_sqws5_40",za="_meta_sqws5_49",Wa="_menuBtn_sqws5_57",La="_workspaceGroup_sqws5_75",Ua="_workspaceHeader_sqws5_78",Ka="_workspaceChevron_sqws5_91",Ga="_workspaceIcon_sqws5_102",Va="_workspaceLabel_sqws5_106",Ja="_workspaceCount_sqws5_112",Ya="_newSessionBtn_sqws5_117",Xa="_workspaceSessions_sqws5_129",A={wrap:$a,header:Da,list:Oa,item:Fa,active:Pa,title:Ha,meta:za,menuBtn:Wa,workspaceGroup:La,workspaceHeader:Ua,workspaceChevron:Ka,workspaceIcon:Ga,workspaceLabel:Va,workspaceCount:Ja,newSessionBtn:Ya,workspaceSessions:Xa};function Qa({session:t,active:e,onSelect:n,onOpenMenu:s}){return i.jsxs("div",{className:M(A.item,e&&A.active),onClick:n,onContextMenu:o=>{o.preventDefault(),s(o.clientX,o.clientY)},children:[i.jsxs("div",{className:A.title,children:[i.jsx(Ba,{status:Aa(t.status),showInactive:!0}),i.jsx("span",{children:t.title})]}),i.jsxs("div",{className:A.meta,children:[t.cwd||"~"," · ",t.agentId?t.agentId.slice(0,8):"new"," ·"," ",t.userMessageCount," msgs"]}),i.jsx("button",{type:"button",className:A.menuBtn,title:"Actions",onClick:o=>{o.stopPropagation();const r=o.currentTarget.getBoundingClientRect();s(r.left,r.bottom)},children:i.jsx(Ct,{size:14})})]})}const Za="_trigger_16o4s_1",ei="_content_16o4s_7",ti="_item_16o4s_16",ni="_danger_16o4s_33",si="_sep_16o4s_36",K={trigger:Za,content:ei,item:ti,danger:ni,sep:si};function oi(){const t=v(w=>w.sessionMenu),e=v(w=>w.closeSessionMenu),n=T(w=>w.client),s=S.useRef(null),[o,r]=S.useState(!1);S.useEffect(()=>{r(t!==null)},[t]);const a=q(w=>t?w.sessions[t.sessionId]:void 0);if(!t)return null;const l=!!(a!=null&&a.agentId)&&(a==null?void 0:a.status)==="running";function d(w){r(w),w||e()}function u(){if(!a)return;const w=window.prompt("Rename:",a.title);if(w!=null&&w.trim()){const b=w.trim();q.getState().setTitle(a.id,b),j.getState().updateLabel(U.chat(a.id),b),a.agentId&&(n==null||n.agent(a.agentId).update({title:b}).catch(()=>{}))}e()}function m(){a!=null&&a.agentId&&(n==null||n.agent(a.agentId).interrupt().catch(()=>{})),e()}function h(w){q.getState().remove(w),j.getState().close(U.chat(w))}async function f(){if(a){if(!window.confirm("Archive this agent? It can be resumed later."))return e();if(e(),!a.agentId){h(a.id);return}if(!n){window.alert("Not connected — cannot archive remotely.");return}try{await n.agent(a.agentId).archive(),h(a.id)}catch(w){window.alert(`Failed to archive: ${w instanceof Error?w.message:String(w)}`)}}}async function g(){if(a){if(!window.confirm("Permanently delete this agent? This cannot be undone."))return e();if(e(),!a.agentId){h(a.id);return}if(!n){window.alert("Not connected — cannot delete remotely.");return}try{await n.agent(a.agentId).delete(),h(a.id)}catch(w){window.alert(`Failed to delete: ${w instanceof Error?w.message:String(w)}`)}}}return i.jsxs(Ye,{open:o,onOpenChange:d,modal:!1,children:[i.jsx(Xe,{asChild:!0,children:i.jsx("button",{ref:s,type:"button",className:K.trigger,style:{left:t.x,top:t.y},"aria-hidden":!0,tabIndex:-1})}),i.jsx(Qe,{children:i.jsxs(Ze,{className:K.content,align:"start",sideOffset:2,children:[i.jsx(Y,{className:K.item,onSelect:u,children:"Rename"}),i.jsx(Y,{className:K.item,disabled:!l,onSelect:m,children:"Stop agent"}),i.jsx(Nt,{className:K.sep}),i.jsx(Y,{className:`${K.item} ${K.danger}`,onSelect:f,children:"Archive"}),i.jsx(Y,{className:`${K.item} ${K.danger}`,onSelect:g,children:"Delete permanently"})]})})]})}function ri({label:t,cwd:e,sessionCount:n,collapsed:s,onToggleCollapsed:o,onNewSession:r}){return i.jsxs("div",{className:A.workspaceHeader,onClick:o,title:e,children:[i.jsx("button",{type:"button",className:A.workspaceChevron,"aria-label":s?"Expand workspace":"Collapse workspace",onClick:a=>{a.stopPropagation(),o()},children:s?i.jsx(Ve,{size:13}):i.jsx(vn,{size:13})}),i.jsx(kn,{size:13,className:M(A.workspaceIcon)}),i.jsx("span",{className:A.workspaceLabel,children:t}),i.jsx("span",{className:A.workspaceCount,children:n}),i.jsx(z,{size:"xs",variant:"ghost",iconOnly:!0,title:"New conversation",className:A.newSessionBtn,onClick:a=>{a.stopPropagation(),r()},children:i.jsx(Tt,{size:13})})]})}function ne(t,e){return e&&(t==="~"||t.startsWith("~/"))?e+t.slice(1):t}function Qt(t,e,n){const s=new Map;for(const o of t){const r=e[o];if(!r)continue;const a=ne(r.cwd||"~",n),l=s.get(a);l?l.push(r):s.set(a,[r])}return Array.from(s,([o,r])=>({cwd:o,sessions:r}))}function ai(t){return!t||t==="~"?"~":t.split("/").filter(Boolean).pop()||t}function ii(){const t=q(b=>b.order),e=q(b=>b.sessions),n=q(b=>b.activeSessionId),s=q(b=>b.activate),o=j(b=>b.open),r=T(b=>b.status),a=v(b=>b.openSessionMenu),l=v(b=>b.setCwd),d=v(b=>b.openCwdPicker),u=v(b=>b.collapsedWorkspaces),m=v(b=>b.toggleWorkspaceCollapsed),h=st();function f(b){const N=ne(b||"~",h);qe(N)}function g(b){s(b);const N=e[b],O=ne((N==null?void 0:N.cwd)||"~",h);N!=null&&N.cwd&&l(N.cwd),o({id:U.chat(b),kind:"chat",label:(N==null?void 0:N.title)??"Chat",closable:!0,data:{sessionId:b},workspaceCwd:O})}const w=Qt(t,e,h);return i.jsxs("div",{className:A.wrap,children:[i.jsxs("div",{className:A.header,children:[i.jsx("h3",{children:"Workspaces"}),i.jsx(z,{size:"xs",variant:"ghost",iconOnly:!0,title:r!=="open"?"Connect to open a workspace":"Open a workspace folder",disabled:r!=="open",onClick:()=>d(),children:i.jsx(In,{size:14})})]}),i.jsx("div",{className:A.list,children:w.map(b=>{const N=u.has(b.cwd);return i.jsxs("div",{className:A.workspaceGroup,children:[i.jsx(ri,{label:ai(b.cwd),cwd:b.cwd,sessionCount:b.sessions.length,collapsed:N,onToggleCollapsed:()=>m(b.cwd),onNewSession:()=>f(b.cwd)}),!N&&i.jsx("div",{className:A.workspaceSessions,children:b.sessions.map(O=>i.jsx(Qa,{session:O,active:O.id===n,onSelect:()=>g(O.id),onOpenMenu:(k,oe)=>a(O.id,k,oe)},O.id))})]},b.cwd)})}),i.jsx(oi,{})]})}const ci="_strip_8jveh_1",li="_tab_8jveh_10",di="_active_8jveh_26",ui="_icon_8jveh_30",pi="_label_8jveh_35",fi="_close_8jveh_40",hi="_newTab_8jveh_50",gi="_content_8jveh_73",mi="_item_8jveh_82",_i="_itemIcon_8jveh_96",P={strip:ci,tab:li,active:di,icon:ui,label:pi,close:fi,newTab:hi,content:gi,item:mi,itemIcon:_i},yi={chat:Et,file:Tn,diff:Cn,terminal:jt};function bi({tab:t}){const e=j(h=>h.activeTabId),n=j(h=>h.activate),s=j(h=>h.close),o=yi[t.kind],{attributes:r,listeners:a,setNodeRef:l,transform:d,transition:u,isDragging:m}=Jn({id:t.id});return i.jsxs("div",{ref:l,className:M(P.tab,t.id===e&&P.active),style:{transform:Yn.Transform.toString(d),transition:u,opacity:m?.5:1},onClick:()=>n(t.id),onAuxClick:h=>{h.button===1&&t.closable&&s(t.id)},title:t.label,...r,...a,children:[i.jsx("span",{className:P.icon,children:i.jsx(o,{size:13})}),i.jsx("span",{className:P.label,children:t.label}),t.closable&&i.jsx("span",{className:P.close,onClick:h=>{h.stopPropagation(),s(t.id)},children:i.jsx(Fe,{size:12})})]})}function wi({workspaceCwd:t}){const e=t??"~";return i.jsxs(Ye,{children:[i.jsx(Xe,{asChild:!0,children:i.jsx("button",{type:"button",className:P.newTab,title:"New tab",disabled:!t,children:i.jsx(Tt,{size:14})})}),i.jsx(Qe,{children:i.jsxs(Ze,{className:P.content,align:"start",sideOffset:4,children:[i.jsxs(Y,{className:P.item,onSelect:()=>qe(e),children:[i.jsx(Et,{size:13,className:P.itemIcon}),"New chat"]}),i.jsxs(Y,{className:P.item,onSelect:()=>Xt(e),children:[i.jsx(jt,{size:13,className:P.itemIcon}),"New terminal"]})]})})]})}function Si(){const t=j(a=>a.tabs),e=j(a=>a.activeWorkspaceCwd),n=j(a=>a.reorder),s=t.filter(a=>a.workspaceCwd===e),o=zn(Wn(Vn,{activationConstraint:{distance:4}}));function r(a){const{active:l,over:d}=a;!d||l.id===d.id||n(String(l.id),String(d.id))}return i.jsxs("div",{className:P.strip,children:[i.jsx(Ln,{sensors:o,collisionDetection:Un,onDragEnd:r,children:i.jsx(Kn,{items:s.map(a=>a.id),strategy:Gn,children:s.map(a=>i.jsx(bi,{tab:a},a.id))})}),i.jsx(wi,{workspaceCwd:e})]})}const xi="_spinner_1tgzp_3",vi={spinner:xi},ki={xs:12,sm:16,md:20,lg:24},Ii={xs:1,sm:2,md:2,lg:3};function Ci({size:t="md",color:e="currentColor",className:n,"aria-label":s="Loading"}){const o=typeof t=="number"?t:ki[t],r=typeof t=="number"?2:Ii[t];return i.jsx("span",{className:`${vi.spinner}${n?` ${n}`:""}`,role:"status","aria-label":s,style:{width:o,height:o,borderWidth:r,color:e}})}const Ti=S.lazy(()=>et(()=>import("./ChatPanel-XI36Imum.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13])).then(t=>({default:t.ChatPanel}))),bt=S.lazy(()=>et(()=>import("./FilePanel-VOhIehHw.js").then(t=>t.F),__vite__mapDeps([14,1,7,6,5,2,9,10,15])).then(t=>({default:t.FilePanel}))),ji=S.lazy(()=>et(()=>import("./TerminalPanel-KNfHGYYL.js"),__vite__mapDeps([16,1,17,18,7,6,5,2,3,11,12,19])).then(t=>({default:t.TerminalPanel}))),Ei={chat:Ti,file:bt,diff:bt,terminal:ji},Ni="_area_1vzxd_1",Ri="_panel_1vzxd_7",qi="_active_1vzxd_14",Bi="_empty_1vzxd_17",ge={area:Ni,panel:Ri,active:qi,empty:Bi};function Mi(){const t=j(o=>o.tabs),e=j(o=>o.activeTabId),n=j(o=>o.activeWorkspaceCwd);return t.some(o=>o.workspaceCwd===n)?i.jsx("div",{className:ge.area,children:t.map(o=>{const r=Ei[o.kind];return i.jsx("div",{className:M(ge.panel,o.id===e&&ge.active),children:i.jsx(S.Suspense,{fallback:i.jsx(Ci,{size:"md"}),children:i.jsx(r,{tab:o})})},o.id)})}):i.jsx("div",{className:ge.area,children:i.jsx("div",{className:ge.empty,children:"No open tabs in this workspace"})})}const Zt={fileRead:t=>["file","read",t],fileDownload:t=>["file","download",t],fileDiff:(t,e,n)=>["file","diff",t,e,n],explorer:t=>["explorer",t],agentList:()=>["agents","list"],agentTimeline:t=>["agents","timeline",t]};function Ai(t){const e=t.kind==="directory"||t.type==="directory"?"directory":"file";return{name:t.name??"",kind:e,size:t.size,mtimeMs:t.mtimeMs}}function $i(t){return t.slice().sort((e,n)=>e.kind!==n.kind?e.kind==="directory"?-1:1:e.name.localeCompare(n.name))}async function en(t,e){const s=(await t.connection.request("file_explorer_request",{path:e})).result;if(!s||s.ok===!1)throw new Error(s&&"error"in s?s.error:"explorer request failed");const o="entries"in s?s.entries??[]:[];return{path:s.resolvedPath??e,entries:$i(o.map(Ai))}}function Di(t,e=!0){const n=T(s=>s.client);return gn({queryKey:Zt.explorer(t),queryFn:()=>{if(!n)throw new Error("not connected");return en(n,t)},enabled:!!n&&!!t&&e})}function Oi(t){const e=T(o=>o.client),n=S.useMemo(()=>Array.from(t),[t]),s=mn({queries:n.map(o=>({queryKey:Zt.explorer(o),queryFn:()=>{if(!e)throw new Error("not connected");return en(e,o)},enabled:!!e&&!!o}))});return S.useMemo(()=>{const o=new Map;return n.forEach((r,a)=>{const l=s[a];o.set(r,{listing:l==null?void 0:l.data,isLoading:!!(l!=null&&l.isLoading),isError:!!(l!=null&&l.isError),error:l==null?void 0:l.error})}),o},[n,s])}const wt=new WeakMap;function St(t){let e=wt.get(t);return e||(e=new Pr(t),e.start(),wt.set(t,e)),e}function Fi(t,e,n){const s=new Blob([Uint8Array.from(t)],{type:n||"application/octet-stream"}),o=URL.createObjectURL(s),r=document.createElement("a");r.href=o,r.download=e,r.rel="noopener",document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(o),0)}function tn(){const t=T(o=>o.daemon),e=Ge(),n=S.useCallback(async(o,r)=>{if(!t)throw new Error("not connected");const a=o?`${o}/${r.name}`:r.name,l=new Uint8Array(await r.arrayBuffer());await St(t).upload(a,l),await e.invalidateQueries({queryKey:["explorer"]})},[t,e]),s=S.useCallback(async o=>{if(!t)throw new Error("not connected");const r=await St(t).download(o);Fi(r.bytes,r.fileName||o.split("/").pop()||"download",r.mimeType)},[t]);return{upload:n,saveToDisk:s}}function Pi(t,e){return t.endsWith("/")?`${t}${e}`:`${t}/${e}`}function nn(t,e,n,s,o){var a;const r=o.get(e);if(!r||r.isLoading){t.push({kind:"loading",path:e,depth:n});return}if(r.isError){const l=r.error instanceof Error?r.error.message:"failed to load";t.push({kind:"error",path:e,depth:n,message:l});return}for(const l of((a=r.listing)==null?void 0:a.entries)??[])Hi(t,e,l,n,s,o)}function Hi(t,e,n,s,o,r){const a=Pi(e,n.name);if(n.kind!=="directory"){t.push({kind:"file",path:a,name:n.name,depth:s});return}const l=o.has(a);t.push({kind:"directory",path:a,name:n.name,depth:s,expanded:l}),l&&nn(t,a,s+1,o,r)}function zi(t,e,n){if(!t)return[];const s=[];return nn(s,t,0,e,n),s}const Wi="_container_yg965_1",Li="_header_yg965_7",Ui="_uploadButton_yg965_13",Ki="_hiddenInput_yg965_32",Gi="_status_yg965_35",Vi="_statusError_yg965_36",Ji="_rowAction_yg965_49",Yi="_item_yg965_64",Xi="_dropOverlay_yg965_67",Qi="_list_yg965_82",Zi="_chevronSlot_yg965_101",ec="_chevron_yg965_101",tc="_chevronOpen_yg965_112",nc="_icon_yg965_115",sc="_name_yg965_122",oc="_dirName_yg965_127",rc="_statusRow_yg965_133",ac="_statusRowError_yg965_144",ic="_emptyState_yg965_147",R={container:Wi,header:Li,uploadButton:Ui,hiddenInput:Ki,status:Gi,statusError:Vi,rowAction:Ji,item:Yi,dropOverlay:Xi,list:Qi,chevronSlot:Zi,chevron:ec,chevronOpen:tc,icon:nc,name:sc,dirName:oc,statusRow:rc,statusRowError:ac,emptyState:ic},cc=14;function lc({row:t,onToggle:e,onOpenFile:n,onContextMenu:s}){const o={paddingLeft:8+t.depth*cc};if(t.kind==="loading")return i.jsx("div",{className:R.statusRow,style:o,children:"Loading…"});if(t.kind==="error")return i.jsx("div",{className:M(R.statusRow,R.statusRowError),style:o,children:t.message??"failed to load"});const r=t.kind==="directory";return i.jsxs("div",{className:R.item,style:o,onClick:()=>r?e(t.path):n(t.path),onContextMenu:a=>{a.preventDefault(),s(t.path,r,a.clientX,a.clientY)},children:[i.jsx("span",{className:R.chevronSlot,children:r&&i.jsx(Ve,{size:12,className:M(R.chevron,t.expanded&&R.chevronOpen)})}),i.jsx("span",{className:R.icon,children:r?i.jsx(Je,{size:14}):i.jsx(jn,{size:14})}),i.jsx("span",{className:r?R.dirName:R.name,children:t.name}),i.jsx("button",{type:"button",className:R.rowAction,title:"Actions",onClick:a=>{a.stopPropagation();const l=a.currentTarget.getBoundingClientRect();s(t.path,r,l.left,l.bottom)},children:i.jsx(Ct,{size:12})})]})}const dc="_trigger_g81d7_1",uc="_content_g81d7_7",pc="_item_g81d7_16",fc="_danger_g81d7_29",hc="_sep_g81d7_32",re={trigger:dc,content:uc,item:pc,danger:fc,sep:hc};function gc(){const t=v(f=>f.fileMenu),e=v(f=>f.closeFileMenu),n=T(f=>f.client),{saveToDisk:s}=tn(),o=Ge(),r=S.useRef(null),[a,l]=S.useState(!1);if(S.useEffect(()=>{l(t!==null)},[t]),!t)return null;const d=t.path.split("/").pop()||t.path;function u(f){l(f),f||e()}async function m(){if(t){e();try{await s(t.path)}catch(f){window.alert(`Failed to download: ${f instanceof Error?f.message:String(f)}`)}}}async function h(){if(!t)return;const f=t.isDirectory?"folder (and everything inside it)":"file";if(!window.confirm(`Permanently delete this ${f}? "${d}" — this cannot be undone.`))return e();if(e(),!n){window.alert("Not connected — cannot delete remotely.");return}try{const g=await n.connection.request("file_delete_request",{path:t.path});if(!g.ok)throw new Error(g.error??"delete failed");await o.invalidateQueries({queryKey:["explorer"]})}catch(g){window.alert(`Failed to delete: ${g instanceof Error?g.message:String(g)}`)}}return i.jsxs(Ye,{open:a,onOpenChange:u,modal:!1,children:[i.jsx(Xe,{asChild:!0,children:i.jsx("button",{ref:r,type:"button",className:re.trigger,style:{left:t.x,top:t.y},"aria-hidden":!0,tabIndex:-1})}),i.jsx(Qe,{children:i.jsxs(Ze,{className:re.content,align:"start",sideOffset:2,children:[!t.isDirectory&&i.jsx(Y,{className:re.item,onSelect:m,children:"Download"}),i.jsx(Nt,{className:re.sep}),i.jsx(Y,{className:`${re.item} ${re.danger}`,onSelect:h,children:"Delete"})]})})]})}const mc=24;function _c(){const t=T(x=>x.client),e=Te(x=>x.rootPath),n=Te(x=>x.expanded),s=Te(x=>x.setRoot),o=Te(x=>x.toggle),r=j(x=>x.activeWorkspaceCwd),a=j(x=>x.open),{upload:l}=tn(),d=v(x=>x.openFileMenu),[u,m]=S.useState(null),[h,f]=S.useState(!1),[g,w]=S.useState(null),b=S.useRef(null),N=S.useRef(null),O=S.useRef(null);S.useEffect(()=>{if(!t)return;const x=r||"~";O.current!==x&&(O.current=x,ja(t,x).then(B=>s(B)))},[t,r,s]);const k=Oi(n),oe=S.useMemo(()=>zi(e,n,k),[e,n,k]),rt=_n({count:oe.length,getScrollElement:()=>N.current,estimateSize:()=>mc,overscan:12,getItemKey:x=>{var B;return((B=oe[x])==null?void 0:B.path)??x}});function rn(x){a({id:U.file(x),kind:"file",label:x.split("/").pop()||x,closable:!0,data:{path:x},workspaceCwd:r||"~"})}async function at(x,B){var xe;if(!B.length||!x)return;const Q=(xe=k.get(x))==null?void 0:xe.listing,Me=new Set((Q==null?void 0:Q.entries.map(W=>W.name))??[]),ue=B.filter(W=>Me.has(W.name));if(ue.length>0){const W=ue.map(ln=>ln.name).join(", ");if(!window.confirm(`Overwrite ${ue.length>1?"these files":"this file"}? ${W}`))return}m({text:`Uploading ${B.length} file${B.length>1?"s":""}…`,error:!1});try{for(const W of B)await l(x,W);m({text:`Uploaded ${B.length} file${B.length>1?"s":""}`,error:!1})}catch(W){m({text:`Upload failed: ${W instanceof Error?W.message:"unknown"}`,error:!0})}}function an(x){x.preventDefault(),f(!1);const B=g??e;w(null);const Q=Array.from(x.dataTransfer.files);at(B,Q)}function cn(x){x.dataTransfer.types.includes("Files")&&(x.preventDefault(),f(!0))}return t?i.jsxs("div",{className:R.container,onDragOver:cn,onDragLeave:()=>f(!1),onDrop:an,children:[i.jsxs("div",{className:R.header,children:[i.jsxs("button",{type:"button",className:R.uploadButton,onClick:()=>{var x;return(x=b.current)==null?void 0:x.click()},disabled:!e,title:"Upload files to the workspace root",children:[i.jsx(En,{size:12}),i.jsx("span",{children:"Upload"})]}),i.jsx("input",{ref:b,type:"file",multiple:!0,className:R.hiddenInput,onChange:x=>{at(e,Array.from(x.target.files??[])),x.target.value=""}})]}),u&&i.jsx("div",{className:u.error?R.statusError:R.status,children:u.text}),i.jsxs("div",{className:R.list,ref:N,children:[oe.length===0&&i.jsx("div",{className:R.emptyState,children:"No files loaded"}),i.jsx("div",{style:{position:"relative",height:rt.getTotalSize()},children:rt.getVirtualItems().map(x=>{const B=oe[x.index];return B?i.jsx("div",{"data-index":x.index,style:{position:"absolute",top:0,left:0,width:"100%",height:x.size,transform:`translateY(${x.start}px)`},onDragEnter:()=>{B.kind==="directory"&&w(B.path)},children:i.jsx(lc,{row:B,onToggle:o,onOpenFile:rn,onContextMenu:(Q,Me,ue,xe)=>d(Q,Me,ue,xe)})},x.key):null})})]}),h&&i.jsx("div",{className:R.dropOverlay,children:"Drop to upload"}),i.jsx(gc,{})]}):i.jsx("div",{className:R.emptyState,children:"Connect to browse files"})}const xt={available:!1,branch:null,upstream:null,ahead:0,behind:0,detached:!1,conflictCount:0},L=se()(t=>({subscribedCwd:null,changes:[],...xt,setSubscribedCwd:e=>t({subscribedCwd:e}),applyProjection:e=>{if(!e||!e.available){t({changes:[],...xt});return}const n=[];for(const s of e.staged)n.push({path:s.path,status:s.indexStatus==="A"?"added":s.indexStatus==="D"?"deleted":"modified",staged:!0});for(const s of e.unstaged)n.push({path:s.path,status:s.worktreeStatus==="D"?"deleted":"modified",staged:!1});for(const s of e.untracked)n.push({path:s,status:"added",staged:!1});t({changes:n,available:!0,branch:e.branch,upstream:e.upstream,ahead:e.ahead,behind:e.behind,detached:e.detached,conflictCount:e.conflicted.length})}})),yc="_list_1pgby_1",bc="_summary_1pgby_4",wc="_item_1pgby_11",Sc="_badge_1pgby_23",xc="_added_1pgby_30",vc="_modified_1pgby_34",kc="_deleted_1pgby_38",Ic="_name_1pgby_42",Cc="_emptyState_1pgby_47",ee={list:yc,summary:bc,item:wc,badge:Sc,added:xc,modified:vc,deleted:kc,name:Ic,emptyState:Cc},Tc={added:"A",modified:"M",deleted:"D"};function jc(){const e=j(r=>r.activeWorkspaceCwd)||"~",n=L(r=>r.changes),s=j(r=>r.open);function o(r,a){s({id:U.diff(r,a),kind:"diff",label:r.split("/").pop()||r,closable:!0,data:{path:r,staged:a},workspaceCwd:e})}return n.length===0?i.jsx("div",{className:ee.emptyState,children:"No changes detected"}):i.jsxs("div",{className:ee.list,children:[i.jsxs("div",{className:ee.summary,children:[n.length," changed file",n.length===1?"":"s"]}),n.map((r,a)=>i.jsxs("div",{className:ee.item,onClick:()=>o(r.path,r.staged),children:[i.jsx("span",{className:M(ee.badge,ee[r.status]),children:Tc[r.status]}),i.jsx("span",{className:ee.name,children:r.path})]},`${r.path}-${r.staged}-${a}`))]})}const Ec="_wrap_r37ok_1",Nc="_tabBar_r37ok_7",Rc="_tabBtn_r37ok_13",qc="_active_r37ok_26",Bc="_refreshBtn_r37ok_30",Mc="_content_r37ok_34",V={wrap:Ec,tabBar:Nc,tabBtn:Rc,active:qc,refreshBtn:Bc,content:Mc};function Ac(){const t=v(l=>l.rightSidebarTab),e=v(l=>l.setRightSidebarTab),s=j(l=>l.activeWorkspaceCwd)||"~",o=T(l=>l.client),r=Ge();function a(){r.invalidateQueries({queryKey:["explorer"]}),o&&s&&o.connection.request("checkout_refresh_request",{cwd:s}).catch(()=>{})}return i.jsxs("div",{className:V.wrap,children:[i.jsxs("div",{className:V.tabBar,children:[i.jsx("button",{type:"button",className:M(V.tabBtn,t==="files"&&V.active),onClick:()=>e("files"),children:"Files"}),i.jsx("button",{type:"button",className:M(V.tabBtn,t==="changes"&&V.active),onClick:()=>e("changes"),children:"Changes"}),i.jsx(z,{size:"xs",variant:"ghost",iconOnly:!0,title:"Refresh",className:V.refreshBtn,onClick:a,children:i.jsx(Nn,{size:13})})]}),i.jsx("div",{className:V.content,children:t==="files"?i.jsx(_c,{}):i.jsx(jc,{})})]})}const sn=se()(t=>({bySession:{},setStats(e,n){t(s=>({bySession:{...s.bySession,[e]:{...s.bySession[e],...n}}}))},clear(e){t(n=>{const{[e]:s,...o}=n.bySession;return{bySession:o}})}})),$c=12e3;function Dc(t,e){return t==="running"&&e!=="running"}function vt(t,e){var s,o,r,a,l,d;const n={};((s=e.contextUsage)==null?void 0:s.tokens)!=null&&(n.contextTokens=e.contextUsage.tokens),((o=e.contextUsage)==null?void 0:o.contextWindow)!==void 0&&(n.contextWindow=e.contextUsage.contextWindow),((r=e.contextUsage)==null?void 0:r.percent)!=null&&(n.contextPercent=e.contextUsage.percent),((a=e.tokens)==null?void 0:a.total)!==void 0&&(n.totalTokens=e.tokens.total),((l=e.tokens)==null?void 0:l.input)!==void 0&&(n.inputTokens=e.tokens.input),((d=e.tokens)==null?void 0:d.output)!==void 0&&(n.outputTokens=e.tokens.output),e.cost!==void 0&&(n.cost=e.cost),e.model!==void 0&&(n.model=e.model,q.getState().setModel(t,e.model)),sn.getState().setStats(t,n)}function Oc(t){const e=T(l=>l.client),n=T(l=>l.status),s=q(l=>{var d;return t?((d=l.sessions[t])==null?void 0:d.agentId)??null:null}),o=q(l=>{var d;return t?(d=l.sessions[t])==null?void 0:d.status:void 0}),r=S.useRef(!1),a=S.useRef(void 0);S.useEffect(()=>{if(n!=="open"||!e||!t||!s)return;let l=!1;const d=async()=>{if(!r.current){r.current=!0;try{const m=await e.agent(s).sessionStats();l||vt(t,m)}catch{}finally{r.current=!1}}};d();const u=setInterval(()=>void d(),$c);return()=>{l=!0,clearInterval(u)}},[n,e,t,s]),S.useEffect(()=>{const l=a.current;a.current=o,Dc(l,o)&&(n!=="open"||!e||!t||!s||(r.current=!1,e.agent(s).sessionStats().then(d=>vt(t,d)).catch(()=>{})))},[o,n,e,t,s])}function Fc(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="checkout_status_update"&&"cwd"in t&&typeof t.cwd=="string"&&"projection"in t&&typeof t.projection=="object"&&t.projection!==null}function Pc(t){const e=T(r=>r.client),n=L(r=>r.applyProjection),s=L(r=>r.setSubscribedCwd),o=S.useRef(e);return o.current=e,S.useEffect(()=>{if(!e||!t)return;let r=!1;e.connection.request("checkout_status_subscribe",{cwd:t}).catch(()=>{}),s(t);const a=e.connection.onSessionMessage(l=>{if(r)return;const d=l;Fc(d)&&d.cwd===t&&n(d.projection)});return e.connection.request("checkout_refresh_request",{cwd:t}).catch(()=>{}),()=>{r=!0,a(),e.connection.request("checkout_status_unsubscribe",{cwd:t}).catch(()=>{}),s(null)}},[e,t,n,s]),{refresh(){const r=o.current;!r||!t||r.connection.request("checkout_refresh_request",{cwd:t}).catch(()=>{})}}}const ot="--";function me(t){return t===void 0?ot:t<1e3?String(t):t<1e6?`${(t/1e3).toFixed(1)}k`:`${(t/1e6).toFixed(1)}M`}function Hc(t){if(t==null)return ot;const e=t<=1?t*100:t;return`${Math.round(e)}%`}function zc(t){if(t===void 0)return ot;const e=t<1?4:2;return`$${t.toFixed(e)}`}function Wc(t,e){return e?t===e?"~":t.startsWith(`${e}/`)?`~${t.slice(e.length)}`:t:t}function Lc(t,e){const n=[];return t>0&&n.push(`↑${t}`),e>0&&n.push(`↓${e}`),n.join(" ")}const Uc="_statusBar_gvk7q_1",Kc="_segmentGroup_gvk7q_16",Gc="_chevron_gvk7q_20",Vc="_segment_gvk7q_16",Jc="_icon_gvk7q_33",Yc="_text_gvk7q_39",ae={statusBar:Uc,segmentGroup:Kc,chevron:Gc,segment:Vc,icon:Jc,text:Yc};function Xc(){const t=q(g=>g.activeSessionId),e=q(g=>t?g.sessions[t]:void 0),n=st(),s=j(g=>g.activeWorkspaceCwd);Pc(s||"");const o=L(g=>g.available),r=L(g=>g.branch),a=L(g=>g.ahead),l=L(g=>g.behind),d=L(g=>g.detached),u=L(g=>g.conflictCount),m=L(g=>g.changes.length),h=sn(g=>t?g.bySession[t]:void 0);Oc(t);const f=[];if(e!=null&&e.model&&f.push({key:"model",icon:i.jsx(Rn,{size:13}),text:e.model}),e){const g=Wc(e.cwd,n);f.push({key:"cwd",icon:i.jsx(Je,{size:13}),text:g,title:e.cwd})}if(o){const g=Lc(a,l),w=[d?"(detached)":r??"?"];g&&w.push(g),m>0&&w.push(`●${m}`),u>0&&w.push(`⚠${u}`),f.push({key:"branch",icon:i.jsx(qn,{size:13}),text:w.join(" ")})}if(e){const g=`${Hc(h==null?void 0:h.contextPercent)} (${me(h==null?void 0:h.contextTokens)}/${me(h==null?void 0:h.contextWindow)})`;f.push({key:"context",icon:i.jsx(Bn,{size:13}),text:g}),f.push({key:"tokens",icon:i.jsx(Mn,{size:13}),text:me(h==null?void 0:h.totalTokens),title:`in ${me(h==null?void 0:h.inputTokens)} / out ${me(h==null?void 0:h.outputTokens)}`}),f.push({key:"cost",icon:i.jsx(An,{size:13}),text:zc(h==null?void 0:h.cost)})}return i.jsx("div",{className:ae.statusBar,children:f.map((g,w)=>i.jsxs("span",{className:ae.segmentGroup,children:[w>0&&i.jsx(Ve,{size:12,className:ae.chevron,"aria-hidden":"true"}),i.jsxs("span",{className:ae.segment,title:g.title,children:[i.jsx("span",{className:ae.icon,children:g.icon}),i.jsx("span",{className:ae.text,children:g.text})]})]},g.key))})}const Qc="_wrapper_131x2_3",Zc="_box_131x2_18",el="_checkmark_131x2_36",tl="_nativeInput_131x2_41",je={wrapper:Qc,box:Zc,checkmark:el,nativeInput:tl};S.forwardRef(function({label:e,checked:n=!1,disabled:s,className:o,onChange:r,...a},l){return i.jsxs("label",{className:je.wrapper,"data-disabled":s||void 0,children:[i.jsx("input",{ref:l,type:"checkbox",className:je.nativeInput,checked:n,disabled:s,onChange:r,...a}),i.jsx("span",{className:je.box,"data-checked":n,"aria-hidden":!0,children:n&&i.jsx($n,{size:12,className:je.checkmark})}),e&&i.jsx("span",{children:e})]})});const nl="_select_vj45v_3",sl={select:nl};S.forwardRef(function({options:e,placeholder:n,className:s,...o},r){return i.jsxs("select",{ref:r,className:M(sl.select,s),...o,children:[n&&i.jsx("option",{value:"",disabled:!0,children:n}),e.map(a=>i.jsx("option",{value:a.value,children:a.label},a.value))]})});const ol="_overlay_1yaef_1",rl="_contentWrapper_1yaef_7",al="_dialog_1yaef_16",il="_header_1yaef_28",cl="_title_1yaef_36",ll="_closeBtn_1yaef_43",dl="_body_1yaef_57",ul="_footer_1yaef_63",pl="_bare_1yaef_72",fl="_bareBody_1yaef_78",hl="_bareCloseBtn_1yaef_82",gl="_visuallyHidden_1yaef_101",F={overlay:ol,contentWrapper:rl,dialog:al,header:il,title:cl,closeBtn:ll,body:dl,footer:ul,bare:pl,bareBody:fl,bareCloseBtn:hl,visuallyHidden:gl},ml=Pe;function _l({open:t,onOpenChange:e,title:n,children:s,footer:o,width:r,className:a,bare:l=!1}){return i.jsx(On,{open:t,onOpenChange:e,children:i.jsxs(Fn,{children:[i.jsx(Pn,{className:F.overlay}),i.jsx("div",{className:F.contentWrapper,children:i.jsxs(Hn,{className:M(F.dialog,l&&F.bare,a),style:r!==void 0?{width:r}:void 0,children:[l?i.jsx(it,{className:F.visuallyHidden,children:n}):i.jsxs("div",{className:F.header,children:[i.jsx(it,{className:F.title,children:n}),i.jsx(Pe,{asChild:!0,children:i.jsx("button",{type:"button",className:F.closeBtn,"aria-label":"Close",children:i.jsx(Fe,{size:16})})})]}),i.jsx("div",{className:M(F.body,l&&F.bareBody),children:s}),l&&i.jsx(Pe,{asChild:!0,children:i.jsx("button",{type:"button",className:F.bareCloseBtn,"aria-label":"Close",children:i.jsx(Fe,{size:16})})}),o&&i.jsx("div",{className:F.footer,children:o})]})})]})})}const yl="_handle_1ocv1_1",bl={handle:yl};function kt({side:t,onResize:e,className:n}){const s=S.useRef(0),o=S.useCallback(l=>{const d=l.clientX-s.current;s.current=l.clientX,e(t==="left"?d:-d)},[e,t]),r=S.useCallback(l=>{var d,u;window.removeEventListener("pointermove",o),window.removeEventListener("pointerup",r),document.body.style.cursor="",document.body.style.userSelect="",(u=(d=l.target)==null?void 0:d.releasePointerCapture)==null||u.call(d,l.pointerId)},[o]);function a(l){l.preventDefault(),s.current=l.clientX,document.body.style.cursor="col-resize",document.body.style.userSelect="none",window.addEventListener("pointermove",o),window.addEventListener("pointerup",r)}return i.jsx("div",{className:M(bl.handle,n),onPointerDown:a,role:"separator","aria-orientation":"vertical"})}function wl(t,e){const{order:n,sessions:s}=q.getState(),r=Qt(n,s,e).find(a=>a.cwd===t);if(r!=null&&r.sessions[0]){const a=r.sessions[0].id;q.getState().activate(a);const l=q.getState().sessions[a];j.getState().open({id:U.chat(a),kind:"chat",label:(l==null?void 0:l.title)??"New chat",closable:!0,data:{sessionId:a},workspaceCwd:t})}else qe(t);v.getState().setCwd(t)}const Sl="_pathRow_9xphl_1",xl="_pathInput_9xphl_9",vl="_list_9xphl_13",kl="_item_9xphl_20",Il="_name_9xphl_32",Cl="_emptyState_9xphl_37",J={pathRow:Sl,pathInput:xl,list:vl,item:kl,name:Il,emptyState:Cl};function Tl(){const t=v(k=>k.cwdPickerOpen),e=v(k=>k.closeCwdPicker),n=j(k=>k.activeWorkspaceCwd),s=T(k=>k.client),o=st(),[r,a]=S.useState("/"),[l,d]=S.useState("/");S.useEffect(()=>{if(!t)return;const k=ne(n||"~",o);a(k),d(k)},[t,s,n]);const{data:u,isLoading:m,isError:h,error:f}=Di(r,t&&!!s),g=((u==null?void 0:u.entries)??[]).filter(k=>k.kind==="directory");function w(k){a(k),d(k)}function b(){w(r.split("/").slice(0,-1).join("/")||"/")}function N(){w(l.trim())}function O(){wl(r,o),e()}return i.jsxs(_l,{open:t,onOpenChange:k=>!k&&e(),title:"Open Workspace",footer:i.jsxs(i.Fragment,{children:[i.jsx(ml,{asChild:!0,children:i.jsx(z,{size:"sm",variant:"secondary",children:"Cancel"})}),i.jsx(z,{size:"sm",onClick:O,children:"Open this folder"})]}),children:[i.jsxs("div",{className:J.pathRow,children:[i.jsx(z,{size:"xs",variant:"ghost",iconOnly:!0,title:"Up",onClick:b,children:i.jsx(Dn,{size:13})}),i.jsx(ze,{className:J.pathInput,value:l,onChange:k=>d(k.target.value),onKeyDown:k=>{k.key==="Enter"&&(k.preventDefault(),N())}}),i.jsx(z,{size:"xs",onClick:N,children:"Go"})]}),i.jsx("div",{className:J.list,children:m?i.jsx("div",{className:J.emptyState,children:"Loading..."}):h?i.jsxs("div",{className:J.emptyState,children:["Error: ",f instanceof Error?f.message:"unknown error"]}):g.length===0?i.jsx("div",{className:J.emptyState,children:"No subdirectories"}):g.map(k=>i.jsxs("div",{className:J.item,onClick:()=>w(r==="/"?`/${k.name}`:`${r}/${k.name}`),children:[i.jsx(Je,{size:14}),i.jsx("span",{className:J.name,children:k.name})]},k.name))})]})}const jl="_shell_1m1nv_1",El="_main_1m1nv_7",Nl="_sidebarLeft_1m1nv_13",Rl="_leftHandle_1m1nv_21",ql="_center_1m1nv_24",Bl="_sidebarRight_1m1nv_31",Ml="_rightHandle_1m1nv_39",te={shell:jl,main:El,sidebarLeft:Nl,leftHandle:Rl,center:ql,sidebarRight:Bl,rightHandle:Ml};function Al(){const t=v(a=>a.leftSidebarCollapsed),e=v(a=>a.rightSidebarCollapsed),n=v(a=>a.leftSidebarWidth),s=v(a=>a.rightSidebarWidth),o=v(a=>a.resizeLeftSidebar),r=v(a=>a.resizeRightSidebar);return i.jsxs("div",{className:te.shell,children:[i.jsx(da,{}),i.jsxs("div",{className:te.main,children:[!t&&i.jsxs("aside",{className:te.sidebarLeft,style:{width:n},children:[i.jsx(ii,{}),i.jsx(kt,{side:"left",className:te.leftHandle,onResize:o})]}),i.jsxs("div",{className:te.center,children:[i.jsx(Si,{}),i.jsx(Mi,{})]}),!e&&i.jsxs("aside",{className:te.sidebarRight,style:{width:s},children:[i.jsx(kt,{side:"right",className:te.rightHandle,onResize:r}),i.jsx(Ac,{})]})]}),i.jsx(Xc,{}),i.jsx(Tl,{})]})}function $l(){const t=S.useRef(!1);S.useEffect(()=>{if(t.current)return;if(t.current=!0,window.location.hash.includes("offer=")){const d=window.location.href;v.getState().setHost(d),T.getState().connect({url:d});return}const e=new URLSearchParams(window.location.search),n=e.get("host"),s=e.get("pair"),o=e.get("password"),r=e.get("cwd"),a=e.get("connect")==="1",l=v.getState();if(s?l.setHost(s):n&&l.setHost(n),o&&l.setPassword(o),r&&l.setCwd(r),s)T.getState().connect({url:s});else if(a){const{host:d,password:u}=v.getState();T.getState().connect({url:d,password:u||void 0})}},[])}function Dl(t){return typeof t=="object"&&t!==null&&"kind"in t}function Ol(t){const e=[];for(const n of t)if(Dl(n))if(n.kind==="other")n.event&&e.push(n.event);else for(const s of n.events??[])e.push(s);return e}function Fl(t){return typeof t.model=="string"}function Pl(){const t=T(s=>s.client),e=T(s=>s.status),n=S.useRef(!1);S.useEffect(()=>{e!=="open"||!t||n.current||(n.current=!0,(async()=>{var d;let s=[];try{s=(await t.connection.request("list_agents_request",{all:!1})).agents??[]}catch{s=[]}s.sort((u,m)=>(m.lastActivity??0)-(u.lastActivity??0));const o=q.getState();for(const u of s){if(o.findByAgentId(u.agentId))continue;let m=Ue;try{const h=await t.agent(u.agentId).timeline.fetch({direction:"after",limit:200});m=Ol(h.items).reduce(Yt,Ue)}catch{}o.hydrate({id:`s-${u.agentId.slice(0,12)}`,agentId:u.agentId,title:u.title||((d=u.cwd)==null?void 0:d.split("/").pop())||"Restored",status:u.status??"idle",cwd:u.cwd||"~",timeline:m,userMessageCount:m.rows.filter(h=>h.kind==="user").length,model:u.model})}const r=await Be(t).catch(()=>null),{order:a,sessions:l}=q.getState();if(a.length>0){const u=l[a[0]??""];if(u){const m=ne(u.cwd||"~",r);q.getState().activate(u.id),v.getState().setCwd(u.cwd),j.getState().open({id:U.chat(u.id),kind:"chat",label:u.title,closable:!0,data:{sessionId:u.id},workspaceCwd:m})}}else{const u=v.getState().cwd||"~",m=ne(u,r);qe(m)}})())},[e,t]),S.useEffect(()=>{if(!(e!=="open"||!t))return t.onAgentUpdate(s=>{Fl(s)&&q.getState().setModelByAgentId(s.agentId,s.model)})},[e,t])}function Hl(){const t=T(s=>s.client),e=T(s=>s.status),n=S.useRef(!1);S.useEffect(()=>{e!=="open"||!t||n.current||(n.current=!0,(async()=>{let s=[];try{s=(await t.connection.request("list_terminals_request",{})).terminals??[]}catch{s=[]}if(s.length===0)return;const o=await Be(t).catch(()=>null),r=j.getState().open;for(const a of s){if(a.closed)continue;const l=ne(a.cwd||"~",o);r({id:U.terminal(a.slot),kind:"terminal",label:a.name,closable:!0,data:{slot:a.slot,cwd:l},workspaceCwd:l})}})())},[e,t])}function zl(){S.useEffect(()=>{function t(e){const n=v.getState();if(e.key==="Escape"){n.closeCwdPicker(),n.closeSessionMenu();return}const s=e.ctrlKey||e.metaKey;if(s&&e.key.toLowerCase()==="t"){e.preventDefault(),Xt(j.getState().activeWorkspaceCwd||"~");return}if(s&&e.key.toLowerCase()==="w"){const{activeTabId:o,tabs:r,close:a}=j.getState();if(!o)return;const l=r.find(d=>d.id===o);(l==null?void 0:l.closable)!==!1&&(e.preventDefault(),a(o))}}return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[])}function Wl(){return $l(),Pl(),Hl(),zl(),null}function Ll(){return i.jsxs(Fs,{children:[i.jsx(Wl,{}),i.jsx(Al,{})]})}const on=document.getElementById("root");if(!on)throw new Error("Missing #root element");pn.createRoot(on).render(i.jsx(S.StrictMode,{children:i.jsx(Ll,{})}));export{z as B,_l as D,Ci as S,ed as T,T as a,j as b,St as c,td as e,Zt as r,ua as t,q as u};
3
+ //# sourceMappingURL=index-C5SpA_B-.js.map