reasonix 0.40.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -13
- package/README.zh-CN.md +19 -13
- package/dashboard/app.css +8 -4
- package/dashboard/dist/app.js +279 -224
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/acp-64VQZLDJ.js +708 -0
- package/dist/cli/acp-64VQZLDJ.js.map +1 -0
- package/dist/cli/chat-ZAGX52RV.js +46 -0
- package/dist/cli/{chunk-UCMTWZKU.js → chunk-2CXPDAWX.js} +2 -2
- package/dist/cli/{chunk-CLAN6PVH.js → chunk-4H3ZRJ2U.js} +19 -7
- package/dist/cli/chunk-4H3ZRJ2U.js.map +1 -0
- package/dist/cli/{chunk-A5LSGEEK.js → chunk-4W2CICFQ.js} +21 -10
- package/dist/cli/{chunk-A5LSGEEK.js.map → chunk-4W2CICFQ.js.map} +1 -1
- package/dist/cli/{chunk-CZSJILQP.js → chunk-65Q5HQ26.js} +39 -1
- package/dist/cli/chunk-65Q5HQ26.js.map +1 -0
- package/dist/cli/{chunk-XHQIK7B6.js → chunk-7SPOFTMT.js} +2 -2
- package/dist/cli/{chunk-5GKJLNP2.js → chunk-7VFNPMKG.js} +2 -2
- package/dist/cli/{chunk-UVRXTSK3.js → chunk-A3LL4XDV.js} +8 -2
- package/dist/cli/chunk-A3LL4XDV.js.map +1 -0
- package/dist/cli/{chunk-VLNRQMCI.js → chunk-A7VHMMDE.js} +2 -2
- package/dist/cli/{chunk-R4YTW7PR.js → chunk-ARF3N2SY.js} +56 -12
- package/dist/cli/chunk-ARF3N2SY.js.map +1 -0
- package/dist/cli/{chunk-AVB3WZWU.js → chunk-AT6GGIBV.js} +10 -10
- package/dist/cli/{chunk-RFX7TYVV.js → chunk-BOFL3T45.js} +14 -1
- package/dist/cli/chunk-BOFL3T45.js.map +1 -0
- package/dist/cli/{chunk-SZH34P45.js → chunk-BYZGO3BX.js} +43 -17
- package/dist/cli/chunk-BYZGO3BX.js.map +1 -0
- package/dist/cli/{chunk-7DLHHBGN.js → chunk-CD4SCQL4.js} +6 -4
- package/dist/cli/chunk-CD4SCQL4.js.map +1 -0
- package/dist/cli/{chunk-HCC42PEI.js → chunk-CFY2XLY6.js} +6 -2
- package/dist/cli/chunk-CFY2XLY6.js.map +1 -0
- package/dist/cli/{chunk-26UDIXLD.js → chunk-F2AV2QDK.js} +493 -460
- package/dist/cli/chunk-F2AV2QDK.js.map +1 -0
- package/dist/cli/{chunk-KMWKGPFZ.js → chunk-H4OLWRSX.js} +10 -1
- package/dist/cli/chunk-H4OLWRSX.js.map +1 -0
- package/dist/cli/{chunk-4YV2GBYG.js → chunk-IEA6JOIP.js} +291 -98
- package/dist/cli/chunk-IEA6JOIP.js.map +1 -0
- package/dist/cli/{chunk-WKOMCPXP.js → chunk-KZYLMMU5.js} +21 -13
- package/dist/cli/chunk-KZYLMMU5.js.map +1 -0
- package/dist/cli/{chunk-JWCTX5S4.js → chunk-L7W3HJZQ.js} +2 -2
- package/dist/cli/{chunk-MRLXEMZ7.js → chunk-LN27AKV3.js} +1 -1
- package/dist/cli/chunk-LN27AKV3.js.map +1 -0
- package/dist/cli/{chunk-IYF36OCJ.js → chunk-LTXADNCO.js} +2 -2
- package/dist/cli/{chunk-H7PHYVPM.js → chunk-MHGPBJ2T.js} +44 -8
- package/dist/cli/chunk-MHGPBJ2T.js.map +1 -0
- package/dist/cli/{chunk-ULBW7DYL.js → chunk-RAUPWSYA.js} +2 -2
- package/dist/cli/chunk-SXLJBFIV.js +245 -0
- package/dist/cli/chunk-SXLJBFIV.js.map +1 -0
- package/dist/cli/{chunk-4X3NY5ZM.js → chunk-UV7XJUJH.js} +2 -2
- package/dist/cli/{chunk-XJLZ4HKU.js → chunk-VFG4GIT3.js} +2 -2
- package/dist/cli/{chunk-FFNOMR32.js → chunk-WE3YZULK.js} +2 -2
- package/dist/cli/chunk-Y5XNV3NX.js +25 -0
- package/dist/cli/chunk-Y5XNV3NX.js.map +1 -0
- package/dist/cli/{chunk-XST7BSZJ.js → chunk-YJFKFTAL.js} +7 -1
- package/dist/cli/chunk-YJFKFTAL.js.map +1 -0
- package/dist/cli/{code-YQGVLIT2.js → code-X3M6ENTQ.js} +38 -35
- package/dist/cli/{code-YQGVLIT2.js.map → code-X3M6ENTQ.js.map} +1 -1
- package/dist/cli/{commands-FQZOBLLZ.js → commands-QY7MSQG7.js} +4 -4
- package/dist/cli/{commit-ZS24SHPG.js → commit-BRCQ3OQO.js} +3 -3
- package/dist/cli/{desktop-6OLENOOO.js → desktop-ZTMHQR2Y.js} +247 -28
- package/dist/cli/desktop-ZTMHQR2Y.js.map +1 -0
- package/dist/cli/{diff-2VUKNGEI.js → diff-YASCB7PU.js} +7 -7
- package/dist/cli/{doctor-JO2WNN6C.js → doctor-XCN5ETVP.js} +9 -9
- package/dist/cli/{events-APSVNROZ.js → events-2AJTXR7I.js} +3 -3
- package/dist/cli/index.js +69 -35
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-DCKOE5RF.js → mcp-YMWBLRR7.js} +2 -2
- package/dist/cli/{mcp-browse-D6GBP5RQ.js → mcp-browse-XLDUE6SB.js} +7 -3
- package/dist/cli/mcp-browse-XLDUE6SB.js.map +1 -0
- package/dist/cli/{mcp-inspect-KFGFPJ3E.js → mcp-inspect-H4D2HSJP.js} +5 -7
- package/dist/cli/{mcp-inspect-KFGFPJ3E.js.map → mcp-inspect-H4D2HSJP.js.map} +1 -1
- package/dist/cli/{prompt-PKCCLLAD.js → prompt-RSIHN62V.js} +4 -3
- package/dist/cli/{prune-sessions-LV33R47N.js → prune-sessions-4N3BVST2.js} +2 -2
- package/dist/cli/{replay-WFCYX7XF.js → replay-3GTWM75X.js} +8 -8
- package/dist/cli/{run-IUJYEPMT.js → run-BLZPTRDX.js} +19 -21
- package/dist/cli/{run-IUJYEPMT.js.map → run-BLZPTRDX.js.map} +1 -1
- package/dist/cli/{server-CN4QPPVJ.js → server-DRFPXXSH.js} +16 -12
- package/dist/cli/{server-CN4QPPVJ.js.map → server-DRFPXXSH.js.map} +1 -1
- package/dist/cli/{sessions-F5GPGTJN.js → sessions-BOWFPTXT.js} +13 -13
- package/dist/cli/{setup-WWMDBPSB.js → setup-FQL2JJC2.js} +5 -5
- package/dist/cli/version-XQXYSJ5L.js +30 -0
- package/dist/index.d.ts +148 -103
- package/dist/index.js +468 -134
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/cli/chat-G7CUW4ZI.js +0 -45
- package/dist/cli/chunk-26UDIXLD.js.map +0 -1
- package/dist/cli/chunk-4YV2GBYG.js.map +0 -1
- package/dist/cli/chunk-7DLHHBGN.js.map +0 -1
- package/dist/cli/chunk-CLAN6PVH.js.map +0 -1
- package/dist/cli/chunk-CPTZ5OHX.js +0 -18
- package/dist/cli/chunk-CPTZ5OHX.js.map +0 -1
- package/dist/cli/chunk-CZSJILQP.js.map +0 -1
- package/dist/cli/chunk-H7PHYVPM.js.map +0 -1
- package/dist/cli/chunk-HCC42PEI.js.map +0 -1
- package/dist/cli/chunk-KMWKGPFZ.js.map +0 -1
- package/dist/cli/chunk-MRLXEMZ7.js.map +0 -1
- package/dist/cli/chunk-R4YTW7PR.js.map +0 -1
- package/dist/cli/chunk-RFX7TYVV.js.map +0 -1
- package/dist/cli/chunk-SZH34P45.js.map +0 -1
- package/dist/cli/chunk-UVRXTSK3.js.map +0 -1
- package/dist/cli/chunk-WKOMCPXP.js.map +0 -1
- package/dist/cli/chunk-XST7BSZJ.js.map +0 -1
- package/dist/cli/desktop-6OLENOOO.js.map +0 -1
- package/dist/cli/mcp-browse-D6GBP5RQ.js.map +0 -1
- package/dist/cli/version-KQUPV6T5.js +0 -30
- /package/dist/cli/{chat-G7CUW4ZI.js.map → chat-ZAGX52RV.js.map} +0 -0
- /package/dist/cli/{chunk-UCMTWZKU.js.map → chunk-2CXPDAWX.js.map} +0 -0
- /package/dist/cli/{chunk-XHQIK7B6.js.map → chunk-7SPOFTMT.js.map} +0 -0
- /package/dist/cli/{chunk-5GKJLNP2.js.map → chunk-7VFNPMKG.js.map} +0 -0
- /package/dist/cli/{chunk-VLNRQMCI.js.map → chunk-A7VHMMDE.js.map} +0 -0
- /package/dist/cli/{chunk-AVB3WZWU.js.map → chunk-AT6GGIBV.js.map} +0 -0
- /package/dist/cli/{chunk-JWCTX5S4.js.map → chunk-L7W3HJZQ.js.map} +0 -0
- /package/dist/cli/{chunk-IYF36OCJ.js.map → chunk-LTXADNCO.js.map} +0 -0
- /package/dist/cli/{chunk-ULBW7DYL.js.map → chunk-RAUPWSYA.js.map} +0 -0
- /package/dist/cli/{chunk-4X3NY5ZM.js.map → chunk-UV7XJUJH.js.map} +0 -0
- /package/dist/cli/{chunk-XJLZ4HKU.js.map → chunk-VFG4GIT3.js.map} +0 -0
- /package/dist/cli/{chunk-FFNOMR32.js.map → chunk-WE3YZULK.js.map} +0 -0
- /package/dist/cli/{commands-FQZOBLLZ.js.map → commands-QY7MSQG7.js.map} +0 -0
- /package/dist/cli/{commit-ZS24SHPG.js.map → commit-BRCQ3OQO.js.map} +0 -0
- /package/dist/cli/{diff-2VUKNGEI.js.map → diff-YASCB7PU.js.map} +0 -0
- /package/dist/cli/{doctor-JO2WNN6C.js.map → doctor-XCN5ETVP.js.map} +0 -0
- /package/dist/cli/{events-APSVNROZ.js.map → events-2AJTXR7I.js.map} +0 -0
- /package/dist/cli/{mcp-DCKOE5RF.js.map → mcp-YMWBLRR7.js.map} +0 -0
- /package/dist/cli/{prompt-PKCCLLAD.js.map → prompt-RSIHN62V.js.map} +0 -0
- /package/dist/cli/{prune-sessions-LV33R47N.js.map → prune-sessions-4N3BVST2.js.map} +0 -0
- /package/dist/cli/{replay-WFCYX7XF.js.map → replay-3GTWM75X.js.map} +0 -0
- /package/dist/cli/{sessions-F5GPGTJN.js.map → sessions-BOWFPTXT.js.map} +0 -0
- /package/dist/cli/{setup-WWMDBPSB.js.map → setup-FQL2JJC2.js.map} +0 -0
- /package/dist/cli/{version-KQUPV6T5.js.map → version-XQXYSJ5L.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/ui/keystroke-context.tsx","../../src/cli/ui/stdin-reader.ts","../../src/cli/ui/Select.tsx"],"sourcesContent":["/**\n * KeystrokeContext — React surface in front of the raw stdin reader.\n *\n * Replaces Ink's `useInput` chain. Reasonix's components no longer\n * import `useInput` from \"ink\"; they call `useKeystroke(handler,\n * isActive)` from this module. The provider mounted once at App\n * level owns a `StdinReader`, subscribes a single fan-out function\n * to it, and dispatches each parsed `KeyEvent` to every active\n * consumer.\n *\n * Why a Context instead of a singleton import: the provider can be\n * disabled in tests / replay mode without touching the components,\n * and the lifecycle (start/stop on mount/unmount) is tied to the\n * React tree rather than a global side effect.\n *\n * Why not just keep Ink's useInput: Ink's parse-keypress uses a\n * 100 ms intra-CSI timeout that's too short for Windows ConPTY,\n * leaking arrow-key bytes / paste markers into the buffer. Our\n * reader uses 250 ms and recognises the ESC-stripped variants too\n * — see `stdin-reader.ts`.\n */\n\nimport { useInput } from \"ink\";\n// biome-ignore lint/style/useImportType: tsconfig jsx=react needs React as a runtime value\nimport React, { createContext, useContext, useEffect, useRef } from \"react\";\nimport { type KeyEvent, type StdinReader, getStdinReader } from \"./stdin-reader.js\";\n\ninterface KeystrokeBus {\n /** Subscribe — returns an unsubscribe function. */\n subscribe(handler: KeystrokeHandler): () => void;\n}\n\nexport type KeystrokeHandler = (ev: KeyEvent) => void;\n\nconst KeystrokeContext = createContext<KeystrokeBus | null>(null);\n\nexport interface KeystrokeProviderProps {\n children: React.ReactNode;\n /**\n * Optional reader override. Tests inject a synthetic reader so\n * they can `feed()` chunks instead of touching real stdin. Production\n * callers leave this unset and get the singleton.\n */\n reader?: StdinReader;\n}\n\nexport function KeystrokeProvider({\n children,\n reader: providedReader,\n}: KeystrokeProviderProps): React.ReactElement {\n const handlersRef = useRef<Set<KeystrokeHandler>>(new Set());\n // Ref so the bus value's identity is stable across re-renders —\n // consumers don't accidentally re-subscribe every render.\n const busRef = useRef<KeystrokeBus | null>(null);\n if (busRef.current === null) {\n busRef.current = {\n subscribe(handler) {\n handlersRef.current.add(handler);\n return () => {\n handlersRef.current.delete(handler);\n };\n },\n };\n }\n\n useEffect(() => {\n const reader = providedReader ?? getStdinReader();\n reader.start();\n const unsubscribe = reader.subscribe((ev) => {\n // Snapshot the handler set so handlers added/removed during\n // dispatch don't perturb iteration. Cheap — typical N=1-3.\n for (const fn of [...handlersRef.current]) fn(ev);\n });\n return () => {\n unsubscribe();\n // Don't `stop()` the singleton on every unmount — multiple\n // mounts (test reruns, hot-reload) must not tear down stdin.\n // The singleton's own start() is idempotent; stop() is the\n // process-exit handler's job.\n };\n }, [providedReader]);\n\n return <KeystrokeContext.Provider value={busRef.current}>{children}</KeystrokeContext.Provider>;\n}\n\n/** Subscribe to keystroke events; falls back to Ink's useInput when no KeystrokeProvider is mounted. */\nexport function useKeystroke(handler: KeystrokeHandler, isActive = true): void {\n const bus = useContext(KeystrokeContext);\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n if (!bus || !isActive) return undefined;\n return bus.subscribe((ev) => handlerRef.current(ev));\n }, [bus, isActive]);\n\n useInput(\n (input, key) => {\n if (bus) return;\n handlerRef.current({\n input,\n upArrow: key.upArrow,\n downArrow: key.downArrow,\n leftArrow: key.leftArrow,\n rightArrow: key.rightArrow,\n return: key.return,\n escape: key.escape,\n backspace: key.backspace,\n delete: key.delete,\n tab: key.tab,\n shift: key.shift,\n ctrl: key.ctrl,\n meta: key.meta,\n pageUp: key.pageUp,\n pageDown: key.pageDown,\n });\n },\n { isActive: !bus && isActive },\n );\n}\n\n/**\n * Lower-level hook for components that need a stable subscription\n * across the lifetime of the consumer (typically StdinReader-aware\n * unit tests).\n */\nexport function useKeystrokeBus(): KeystrokeBus | null {\n return useContext(KeystrokeContext);\n}\n\n/** Test helper — assemble a KeyEvent with sensible defaults. */\nexport function makeKeyEvent(overrides: Partial<KeyEvent> = {}): KeyEvent {\n return { input: \"\", ...overrides };\n}\n","/** Sole stdin owner; 250 ms ESC-ambiguity timer (ConPTY splits sequences past parse-keypress's 100 ms). */\n\nimport { stdin } from \"node:process\";\n\nexport interface KeyEvent {\n /** Empty for control keys (arrows / Enter / Esc); holds the letter for Ctrl+/Alt+. */\n input: string;\n upArrow?: boolean;\n downArrow?: boolean;\n leftArrow?: boolean;\n rightArrow?: boolean;\n pageUp?: boolean;\n pageDown?: boolean;\n home?: boolean;\n end?: boolean;\n delete?: boolean;\n backspace?: boolean;\n tab?: boolean;\n return?: boolean;\n escape?: boolean;\n shift?: boolean;\n ctrl?: boolean;\n meta?: boolean;\n /** Bracketed-paste content; consumers MUST NOT re-interpret as keystrokes (e.g. `\\n` ≠ submit). */\n paste?: boolean;\n /** xterm SGR mode 1006 wheel-up. */\n mouseScrollUp?: boolean;\n /** Mouse wheel down — symmetric to `mouseScrollUp`. */\n mouseScrollDown?: boolean;\n /** Left-button press; row/col are 1-based. */\n mouseClick?: boolean;\n /** Left-button motion (button held during drag). Mode 1002 only. */\n mouseDrag?: boolean;\n /** Any-button release. Mode 1002 only. */\n mouseRelease?: boolean;\n mouseRow?: number;\n mouseCol?: number;\n}\n\ntype Subscriber = (ev: KeyEvent) => void;\n\n/** ESC ambiguity timeout. Long enough for ConPTY-split sequences. */\nconst ESC_TIMEOUT_MS = 250;\n\n/** Bracketed-paste markers (DECSET 2004). */\nconst PASTE_START = \"\\x1b[200~\";\nconst PASTE_END = \"\\x1b[201~\";\n/** ESC-stripped variants — ConPTY occasionally eats the leading ESC. */\nconst PASTE_START_BARE = \"[200~\";\nconst PASTE_END_BARE = \"[201~\";\n\nconst CSI_TAIL_MAP: ReadonlyArray<{ tail: string; ev: KeyEvent }> = [\n { tail: \"A\", ev: { input: \"\", upArrow: true } },\n { tail: \"B\", ev: { input: \"\", downArrow: true } },\n { tail: \"C\", ev: { input: \"\", rightArrow: true } },\n { tail: \"D\", ev: { input: \"\", leftArrow: true } },\n { tail: \"H\", ev: { input: \"\", home: true } },\n { tail: \"F\", ev: { input: \"\", end: true } },\n { tail: \"1~\", ev: { input: \"\", home: true } },\n { tail: \"4~\", ev: { input: \"\", end: true } },\n { tail: \"5~\", ev: { input: \"\", pageUp: true } },\n { tail: \"6~\", ev: { input: \"\", pageDown: true } },\n { tail: \"3~\", ev: { input: \"\", delete: true } },\n { tail: \"Z\", ev: { input: \"\", shift: true, tab: true } },\n // Some Windows hosts (PowerShell 7.x conhost path) emit the\n // modifier-encoded back-tab `\\x1b[1;2Z` instead of bare `\\x1b[Z`.\n // Issue #373 — without this entry Shift+Tab is silently dropped.\n { tail: \"1;2Z\", ev: { input: \"\", shift: true, tab: true } },\n // modifyOtherKeys (xterm CSI > 4 ; 2 m) sequences for Enter / Tab\n // with modifiers. Only fired when App.tsx has enabled the mode at\n // startup; otherwise Shift+Enter stays indistinguishable from Enter.\n // Modifier encoding: 2=shift, 3=alt, 4=alt+shift, 5=ctrl,\n // 6=ctrl+shift, 7=ctrl+alt, 8=ctrl+alt+shift. Keycodes: 9=Tab, 13=Enter.\n { tail: \"27;2;9~\", ev: { input: \"\", tab: true, shift: true } },\n { tail: \"27;2;13~\", ev: { input: \"\", return: true, shift: true } },\n { tail: \"27;5;13~\", ev: { input: \"\", return: true, ctrl: true } },\n { tail: \"27;6;13~\", ev: { input: \"\", return: true, ctrl: true, shift: true } },\n // Kitty keyboard protocol — same idea, different envelope:\n // `\\x1b[<keycode>;<mod>u`. Some terminals (kitty, recent Windows\n // Terminal previews) prefer this shape. Harmless to map here too.\n { tail: \"9;2u\", ev: { input: \"\", tab: true, shift: true } },\n { tail: \"13;2u\", ev: { input: \"\", return: true, shift: true } },\n { tail: \"13;5u\", ev: { input: \"\", return: true, ctrl: true } },\n { tail: \"13;6u\", ev: { input: \"\", return: true, ctrl: true, shift: true } },\n];\n\n/** SS3 sequences (`\\x1bO<letter>`) — some terminals send these for arrows. */\nconst SS3_MAP: Record<string, KeyEvent> = {\n A: { input: \"\", upArrow: true },\n B: { input: \"\", downArrow: true },\n C: { input: \"\", rightArrow: true },\n D: { input: \"\", leftArrow: true },\n H: { input: \"\", home: true },\n F: { input: \"\", end: true },\n};\n\n/** ESC-stripped CSI lookahead — ConPTY occasionally drops the leading ESC. */\nfunction tryEscapelessCsi(chunk: string, i: number): { advance: number; ev: KeyEvent } | null {\n if (chunk[i] !== \"[\") return null;\n // Paste start as a special case (handled by caller).\n // Try each known tail.\n for (const entry of CSI_TAIL_MAP) {\n const candidate = `[${entry.tail}`;\n if (chunk.slice(i, i + candidate.length) === candidate) {\n return { advance: candidate.length, ev: entry.ev };\n }\n }\n return null;\n}\n\nfunction isCsiFinal(ch: string): boolean {\n const code = ch.charCodeAt(0);\n return code >= 0x40 && code <= 0x7e;\n}\n\n/** Unknown sequence → null → caller drops bytes silently (don't insert as text). */\nfunction lookupCsi(tail: string): KeyEvent | null {\n for (const entry of CSI_TAIL_MAP) {\n if (entry.tail === tail) return entry.ev;\n }\n return null;\n}\n\n/** modifyOtherKeys / Kitty: reconstruct the keystroke from `<codepoint>` + `<mod>`. */\nfunction decodeModifiedKey(cp: number, mod: number): KeyEvent | null {\n if (mod < 1 || mod > 8) return null;\n const bits = mod - 1;\n const shift = (bits & 1) !== 0;\n const alt = (bits & 2) !== 0;\n const ctrl = (bits & 4) !== 0;\n if (cp >= 0x20 && cp <= 0x7e && !ctrl && !alt) {\n const ev: KeyEvent = { input: String.fromCharCode(cp) };\n if (shift) ev.shift = true;\n return ev;\n }\n if (cp >= 0x20 && cp <= 0x7e && alt && !ctrl) {\n const ev: KeyEvent = { input: String.fromCharCode(cp), meta: true };\n if (shift) ev.shift = true;\n return ev;\n }\n if (cp >= 0x41 && cp <= 0x7a && ctrl && !alt) {\n const ev: KeyEvent = { input: String.fromCharCode(cp).toLowerCase(), ctrl: true };\n if (shift) ev.shift = true;\n return ev;\n }\n return null;\n}\n\n/** Generic modifyOtherKeys / Kitty envelope — picks up the keys lookupCsi misses (`@`, `_`, `[`, `\\`, `]`, `^` under `>4;2m`). */\nfunction tryDecodeGenericCsi(seq: string): KeyEvent | null {\n let m = /^27;(\\d+);(\\d+)~$/.exec(seq);\n if (m) return decodeModifiedKey(Number.parseInt(m[2]!, 10), Number.parseInt(m[1]!, 10));\n m = /^(\\d+);(\\d+)u$/.exec(seq);\n if (m) return decodeModifiedKey(Number.parseInt(m[1]!, 10), Number.parseInt(m[2]!, 10));\n m = /^(\\d+)u$/.exec(seq);\n if (m) return decodeModifiedKey(Number.parseInt(m[1]!, 10), 1);\n return null;\n}\n\n/** Heuristic paste-burst detector — wraps raw multi-line chunks when the terminal didn't (#522). */\nexport function looksLikeUnbracketedPaste(chunk: string): boolean {\n if (chunk.length < 2) return false;\n if (chunk.includes(PASTE_START) || chunk.includes(PASTE_START_BARE)) return false;\n if (chunk.includes(PASTE_END) || chunk.includes(PASTE_END_BARE)) return false;\n // ESC anywhere = real keypress / control sequence, not a paste burst.\n if (chunk.includes(\"\\x1b\")) return false;\n // \\r\\n is one terminal-converted Enter, not two breaks — fold first.\n const norm = chunk.replace(/\\r\\n/g, \"\\n\");\n if (norm === \"\\r\" || norm === \"\\n\") return false;\n let breaks = 0;\n let firstBreakIdx = -1;\n for (let i = 0; i < norm.length; i++) {\n const c = norm[i];\n if (c === \"\\r\" || c === \"\\n\") {\n if (firstBreakIdx < 0) firstBreakIdx = i;\n breaks++;\n }\n }\n if (breaks >= 2) return true;\n // 1 break with non-empty text on BOTH sides — paste burst. (\"abc\\r\"\n // alone stays as type-then-Enter so a fast typist still submits.)\n if (breaks === 1) return firstBreakIdx > 0 && firstBreakIdx < norm.length - 1;\n return false;\n}\n\nexport class StdinReader {\n private subscribers = new Set<Subscriber>();\n private state: \"idle\" | \"esc\" | \"csi\" | \"ss3\" | \"paste\" = \"idle\";\n /** Buffer for partial sequences across chunks. */\n private csiBuf = \"\";\n /** Buffer for paste content. */\n private pasteBuf = \"\";\n private escTimer: NodeJS.Timeout | null = null;\n // Deferred-dispatch handle paired with `escTimer`. The timer\n // queues an Immediate that runs in the event loop's CHECK phase —\n // i.e. AFTER the POLL phase where stdin 'data' events fire — so\n // a multi-byte sequence whose chunks queued up while the loop was\n // blocked (heavy render, etc.) gets a chance to be processed\n // BEFORE we emit a bogus standalone-Esc. Fixes the \"I didn't press\n // Esc but it aborted the turn\" class of bug: previously the timer's\n // setTimeout callback ran in the timers phase ahead of poll, so a\n // split sequence like `\\x1b` + `[A` would dispatch escape+upArrow\n // even though the user only pressed Up.\n private escImmediate: NodeJS.Immediate | null = null;\n private started = false;\n /** The actual `data` listener — kept as a field so `stop()` can detach it. */\n private listener: ((chunk: Buffer | string) => void) | null = null;\n\n start(): void {\n if (this.started) return;\n // bun leaves `isTTY` undefined in a real terminal, so probe setRawMode directly.\n try {\n stdin.setRawMode(true);\n } catch {\n return;\n }\n stdin.setEncoding(\"utf8\");\n stdin.resume();\n this.listener = (chunk) =>\n this.handleChunk(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"));\n stdin.on(\"data\", this.listener);\n this.started = true;\n }\n\n stop(): void {\n if (!this.started) return;\n if (this.listener) {\n stdin.off(\"data\", this.listener);\n this.listener = null;\n }\n try {\n stdin.setRawMode(false);\n } catch {\n // setRawMode may throw if stdin is already closed; ignore.\n }\n stdin.pause();\n this.cancelEscTimer();\n this.state = \"idle\";\n this.csiBuf = \"\";\n this.pasteBuf = \"\";\n this.started = false;\n }\n\n subscribe(fn: Subscriber): () => void {\n this.subscribers.add(fn);\n return () => {\n this.subscribers.delete(fn);\n };\n }\n\n /** Test seam — drives the parser without a real TTY. */\n feed(chunk: string): void {\n this.handleChunk(chunk);\n }\n\n private dispatch(ev: KeyEvent): void {\n for (const sub of this.subscribers) sub(ev);\n }\n\n private cancelEscTimer(): void {\n if (this.escTimer) {\n clearTimeout(this.escTimer);\n this.escTimer = null;\n }\n if (this.escImmediate) {\n clearImmediate(this.escImmediate);\n this.escImmediate = null;\n }\n }\n\n private scheduleEscTimer(): void {\n this.cancelEscTimer();\n this.escTimer = setTimeout(() => {\n this.escTimer = null;\n // Defer the actual dispatch to the CHECK phase so any pending\n // stdin 'data' events that queued up during a long render still\n // get a chance to consume the rest of a split sequence. The\n // chunk handler cancels this Immediate at its start, so a\n // sequence completing first wins; only a truly-orphaned `\\x1b`\n // reaches the dispatch below.\n this.escImmediate = setImmediate(() => {\n this.escImmediate = null;\n if (this.state === \"esc\") {\n this.state = \"idle\";\n this.dispatch({ input: \"\", escape: true });\n }\n });\n }, ESC_TIMEOUT_MS);\n }\n\n private handleChunk(rawChunk: string): void {\n this.cancelEscTimer();\n // Paste rescue when DECSET 2004 markers don't arrive (multiplexers\n // strip them, some Windows pipes too) — otherwise each \\r in a\n // multi-line paste fires Enter and the loop submits N prompts (#522).\n const chunk =\n this.state === \"idle\" && looksLikeUnbracketedPaste(rawChunk)\n ? PASTE_START + rawChunk + PASTE_END\n : rawChunk;\n let i = 0;\n while (i < chunk.length) {\n // ── paste accumulator ──\n if (this.state === \"paste\") {\n // Look for end marker (with or without ESC).\n const endA = chunk.indexOf(PASTE_END, i);\n const endB = chunk.indexOf(PASTE_END_BARE, i);\n let endIdx = -1;\n let endLen = 0;\n if (endA !== -1 && (endB === -1 || endA <= endB)) {\n endIdx = endA;\n endLen = PASTE_END.length;\n } else if (endB !== -1) {\n endIdx = endB;\n endLen = PASTE_END_BARE.length;\n }\n if (endIdx === -1) {\n this.pasteBuf += chunk.slice(i);\n i = chunk.length;\n break;\n }\n this.pasteBuf += chunk.slice(i, endIdx);\n this.dispatch({ input: this.pasteBuf, paste: true });\n this.pasteBuf = \"\";\n this.state = \"idle\";\n i = endIdx + endLen;\n continue;\n }\n\n // ── CSI accumulator ──\n if (this.state === \"csi\") {\n const ch = chunk[i]!;\n this.csiBuf += ch;\n if (isCsiFinal(ch)) {\n this.dispatchCsi(this.csiBuf);\n this.csiBuf = \"\";\n // Only reset state if `dispatchCsi` didn't already mutate it\n // (it transitions to `paste` for the `200~` start marker —\n // resetting here would clobber that and the paste content\n // would be parsed as keystrokes).\n if (this.state === \"csi\") this.state = \"idle\";\n }\n i++;\n continue;\n }\n\n // ── SS3 single-byte tail ──\n if (this.state === \"ss3\") {\n const ev = SS3_MAP[chunk[i]!];\n if (ev) this.dispatch(ev);\n this.state = \"idle\";\n i++;\n continue;\n }\n\n // ── ESC pending ──\n if (this.state === \"esc\") {\n const ch = chunk[i]!;\n if (ch === \"[\") {\n this.state = \"csi\";\n this.csiBuf = \"\";\n i++;\n continue;\n }\n if (ch === \"O\") {\n this.state = \"ss3\";\n i++;\n continue;\n }\n // Alt+Enter: ESC + CR (or ESC + LF). Universal newline shortcut on terminals\n // that don't support modifyOtherKeys (Shift+Enter falls through to plain Enter there).\n if (ch === \"\\r\" || ch === \"\\n\") {\n this.dispatch({ input: \"\", return: true, meta: true });\n this.state = \"idle\";\n i++;\n continue;\n }\n // ESC + any other char = Alt+key (rare; we still dispatch).\n this.dispatch({ input: ch, meta: true });\n this.state = \"idle\";\n i++;\n continue;\n }\n\n // ── idle ──\n const ch = chunk[i]!;\n\n if (ch === \"\\x1b\") {\n this.state = \"esc\";\n i++;\n continue;\n }\n\n // ESC-stripped paste-start (ConPTY): bare `[200~` at idle.\n if (chunk.slice(i, i + PASTE_START_BARE.length) === PASTE_START_BARE) {\n this.state = \"paste\";\n this.pasteBuf = \"\";\n i += PASTE_START_BARE.length;\n continue;\n }\n // ESC-stripped CSI tails — recover before treating `[` as text.\n const escapeless = tryEscapelessCsi(chunk, i);\n if (escapeless) {\n this.dispatch(escapeless.ev);\n i += escapeless.advance;\n continue;\n }\n\n // Single-byte control keys.\n // \\r (CR, 0x0D) is Enter on every terminal in raw mode.\n // \\n (LF, 0x0A) is what Ctrl+J emits — keep it distinct so the\n // multiline reducer can map it to \"insert newline\" instead of\n // \"submit\". Pastes containing \\n still arrive via either the\n // bracketed-paste accumulator or a multi-byte printable chunk\n // that includes the newline; neither hits this single-byte\n // branch, so this split is safe.\n if (ch === \"\\r\") {\n this.dispatch({ input: \"\", return: true });\n i++;\n continue;\n }\n if (ch === \"\\n\") {\n this.dispatch({ input: \"j\", ctrl: true });\n i++;\n continue;\n }\n if (ch === \"\\t\") {\n this.dispatch({ input: \"\", tab: true });\n i++;\n continue;\n }\n if (ch === \"\\x7f\" || ch === \"\\b\") {\n this.dispatch({ input: \"\", backspace: true });\n i++;\n continue;\n }\n if (ch === \"\\x03\") {\n // Ctrl+C — terminate the process. Raw mode disables the\n // default SIGINT, so we have to handle it ourselves.\n this.dispatch({ input: \"c\", ctrl: true });\n i++;\n continue;\n }\n\n const code = ch.charCodeAt(0);\n // Other Ctrl+letter (0x01-0x1A → A-Z, except already-handled).\n if (code >= 1 && code <= 26) {\n const letter = String.fromCharCode(0x60 + code); // a..z\n this.dispatch({ input: letter, ctrl: true });\n i++;\n continue;\n }\n\n // Regular printable input. Coalesce a run of printable chars\n // into one event so a multi-byte UTF-8 paste-burst arrives as\n // one `input` rather than N adjacent events.\n let end = i + 1;\n while (end < chunk.length) {\n const c = chunk[end]!;\n if (c === \"\\x1b\" || c === \"\\r\" || c === \"\\n\" || c === \"\\t\") break;\n if (c === \"\\x7f\" || c === \"\\b\" || c === \"\\x03\") break;\n const cc = c.charCodeAt(0);\n if (cc >= 1 && cc <= 26) break;\n // Don't swallow into a printable run if a CSI / paste prefix\n // starts at this position.\n if (c === \"[\" && tryEscapelessCsi(chunk, end)) break;\n if (chunk.slice(end, end + PASTE_START_BARE.length) === PASTE_START_BARE) break;\n end++;\n }\n this.dispatch({ input: chunk.slice(i, end) });\n i = end;\n }\n\n // After processing, if we're still in `esc` state, schedule the\n // ambiguity timer. The next chunk may carry the rest of the CSI;\n // if not, the timer fires and dispatches a standalone Esc.\n if (this.state === \"esc\") {\n this.scheduleEscTimer();\n }\n }\n\n private dispatchCsi(seq: string): void {\n // seq is the bytes after `\\x1b[`, e.g. \"A\", \"5~\", \"200~\", \"Z\".\n if (seq === \"200~\") {\n this.state = \"paste\";\n this.pasteBuf = \"\";\n return;\n }\n if (seq === \"201~\") {\n // Stray paste-end — we shouldn't reach here outside paste mode,\n // but if we do, drop it silently.\n return;\n }\n // SGR mouse: `<button;col;rowM` (press) or `<button;col;rowm`\n // (release). Only fired when the App enabled SGR mode + button-\n // event tracking at startup. Buttons:\n // 0 = left, 1 = middle, 2 = right\n // 64 = scroll up, 65 = scroll down (no release event for wheel)\n // We surface scroll wheels and left-button presses; the rest are\n // dropped to avoid noisy events.\n if (seq.length > 1 && seq.charCodeAt(0) === 60 /* '<' */) {\n const tail = seq[seq.length - 1]!;\n if (tail === \"M\" || tail === \"m\") {\n const body = seq.slice(1, -1);\n const parts = body.split(\";\");\n if (parts.length === 3) {\n const btn = Number.parseInt(parts[0]!, 10);\n const col = Number.parseInt(parts[1]!, 10);\n const row = Number.parseInt(parts[2]!, 10);\n if (Number.isFinite(btn) && Number.isFinite(col) && Number.isFinite(row)) {\n // SGR mouse: bit 5 (32) = motion, bit 6 (64) = wheel.\n if (tail === \"M\" && btn === 64) {\n this.dispatch({ input: \"\", mouseScrollUp: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"M\" && btn === 65) {\n this.dispatch({ input: \"\", mouseScrollDown: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"M\" && btn === 0) {\n this.dispatch({ input: \"\", mouseClick: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"M\" && btn === 32) {\n this.dispatch({ input: \"\", mouseDrag: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"m\") {\n this.dispatch({ input: \"\", mouseRelease: true, mouseRow: row, mouseCol: col });\n return;\n }\n return;\n }\n }\n }\n }\n const ev = lookupCsi(seq);\n if (ev) {\n this.dispatch(ev);\n return;\n }\n const generic = tryDecodeGenericCsi(seq);\n if (generic) {\n this.dispatch(generic);\n return;\n }\n // Unknown CSI → drop. Do NOT insert raw bytes as text.\n }\n}\n\n/** Singleton — one reader per process. */\nlet singleton: StdinReader | null = null;\n\nexport function getStdinReader(): StdinReader {\n if (!singleton) singleton = new StdinReader();\n return singleton;\n}\n","/** Arrow-key list components for Ink — single-select and multi-select. */\n\nimport { Box, Text } from \"ink\";\nimport React, { useState } from \"react\";\nimport { useKeystroke } from \"./keystroke-context.js\";\nimport { type UiColor, useColor } from \"./theme.js\";\n\nexport interface SelectItem<V extends string = string> {\n value: V;\n label: string;\n /** Optional second row rendered dimmed. */\n hint?: string;\n /** Disabled rows render dimmed and are skipped on nav. */\n disabled?: boolean;\n}\n\nexport interface SingleSelectProps<V extends string> {\n items: SelectItem<V>[];\n initialValue?: V;\n onSubmit: (value: V) => void;\n onCancel?: () => void;\n /** Fired when Tab is pressed on the currently highlighted item. */\n onTab?: (value: V) => void;\n /** Optional dim footer beneath the list. */\n footer?: string;\n}\n\nexport function SingleSelect<V extends string>({\n items,\n initialValue,\n onSubmit,\n onTab,\n onCancel,\n footer,\n}: SingleSelectProps<V>) {\n const color = useColor();\n const initialIndex = Math.max(\n 0,\n items.findIndex((i) => i.value === initialValue && !i.disabled),\n );\n const [index, setIndex] = useState(initialIndex === -1 ? 0 : initialIndex);\n\n useKeystroke((ev) => {\n if (ev.paste) return;\n if (ev.upArrow) {\n setIndex((i) => findNextEnabled(items, i, -1));\n } else if (ev.downArrow) {\n setIndex((i) => findNextEnabled(items, i, +1));\n } else if (ev.return) {\n const chosen = items[index];\n if (chosen && !chosen.disabled) onSubmit(chosen.value);\n } else if (ev.tab) {\n const chosen = items[index];\n if (chosen && !chosen.disabled) onTab?.(chosen.value);\n } else if (ev.escape && onCancel) {\n onCancel();\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n {items.map((item, i) => (\n <SelectRow\n key={item.value}\n item={item}\n active={i === index}\n marker={i === index ? \"▸\" : \" \"}\n color={color}\n />\n ))}\n {footer ? (\n <Box marginTop={1}>\n <Text dimColor>{footer}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nexport interface MultiSelectProps<V extends string> {\n items: SelectItem<V>[];\n initialSelected?: V[];\n onSubmit: (values: V[]) => void;\n onCancel?: () => void;\n /** Footer hint under the list — e.g. \"[Space] toggle · [Enter] confirm\". */\n footer?: string;\n}\n\nexport function MultiSelect<V extends string>({\n items,\n initialSelected = [],\n onSubmit,\n onCancel,\n footer,\n}: MultiSelectProps<V>) {\n const color = useColor();\n const [index, setIndex] = useState(() => {\n const first = items.findIndex((i) => !i.disabled);\n return first === -1 ? 0 : first;\n });\n const [selected, setSelected] = useState<Set<V>>(new Set(initialSelected));\n\n useKeystroke((ev) => {\n if (ev.paste) return;\n if (ev.upArrow) {\n setIndex((i) => findNextEnabled(items, i, -1));\n } else if (ev.downArrow) {\n setIndex((i) => findNextEnabled(items, i, +1));\n } else if (ev.input === \" \") {\n const item = items[index];\n if (!item || item.disabled) return;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(item.value)) next.delete(item.value);\n else next.add(item.value);\n return next;\n });\n } else if (ev.return) {\n const ordered = items.filter((i) => selected.has(i.value)).map((i) => i.value);\n onSubmit(ordered);\n } else if (ev.escape && onCancel) {\n onCancel();\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n {items.map((item, i) => {\n const checked = selected.has(item.value);\n const marker = checked ? \"[x]\" : \"[ ]\";\n return (\n <SelectRow\n key={item.value}\n item={item}\n active={i === index}\n marker={`${i === index ? \"▸\" : \" \"} ${marker}`}\n color={color}\n />\n );\n })}\n {footer ? (\n <Box marginTop={1}>\n <Text dimColor>{footer}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction SelectRow<V extends string>({\n item,\n active,\n marker,\n color,\n}: {\n item: SelectItem<V>;\n active: boolean;\n marker: string;\n color: UiColor;\n}) {\n const rowColor = item.disabled ? color.info : active ? color.primary : undefined;\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Text color={rowColor} bold={active} dimColor={item.disabled}>\n {marker} {item.label}\n </Text>\n </Box>\n {item.hint ? (\n <Box paddingLeft={marker.length + 1}>\n <Text dimColor>{item.hint}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction findNextEnabled<V extends string>(\n items: SelectItem<V>[],\n from: number,\n step: -1 | 1,\n): number {\n if (items.length === 0) return 0;\n let i = from;\n for (let tries = 0; tries < items.length; tries++) {\n i = (i + step + items.length) % items.length;\n if (!items[i]?.disabled) return i;\n }\n return from;\n}\n"],"mappings":"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","names":["ch","React","React"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/ui/keystroke-context.tsx","../../src/cli/ui/stdin-reader.ts","../../src/cli/ui/Select.tsx"],"sourcesContent":["/**\n * KeystrokeContext — React surface in front of the raw stdin reader.\n *\n * Replaces Ink's `useInput` chain. Reasonix's components no longer\n * import `useInput` from \"ink\"; they call `useKeystroke(handler,\n * isActive)` from this module. The provider mounted once at App\n * level owns a `StdinReader`, subscribes a single fan-out function\n * to it, and dispatches each parsed `KeyEvent` to every active\n * consumer.\n *\n * Why a Context instead of a singleton import: the provider can be\n * disabled in tests / replay mode without touching the components,\n * and the lifecycle (start/stop on mount/unmount) is tied to the\n * React tree rather than a global side effect.\n *\n * Why not just keep Ink's useInput: Ink's parse-keypress uses a\n * 100 ms intra-CSI timeout that's too short for Windows ConPTY,\n * leaking arrow-key bytes / paste markers into the buffer. Our\n * reader uses 250 ms and recognises the ESC-stripped variants too\n * — see `stdin-reader.ts`.\n */\n\nimport { useInput } from \"ink\";\n// biome-ignore lint/style/useImportType: tsconfig jsx=react needs React as a runtime value\nimport React, { createContext, useContext, useEffect, useRef } from \"react\";\nimport { type KeyEvent, type StdinReader, getStdinReader } from \"./stdin-reader.js\";\n\ninterface KeystrokeBus {\n /** Subscribe — returns an unsubscribe function. */\n subscribe(handler: KeystrokeHandler): () => void;\n}\n\nexport type KeystrokeHandler = (ev: KeyEvent) => void;\n\nconst KeystrokeContext = createContext<KeystrokeBus | null>(null);\n\nexport interface KeystrokeProviderProps {\n children: React.ReactNode;\n /**\n * Optional reader override. Tests inject a synthetic reader so\n * they can `feed()` chunks instead of touching real stdin. Production\n * callers leave this unset and get the singleton.\n */\n reader?: StdinReader;\n}\n\nexport function KeystrokeProvider({\n children,\n reader: providedReader,\n}: KeystrokeProviderProps): React.ReactElement {\n const handlersRef = useRef<Set<KeystrokeHandler>>(new Set());\n // Ref so the bus value's identity is stable across re-renders —\n // consumers don't accidentally re-subscribe every render.\n const busRef = useRef<KeystrokeBus | null>(null);\n if (busRef.current === null) {\n busRef.current = {\n subscribe(handler) {\n handlersRef.current.add(handler);\n return () => {\n handlersRef.current.delete(handler);\n };\n },\n };\n }\n\n useEffect(() => {\n const reader = providedReader ?? getStdinReader();\n reader.start();\n const unsubscribe = reader.subscribe((ev) => {\n // Snapshot the handler set so handlers added/removed during\n // dispatch don't perturb iteration. Cheap — typical N=1-3.\n for (const fn of [...handlersRef.current]) fn(ev);\n });\n return () => {\n unsubscribe();\n // Don't `stop()` the singleton on every unmount — multiple\n // mounts (test reruns, hot-reload) must not tear down stdin.\n // The singleton's own start() is idempotent; stop() is the\n // process-exit handler's job.\n };\n }, [providedReader]);\n\n return <KeystrokeContext.Provider value={busRef.current}>{children}</KeystrokeContext.Provider>;\n}\n\n/** Subscribe to keystroke events; falls back to Ink's useInput when no KeystrokeProvider is mounted. */\nexport function useKeystroke(handler: KeystrokeHandler, isActive = true): void {\n const bus = useContext(KeystrokeContext);\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n if (!bus || !isActive) return undefined;\n return bus.subscribe((ev) => handlerRef.current(ev));\n }, [bus, isActive]);\n\n useInput(\n (input, key) => {\n if (bus) return;\n handlerRef.current({\n input,\n upArrow: key.upArrow,\n downArrow: key.downArrow,\n leftArrow: key.leftArrow,\n rightArrow: key.rightArrow,\n return: key.return,\n escape: key.escape,\n backspace: key.backspace,\n delete: key.delete,\n tab: key.tab,\n shift: key.shift,\n ctrl: key.ctrl,\n meta: key.meta,\n pageUp: key.pageUp,\n pageDown: key.pageDown,\n });\n },\n { isActive: !bus && isActive },\n );\n}\n\n/**\n * Lower-level hook for components that need a stable subscription\n * across the lifetime of the consumer (typically StdinReader-aware\n * unit tests).\n */\nexport function useKeystrokeBus(): KeystrokeBus | null {\n return useContext(KeystrokeContext);\n}\n\n/** Test helper — assemble a KeyEvent with sensible defaults. */\nexport function makeKeyEvent(overrides: Partial<KeyEvent> = {}): KeyEvent {\n return { input: \"\", ...overrides };\n}\n","/** Sole stdin owner; 250 ms ESC-ambiguity timer (ConPTY splits sequences past parse-keypress's 100 ms). */\n\nimport { stdin } from \"node:process\";\n\nexport interface KeyEvent {\n /** Empty for control keys (arrows / Enter / Esc); holds the letter for Ctrl+/Alt+. */\n input: string;\n upArrow?: boolean;\n downArrow?: boolean;\n leftArrow?: boolean;\n rightArrow?: boolean;\n pageUp?: boolean;\n pageDown?: boolean;\n home?: boolean;\n end?: boolean;\n delete?: boolean;\n backspace?: boolean;\n tab?: boolean;\n return?: boolean;\n escape?: boolean;\n shift?: boolean;\n ctrl?: boolean;\n meta?: boolean;\n /** Bracketed-paste content; consumers MUST NOT re-interpret as keystrokes (e.g. `\\n` ≠ submit). */\n paste?: boolean;\n /** xterm SGR mode 1006 wheel-up. */\n mouseScrollUp?: boolean;\n /** Mouse wheel down — symmetric to `mouseScrollUp`. */\n mouseScrollDown?: boolean;\n /** Left-button press; row/col are 1-based. */\n mouseClick?: boolean;\n /** Left-button motion (button held during drag). Mode 1002 only. */\n mouseDrag?: boolean;\n /** Any-button release. Mode 1002 only. */\n mouseRelease?: boolean;\n mouseRow?: number;\n mouseCol?: number;\n}\n\ntype Subscriber = (ev: KeyEvent) => void;\n\n/** ESC ambiguity timeout. Long enough for ConPTY-split sequences. */\nconst ESC_TIMEOUT_MS = 250;\n\n/** Bracketed-paste markers (DECSET 2004). */\nconst PASTE_START = \"\\x1b[200~\";\nconst PASTE_END = \"\\x1b[201~\";\n/** ESC-stripped variants — ConPTY occasionally eats the leading ESC. */\nconst PASTE_START_BARE = \"[200~\";\nconst PASTE_END_BARE = \"[201~\";\n\nconst CSI_TAIL_MAP: ReadonlyArray<{ tail: string; ev: KeyEvent }> = [\n { tail: \"A\", ev: { input: \"\", upArrow: true } },\n { tail: \"B\", ev: { input: \"\", downArrow: true } },\n { tail: \"C\", ev: { input: \"\", rightArrow: true } },\n { tail: \"D\", ev: { input: \"\", leftArrow: true } },\n { tail: \"H\", ev: { input: \"\", home: true } },\n { tail: \"F\", ev: { input: \"\", end: true } },\n { tail: \"1~\", ev: { input: \"\", home: true } },\n { tail: \"4~\", ev: { input: \"\", end: true } },\n { tail: \"5~\", ev: { input: \"\", pageUp: true } },\n { tail: \"6~\", ev: { input: \"\", pageDown: true } },\n { tail: \"3~\", ev: { input: \"\", delete: true } },\n { tail: \"Z\", ev: { input: \"\", shift: true, tab: true } },\n // Some Windows hosts (PowerShell 7.x conhost path) emit the\n // modifier-encoded back-tab `\\x1b[1;2Z` instead of bare `\\x1b[Z`.\n // Issue #373 — without this entry Shift+Tab is silently dropped.\n { tail: \"1;2Z\", ev: { input: \"\", shift: true, tab: true } },\n // modifyOtherKeys (xterm CSI > 4 ; 2 m) sequences for Enter / Tab\n // with modifiers. Only fired when App.tsx has enabled the mode at\n // startup; otherwise Shift+Enter stays indistinguishable from Enter.\n // Modifier encoding: 2=shift, 3=alt, 4=alt+shift, 5=ctrl,\n // 6=ctrl+shift, 7=ctrl+alt, 8=ctrl+alt+shift. Keycodes: 9=Tab, 13=Enter.\n { tail: \"27;2;9~\", ev: { input: \"\", tab: true, shift: true } },\n { tail: \"27;2;13~\", ev: { input: \"\", return: true, shift: true } },\n { tail: \"27;5;13~\", ev: { input: \"\", return: true, ctrl: true } },\n { tail: \"27;6;13~\", ev: { input: \"\", return: true, ctrl: true, shift: true } },\n // Kitty keyboard protocol — same idea, different envelope:\n // `\\x1b[<keycode>;<mod>u`. Some terminals (kitty, recent Windows\n // Terminal previews) prefer this shape. Harmless to map here too.\n { tail: \"9;2u\", ev: { input: \"\", tab: true, shift: true } },\n { tail: \"13;2u\", ev: { input: \"\", return: true, shift: true } },\n { tail: \"13;5u\", ev: { input: \"\", return: true, ctrl: true } },\n { tail: \"13;6u\", ev: { input: \"\", return: true, ctrl: true, shift: true } },\n];\n\n/** SS3 sequences (`\\x1bO<letter>`) — some terminals send these for arrows. */\nconst SS3_MAP: Record<string, KeyEvent> = {\n A: { input: \"\", upArrow: true },\n B: { input: \"\", downArrow: true },\n C: { input: \"\", rightArrow: true },\n D: { input: \"\", leftArrow: true },\n H: { input: \"\", home: true },\n F: { input: \"\", end: true },\n};\n\n/** ESC-stripped CSI lookahead — ConPTY occasionally drops the leading ESC. */\nfunction tryEscapelessCsi(chunk: string, i: number): { advance: number; ev: KeyEvent } | null {\n if (chunk[i] !== \"[\") return null;\n // Paste start as a special case (handled by caller).\n // Try each known tail.\n for (const entry of CSI_TAIL_MAP) {\n const candidate = `[${entry.tail}`;\n if (chunk.slice(i, i + candidate.length) === candidate) {\n return { advance: candidate.length, ev: entry.ev };\n }\n }\n return null;\n}\n\nfunction isCsiFinal(ch: string): boolean {\n const code = ch.charCodeAt(0);\n return code >= 0x40 && code <= 0x7e;\n}\n\n/** Unknown sequence → null → caller drops bytes silently (don't insert as text). */\nfunction lookupCsi(tail: string): KeyEvent | null {\n for (const entry of CSI_TAIL_MAP) {\n if (entry.tail === tail) return entry.ev;\n }\n return null;\n}\n\n/** modifyOtherKeys / Kitty: reconstruct the keystroke from `<codepoint>` + `<mod>`. */\nfunction decodeModifiedKey(cp: number, mod: number): KeyEvent | null {\n if (mod < 1 || mod > 8) return null;\n const bits = mod - 1;\n const shift = (bits & 1) !== 0;\n const alt = (bits & 2) !== 0;\n const ctrl = (bits & 4) !== 0;\n if (cp >= 0x20 && cp <= 0x7e && !ctrl && !alt) {\n const ev: KeyEvent = { input: String.fromCharCode(cp) };\n if (shift) ev.shift = true;\n return ev;\n }\n if (cp >= 0x20 && cp <= 0x7e && alt && !ctrl) {\n const ev: KeyEvent = { input: String.fromCharCode(cp), meta: true };\n if (shift) ev.shift = true;\n return ev;\n }\n if (cp >= 0x41 && cp <= 0x7a && ctrl && !alt) {\n const ev: KeyEvent = { input: String.fromCharCode(cp).toLowerCase(), ctrl: true };\n if (shift) ev.shift = true;\n return ev;\n }\n return null;\n}\n\n/** Generic modifyOtherKeys / Kitty envelope — picks up the keys lookupCsi misses (`@`, `_`, `[`, `\\`, `]`, `^` under `>4;2m`). */\nfunction tryDecodeGenericCsi(seq: string): KeyEvent | null {\n let m = /^27;(\\d+);(\\d+)~$/.exec(seq);\n if (m) return decodeModifiedKey(Number.parseInt(m[2]!, 10), Number.parseInt(m[1]!, 10));\n m = /^(\\d+);(\\d+)u$/.exec(seq);\n if (m) return decodeModifiedKey(Number.parseInt(m[1]!, 10), Number.parseInt(m[2]!, 10));\n m = /^(\\d+)u$/.exec(seq);\n if (m) return decodeModifiedKey(Number.parseInt(m[1]!, 10), 1);\n return null;\n}\n\n/** Heuristic paste-burst detector — wraps raw multi-line chunks when the terminal didn't (#522). */\nexport function looksLikeUnbracketedPaste(chunk: string): boolean {\n if (chunk.length < 2) return false;\n if (chunk.includes(PASTE_START) || chunk.includes(PASTE_START_BARE)) return false;\n if (chunk.includes(PASTE_END) || chunk.includes(PASTE_END_BARE)) return false;\n // ESC anywhere = real keypress / control sequence, not a paste burst.\n if (chunk.includes(\"\\x1b\")) return false;\n // \\r\\n is one terminal-converted Enter, not two breaks — fold first.\n const norm = chunk.replace(/\\r\\n/g, \"\\n\");\n if (norm === \"\\r\" || norm === \"\\n\") return false;\n let breaks = 0;\n let firstBreakIdx = -1;\n for (let i = 0; i < norm.length; i++) {\n const c = norm[i];\n if (c === \"\\r\" || c === \"\\n\") {\n if (firstBreakIdx < 0) firstBreakIdx = i;\n breaks++;\n }\n }\n if (breaks >= 2) return true;\n // 1 break with non-empty text on BOTH sides — paste burst. (\"abc\\r\"\n // alone stays as type-then-Enter so a fast typist still submits.)\n if (breaks === 1) return firstBreakIdx > 0 && firstBreakIdx < norm.length - 1;\n return false;\n}\n\nexport class StdinReader {\n private subscribers = new Set<Subscriber>();\n private state: \"idle\" | \"esc\" | \"csi\" | \"ss3\" | \"paste\" = \"idle\";\n /** Buffer for partial sequences across chunks. */\n private csiBuf = \"\";\n /** Buffer for paste content. */\n private pasteBuf = \"\";\n private escTimer: NodeJS.Timeout | null = null;\n // Deferred-dispatch handle paired with `escTimer`. The timer\n // queues an Immediate that runs in the event loop's CHECK phase —\n // i.e. AFTER the POLL phase where stdin 'data' events fire — so\n // a multi-byte sequence whose chunks queued up while the loop was\n // blocked (heavy render, etc.) gets a chance to be processed\n // BEFORE we emit a bogus standalone-Esc. Fixes the \"I didn't press\n // Esc but it aborted the turn\" class of bug: previously the timer's\n // setTimeout callback ran in the timers phase ahead of poll, so a\n // split sequence like `\\x1b` + `[A` would dispatch escape+upArrow\n // even though the user only pressed Up.\n private escImmediate: NodeJS.Immediate | null = null;\n private started = false;\n /** The actual `data` listener — kept as a field so `stop()` can detach it. */\n private listener: ((chunk: Buffer | string) => void) | null = null;\n\n start(): void {\n if (this.started) return;\n // bun leaves `isTTY` undefined in a real terminal, so probe setRawMode directly.\n try {\n stdin.setRawMode(true);\n } catch {\n return;\n }\n stdin.setEncoding(\"utf8\");\n stdin.resume();\n this.listener = (chunk) =>\n this.handleChunk(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"));\n stdin.on(\"data\", this.listener);\n this.started = true;\n }\n\n stop(): void {\n if (!this.started) return;\n if (this.listener) {\n stdin.off(\"data\", this.listener);\n this.listener = null;\n }\n try {\n stdin.setRawMode(false);\n } catch {\n // setRawMode may throw if stdin is already closed; ignore.\n }\n stdin.pause();\n this.cancelEscTimer();\n this.state = \"idle\";\n this.csiBuf = \"\";\n this.pasteBuf = \"\";\n this.started = false;\n }\n\n subscribe(fn: Subscriber): () => void {\n this.subscribers.add(fn);\n return () => {\n this.subscribers.delete(fn);\n };\n }\n\n /** Test seam — drives the parser without a real TTY. */\n feed(chunk: string): void {\n this.handleChunk(chunk);\n }\n\n private dispatch(ev: KeyEvent): void {\n for (const sub of this.subscribers) sub(ev);\n }\n\n private cancelEscTimer(): void {\n if (this.escTimer) {\n clearTimeout(this.escTimer);\n this.escTimer = null;\n }\n if (this.escImmediate) {\n clearImmediate(this.escImmediate);\n this.escImmediate = null;\n }\n }\n\n private scheduleEscTimer(): void {\n this.cancelEscTimer();\n this.escTimer = setTimeout(() => {\n this.escTimer = null;\n // Defer the actual dispatch to the CHECK phase so any pending\n // stdin 'data' events that queued up during a long render still\n // get a chance to consume the rest of a split sequence. The\n // chunk handler cancels this Immediate at its start, so a\n // sequence completing first wins; only a truly-orphaned `\\x1b`\n // reaches the dispatch below.\n this.escImmediate = setImmediate(() => {\n this.escImmediate = null;\n if (this.state === \"esc\") {\n this.state = \"idle\";\n this.dispatch({ input: \"\", escape: true });\n }\n });\n }, ESC_TIMEOUT_MS);\n }\n\n private handleChunk(rawChunk: string): void {\n this.cancelEscTimer();\n // Paste rescue when DECSET 2004 markers don't arrive (multiplexers\n // strip them, some Windows pipes too) — otherwise each \\r in a\n // multi-line paste fires Enter and the loop submits N prompts (#522).\n const chunk =\n this.state === \"idle\" && looksLikeUnbracketedPaste(rawChunk)\n ? PASTE_START + rawChunk + PASTE_END\n : rawChunk;\n let i = 0;\n while (i < chunk.length) {\n // ── paste accumulator ──\n if (this.state === \"paste\") {\n // Look for end marker (with or without ESC).\n const endA = chunk.indexOf(PASTE_END, i);\n const endB = chunk.indexOf(PASTE_END_BARE, i);\n let endIdx = -1;\n let endLen = 0;\n if (endA !== -1 && (endB === -1 || endA <= endB)) {\n endIdx = endA;\n endLen = PASTE_END.length;\n } else if (endB !== -1) {\n endIdx = endB;\n endLen = PASTE_END_BARE.length;\n }\n if (endIdx === -1) {\n this.pasteBuf += chunk.slice(i);\n i = chunk.length;\n break;\n }\n this.pasteBuf += chunk.slice(i, endIdx);\n this.dispatch({ input: this.pasteBuf, paste: true });\n this.pasteBuf = \"\";\n this.state = \"idle\";\n i = endIdx + endLen;\n continue;\n }\n\n // ── CSI accumulator ──\n if (this.state === \"csi\") {\n const ch = chunk[i]!;\n this.csiBuf += ch;\n if (isCsiFinal(ch)) {\n this.dispatchCsi(this.csiBuf);\n this.csiBuf = \"\";\n // Only reset state if `dispatchCsi` didn't already mutate it\n // (it transitions to `paste` for the `200~` start marker —\n // resetting here would clobber that and the paste content\n // would be parsed as keystrokes).\n if (this.state === \"csi\") this.state = \"idle\";\n }\n i++;\n continue;\n }\n\n // ── SS3 single-byte tail ──\n if (this.state === \"ss3\") {\n const ev = SS3_MAP[chunk[i]!];\n if (ev) this.dispatch(ev);\n this.state = \"idle\";\n i++;\n continue;\n }\n\n // ── ESC pending ──\n if (this.state === \"esc\") {\n const ch = chunk[i]!;\n if (ch === \"[\") {\n this.state = \"csi\";\n this.csiBuf = \"\";\n i++;\n continue;\n }\n if (ch === \"O\") {\n this.state = \"ss3\";\n i++;\n continue;\n }\n // Alt+Enter: ESC + CR (or ESC + LF). Universal newline shortcut on terminals\n // that don't support modifyOtherKeys (Shift+Enter falls through to plain Enter there).\n if (ch === \"\\r\" || ch === \"\\n\") {\n this.dispatch({ input: \"\", return: true, meta: true });\n this.state = \"idle\";\n i++;\n continue;\n }\n // ESC + any other char = Alt+key (rare; we still dispatch).\n this.dispatch({ input: ch, meta: true });\n this.state = \"idle\";\n i++;\n continue;\n }\n\n // ── idle ──\n const ch = chunk[i]!;\n\n if (ch === \"\\x1b\") {\n this.state = \"esc\";\n i++;\n continue;\n }\n\n // ESC-stripped paste-start (ConPTY): bare `[200~` at idle.\n if (chunk.slice(i, i + PASTE_START_BARE.length) === PASTE_START_BARE) {\n this.state = \"paste\";\n this.pasteBuf = \"\";\n i += PASTE_START_BARE.length;\n continue;\n }\n // ESC-stripped CSI tails — recover before treating `[` as text.\n const escapeless = tryEscapelessCsi(chunk, i);\n if (escapeless) {\n this.dispatch(escapeless.ev);\n i += escapeless.advance;\n continue;\n }\n\n // Single-byte control keys.\n // \\r (CR, 0x0D) is Enter on every terminal in raw mode.\n // \\n (LF, 0x0A) is what Ctrl+J emits — keep it distinct so the\n // multiline reducer can map it to \"insert newline\" instead of\n // \"submit\". Pastes containing \\n still arrive via either the\n // bracketed-paste accumulator or a multi-byte printable chunk\n // that includes the newline; neither hits this single-byte\n // branch, so this split is safe.\n if (ch === \"\\r\") {\n this.dispatch({ input: \"\", return: true });\n i++;\n continue;\n }\n if (ch === \"\\n\") {\n this.dispatch({ input: \"j\", ctrl: true });\n i++;\n continue;\n }\n if (ch === \"\\t\") {\n this.dispatch({ input: \"\", tab: true });\n i++;\n continue;\n }\n if (ch === \"\\x7f\" || ch === \"\\b\") {\n this.dispatch({ input: \"\", backspace: true });\n i++;\n continue;\n }\n if (ch === \"\\x03\") {\n // Ctrl+C — terminate the process. Raw mode disables the\n // default SIGINT, so we have to handle it ourselves.\n this.dispatch({ input: \"c\", ctrl: true });\n i++;\n continue;\n }\n\n const code = ch.charCodeAt(0);\n // Other Ctrl+letter (0x01-0x1A → A-Z, except already-handled).\n if (code >= 1 && code <= 26) {\n const letter = String.fromCharCode(0x60 + code); // a..z\n this.dispatch({ input: letter, ctrl: true });\n i++;\n continue;\n }\n\n // Regular printable input. Coalesce a run of printable chars\n // into one event so a multi-byte UTF-8 paste-burst arrives as\n // one `input` rather than N adjacent events.\n let end = i + 1;\n while (end < chunk.length) {\n const c = chunk[end]!;\n if (c === \"\\x1b\" || c === \"\\r\" || c === \"\\n\" || c === \"\\t\") break;\n if (c === \"\\x7f\" || c === \"\\b\" || c === \"\\x03\") break;\n const cc = c.charCodeAt(0);\n if (cc >= 1 && cc <= 26) break;\n // Don't swallow into a printable run if a CSI / paste prefix\n // starts at this position.\n if (c === \"[\" && tryEscapelessCsi(chunk, end)) break;\n if (chunk.slice(end, end + PASTE_START_BARE.length) === PASTE_START_BARE) break;\n end++;\n }\n this.dispatch({ input: chunk.slice(i, end) });\n i = end;\n }\n\n // After processing, if we're still in `esc` state, schedule the\n // ambiguity timer. The next chunk may carry the rest of the CSI;\n // if not, the timer fires and dispatches a standalone Esc.\n if (this.state === \"esc\") {\n this.scheduleEscTimer();\n }\n }\n\n private dispatchCsi(seq: string): void {\n // seq is the bytes after `\\x1b[`, e.g. \"A\", \"5~\", \"200~\", \"Z\".\n if (seq === \"200~\") {\n this.state = \"paste\";\n this.pasteBuf = \"\";\n return;\n }\n if (seq === \"201~\") {\n // Stray paste-end — we shouldn't reach here outside paste mode,\n // but if we do, drop it silently.\n return;\n }\n // SGR mouse: `<button;col;rowM` (press) or `<button;col;rowm`\n // (release). Only fired when the App enabled SGR mode + button-\n // event tracking at startup. Buttons:\n // 0 = left, 1 = middle, 2 = right\n // 64 = scroll up, 65 = scroll down (no release event for wheel)\n // We surface scroll wheels and left-button presses; the rest are\n // dropped to avoid noisy events.\n if (seq.length > 1 && seq.charCodeAt(0) === 60 /* '<' */) {\n const tail = seq[seq.length - 1]!;\n if (tail === \"M\" || tail === \"m\") {\n const body = seq.slice(1, -1);\n const parts = body.split(\";\");\n if (parts.length === 3) {\n const btn = Number.parseInt(parts[0]!, 10);\n const col = Number.parseInt(parts[1]!, 10);\n const row = Number.parseInt(parts[2]!, 10);\n if (Number.isFinite(btn) && Number.isFinite(col) && Number.isFinite(row)) {\n // SGR mouse: bit 5 (32) = motion, bit 6 (64) = wheel.\n if (tail === \"M\" && btn === 64) {\n this.dispatch({ input: \"\", mouseScrollUp: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"M\" && btn === 65) {\n this.dispatch({ input: \"\", mouseScrollDown: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"M\" && btn === 0) {\n this.dispatch({ input: \"\", mouseClick: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"M\" && btn === 32) {\n this.dispatch({ input: \"\", mouseDrag: true, mouseRow: row, mouseCol: col });\n return;\n }\n if (tail === \"m\") {\n this.dispatch({ input: \"\", mouseRelease: true, mouseRow: row, mouseCol: col });\n return;\n }\n return;\n }\n }\n }\n }\n const ev = lookupCsi(seq);\n if (ev) {\n this.dispatch(ev);\n return;\n }\n const generic = tryDecodeGenericCsi(seq);\n if (generic) {\n this.dispatch(generic);\n return;\n }\n // Unknown CSI → drop. Do NOT insert raw bytes as text.\n }\n}\n\n/** Singleton — one reader per process. */\nlet singleton: StdinReader | null = null;\n\nexport function getStdinReader(): StdinReader {\n if (!singleton) singleton = new StdinReader();\n return singleton;\n}\n","/** Arrow-key list components for Ink — single-select and multi-select. */\n\nimport { Box, Text } from \"ink\";\nimport React, { useState } from \"react\";\nimport { useKeystroke } from \"./keystroke-context.js\";\nimport type { KeyEvent } from \"./stdin-reader.js\";\nimport { type UiColor, useColor } from \"./theme.js\";\n\nexport interface SelectItem<V extends string = string> {\n value: V;\n label: string;\n /** Optional descriptive text rendered dimmed. */\n hint?: string;\n /** Disabled rows render dimmed and are skipped on nav. */\n disabled?: boolean;\n}\n\nexport interface SingleSelectProps<V extends string> {\n items: SelectItem<V>[];\n initialValue?: V;\n onSubmit: (value: V) => void;\n onCancel?: () => void;\n /** Fired when Tab is pressed on the currently highlighted item. */\n onTab?: (value: V) => void;\n /** Optional dim footer beneath the list. */\n footer?: string;\n /** Render item hints on the same row as the label instead of a second row. */\n inlineHints?: boolean;\n /** Ignore matching keystrokes so an enclosing component can own them. */\n ignoreKey?: (ev: KeyEvent) => boolean;\n}\n\nexport function SingleSelect<V extends string>({\n items,\n initialValue,\n onSubmit,\n onTab,\n onCancel,\n footer,\n inlineHints = false,\n ignoreKey,\n}: SingleSelectProps<V>) {\n const color = useColor();\n const initialIndex = Math.max(\n 0,\n items.findIndex((i) => i.value === initialValue && !i.disabled),\n );\n const [index, setIndex] = useState(initialIndex === -1 ? 0 : initialIndex);\n\n useKeystroke((ev) => {\n if (ev.paste || ignoreKey?.(ev)) return;\n if (ev.upArrow) {\n setIndex((i) => findNextEnabled(items, i, -1));\n } else if (ev.downArrow) {\n setIndex((i) => findNextEnabled(items, i, +1));\n } else if (ev.return) {\n const chosen = items[index];\n if (chosen && !chosen.disabled) onSubmit(chosen.value);\n } else if (ev.tab) {\n const chosen = items[index];\n if (chosen && !chosen.disabled) onTab?.(chosen.value);\n } else if (ev.escape && onCancel) {\n onCancel();\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n {items.map((item, i) => (\n <SelectRow\n key={item.value}\n item={item}\n active={i === index}\n marker={i === index ? \"▸\" : \" \"}\n color={color}\n inlineHint={inlineHints}\n />\n ))}\n {footer ? (\n <Box marginTop={1}>\n <Text dimColor>{footer}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nexport interface MultiSelectProps<V extends string> {\n items: SelectItem<V>[];\n initialSelected?: V[];\n onSubmit: (values: V[]) => void;\n onCancel?: () => void;\n /** Footer hint under the list — e.g. \"[Space] toggle · [Enter] confirm\". */\n footer?: string;\n /** Render item hints on the same row as the label instead of a second row. */\n inlineHints?: boolean;\n /** Ignore matching keystrokes so an enclosing component can own them. */\n ignoreKey?: (ev: KeyEvent) => boolean;\n}\n\nexport function MultiSelect<V extends string>({\n items,\n initialSelected = [],\n onSubmit,\n onCancel,\n footer,\n inlineHints = false,\n ignoreKey,\n}: MultiSelectProps<V>) {\n const color = useColor();\n const [index, setIndex] = useState(() => {\n const first = items.findIndex((i) => !i.disabled);\n return first === -1 ? 0 : first;\n });\n const [selected, setSelected] = useState<Set<V>>(new Set(initialSelected));\n\n useKeystroke((ev) => {\n if (ev.paste || ignoreKey?.(ev)) return;\n if (ev.upArrow) {\n setIndex((i) => findNextEnabled(items, i, -1));\n } else if (ev.downArrow) {\n setIndex((i) => findNextEnabled(items, i, +1));\n } else if (ev.input === \" \") {\n const item = items[index];\n if (!item || item.disabled) return;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(item.value)) next.delete(item.value);\n else next.add(item.value);\n return next;\n });\n } else if (ev.return) {\n const ordered = items.filter((i) => selected.has(i.value)).map((i) => i.value);\n onSubmit(ordered);\n } else if (ev.escape && onCancel) {\n onCancel();\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n {items.map((item, i) => {\n const checked = selected.has(item.value);\n const marker = checked ? \"[x]\" : \"[ ]\";\n return (\n <SelectRow\n key={item.value}\n item={item}\n active={i === index}\n marker={`${i === index ? \"▸\" : \" \"} ${marker}`}\n color={color}\n inlineHint={inlineHints}\n />\n );\n })}\n {footer ? (\n <Box marginTop={1}>\n <Text dimColor>{footer}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction SelectRow<V extends string>({\n item,\n active,\n marker,\n color,\n inlineHint = false,\n}: {\n item: SelectItem<V>;\n active: boolean;\n marker: string;\n color: UiColor;\n inlineHint?: boolean;\n}) {\n const rowColor = item.disabled ? color.info : active ? color.primary : undefined;\n const labelText = `${marker} ${item.label}`;\n if (inlineHint) {\n return (\n <Box flexDirection=\"row\" flexWrap=\"nowrap\" minHeight={1}>\n <Text color={rowColor} bold={active} dimColor={item.disabled} wrap=\"truncate\">\n {labelText}\n </Text>\n {item.hint ? <Text dimColor wrap=\"truncate\">{` ${item.hint}`}</Text> : null}\n </Box>\n );\n }\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Text color={rowColor} bold={active} dimColor={item.disabled}>\n {labelText}\n </Text>\n </Box>\n {item.hint ? (\n <Box paddingLeft={marker.length + 1}>\n <Text dimColor>{item.hint}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction findNextEnabled<V extends string>(\n items: SelectItem<V>[],\n from: number,\n step: -1 | 1,\n): number {\n if (items.length === 0) return 0;\n let i = from;\n for (let tries = 0; tries < items.length; tries++) {\n i = (i + step + items.length) % items.length;\n if (!items[i]?.disabled) return i;\n }\n return from;\n}\n"],"mappings":";;;;;;AAsBA,SAAS,gBAAgB;AAEzB,OAAO,SAAS,eAAe,YAAY,WAAW,cAAc;;;ACtBpE,SAAS,aAAa;AAwCtB,IAAM,iBAAiB;AAGvB,IAAM,cAAc;AACpB,IAAM,YAAY;AAElB,IAAM,mBAAmB;AACzB,IAAM,iBAAiB;AAEvB,IAAM,eAA8D;AAAA,EAClE,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,SAAS,KAAK,EAAE;AAAA,EAC9C,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,WAAW,KAAK,EAAE;AAAA,EAChD,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,YAAY,KAAK,EAAE;AAAA,EACjD,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,WAAW,KAAK,EAAE;AAAA,EAChD,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,MAAM,KAAK,EAAE;AAAA,EAC3C,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,KAAK,KAAK,EAAE;AAAA,EAC1C,EAAE,MAAM,MAAM,IAAI,EAAE,OAAO,IAAI,MAAM,KAAK,EAAE;AAAA,EAC5C,EAAE,MAAM,MAAM,IAAI,EAAE,OAAO,IAAI,KAAK,KAAK,EAAE;AAAA,EAC3C,EAAE,MAAM,MAAM,IAAI,EAAE,OAAO,IAAI,QAAQ,KAAK,EAAE;AAAA,EAC9C,EAAE,MAAM,MAAM,IAAI,EAAE,OAAO,IAAI,UAAU,KAAK,EAAE;AAAA,EAChD,EAAE,MAAM,MAAM,IAAI,EAAE,OAAO,IAAI,QAAQ,KAAK,EAAE;AAAA,EAC9C,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,IAAI,OAAO,MAAM,KAAK,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA,EAIvD,EAAE,MAAM,QAAQ,IAAI,EAAE,OAAO,IAAI,OAAO,MAAM,KAAK,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1D,EAAE,MAAM,WAAW,IAAI,EAAE,OAAO,IAAI,KAAK,MAAM,OAAO,KAAK,EAAE;AAAA,EAC7D,EAAE,MAAM,YAAY,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,OAAO,KAAK,EAAE;AAAA,EACjE,EAAE,MAAM,YAAY,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,MAAM,KAAK,EAAE;AAAA,EAChE,EAAE,MAAM,YAAY,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA,EAI7E,EAAE,MAAM,QAAQ,IAAI,EAAE,OAAO,IAAI,KAAK,MAAM,OAAO,KAAK,EAAE;AAAA,EAC1D,EAAE,MAAM,SAAS,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,OAAO,KAAK,EAAE;AAAA,EAC9D,EAAE,MAAM,SAAS,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,MAAM,KAAK,EAAE;AAAA,EAC7D,EAAE,MAAM,SAAS,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK,EAAE;AAC5E;AAGA,IAAM,UAAoC;AAAA,EACxC,GAAG,EAAE,OAAO,IAAI,SAAS,KAAK;AAAA,EAC9B,GAAG,EAAE,OAAO,IAAI,WAAW,KAAK;AAAA,EAChC,GAAG,EAAE,OAAO,IAAI,YAAY,KAAK;AAAA,EACjC,GAAG,EAAE,OAAO,IAAI,WAAW,KAAK;AAAA,EAChC,GAAG,EAAE,OAAO,IAAI,MAAM,KAAK;AAAA,EAC3B,GAAG,EAAE,OAAO,IAAI,KAAK,KAAK;AAC5B;AAGA,SAAS,iBAAiB,OAAe,GAAqD;AAC5F,MAAI,MAAM,CAAC,MAAM,IAAK,QAAO;AAG7B,aAAW,SAAS,cAAc;AAChC,UAAM,YAAY,IAAI,MAAM,IAAI;AAChC,QAAI,MAAM,MAAM,GAAG,IAAI,UAAU,MAAM,MAAM,WAAW;AACtD,aAAO,EAAE,SAAS,UAAU,QAAQ,IAAI,MAAM,GAAG;AAAA,IACnD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,IAAqB;AACvC,QAAM,OAAO,GAAG,WAAW,CAAC;AAC5B,SAAO,QAAQ,MAAQ,QAAQ;AACjC;AAGA,SAAS,UAAU,MAA+B;AAChD,aAAW,SAAS,cAAc;AAChC,QAAI,MAAM,SAAS,KAAM,QAAO,MAAM;AAAA,EACxC;AACA,SAAO;AACT;AAGA,SAAS,kBAAkB,IAAY,KAA8B;AACnE,MAAI,MAAM,KAAK,MAAM,EAAG,QAAO;AAC/B,QAAM,OAAO,MAAM;AACnB,QAAM,SAAS,OAAO,OAAO;AAC7B,QAAM,OAAO,OAAO,OAAO;AAC3B,QAAM,QAAQ,OAAO,OAAO;AAC5B,MAAI,MAAM,MAAQ,MAAM,OAAQ,CAAC,QAAQ,CAAC,KAAK;AAC7C,UAAM,KAAe,EAAE,OAAO,OAAO,aAAa,EAAE,EAAE;AACtD,QAAI,MAAO,IAAG,QAAQ;AACtB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAQ,MAAM,OAAQ,OAAO,CAAC,MAAM;AAC5C,UAAM,KAAe,EAAE,OAAO,OAAO,aAAa,EAAE,GAAG,MAAM,KAAK;AAClE,QAAI,MAAO,IAAG,QAAQ;AACtB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAQ,MAAM,OAAQ,QAAQ,CAAC,KAAK;AAC5C,UAAM,KAAe,EAAE,OAAO,OAAO,aAAa,EAAE,EAAE,YAAY,GAAG,MAAM,KAAK;AAChF,QAAI,MAAO,IAAG,QAAQ;AACtB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGA,SAAS,oBAAoB,KAA8B;AACzD,MAAI,IAAI,oBAAoB,KAAK,GAAG;AACpC,MAAI,EAAG,QAAO,kBAAkB,OAAO,SAAS,EAAE,CAAC,GAAI,EAAE,GAAG,OAAO,SAAS,EAAE,CAAC,GAAI,EAAE,CAAC;AACtF,MAAI,iBAAiB,KAAK,GAAG;AAC7B,MAAI,EAAG,QAAO,kBAAkB,OAAO,SAAS,EAAE,CAAC,GAAI,EAAE,GAAG,OAAO,SAAS,EAAE,CAAC,GAAI,EAAE,CAAC;AACtF,MAAI,WAAW,KAAK,GAAG;AACvB,MAAI,EAAG,QAAO,kBAAkB,OAAO,SAAS,EAAE,CAAC,GAAI,EAAE,GAAG,CAAC;AAC7D,SAAO;AACT;AAGO,SAAS,0BAA0B,OAAwB;AAChE,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,MAAI,MAAM,SAAS,WAAW,KAAK,MAAM,SAAS,gBAAgB,EAAG,QAAO;AAC5E,MAAI,MAAM,SAAS,SAAS,KAAK,MAAM,SAAS,cAAc,EAAG,QAAO;AAExE,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AAEnC,QAAM,OAAO,MAAM,QAAQ,SAAS,IAAI;AACxC,MAAI,SAAS,QAAQ,SAAS,KAAM,QAAO;AAC3C,MAAI,SAAS;AACb,MAAI,gBAAgB;AACpB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,MAAM,QAAQ,MAAM,MAAM;AAC5B,UAAI,gBAAgB,EAAG,iBAAgB;AACvC;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,EAAG,QAAO;AAGxB,MAAI,WAAW,EAAG,QAAO,gBAAgB,KAAK,gBAAgB,KAAK,SAAS;AAC5E,SAAO;AACT;AAEO,IAAM,cAAN,MAAkB;AAAA,EACf,cAAc,oBAAI,IAAgB;AAAA,EAClC,QAAkD;AAAA;AAAA,EAElD,SAAS;AAAA;AAAA,EAET,WAAW;AAAA,EACX,WAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWlC,eAAwC;AAAA,EACxC,UAAU;AAAA;AAAA,EAEV,WAAsD;AAAA,EAE9D,QAAc;AACZ,QAAI,KAAK,QAAS;AAElB,QAAI;AACF,YAAM,WAAW,IAAI;AAAA,IACvB,QAAQ;AACN;AAAA,IACF;AACA,UAAM,YAAY,MAAM;AACxB,UAAM,OAAO;AACb,SAAK,WAAW,CAAC,UACf,KAAK,YAAY,OAAO,UAAU,WAAW,QAAQ,MAAM,SAAS,MAAM,CAAC;AAC7E,UAAM,GAAG,QAAQ,KAAK,QAAQ;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAa;AACX,QAAI,CAAC,KAAK,QAAS;AACnB,QAAI,KAAK,UAAU;AACjB,YAAM,IAAI,QAAQ,KAAK,QAAQ;AAC/B,WAAK,WAAW;AAAA,IAClB;AACA,QAAI;AACF,YAAM,WAAW,KAAK;AAAA,IACxB,QAAQ;AAAA,IAER;AACA,UAAM,MAAM;AACZ,SAAK,eAAe;AACpB,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAU,IAA4B;AACpC,SAAK,YAAY,IAAI,EAAE;AACvB,WAAO,MAAM;AACX,WAAK,YAAY,OAAO,EAAE;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA,EAGA,KAAK,OAAqB;AACxB,SAAK,YAAY,KAAK;AAAA,EACxB;AAAA,EAEQ,SAAS,IAAoB;AACnC,eAAW,OAAO,KAAK,YAAa,KAAI,EAAE;AAAA,EAC5C;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,UAAU;AACjB,mBAAa,KAAK,QAAQ;AAC1B,WAAK,WAAW;AAAA,IAClB;AACA,QAAI,KAAK,cAAc;AACrB,qBAAe,KAAK,YAAY;AAChC,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,SAAK,eAAe;AACpB,SAAK,WAAW,WAAW,MAAM;AAC/B,WAAK,WAAW;AAOhB,WAAK,eAAe,aAAa,MAAM;AACrC,aAAK,eAAe;AACpB,YAAI,KAAK,UAAU,OAAO;AACxB,eAAK,QAAQ;AACb,eAAK,SAAS,EAAE,OAAO,IAAI,QAAQ,KAAK,CAAC;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH,GAAG,cAAc;AAAA,EACnB;AAAA,EAEQ,YAAY,UAAwB;AAC1C,SAAK,eAAe;AAIpB,UAAM,QACJ,KAAK,UAAU,UAAU,0BAA0B,QAAQ,IACvD,cAAc,WAAW,YACzB;AACN,QAAI,IAAI;AACR,WAAO,IAAI,MAAM,QAAQ;AAEvB,UAAI,KAAK,UAAU,SAAS;AAE1B,cAAM,OAAO,MAAM,QAAQ,WAAW,CAAC;AACvC,cAAM,OAAO,MAAM,QAAQ,gBAAgB,CAAC;AAC5C,YAAI,SAAS;AACb,YAAI,SAAS;AACb,YAAI,SAAS,OAAO,SAAS,MAAM,QAAQ,OAAO;AAChD,mBAAS;AACT,mBAAS,UAAU;AAAA,QACrB,WAAW,SAAS,IAAI;AACtB,mBAAS;AACT,mBAAS,eAAe;AAAA,QAC1B;AACA,YAAI,WAAW,IAAI;AACjB,eAAK,YAAY,MAAM,MAAM,CAAC;AAC9B,cAAI,MAAM;AACV;AAAA,QACF;AACA,aAAK,YAAY,MAAM,MAAM,GAAG,MAAM;AACtC,aAAK,SAAS,EAAE,OAAO,KAAK,UAAU,OAAO,KAAK,CAAC;AACnD,aAAK,WAAW;AAChB,aAAK,QAAQ;AACb,YAAI,SAAS;AACb;AAAA,MACF;AAGA,UAAI,KAAK,UAAU,OAAO;AACxB,cAAMA,MAAK,MAAM,CAAC;AAClB,aAAK,UAAUA;AACf,YAAI,WAAWA,GAAE,GAAG;AAClB,eAAK,YAAY,KAAK,MAAM;AAC5B,eAAK,SAAS;AAKd,cAAI,KAAK,UAAU,MAAO,MAAK,QAAQ;AAAA,QACzC;AACA;AACA;AAAA,MACF;AAGA,UAAI,KAAK,UAAU,OAAO;AACxB,cAAM,KAAK,QAAQ,MAAM,CAAC,CAAE;AAC5B,YAAI,GAAI,MAAK,SAAS,EAAE;AACxB,aAAK,QAAQ;AACb;AACA;AAAA,MACF;AAGA,UAAI,KAAK,UAAU,OAAO;AACxB,cAAMA,MAAK,MAAM,CAAC;AAClB,YAAIA,QAAO,KAAK;AACd,eAAK,QAAQ;AACb,eAAK,SAAS;AACd;AACA;AAAA,QACF;AACA,YAAIA,QAAO,KAAK;AACd,eAAK,QAAQ;AACb;AACA;AAAA,QACF;AAGA,YAAIA,QAAO,QAAQA,QAAO,MAAM;AAC9B,eAAK,SAAS,EAAE,OAAO,IAAI,QAAQ,MAAM,MAAM,KAAK,CAAC;AACrD,eAAK,QAAQ;AACb;AACA;AAAA,QACF;AAEA,aAAK,SAAS,EAAE,OAAOA,KAAI,MAAM,KAAK,CAAC;AACvC,aAAK,QAAQ;AACb;AACA;AAAA,MACF;AAGA,YAAM,KAAK,MAAM,CAAC;AAElB,UAAI,OAAO,QAAQ;AACjB,aAAK,QAAQ;AACb;AACA;AAAA,MACF;AAGA,UAAI,MAAM,MAAM,GAAG,IAAI,iBAAiB,MAAM,MAAM,kBAAkB;AACpE,aAAK,QAAQ;AACb,aAAK,WAAW;AAChB,aAAK,iBAAiB;AACtB;AAAA,MACF;AAEA,YAAM,aAAa,iBAAiB,OAAO,CAAC;AAC5C,UAAI,YAAY;AACd,aAAK,SAAS,WAAW,EAAE;AAC3B,aAAK,WAAW;AAChB;AAAA,MACF;AAUA,UAAI,OAAO,MAAM;AACf,aAAK,SAAS,EAAE,OAAO,IAAI,QAAQ,KAAK,CAAC;AACzC;AACA;AAAA,MACF;AACA,UAAI,OAAO,MAAM;AACf,aAAK,SAAS,EAAE,OAAO,KAAK,MAAM,KAAK,CAAC;AACxC;AACA;AAAA,MACF;AACA,UAAI,OAAO,KAAM;AACf,aAAK,SAAS,EAAE,OAAO,IAAI,KAAK,KAAK,CAAC;AACtC;AACA;AAAA,MACF;AACA,UAAI,OAAO,UAAU,OAAO,MAAM;AAChC,aAAK,SAAS,EAAE,OAAO,IAAI,WAAW,KAAK,CAAC;AAC5C;AACA;AAAA,MACF;AACA,UAAI,OAAO,KAAQ;AAGjB,aAAK,SAAS,EAAE,OAAO,KAAK,MAAM,KAAK,CAAC;AACxC;AACA;AAAA,MACF;AAEA,YAAM,OAAO,GAAG,WAAW,CAAC;AAE5B,UAAI,QAAQ,KAAK,QAAQ,IAAI;AAC3B,cAAM,SAAS,OAAO,aAAa,KAAO,IAAI;AAC9C,aAAK,SAAS,EAAE,OAAO,QAAQ,MAAM,KAAK,CAAC;AAC3C;AACA;AAAA,MACF;AAKA,UAAI,MAAM,IAAI;AACd,aAAO,MAAM,MAAM,QAAQ;AACzB,cAAM,IAAI,MAAM,GAAG;AACnB,YAAI,MAAM,UAAU,MAAM,QAAQ,MAAM,QAAQ,MAAM,IAAM;AAC5D,YAAI,MAAM,UAAU,MAAM,QAAQ,MAAM,IAAQ;AAChD,cAAM,KAAK,EAAE,WAAW,CAAC;AACzB,YAAI,MAAM,KAAK,MAAM,GAAI;AAGzB,YAAI,MAAM,OAAO,iBAAiB,OAAO,GAAG,EAAG;AAC/C,YAAI,MAAM,MAAM,KAAK,MAAM,iBAAiB,MAAM,MAAM,iBAAkB;AAC1E;AAAA,MACF;AACA,WAAK,SAAS,EAAE,OAAO,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC;AAC5C,UAAI;AAAA,IACN;AAKA,QAAI,KAAK,UAAU,OAAO;AACxB,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,YAAY,KAAmB;AAErC,QAAI,QAAQ,QAAQ;AAClB,WAAK,QAAQ;AACb,WAAK,WAAW;AAChB;AAAA,IACF;AACA,QAAI,QAAQ,QAAQ;AAGlB;AAAA,IACF;AAQA,QAAI,IAAI,SAAS,KAAK,IAAI,WAAW,CAAC,MAAM,IAAc;AACxD,YAAM,OAAO,IAAI,IAAI,SAAS,CAAC;AAC/B,UAAI,SAAS,OAAO,SAAS,KAAK;AAChC,cAAM,OAAO,IAAI,MAAM,GAAG,EAAE;AAC5B,cAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,YAAI,MAAM,WAAW,GAAG;AACtB,gBAAM,MAAM,OAAO,SAAS,MAAM,CAAC,GAAI,EAAE;AACzC,gBAAM,MAAM,OAAO,SAAS,MAAM,CAAC,GAAI,EAAE;AACzC,gBAAM,MAAM,OAAO,SAAS,MAAM,CAAC,GAAI,EAAE;AACzC,cAAI,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,GAAG;AAExE,gBAAI,SAAS,OAAO,QAAQ,IAAI;AAC9B,mBAAK,SAAS,EAAE,OAAO,IAAI,eAAe,MAAM,UAAU,KAAK,UAAU,IAAI,CAAC;AAC9E;AAAA,YACF;AACA,gBAAI,SAAS,OAAO,QAAQ,IAAI;AAC9B,mBAAK,SAAS,EAAE,OAAO,IAAI,iBAAiB,MAAM,UAAU,KAAK,UAAU,IAAI,CAAC;AAChF;AAAA,YACF;AACA,gBAAI,SAAS,OAAO,QAAQ,GAAG;AAC7B,mBAAK,SAAS,EAAE,OAAO,IAAI,YAAY,MAAM,UAAU,KAAK,UAAU,IAAI,CAAC;AAC3E;AAAA,YACF;AACA,gBAAI,SAAS,OAAO,QAAQ,IAAI;AAC9B,mBAAK,SAAS,EAAE,OAAO,IAAI,WAAW,MAAM,UAAU,KAAK,UAAU,IAAI,CAAC;AAC1E;AAAA,YACF;AACA,gBAAI,SAAS,KAAK;AAChB,mBAAK,SAAS,EAAE,OAAO,IAAI,cAAc,MAAM,UAAU,KAAK,UAAU,IAAI,CAAC;AAC7E;AAAA,YACF;AACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,UAAU,GAAG;AACxB,QAAI,IAAI;AACN,WAAK,SAAS,EAAE;AAChB;AAAA,IACF;AACA,UAAM,UAAU,oBAAoB,GAAG;AACvC,QAAI,SAAS;AACX,WAAK,SAAS,OAAO;AACrB;AAAA,IACF;AAAA,EAEF;AACF;AAGA,IAAI,YAAgC;AAE7B,SAAS,iBAA8B;AAC5C,MAAI,CAAC,UAAW,aAAY,IAAI,YAAY;AAC5C,SAAO;AACT;;;ADzgBA,IAAM,mBAAmB,cAAmC,IAAI;AAYzD,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,QAAQ;AACV,GAA+C;AAC7C,QAAM,cAAc,OAA8B,oBAAI,IAAI,CAAC;AAG3D,QAAM,SAAS,OAA4B,IAAI;AAC/C,MAAI,OAAO,YAAY,MAAM;AAC3B,WAAO,UAAU;AAAA,MACf,UAAU,SAAS;AACjB,oBAAY,QAAQ,IAAI,OAAO;AAC/B,eAAO,MAAM;AACX,sBAAY,QAAQ,OAAO,OAAO;AAAA,QACpC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,YAAU,MAAM;AACd,UAAM,SAAS,kBAAkB,eAAe;AAChD,WAAO,MAAM;AACb,UAAM,cAAc,OAAO,UAAU,CAAC,OAAO;AAG3C,iBAAW,MAAM,CAAC,GAAG,YAAY,OAAO,EAAG,IAAG,EAAE;AAAA,IAClD,CAAC;AACD,WAAO,MAAM;AACX,kBAAY;AAAA,IAKd;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,SAAO,oCAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAO,WAAU,QAAS;AACrE;AAGO,SAAS,aAAa,SAA2B,WAAW,MAAY;AAC7E,QAAM,MAAM,WAAW,gBAAgB;AACvC,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,YAAU,MAAM;AACd,QAAI,CAAC,OAAO,CAAC,SAAU,QAAO;AAC9B,WAAO,IAAI,UAAU,CAAC,OAAO,WAAW,QAAQ,EAAE,CAAC;AAAA,EACrD,GAAG,CAAC,KAAK,QAAQ,CAAC;AAElB;AAAA,IACE,CAAC,OAAO,QAAQ;AACd,UAAI,IAAK;AACT,iBAAW,QAAQ;AAAA,QACjB;AAAA,QACA,SAAS,IAAI;AAAA,QACb,WAAW,IAAI;AAAA,QACf,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,QAChB,QAAQ,IAAI;AAAA,QACZ,QAAQ,IAAI;AAAA,QACZ,WAAW,IAAI;AAAA,QACf,QAAQ,IAAI;AAAA,QACZ,KAAK,IAAI;AAAA,QACT,OAAO,IAAI;AAAA,QACX,MAAM,IAAI;AAAA,QACV,MAAM,IAAI;AAAA,QACV,QAAQ,IAAI;AAAA,QACZ,UAAU,IAAI;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,IACA,EAAE,UAAU,CAAC,OAAO,SAAS;AAAA,EAC/B;AACF;;;AErHA,SAAS,KAAK,YAAY;AAC1B,OAAOC,UAAS,gBAAgB;AA6BzB,SAAS,aAA+B;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAyB;AACvB,QAAM,QAAQ,SAAS;AACvB,QAAM,eAAe,KAAK;AAAA,IACxB;AAAA,IACA,MAAM,UAAU,CAAC,MAAM,EAAE,UAAU,gBAAgB,CAAC,EAAE,QAAQ;AAAA,EAChE;AACA,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,iBAAiB,KAAK,IAAI,YAAY;AAEzE,eAAa,CAAC,OAAO;AACnB,QAAI,GAAG,SAAS,YAAY,EAAE,EAAG;AACjC,QAAI,GAAG,SAAS;AACd,eAAS,CAAC,MAAM,gBAAgB,OAAO,GAAG,EAAE,CAAC;AAAA,IAC/C,WAAW,GAAG,WAAW;AACvB,eAAS,CAAC,MAAM,gBAAgB,OAAO,GAAG,CAAE,CAAC;AAAA,IAC/C,WAAW,GAAG,QAAQ;AACpB,YAAM,SAAS,MAAM,KAAK;AAC1B,UAAI,UAAU,CAAC,OAAO,SAAU,UAAS,OAAO,KAAK;AAAA,IACvD,WAAW,GAAG,KAAK;AACjB,YAAM,SAAS,MAAM,KAAK;AAC1B,UAAI,UAAU,CAAC,OAAO,SAAU,SAAQ,OAAO,KAAK;AAAA,IACtD,WAAW,GAAG,UAAU,UAAU;AAChC,eAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,SACE,gBAAAC,OAAA,cAAC,OAAI,eAAc,YAChB,MAAM,IAAI,CAAC,MAAM,MAChB,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,KAAK;AAAA,MACV;AAAA,MACA,QAAQ,MAAM;AAAA,MACd,QAAQ,MAAM,QAAQ,WAAM;AAAA,MAC5B;AAAA,MACA,YAAY;AAAA;AAAA,EACd,CACD,GACA,SACC,gBAAAA,OAAA,cAAC,OAAI,WAAW,KACd,gBAAAA,OAAA,cAAC,QAAK,UAAQ,QAAE,MAAO,CACzB,IACE,IACN;AAEJ;AAeO,SAAS,YAA8B;AAAA,EAC5C;AAAA,EACA,kBAAkB,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAwB;AACtB,QAAM,QAAQ,SAAS;AACvB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,MAAM;AACvC,UAAM,QAAQ,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ;AAChD,WAAO,UAAU,KAAK,IAAI;AAAA,EAC5B,CAAC;AACD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAiB,IAAI,IAAI,eAAe,CAAC;AAEzE,eAAa,CAAC,OAAO;AACnB,QAAI,GAAG,SAAS,YAAY,EAAE,EAAG;AACjC,QAAI,GAAG,SAAS;AACd,eAAS,CAAC,MAAM,gBAAgB,OAAO,GAAG,EAAE,CAAC;AAAA,IAC/C,WAAW,GAAG,WAAW;AACvB,eAAS,CAAC,MAAM,gBAAgB,OAAO,GAAG,CAAE,CAAC;AAAA,IAC/C,WAAW,GAAG,UAAU,KAAK;AAC3B,YAAM,OAAO,MAAM,KAAK;AACxB,UAAI,CAAC,QAAQ,KAAK,SAAU;AAC5B,kBAAY,CAAC,SAAS;AACpB,cAAM,OAAO,IAAI,IAAI,IAAI;AACzB,YAAI,KAAK,IAAI,KAAK,KAAK,EAAG,MAAK,OAAO,KAAK,KAAK;AAAA,YAC3C,MAAK,IAAI,KAAK,KAAK;AACxB,eAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,GAAG,QAAQ;AACpB,YAAM,UAAU,MAAM,OAAO,CAAC,MAAM,SAAS,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK;AAC7E,eAAS,OAAO;AAAA,IAClB,WAAW,GAAG,UAAU,UAAU;AAChC,eAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,SACE,gBAAAA,OAAA,cAAC,OAAI,eAAc,YAChB,MAAM,IAAI,CAAC,MAAM,MAAM;AACtB,UAAM,UAAU,SAAS,IAAI,KAAK,KAAK;AACvC,UAAM,SAAS,UAAU,QAAQ;AACjC,WACE,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK,KAAK;AAAA,QACV;AAAA,QACA,QAAQ,MAAM;AAAA,QACd,QAAQ,GAAG,MAAM,QAAQ,WAAM,GAAG,IAAI,MAAM;AAAA,QAC5C;AAAA,QACA,YAAY;AAAA;AAAA,IACd;AAAA,EAEJ,CAAC,GACA,SACC,gBAAAA,OAAA,cAAC,OAAI,WAAW,KACd,gBAAAA,OAAA,cAAC,QAAK,UAAQ,QAAE,MAAO,CACzB,IACE,IACN;AAEJ;AAEA,SAAS,UAA4B;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AACf,GAMG;AACD,QAAM,WAAW,KAAK,WAAW,MAAM,OAAO,SAAS,MAAM,UAAU;AACvE,QAAM,YAAY,GAAG,MAAM,IAAI,KAAK,KAAK;AACzC,MAAI,YAAY;AACd,WACE,gBAAAA,OAAA,cAAC,OAAI,eAAc,OAAM,UAAS,UAAS,WAAW,KACpD,gBAAAA,OAAA,cAAC,QAAK,OAAO,UAAU,MAAM,QAAQ,UAAU,KAAK,UAAU,MAAK,cAChE,SACH,GACC,KAAK,OAAO,gBAAAA,OAAA,cAAC,QAAK,UAAQ,MAAC,MAAK,cAAY,KAAK,KAAK,IAAI,EAAG,IAAU,IAC1E;AAAA,EAEJ;AACA,SACE,gBAAAA,OAAA,cAAC,OAAI,eAAc,YACjB,gBAAAA,OAAA,cAAC,WACC,gBAAAA,OAAA,cAAC,QAAK,OAAO,UAAU,MAAM,QAAQ,UAAU,KAAK,YACjD,SACH,CACF,GACC,KAAK,OACJ,gBAAAA,OAAA,cAAC,OAAI,aAAa,OAAO,SAAS,KAChC,gBAAAA,OAAA,cAAC,QAAK,UAAQ,QAAE,KAAK,IAAK,CAC5B,IACE,IACN;AAEJ;AAEA,SAAS,gBACP,OACA,MACA,MACQ;AACR,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,IAAI;AACR,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;AACjD,SAAK,IAAI,OAAO,MAAM,UAAU,MAAM;AACtC,QAAI,CAAC,MAAM,CAAC,GAAG,SAAU,QAAO;AAAA,EAClC;AACA,SAAO;AACT;","names":["ch","React","React"]}
|
|
@@ -425,6 +425,42 @@ function compileFilters(cfg) {
|
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
// src/config.ts
|
|
428
|
+
var BUILTIN_TYPE_DOCS = {
|
|
429
|
+
user: "role / skills / preferences",
|
|
430
|
+
feedback: "corrections or confirmed approaches",
|
|
431
|
+
project: "facts / decisions about the current work",
|
|
432
|
+
reference: "pointers to external systems the user uses"
|
|
433
|
+
};
|
|
434
|
+
function loadMemoryTypeRegistry(cfg = readConfig()) {
|
|
435
|
+
const out = [];
|
|
436
|
+
for (const name of ["user", "feedback", "project", "reference"]) {
|
|
437
|
+
out.push({ name, builtin: true, description: BUILTIN_TYPE_DOCS[name] });
|
|
438
|
+
}
|
|
439
|
+
const seen = new Set(out.map((e) => e.name));
|
|
440
|
+
for (const raw of cfg.memory?.customTypes ?? []) {
|
|
441
|
+
if (!raw || typeof raw.name !== "string") continue;
|
|
442
|
+
const name = raw.name.trim();
|
|
443
|
+
if (!name || !/^[a-zA-Z][a-zA-Z0-9_-]{0,31}$/.test(name)) continue;
|
|
444
|
+
if (seen.has(name)) continue;
|
|
445
|
+
seen.add(name);
|
|
446
|
+
const entry = { name, builtin: false };
|
|
447
|
+
if (typeof raw.description === "string") entry.description = raw.description;
|
|
448
|
+
if (raw.priority === "low" || raw.priority === "medium" || raw.priority === "high") {
|
|
449
|
+
entry.priority = raw.priority;
|
|
450
|
+
}
|
|
451
|
+
if (raw.expires === "project_end") entry.expires = raw.expires;
|
|
452
|
+
out.push(entry);
|
|
453
|
+
}
|
|
454
|
+
return out;
|
|
455
|
+
}
|
|
456
|
+
function memoryTypeDefaults(typeName, cfg = readConfig()) {
|
|
457
|
+
const found = loadMemoryTypeRegistry(cfg).find((e) => e.name === typeName);
|
|
458
|
+
if (!found) return {};
|
|
459
|
+
const out = {};
|
|
460
|
+
if (found.priority) out.priority = found.priority;
|
|
461
|
+
if (found.expires) out.expires = found.expires;
|
|
462
|
+
return out;
|
|
463
|
+
}
|
|
428
464
|
var DEFAULT_OLLAMA_URL = "http://localhost:11434";
|
|
429
465
|
var DEFAULT_EMBED_MODEL = "nomic-embed-text";
|
|
430
466
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -804,6 +840,8 @@ export {
|
|
|
804
840
|
defaultIndexConfig,
|
|
805
841
|
resolveIndexConfig,
|
|
806
842
|
compileFilters,
|
|
843
|
+
loadMemoryTypeRegistry,
|
|
844
|
+
memoryTypeDefaults,
|
|
807
845
|
defaultConfigPath,
|
|
808
846
|
readConfig,
|
|
809
847
|
writeConfig,
|
|
@@ -851,4 +889,4 @@ export {
|
|
|
851
889
|
isPlausibleKey,
|
|
852
890
|
redactKey
|
|
853
891
|
};
|
|
854
|
-
//# sourceMappingURL=chunk-
|
|
892
|
+
//# sourceMappingURL=chunk-65Q5HQ26.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/config.ts","../../src/cli/ui/theme/tokens.ts","../../src/index/config.ts"],"sourcesContent":["/** Library reads only DEEPSEEK_API_KEY from env; the CLI bridges config.json → env var. */\n\nimport { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { type ThemeName, isThemeName, resolveThemeName } from \"./cli/ui/theme/tokens.js\";\nimport type { LanguageCode } from \"./i18n/types.js\";\nimport {\n type IndexUserConfig,\n type ResolvedIndexConfig,\n resolveIndexConfig,\n} from \"./index/config.js\";\n\n/** Legacy `fast|smart|max` kept for back-compat with existing config.json files. */\nexport type PresetName = \"auto\" | \"flash\" | \"pro\" | \"fast\" | \"smart\" | \"max\";\n\n/** Single trust dial: review queues edits + gates shell; auto applies + gates shell; yolo skips both gates. */\nexport type EditMode = \"review\" | \"auto\" | \"yolo\";\n\nexport type ReasoningEffort = \"high\" | \"max\";\n\nexport type EmbeddingProvider = \"ollama\" | \"openai-compat\";\n\nexport interface OllamaEmbeddingUserConfig {\n baseUrl?: string;\n model?: string;\n}\n\nexport interface OpenAICompatEmbeddingUserConfig {\n baseUrl?: string;\n apiKey?: string;\n model?: string;\n extraBody?: Record<string, unknown>;\n}\n\nexport interface SemanticEmbeddingUserConfig {\n provider?: EmbeddingProvider;\n ollama?: OllamaEmbeddingUserConfig;\n openaiCompat?: OpenAICompatEmbeddingUserConfig;\n}\n\nexport interface ResolvedOllamaEmbeddingConfig {\n provider: \"ollama\";\n baseUrl: string;\n model: string;\n timeoutMs: number;\n}\n\nexport interface ResolvedOpenAICompatEmbeddingConfig {\n provider: \"openai-compat\";\n baseUrl: string;\n apiKey: string;\n model: string;\n extraBody: Record<string, unknown>;\n timeoutMs: number;\n}\n\nexport type ResolvedEmbeddingConfig =\n | ResolvedOllamaEmbeddingConfig\n | ResolvedOpenAICompatEmbeddingConfig;\n\nexport interface SemanticEmbeddingConfigView {\n provider: EmbeddingProvider;\n ollama: {\n baseUrl: string;\n model: string;\n };\n openaiCompat: {\n baseUrl: string;\n apiKey: string;\n apiKeySet: boolean;\n model: string;\n extraBody: Record<string, unknown>;\n };\n}\n\nexport interface ReasonixConfig {\n apiKey?: string;\n baseUrl?: string;\n lang?: LanguageCode;\n preset?: PresetName;\n editMode?: EditMode;\n editModeHintShown?: boolean;\n mouseClipboardHintShown?: boolean;\n reasoningEffort?: ReasoningEffort;\n /** Default workspace root for the desktop client. CLI uses cwd. */\n workspaceDir?: string;\n /** Last N workspace paths the desktop client has opened, most recent first. */\n recentWorkspaces?: string[];\n /** Desktop only — `openWith` value for clicking file links. Empty/undefined = OS default app. Examples: \"code\", \"cursor\", \"C:\\\\path\\\\to\\\\editor.exe\". */\n editor?: string;\n theme?: ThemeName | \"auto\";\n /** Stored as `--mcp`-format strings so one parser handles both flag and config. */\n mcp?: string[];\n /** Names of servers in `mcp` to skip on bridge — see `/mcp disable <name>`. */\n mcpDisabled?: string[];\n /** Env overlay per MCP server name (matches the `name=` prefix of the spec). Stdio transports merge this over process.env; SSE/HTTP ignore it. */\n mcpEnv?: Record<string, Record<string, string>>;\n session?: string | null;\n setupCompleted?: boolean;\n search?: boolean;\n /** Web search engine backend: \"mojeek\" (default, scrapes Mojeek) or \"searxng\" (self-hosted SearXNG). */\n webSearchEngine?: \"mojeek\" | \"searxng\";\n /** Base URL for SearXNG instance (default http://localhost:8080). */\n webSearchEndpoint?: string;\n dashboard?: {\n /** Pin the embedded dashboard to a fixed port — required for stable SSH tunnels. 0/absent → ephemeral. */\n port?: number;\n };\n escalation?: {\n /** Per-turn repair/error signal count required to escalate flash→pro. Defaults to 3. Out-of-range → default. */\n failureThreshold?: number;\n };\n /** Per-field visibility toggles for the bottom status row. All default to true (visible). */\n statusBar?: {\n showBalance?: boolean;\n showSessionCost?: boolean;\n showTurnCost?: boolean;\n showCacheHit?: boolean;\n showVersion?: boolean;\n showFeedbackHint?: boolean;\n };\n projects?: {\n [absoluteRootDir: string]: {\n shellAllowed?: string[];\n /** Absolute directory prefixes the user pre-approved for outside-sandbox file access (#684). */\n pathAllowed?: string[];\n };\n };\n index?: IndexUserConfig;\n semantic?: SemanticEmbeddingUserConfig;\n /** User-declared extensions to the built-in memory types (#709). Unknown types round-trip even without a declaration; declaring one lets you attach a default priority + lifecycle. */\n memory?: {\n customTypes?: CustomMemoryTypeConfig[];\n };\n}\n\nexport interface CustomMemoryTypeConfig {\n name: string;\n description?: string;\n priority?: \"low\" | \"medium\" | \"high\";\n expires?: \"project_end\";\n}\n\nexport interface MemoryTypeRegistryEntry {\n name: string;\n builtin: boolean;\n description?: string;\n priority?: \"low\" | \"medium\" | \"high\";\n expires?: \"project_end\";\n}\n\nconst BUILTIN_TYPE_DOCS: Record<string, string> = {\n user: \"role / skills / preferences\",\n feedback: \"corrections or confirmed approaches\",\n project: \"facts / decisions about the current work\",\n reference: \"pointers to external systems the user uses\",\n};\n\n/** Resolve the merged registry of memory types — built-ins, overlaid by anything in `config.memory.customTypes`. */\nexport function loadMemoryTypeRegistry(\n cfg: ReasonixConfig = readConfig(),\n): MemoryTypeRegistryEntry[] {\n const out: MemoryTypeRegistryEntry[] = [];\n for (const name of [\"user\", \"feedback\", \"project\", \"reference\"]) {\n out.push({ name, builtin: true, description: BUILTIN_TYPE_DOCS[name] });\n }\n const seen = new Set(out.map((e) => e.name));\n for (const raw of cfg.memory?.customTypes ?? []) {\n if (!raw || typeof raw.name !== \"string\") continue;\n const name = raw.name.trim();\n if (!name || !/^[a-zA-Z][a-zA-Z0-9_-]{0,31}$/.test(name)) continue;\n if (seen.has(name)) continue;\n seen.add(name);\n const entry: MemoryTypeRegistryEntry = { name, builtin: false };\n if (typeof raw.description === \"string\") entry.description = raw.description;\n if (raw.priority === \"low\" || raw.priority === \"medium\" || raw.priority === \"high\") {\n entry.priority = raw.priority;\n }\n if (raw.expires === \"project_end\") entry.expires = raw.expires;\n out.push(entry);\n }\n return out;\n}\n\nexport function memoryTypeDefaults(\n typeName: string,\n cfg: ReasonixConfig = readConfig(),\n): { priority?: \"low\" | \"medium\" | \"high\"; expires?: \"project_end\" } {\n const found = loadMemoryTypeRegistry(cfg).find((e) => e.name === typeName);\n if (!found) return {};\n const out: { priority?: \"low\" | \"medium\" | \"high\"; expires?: \"project_end\" } = {};\n if (found.priority) out.priority = found.priority;\n if (found.expires) out.expires = found.expires;\n return out;\n}\n\nconst DEFAULT_OLLAMA_URL = \"http://localhost:11434\";\nconst DEFAULT_EMBED_MODEL = \"nomic-embed-text\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function defaultConfigPath(): string {\n return join(homedir(), \".reasonix\", \"config.json\");\n}\n\nexport function readConfig(path: string = defaultConfigPath()): ReasonixConfig {\n try {\n const raw = readFileSync(path, \"utf8\");\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\") return parsed as ReasonixConfig;\n } catch {\n /* missing or malformed → empty config */\n }\n return {};\n}\n\nexport function writeConfig(cfg: ReasonixConfig, path: string = defaultConfigPath()): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(cfg, null, 2), \"utf8\");\n try {\n chmodSync(path, 0o600);\n } catch {\n /* ignore on platforms without chmod */\n }\n}\n\n/** Resolve the language from config file. */\nexport function loadLanguage(path: string = defaultConfigPath()): LanguageCode | undefined {\n return readConfig(path).lang;\n}\n\nexport function mcpEnvFor(\n serverName: string | null | undefined,\n cfg: ReasonixConfig,\n): Record<string, string> | undefined {\n if (!serverName) return undefined;\n const entry = cfg.mcpEnv?.[serverName];\n if (!entry) return undefined;\n // Coerce to string and drop empty values — JSON config could be sloppy.\n const filtered: Record<string, string> = {};\n for (const [k, v] of Object.entries(entry)) {\n if (typeof v === \"string\" && v.length > 0) filtered[k] = v;\n }\n return Object.keys(filtered).length > 0 ? filtered : undefined;\n}\n\n/** Persist the language so it survives a relaunch. */\nexport function saveLanguage(lang: LanguageCode, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n cfg.lang = lang;\n writeConfig(cfg, path);\n}\n\n/** Resolve the API key from env var first, then the config file. */\nexport function loadApiKey(path: string = defaultConfigPath()): string | undefined {\n if (process.env.DEEPSEEK_API_KEY) return process.env.DEEPSEEK_API_KEY;\n return readConfig(path).apiKey;\n}\n\n/** env > config > undefined. Client falls back to api.deepseek.com when undefined. */\nexport function loadBaseUrl(path: string = defaultConfigPath()): string | undefined {\n if (process.env.DEEPSEEK_BASE_URL) return process.env.DEEPSEEK_BASE_URL;\n return readConfig(path).baseUrl;\n}\n\nexport function saveBaseUrl(url: string, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n const trimmed = url.trim();\n if (trimmed) {\n cfg.baseUrl = trimmed;\n } else {\n cfg.baseUrl = undefined;\n }\n writeConfig(cfg, path);\n}\n\nexport function searchEnabled(path: string = defaultConfigPath()): boolean {\n const env = process.env.REASONIX_SEARCH;\n if (env === \"off\" || env === \"false\" || env === \"0\") return false;\n const cfg = readConfig(path).search;\n if (cfg === false) return false;\n return true;\n}\n\nexport function webSearchEngine(path: string = defaultConfigPath()): \"mojeek\" | \"searxng\" {\n const cfg = readConfig(path).webSearchEngine;\n if (cfg === \"searxng\") return \"searxng\";\n return \"mojeek\";\n}\n\nexport function webSearchEndpoint(path: string = defaultConfigPath()): string {\n const cfg = readConfig(path).webSearchEndpoint;\n if (cfg && typeof cfg === \"string\") return cfg;\n return \"http://localhost:8080\";\n}\n\nexport function saveApiKey(key: string, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n cfg.apiKey = key.trim();\n writeConfig(cfg, path);\n}\n\n/** Windows: case-insensitive — NTFS treats `F:\\Foo` and `f:\\foo` as one directory (#402). */\nfunction findProjectKey(cfg: ReasonixConfig, rootDir: string): string | undefined {\n const projects = cfg.projects;\n if (!projects) return undefined;\n if (Object.hasOwn(projects, rootDir)) return rootDir;\n if (process.platform !== \"win32\") return undefined;\n const lower = rootDir.toLowerCase();\n for (const k of Object.keys(projects)) {\n if (k.toLowerCase() === lower) return k;\n }\n return undefined;\n}\n\nexport function loadProjectShellAllowed(\n rootDir: string,\n path: string = defaultConfigPath(),\n): string[] {\n const cfg = readConfig(path);\n const key = findProjectKey(cfg, rootDir);\n if (key === undefined) return [];\n return cfg.projects?.[key]?.shellAllowed ?? [];\n}\n\nexport function addProjectShellAllowed(\n rootDir: string,\n prefix: string,\n path: string = defaultConfigPath(),\n): void {\n const trimmed = prefix.trim();\n if (!trimmed) return;\n const cfg = readConfig(path);\n if (!cfg.projects) cfg.projects = {};\n const key = findProjectKey(cfg, rootDir) ?? rootDir;\n if (!cfg.projects[key]) cfg.projects[key] = {};\n const existing = cfg.projects[key].shellAllowed ?? [];\n if (existing.includes(trimmed)) return;\n cfg.projects[key].shellAllowed = [...existing, trimmed];\n writeConfig(cfg, path);\n}\n\n/** Match is exact after trim — NOT prefix-match: removing `git` MUST NOT drop `git push origin main`. */\nexport function removeProjectShellAllowed(\n rootDir: string,\n prefix: string,\n path: string = defaultConfigPath(),\n): boolean {\n const trimmed = prefix.trim();\n if (!trimmed) return false;\n const cfg = readConfig(path);\n const key = findProjectKey(cfg, rootDir);\n if (key === undefined) return false;\n const existing = cfg.projects?.[key]?.shellAllowed ?? [];\n if (!existing.includes(trimmed)) return false;\n const next = existing.filter((p) => p !== trimmed);\n if (!cfg.projects) cfg.projects = {};\n if (!cfg.projects[key]) cfg.projects[key] = {};\n cfg.projects[key].shellAllowed = next;\n writeConfig(cfg, path);\n return true;\n}\n\nexport function clearProjectShellAllowed(\n rootDir: string,\n path: string = defaultConfigPath(),\n): number {\n const cfg = readConfig(path);\n const key = findProjectKey(cfg, rootDir);\n if (key === undefined) return 0;\n const existing = cfg.projects?.[key]?.shellAllowed ?? [];\n if (existing.length === 0) return 0;\n if (!cfg.projects) cfg.projects = {};\n if (!cfg.projects[key]) cfg.projects[key] = {};\n cfg.projects[key].shellAllowed = [];\n writeConfig(cfg, path);\n return existing.length;\n}\n\nexport function loadProjectPathAllowed(\n rootDir: string,\n path: string = defaultConfigPath(),\n): string[] {\n const cfg = readConfig(path);\n const key = findProjectKey(cfg, rootDir);\n if (key === undefined) return [];\n return cfg.projects?.[key]?.pathAllowed ?? [];\n}\n\nexport function addProjectPathAllowed(\n rootDir: string,\n prefix: string,\n path: string = defaultConfigPath(),\n): void {\n const trimmed = prefix.trim();\n if (!trimmed) return;\n const cfg = readConfig(path);\n if (!cfg.projects) cfg.projects = {};\n const key = findProjectKey(cfg, rootDir) ?? rootDir;\n if (!cfg.projects[key]) cfg.projects[key] = {};\n const existing = cfg.projects[key].pathAllowed ?? [];\n if (existing.includes(trimmed)) return;\n cfg.projects[key].pathAllowed = [...existing, trimmed];\n writeConfig(cfg, path);\n}\n\nexport function removeProjectPathAllowed(\n rootDir: string,\n prefix: string,\n path: string = defaultConfigPath(),\n): boolean {\n const trimmed = prefix.trim();\n if (!trimmed) return false;\n const cfg = readConfig(path);\n const key = findProjectKey(cfg, rootDir);\n if (key === undefined) return false;\n const existing = cfg.projects?.[key]?.pathAllowed ?? [];\n if (!existing.includes(trimmed)) return false;\n const next = existing.filter((p) => p !== trimmed);\n if (!cfg.projects) cfg.projects = {};\n if (!cfg.projects[key]) cfg.projects[key] = {};\n cfg.projects[key].pathAllowed = next;\n writeConfig(cfg, path);\n return true;\n}\n\nexport function clearProjectPathAllowed(\n rootDir: string,\n path: string = defaultConfigPath(),\n): number {\n const cfg = readConfig(path);\n const key = findProjectKey(cfg, rootDir);\n if (key === undefined) return 0;\n const existing = cfg.projects?.[key]?.pathAllowed ?? [];\n if (existing.length === 0) return 0;\n if (!cfg.projects) cfg.projects = {};\n if (!cfg.projects[key]) cfg.projects[key] = {};\n cfg.projects[key].pathAllowed = [];\n writeConfig(cfg, path);\n return existing.length;\n}\n\n/** Unknown values fall back to \"review\" so hand-edited bad config gets the safe default. */\nexport function loadEditMode(path: string = defaultConfigPath()): EditMode {\n const v = readConfig(path).editMode;\n if (v === \"auto\" || v === \"yolo\") return v;\n return \"review\";\n}\n\n/** Persist the edit mode so `/mode auto` survives a relaunch. */\nexport function saveEditMode(mode: EditMode, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n cfg.editMode = mode;\n writeConfig(cfg, path);\n}\n\n/** True when the onboarding tip for the review/AUTO gate has been shown. */\nexport function editModeHintShown(path: string = defaultConfigPath()): boolean {\n return readConfig(path).editModeHintShown === true;\n}\n\n/** True when the mouse-tracking + clipboard tip has been shown. */\nexport function mouseClipboardHintShown(path: string = defaultConfigPath()): boolean {\n return readConfig(path).mouseClipboardHintShown === true;\n}\n\n/** Unknown / missing fall back to \"max\" so hand-edited bad config can't silently override the default. */\nexport function loadReasoningEffort(path: string = defaultConfigPath()): ReasoningEffort {\n const v = readConfig(path).reasoningEffort;\n return v === \"high\" ? \"high\" : \"max\";\n}\n\nexport function loadTheme(path: string = defaultConfigPath()): ThemeName | \"auto\" | undefined {\n const value = readConfig(path).theme;\n if (value === \"auto\") return \"auto\";\n if (typeof value === \"string\" && isThemeName(value)) return value;\n return undefined;\n}\n\nexport function resolveThemePreference(\n configTheme: ThemeName | \"auto\" | undefined,\n envTheme?: string | null,\n): ThemeName {\n if (configTheme && configTheme !== \"auto\") return configTheme;\n return resolveThemeName(envTheme);\n}\n\nexport function saveTheme(theme: ThemeName | \"auto\", path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n cfg.theme = theme;\n writeConfig(cfg, path);\n}\n\n/** Persist the reasoning_effort cap so `/effort high` survives a relaunch. */\nexport function saveReasoningEffort(\n effort: ReasoningEffort,\n path: string = defaultConfigPath(),\n): void {\n const cfg = readConfig(path);\n cfg.reasoningEffort = effort;\n writeConfig(cfg, path);\n}\n\nexport function loadWorkspaceDir(path: string = defaultConfigPath()): string | undefined {\n const v = readConfig(path).workspaceDir;\n return typeof v === \"string\" && v.trim() ? v : undefined;\n}\n\nexport function saveWorkspaceDir(dir: string, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n const trimmed = dir.trim();\n if (trimmed) cfg.workspaceDir = trimmed;\n else cfg.workspaceDir = undefined;\n writeConfig(cfg, path);\n}\n\nexport function loadEditor(path: string = defaultConfigPath()): string | undefined {\n const v = readConfig(path).editor;\n return typeof v === \"string\" && v.trim() ? v : undefined;\n}\n\nexport function saveEditor(editor: string, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n const trimmed = editor.trim();\n if (trimmed) cfg.editor = trimmed;\n else cfg.editor = undefined;\n writeConfig(cfg, path);\n}\n\nexport function loadRecentWorkspaces(path: string = defaultConfigPath()): string[] {\n const v = readConfig(path).recentWorkspaces;\n return Array.isArray(v) ? v.filter((s): s is string => typeof s === \"string\") : [];\n}\n\nconst MAX_RECENT_WORKSPACES = 8;\nexport function pushRecentWorkspace(dir: string, path: string = defaultConfigPath()): void {\n const trimmed = dir.trim();\n if (!trimmed) return;\n const cfg = readConfig(path);\n const list = (cfg.recentWorkspaces ?? []).filter((s) => s !== trimmed);\n list.unshift(trimmed);\n cfg.recentWorkspaces = list.slice(0, MAX_RECENT_WORKSPACES);\n writeConfig(cfg, path);\n}\n\nexport function loadPreset(path: string = defaultConfigPath()): PresetName | undefined {\n return readConfig(path).preset;\n}\n\n/** Persist preset so `/preset pro` (or `/model deepseek-v4-pro`) sticks across relaunches. */\nexport function savePreset(preset: PresetName, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n cfg.preset = preset;\n writeConfig(cfg, path);\n}\n\nexport function loadIndexUserConfig(path: string = defaultConfigPath()): IndexUserConfig {\n return readConfig(path).index ?? {};\n}\n\nexport function loadIndexConfig(path: string = defaultConfigPath()): ResolvedIndexConfig {\n return resolveIndexConfig(readConfig(path).index);\n}\n\nexport function saveIndexConfig(user: IndexUserConfig, path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n cfg.index = user;\n writeConfig(cfg, path);\n}\n\nexport function loadSemanticEmbeddingUserConfig(\n path: string = defaultConfigPath(),\n): SemanticEmbeddingUserConfig {\n return normalizeSemanticEmbeddingUserConfig(readConfig(path).semantic);\n}\n\nexport function saveSemanticEmbeddingConfig(\n user: SemanticEmbeddingUserConfig,\n path: string = defaultConfigPath(),\n): void {\n const cfg = readConfig(path);\n cfg.semantic = normalizeSemanticEmbeddingUserConfig(user);\n writeConfig(cfg, path);\n}\n\nexport function resolveSemanticEmbeddingConfig(\n path: string = defaultConfigPath(),\n): ResolvedEmbeddingConfig {\n const user = loadSemanticEmbeddingUserConfig(path);\n const provider = user.provider ?? \"ollama\";\n if (provider === \"openai-compat\") {\n const baseUrl = user.openaiCompat?.baseUrl?.trim() ?? \"\";\n const apiKey = user.openaiCompat?.apiKey?.trim() ?? \"\";\n const model = user.openaiCompat?.model?.trim() ?? \"\";\n if (!baseUrl) throw new Error(\"OpenAI-compatible embeddings require an API URL.\");\n requireValidUrl(baseUrl, \"OpenAI-compatible API URL\");\n if (!apiKey) throw new Error(\"OpenAI-compatible embeddings require an API key.\");\n if (!model) throw new Error(\"OpenAI-compatible embeddings require a model.\");\n return {\n provider,\n baseUrl,\n apiKey,\n model,\n extraBody: normalizeExtraBody(user.openaiCompat?.extraBody),\n timeoutMs: DEFAULT_TIMEOUT_MS,\n };\n }\n return {\n provider: \"ollama\",\n baseUrl: user.ollama?.baseUrl?.trim() || process.env.OLLAMA_URL || DEFAULT_OLLAMA_URL,\n model: user.ollama?.model?.trim() || process.env.REASONIX_EMBED_MODEL || DEFAULT_EMBED_MODEL,\n timeoutMs: DEFAULT_TIMEOUT_MS,\n };\n}\n\nexport function redactSemanticEmbeddingConfig(\n user: SemanticEmbeddingUserConfig,\n): SemanticEmbeddingConfigView {\n const normalized = normalizeSemanticEmbeddingUserConfig(user);\n return {\n provider: normalized.provider ?? \"ollama\",\n ollama: {\n baseUrl: normalized.ollama?.baseUrl?.trim() || process.env.OLLAMA_URL || DEFAULT_OLLAMA_URL,\n model:\n normalized.ollama?.model?.trim() || process.env.REASONIX_EMBED_MODEL || DEFAULT_EMBED_MODEL,\n },\n openaiCompat: {\n baseUrl: normalized.openaiCompat?.baseUrl?.trim() ?? \"\",\n apiKey: normalized.openaiCompat?.apiKey ? redactKey(normalized.openaiCompat.apiKey) : \"\",\n apiKeySet: Boolean(normalized.openaiCompat?.apiKey?.trim()),\n model: normalized.openaiCompat?.model?.trim() ?? \"\",\n extraBody: normalizeExtraBody(normalized.openaiCompat?.extraBody),\n },\n };\n}\n\n/** Mark the onboarding tip as shown so subsequent launches skip it. */\nexport function markEditModeHintShown(path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n if (cfg.editModeHintShown === true) return;\n cfg.editModeHintShown = true;\n writeConfig(cfg, path);\n}\n\n/** Mark the mouse + clipboard tip as shown. */\nexport function markMouseClipboardHintShown(path: string = defaultConfigPath()): void {\n const cfg = readConfig(path);\n if (cfg.mouseClipboardHintShown === true) return;\n cfg.mouseClipboardHintShown = true;\n writeConfig(cfg, path);\n}\n\n/** Self-hosted DeepSeek-compatible endpoints may issue any token shape, so we only typo-guard here — the real auth check is the first API call against `baseUrl`. */\nexport function isPlausibleKey(key: string): boolean {\n const trimmed = key.trim();\n if (trimmed.length < 16) return false;\n return !/\\s/.test(trimmed);\n}\n\n/** Mask a key for display: `sk-abcd...wxyz`. */\nexport function redactKey(key: string): string {\n if (!key) return \"\";\n if (key.length <= 12) return \"****\";\n return `${key.slice(0, 6)}…${key.slice(-4)}`;\n}\n\nfunction normalizeSemanticEmbeddingUserConfig(\n cfg: SemanticEmbeddingUserConfig | undefined,\n): SemanticEmbeddingUserConfig {\n return {\n provider: cfg?.provider === \"openai-compat\" ? \"openai-compat\" : \"ollama\",\n ollama: {\n baseUrl: normalizeOptionalString(cfg?.ollama?.baseUrl),\n model: normalizeOptionalString(cfg?.ollama?.model),\n },\n openaiCompat: {\n baseUrl: normalizeOptionalString(cfg?.openaiCompat?.baseUrl),\n apiKey: normalizeOptionalString(cfg?.openaiCompat?.apiKey),\n model: normalizeOptionalString(cfg?.openaiCompat?.model),\n extraBody: normalizeExtraBody(cfg?.openaiCompat?.extraBody),\n },\n };\n}\n\nfunction normalizeOptionalString(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction normalizeExtraBody(value: Record<string, unknown> | undefined): Record<string, unknown> {\n if (value === undefined) return {};\n if (!isPlainObject(value)) {\n throw new Error(\"Semantic embedding extraBody must be a JSON object.\");\n }\n return { ...value };\n}\n\nfunction requireValidUrl(value: string, label: string): void {\n try {\n new URL(value);\n } catch {\n throw new Error(`${label} must be a valid URL.`);\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n","export type ThemeName =\n | \"default\"\n | \"dark\"\n | \"light\"\n | \"tokyo-night\"\n | \"github-dark\"\n | \"github-light\"\n | \"high-contrast\";\n\nexport interface ThemeTokens {\n fg: {\n strong: string;\n body: string;\n sub: string;\n meta: string;\n faint: string;\n };\n tone: {\n brand: string;\n accent: string;\n violet: string;\n ok: string;\n warn: string;\n err: string;\n info: string;\n };\n toneActive: ThemeTokens[\"tone\"];\n surface: {\n bg: string;\n bgInput: string;\n bgCode: string;\n bgElev: string;\n };\n card: Record<\n | \"user\"\n | \"reasoning\"\n | \"streaming\"\n | \"task\"\n | \"tool\"\n | \"plan\"\n | \"diff\"\n | \"error\"\n | \"warn\"\n | \"usage\"\n | \"subagent\"\n | \"approval\"\n | \"search\"\n | \"memory\"\n | \"ctx\"\n | \"doctor\"\n | \"branch\",\n { color: string; glyph: string }\n >;\n}\n\ntype ThemeBase = Omit<ThemeTokens, \"card\">;\n\nfunction card(fg: ThemeTokens[\"fg\"], tone: ThemeTokens[\"tone\"]): ThemeTokens[\"card\"] {\n return {\n user: { color: fg.meta, glyph: \"◇\" },\n reasoning: { color: tone.accent, glyph: \"◆\" },\n streaming: { color: tone.brand, glyph: \"◈\" },\n task: { color: tone.warn, glyph: \"▶\" },\n tool: { color: tone.info, glyph: \"▣\" },\n plan: { color: tone.accent, glyph: \"⊞\" },\n diff: { color: tone.ok, glyph: \"±\" },\n error: { color: tone.err, glyph: \"✖\" },\n warn: { color: tone.warn, glyph: \"⚠\" },\n usage: { color: fg.meta, glyph: \"Σ\" },\n subagent: { color: tone.violet, glyph: \"⌬\" },\n approval: { color: tone.warn, glyph: \"?\" },\n search: { color: tone.info, glyph: \"⊙\" },\n memory: { color: fg.meta, glyph: \"⌑\" },\n ctx: { color: tone.brand, glyph: \"◔\" },\n doctor: { color: fg.meta, glyph: \"⚕\" },\n branch: { color: tone.violet, glyph: \"⎇\" },\n };\n}\n\nfunction defineTheme(base: ThemeBase): ThemeTokens {\n return { ...base, card: card(base.fg, base.tone) };\n}\n\nconst githubDark = defineTheme({\n fg: {\n strong: \"#e6edf3\",\n body: \"#c9d1d9\",\n sub: \"#8b949e\",\n meta: \"#6e7681\",\n faint: \"#484f58\",\n },\n tone: {\n brand: \"#79c0ff\",\n accent: \"#d2a8ff\",\n violet: \"#b395f5\",\n ok: \"#7ee787\",\n warn: \"#f0b07d\",\n err: \"#ff8b81\",\n info: \"#79c0ff\",\n },\n toneActive: {\n brand: \"#a5d6ff\",\n accent: \"#e2c5ff\",\n violet: \"#c8aaff\",\n ok: \"#a8f5ad\",\n warn: \"#ffc99e\",\n err: \"#ffaba3\",\n info: \"#a5d6ff\",\n },\n surface: {\n bg: \"#0a0c10\",\n bgInput: \"#0d1015\",\n bgCode: \"#06080c\",\n bgElev: \"#11141a\",\n },\n});\n\nconst dark = defineTheme({\n fg: {\n strong: \"#f4f7fb\",\n body: \"#d8dee9\",\n sub: \"#a7b1c2\",\n meta: \"#778294\",\n faint: \"#4d5666\",\n },\n tone: {\n brand: \"#7dd3fc\",\n accent: \"#c084fc\",\n violet: \"#a78bfa\",\n ok: \"#86efac\",\n warn: \"#fbbf24\",\n err: \"#f87171\",\n info: \"#60a5fa\",\n },\n toneActive: {\n brand: \"#bae6fd\",\n accent: \"#e9d5ff\",\n violet: \"#ddd6fe\",\n ok: \"#bbf7d0\",\n warn: \"#fde68a\",\n err: \"#fecaca\",\n info: \"#bfdbfe\",\n },\n surface: {\n bg: \"#0b1020\",\n bgInput: \"#111827\",\n bgCode: \"#080c16\",\n bgElev: \"#151d2f\",\n },\n});\n\nconst light = defineTheme({\n fg: {\n strong: \"#111827\",\n body: \"#1f2937\",\n sub: \"#4b5563\",\n meta: \"#6b7280\",\n faint: \"#9ca3af\",\n },\n tone: {\n brand: \"#2563eb\",\n accent: \"#7c3aed\",\n violet: \"#6d28d9\",\n ok: \"#15803d\",\n warn: \"#b45309\",\n err: \"#dc2626\",\n info: \"#0369a1\",\n },\n toneActive: {\n brand: \"#1d4ed8\",\n accent: \"#6d28d9\",\n violet: \"#5b21b6\",\n ok: \"#166534\",\n warn: \"#92400e\",\n err: \"#b91c1c\",\n info: \"#075985\",\n },\n surface: {\n bg: \"#ffffff\",\n bgInput: \"#f8fafc\",\n bgCode: \"#f3f4f6\",\n bgElev: \"#eef2f7\",\n },\n});\n\nconst tokyoNight = defineTheme({\n fg: {\n strong: \"#c0caf5\",\n body: \"#a9b1d6\",\n sub: \"#9aa5ce\",\n meta: \"#565f89\",\n faint: \"#414868\",\n },\n tone: {\n brand: \"#7aa2f7\",\n accent: \"#bb9af7\",\n violet: \"#9d7cd8\",\n ok: \"#9ece6a\",\n warn: \"#e0af68\",\n err: \"#f7768e\",\n info: \"#2ac3de\",\n },\n toneActive: {\n brand: \"#a9c7ff\",\n accent: \"#d7b9ff\",\n violet: \"#c6a0f6\",\n ok: \"#b9f27c\",\n warn: \"#ffd089\",\n err: \"#ff9cac\",\n info: \"#7dcfff\",\n },\n surface: {\n bg: \"#1a1b26\",\n bgInput: \"#1f2335\",\n bgCode: \"#16161e\",\n bgElev: \"#24283b\",\n },\n});\n\nconst githubLight = defineTheme({\n fg: {\n strong: \"#1f2328\",\n body: \"#24292f\",\n sub: \"#57606a\",\n meta: \"#6e7781\",\n faint: \"#8c959f\",\n },\n tone: {\n brand: \"#0969da\",\n accent: \"#8250df\",\n violet: \"#6639ba\",\n ok: \"#1a7f37\",\n warn: \"#9a6700\",\n err: \"#cf222e\",\n info: \"#0969da\",\n },\n toneActive: {\n brand: \"#0550ae\",\n accent: \"#6639ba\",\n violet: \"#512a97\",\n ok: \"#116329\",\n warn: \"#7d4e00\",\n err: \"#a40e26\",\n info: \"#0550ae\",\n },\n surface: {\n bg: \"#ffffff\",\n bgInput: \"#f6f8fa\",\n bgCode: \"#f6f8fa\",\n bgElev: \"#eaeef2\",\n },\n});\n\nconst highContrast = defineTheme({\n fg: {\n strong: \"#ffffff\",\n body: \"#f5f5f5\",\n sub: \"#d4d4d4\",\n meta: \"#bdbdbd\",\n faint: \"#8a8a8a\",\n },\n tone: {\n brand: \"#00e5ff\",\n accent: \"#ff4dff\",\n violet: \"#b388ff\",\n ok: \"#00ff66\",\n warn: \"#ffdd00\",\n err: \"#ff4d4d\",\n info: \"#4da3ff\",\n },\n toneActive: {\n brand: \"#80f2ff\",\n accent: \"#ff99ff\",\n violet: \"#d0b3ff\",\n ok: \"#80ffb3\",\n warn: \"#ffee80\",\n err: \"#ff9999\",\n info: \"#99c9ff\",\n },\n surface: {\n bg: \"#000000\",\n bgInput: \"#0a0a0a\",\n bgCode: \"#050505\",\n bgElev: \"#141414\",\n },\n});\n\nexport const THEMES = {\n default: githubDark,\n dark,\n light,\n \"tokyo-night\": tokyoNight,\n \"github-dark\": githubDark,\n \"github-light\": githubLight,\n \"high-contrast\": highContrast,\n} as const satisfies Record<ThemeName, ThemeTokens>;\n\nexport const DEFAULT_THEME_NAME: ThemeName = \"default\";\n\nexport function isThemeName(value: string): value is ThemeName {\n return Object.prototype.hasOwnProperty.call(THEMES, value);\n}\n\nexport function resolveThemeName(value?: string | null): ThemeName {\n if (!value || value === \"auto\") return DEFAULT_THEME_NAME;\n return isThemeName(value) ? value : DEFAULT_THEME_NAME;\n}\n\nexport function listThemeNames(): ThemeName[] {\n return Object.keys(THEMES) as ThemeName[];\n}\n\nexport function themeTokens(name?: string | null): ThemeTokens {\n return THEMES[resolveThemeName(name)];\n}\n\nexport const DEFAULT_THEME = THEMES[DEFAULT_THEME_NAME];\n\nlet activeTheme: ThemeTokens = DEFAULT_THEME;\nlet activeThemeVersion = 0;\n\nexport function setActiveTheme(theme: ThemeTokens): () => void {\n const previousTheme = activeTheme;\n activeTheme = theme;\n activeThemeVersion += 1;\n const version = activeThemeVersion;\n return () => {\n if (activeThemeVersion !== version || activeTheme !== theme) return;\n activeTheme = previousTheme;\n activeThemeVersion += 1;\n };\n}\n\nfunction proxyTokens<T extends object>(select: (theme: ThemeTokens) => T): T {\n const target = select(DEFAULT_THEME);\n return new Proxy(target, {\n get(_target, prop: string | symbol) {\n return select(activeTheme)[prop as keyof T];\n },\n getOwnPropertyDescriptor(_target, prop: string | symbol) {\n return Reflect.getOwnPropertyDescriptor(select(activeTheme), prop);\n },\n has(_target, prop: string | symbol) {\n return prop in select(activeTheme);\n },\n ownKeys() {\n return Reflect.ownKeys(select(activeTheme));\n },\n });\n}\n\nexport const FG = proxyTokens((theme) => theme.fg);\nexport const TONE = proxyTokens((theme) => theme.tone);\nexport const TONE_ACTIVE = proxyTokens((theme) => theme.toneActive);\nexport const SURFACE = proxyTokens((theme) => theme.surface);\nexport const CARD = proxyTokens((theme) => theme.card);\n\nexport type CardTone = keyof ThemeTokens[\"card\"];\n\n/** DeepSeek prices in CNY; our internal table is USD divided by 7.2. Multiply back for display. */\nexport const USD_TO_CNY = 7.2;\n\nconst SYMBOL: Record<string, string> = { USD: \"$\", CNY: \"¥\" };\n\n/** Format an amount already in `currency`. Undefined currency → CNY (matches pre-fix behavior). */\nexport function formatBalance(\n amount: number,\n currency?: string,\n opts?: { fractionDigits?: number; label?: boolean },\n): string {\n const cur = currency ?? \"CNY\";\n const sym = SYMBOL[cur];\n const digits = opts?.fractionDigits ?? 2;\n const body = sym ? `${sym}${amount.toFixed(digits)}` : `${cur} ${amount.toFixed(digits)}`;\n return opts?.label ? `w ${body}` : body;\n}\n\n/** Format an internal USD cost in the wallet's display currency. Undefined currency → CNY. */\nexport function formatCost(costUsd: number, currency?: string, fractionDigits = 4): string {\n const cur = currency ?? \"CNY\";\n const amount = cur === \"CNY\" ? costUsd * USD_TO_CNY : costUsd;\n return formatBalance(amount, cur, { fractionDigits });\n}\n\n/** Threshold color for a wallet balance. USD is converted to CNY before the threshold check. */\nexport function balanceColor(amount: number, currency?: string): string {\n const cny = (currency ?? \"CNY\") === \"USD\" ? amount * USD_TO_CNY : amount;\n if (cny < 5) return TONE.err;\n if (cny < 20) return TONE.warn;\n return TONE.brand;\n}\n","/** Shared exclude defaults + resolver — chunker, directory_tree, and dashboard read from here. */\n\nimport picomatch from \"picomatch\";\n\nexport interface IndexUserConfig {\n excludeDirs?: string[];\n excludeFiles?: string[];\n excludeExts?: string[];\n excludePatterns?: string[];\n respectGitignore?: boolean;\n maxFileBytes?: number;\n}\n\n/** Plain-data shape — JSON-safe so the dashboard endpoint can serialize. */\nexport interface ResolvedIndexConfig {\n excludeDirs: readonly string[];\n excludeFiles: readonly string[];\n excludeExts: readonly string[];\n excludePatterns: readonly string[];\n respectGitignore: boolean;\n maxFileBytes: number;\n}\n\n/** Hot-path lookup wrapper — built once per indexer run, never serialized. */\nexport interface IndexFilters {\n dirSet: ReadonlySet<string>;\n fileSet: ReadonlySet<string>;\n extSet: ReadonlySet<string>;\n patternMatch: (relPath: string) => boolean;\n respectGitignore: boolean;\n maxFileBytes: number;\n}\n\nexport const DEFAULT_INDEX_EXCLUDES = {\n dirs: [\n \"node_modules\",\n \".git\",\n \".hg\",\n \".svn\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \".nuxt\",\n \"target\",\n \".venv\",\n \"venv\",\n \"__pycache__\",\n \".pytest_cache\",\n \".mypy_cache\",\n \".cache\",\n \"coverage\",\n \".turbo\",\n \".vercel\",\n \".reasonix\",\n ] as const,\n files: [\n \"package-lock.json\",\n \"yarn.lock\",\n \"pnpm-lock.yaml\",\n \"Cargo.lock\",\n \"poetry.lock\",\n \"Pipfile.lock\",\n \"go.sum\",\n \".DS_Store\",\n ] as const,\n exts: [\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".webp\",\n \".bmp\",\n \".ico\",\n \".tiff\",\n \".woff\",\n \".woff2\",\n \".ttf\",\n \".otf\",\n \".eot\",\n \".zip\",\n \".tar\",\n \".gz\",\n \".bz2\",\n \".xz\",\n \".rar\",\n \".7z\",\n \".exe\",\n \".dll\",\n \".so\",\n \".dylib\",\n \".bin\",\n \".class\",\n \".jar\",\n \".war\",\n \".wasm\",\n \".o\",\n \".obj\",\n \".lib\",\n \".a\",\n \".pyc\",\n \".pyo\",\n \".mp3\",\n \".mp4\",\n \".wav\",\n \".ogg\",\n \".webm\",\n \".mov\",\n \".avi\",\n \".pdf\",\n \".sqlite\",\n \".db\",\n ] as const,\n} as const;\n\nexport const DEFAULT_MAX_FILE_BYTES = 256 * 1024;\nexport const DEFAULT_RESPECT_GITIGNORE = true;\n\nexport function defaultIndexConfig(): ResolvedIndexConfig {\n return {\n excludeDirs: [...DEFAULT_INDEX_EXCLUDES.dirs],\n excludeFiles: [...DEFAULT_INDEX_EXCLUDES.files],\n excludeExts: [...DEFAULT_INDEX_EXCLUDES.exts],\n excludePatterns: [],\n respectGitignore: DEFAULT_RESPECT_GITIGNORE,\n maxFileBytes: DEFAULT_MAX_FILE_BYTES,\n };\n}\n\n/** A field present in user config fully replaces the default for that field. Absent → default. */\nexport function resolveIndexConfig(user?: IndexUserConfig | null): ResolvedIndexConfig {\n const d = defaultIndexConfig();\n if (!user) return d;\n return {\n excludeDirs: Array.isArray(user.excludeDirs) ? [...user.excludeDirs] : d.excludeDirs,\n excludeFiles: Array.isArray(user.excludeFiles) ? [...user.excludeFiles] : d.excludeFiles,\n excludeExts: Array.isArray(user.excludeExts)\n ? user.excludeExts.map((e) => e.toLowerCase())\n : d.excludeExts,\n excludePatterns: Array.isArray(user.excludePatterns) ? [...user.excludePatterns] : [],\n respectGitignore:\n typeof user.respectGitignore === \"boolean\" ? user.respectGitignore : d.respectGitignore,\n maxFileBytes:\n typeof user.maxFileBytes === \"number\" && user.maxFileBytes > 0\n ? user.maxFileBytes\n : d.maxFileBytes,\n };\n}\n\nexport function compileFilters(cfg: ResolvedIndexConfig): IndexFilters {\n const matcher =\n cfg.excludePatterns.length === 0\n ? () => false\n : picomatch(cfg.excludePatterns as string[], { dot: true });\n return {\n dirSet: new Set(cfg.excludeDirs),\n fileSet: new Set(cfg.excludeFiles),\n extSet: new Set(cfg.excludeExts.map((e) => e.toLowerCase())),\n patternMatch: matcher as (p: string) => boolean,\n respectGitignore: cfg.respectGitignore,\n maxFileBytes: cfg.maxFileBytes,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
Usage
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H4OLWRSX.js";
|
|
5
5
|
import {
|
|
6
6
|
claudeEquivalentCost,
|
|
7
7
|
costUsd,
|
|
@@ -186,4 +186,4 @@ export {
|
|
|
186
186
|
replayFromFile,
|
|
187
187
|
computeReplayStats
|
|
188
188
|
};
|
|
189
|
-
//# sourceMappingURL=chunk-
|
|
189
|
+
//# sourceMappingURL=chunk-7SPOFTMT.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
sanitizeName,
|
|
4
4
|
sessionsDir
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YJFKFTAL.js";
|
|
6
6
|
|
|
7
7
|
// src/adapters/event-sink-jsonl.ts
|
|
8
8
|
import { chmodSync, createWriteStream, mkdirSync } from "fs";
|
|
@@ -50,4 +50,4 @@ export {
|
|
|
50
50
|
eventLogPath,
|
|
51
51
|
openEventSink
|
|
52
52
|
};
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
53
|
+
//# sourceMappingURL=chunk-7VFNPMKG.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
sanitizeName,
|
|
4
4
|
sessionsDir
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YJFKFTAL.js";
|
|
6
6
|
|
|
7
7
|
// src/code/checkpoints.ts
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
@@ -372,6 +372,12 @@ var SLASH_COMMANDS = [
|
|
|
372
372
|
group: "chat",
|
|
373
373
|
summary: "abort the current model turn (typed alternative to Esc)"
|
|
374
374
|
},
|
|
375
|
+
{
|
|
376
|
+
cmd: "btw",
|
|
377
|
+
group: "chat",
|
|
378
|
+
argsHint: "<question>",
|
|
379
|
+
summary: "ask a quick side question \u2014 answered from a blank slate, never added to the conversation context"
|
|
380
|
+
},
|
|
375
381
|
{
|
|
376
382
|
cmd: "preset",
|
|
377
383
|
group: "setup",
|
|
@@ -739,4 +745,4 @@ export {
|
|
|
739
745
|
detectSlashArgContext,
|
|
740
746
|
parseSlash
|
|
741
747
|
};
|
|
742
|
-
//# sourceMappingURL=chunk-
|
|
748
|
+
//# sourceMappingURL=chunk-A3LL4XDV.js.map
|