reasonix 0.36.2 → 0.38.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 +48 -75
- package/README.zh-CN.md +48 -32
- package/dist/cli/{chat-QSM6JKUA.js → chat-FPEYKTMI.js} +16 -17
- package/dist/cli/{chunk-T52GAWPP.js → chunk-3VTV4WAH.js} +2 -2
- package/dist/cli/{chunk-NHV5YGTB.js → chunk-4PNXH2MH.js} +1860 -1249
- package/dist/cli/chunk-4PNXH2MH.js.map +1 -0
- package/dist/cli/{chunk-DFP4YSVM.js → chunk-6CXT5JRM.js} +17 -2
- package/dist/cli/{chunk-DFP4YSVM.js.map → chunk-6CXT5JRM.js.map} +1 -1
- package/dist/cli/{chunk-G3XNWSFN.js → chunk-6NMWJSES.js} +2 -2
- package/dist/cli/{chunk-4D6TT2IB.js → chunk-A63QT566.js} +36 -15
- package/dist/cli/chunk-A63QT566.js.map +1 -0
- package/dist/cli/{chunk-4Q3GRJIU.js → chunk-AATCLE5N.js} +2 -2
- package/dist/cli/{chunk-BHLHOS5Y.js → chunk-BW2HWSYH.js} +315 -5
- package/dist/cli/chunk-BW2HWSYH.js.map +1 -0
- package/dist/cli/{chunk-ZJR4QLXB.js → chunk-FB46F6H4.js} +2 -2
- package/dist/cli/{chunk-MLXUGPJE.js → chunk-FYKZB6TX.js} +490 -8
- package/dist/cli/chunk-FYKZB6TX.js.map +1 -0
- package/dist/cli/{chunk-XQIFIB3U.js → chunk-JOFZ6AW5.js} +2 -2
- package/dist/cli/{chunk-IPCPEZWQ.js → chunk-LMNAMITH.js} +2 -2
- package/dist/cli/{chunk-S4GF3HPO.js → chunk-LY352GTC.js} +6 -4
- package/dist/cli/chunk-LY352GTC.js.map +1 -0
- package/dist/cli/{chunk-C5543CRX.js → chunk-NYP2DDDV.js} +41 -2
- package/dist/cli/chunk-NYP2DDDV.js.map +1 -0
- package/dist/cli/{chunk-BJ376EN3.js → chunk-T5U5JO7Q.js} +12 -9
- package/dist/cli/chunk-T5U5JO7Q.js.map +1 -0
- package/dist/cli/{chunk-K6W64QVE.js → chunk-XOIDSPMQ.js} +27 -7
- package/dist/cli/chunk-XOIDSPMQ.js.map +1 -0
- package/dist/cli/{chunk-RNSZYYGB.js → chunk-YJKLNYCP.js} +122 -33
- package/dist/cli/chunk-YJKLNYCP.js.map +1 -0
- package/dist/cli/{code-6C5A2CY3.js → code-GTE65OUT.js} +28 -21
- package/dist/cli/code-GTE65OUT.js.map +1 -0
- package/dist/cli/{commands-FE2UDFBC.js → commands-R4JWISND.js} +3 -4
- package/dist/cli/{commands-FE2UDFBC.js.map → commands-R4JWISND.js.map} +1 -1
- package/dist/cli/{commit-3IAGB22T.js → commit-TQ4DMUNS.js} +2 -3
- package/dist/cli/{commit-3IAGB22T.js.map → commit-TQ4DMUNS.js.map} +1 -1
- package/dist/cli/{doctor-DKD34EFD.js → doctor-GGK2JKTA.js} +7 -8
- package/dist/cli/{events-P27CX7LN.js → events-SQXPVV7B.js} +3 -3
- package/dist/cli/index.js +38 -37
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-2RDEQST6.js → mcp-M7I23TQ7.js} +2 -3
- package/dist/cli/{mcp-2RDEQST6.js.map → mcp-M7I23TQ7.js.map} +1 -1
- package/dist/cli/{mcp-browse-VM5GLRBQ.js → mcp-browse-TWO7RYT4.js} +2 -3
- package/dist/cli/{mcp-browse-VM5GLRBQ.js.map → mcp-browse-TWO7RYT4.js.map} +1 -1
- package/dist/cli/prompt-ODPFOKSH.js +13 -0
- package/dist/cli/{prune-sessions-ERL6B4G5.js → prune-sessions-FCFOYCBP.js} +2 -2
- package/dist/cli/{replay-D7RT2DR7.js → replay-R3QRXPI2.js} +13 -9
- package/dist/cli/replay-R3QRXPI2.js.map +1 -0
- package/dist/cli/{run-AG4Y45X7.js → run-WGSPYYOJ.js} +9 -10
- package/dist/cli/{run-AG4Y45X7.js.map → run-WGSPYYOJ.js.map} +1 -1
- package/dist/cli/{server-GNHR5K3N.js → server-IZPWQYG3.js} +98 -53
- package/dist/cli/{server-GNHR5K3N.js.map → server-IZPWQYG3.js.map} +1 -1
- package/dist/cli/{sessions-MHRF3GU4.js → sessions-E4UH5JYL.js} +9 -10
- package/dist/cli/{sessions-MHRF3GU4.js.map → sessions-E4UH5JYL.js.map} +1 -1
- package/dist/cli/{setup-IIAJXHP4.js → setup-FTZNN3TZ.js} +60 -15
- package/dist/cli/setup-FTZNN3TZ.js.map +1 -0
- package/dist/cli/{version-7AL4JZ63.js → version-MDVCFTKA.js} +9 -10
- package/dist/cli/{version-7AL4JZ63.js.map → version-MDVCFTKA.js.map} +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +714 -54
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-4D6TT2IB.js.map +0 -1
- package/dist/cli/chunk-BHLHOS5Y.js.map +0 -1
- package/dist/cli/chunk-BJ376EN3.js.map +0 -1
- package/dist/cli/chunk-C5543CRX.js.map +0 -1
- package/dist/cli/chunk-K6W64QVE.js.map +0 -1
- package/dist/cli/chunk-MLXUGPJE.js.map +0 -1
- package/dist/cli/chunk-NHV5YGTB.js.map +0 -1
- package/dist/cli/chunk-RNSZYYGB.js.map +0 -1
- package/dist/cli/chunk-S4GF3HPO.js.map +0 -1
- package/dist/cli/chunk-WUI3P4RA.js +0 -319
- package/dist/cli/chunk-WUI3P4RA.js.map +0 -1
- package/dist/cli/code-6C5A2CY3.js.map +0 -1
- package/dist/cli/prompt-QSEB7HNQ.js +0 -11
- package/dist/cli/replay-D7RT2DR7.js.map +0 -1
- package/dist/cli/setup-IIAJXHP4.js.map +0 -1
- /package/dist/cli/{chat-QSM6JKUA.js.map → chat-FPEYKTMI.js.map} +0 -0
- /package/dist/cli/{chunk-T52GAWPP.js.map → chunk-3VTV4WAH.js.map} +0 -0
- /package/dist/cli/{chunk-G3XNWSFN.js.map → chunk-6NMWJSES.js.map} +0 -0
- /package/dist/cli/{chunk-4Q3GRJIU.js.map → chunk-AATCLE5N.js.map} +0 -0
- /package/dist/cli/{chunk-ZJR4QLXB.js.map → chunk-FB46F6H4.js.map} +0 -0
- /package/dist/cli/{chunk-XQIFIB3U.js.map → chunk-JOFZ6AW5.js.map} +0 -0
- /package/dist/cli/{chunk-IPCPEZWQ.js.map → chunk-LMNAMITH.js.map} +0 -0
- /package/dist/cli/{doctor-DKD34EFD.js.map → doctor-GGK2JKTA.js.map} +0 -0
- /package/dist/cli/{events-P27CX7LN.js.map → events-SQXPVV7B.js.map} +0 -0
- /package/dist/cli/{prompt-QSEB7HNQ.js.map → prompt-ODPFOKSH.js.map} +0 -0
- /package/dist/cli/{prune-sessions-ERL6B4G5.js.map → prune-sessions-FCFOYCBP.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/code.tsx","../../src/tools/scaffold.ts"],"sourcesContent":["/**\n * `reasonix code [dir]` — opinionated wrapper around `reasonix chat` for\n * code-editing workflows.\n *\n * What it does differently from plain chat:\n * - Registers native filesystem tools rooted at the given directory\n * (CWD by default). No subprocess, no `npx install` step, R1-\n * friendly schemas. Replaced the old `@modelcontextprotocol/server-filesystem`\n * subprocess in 0.4.9 because its `edit_file` argv shape was the\n * biggest driver of R1 DSML hallucinations.\n * - Uses a coding-focused system prompt (src/code/prompt.ts) that\n * teaches the model to propose edits as SEARCH/REPLACE blocks.\n * - Defaults to the `smart` preset (reasoner + harvest) because\n * coding tasks pay back R1 thinking.\n * - Scopes its session to the directory so projects don't share\n * conversation history.\n * - Hooks `codeMode` into the TUI so assistant replies get parsed\n * for SEARCH/REPLACE blocks and applied on disk after each turn.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { basename, resolve } from \"node:path\";\nimport { loadEditMode, loadProjectShellAllowed, readConfig } from \"../../config.js\";\nimport { bootstrapSemanticSearchInCodeMode } from \"../../index/semantic/tool.js\";\nimport { detectForeignAgentPlatform } from \"../../memory/project.js\";\nimport { sanitizeName } from \"../../memory/session.js\";\nimport { ToolRegistry } from \"../../tools.js\";\nimport { registerChoiceTool } from \"../../tools/choice.js\";\nimport { registerFilesystemTools } from \"../../tools/filesystem.js\";\nimport { JobRegistry } from \"../../tools/jobs.js\";\nimport { registerMemoryTools } from \"../../tools/memory.js\";\nimport { registerPlanTool } from \"../../tools/plan.js\";\nimport { registerScaffoldTools } from \"../../tools/scaffold.js\";\nimport { registerShellTools } from \"../../tools/shell.js\";\nimport { registerTodoTool } from \"../../tools/todo.js\";\nimport { markPhase } from \"../startup-profile.js\";\nimport { chatCommand } from \"./chat.js\";\n\nexport interface CodeOptions {\n /** Directory to root the filesystem tools at. Defaults to process.cwd(). */\n dir?: string;\n /** Override the default `smart` model. */\n model?: string;\n /** Disable session persistence. */\n noSession?: boolean;\n /** Transcript file for replay/diff. */\n transcript?: string;\n /** Skip the session picker — always resume prior messages. */\n forceResume?: boolean;\n /** Skip the session picker — always wipe prior messages and start fresh. */\n forceNew?: boolean;\n /**\n * Soft USD spend cap. Off by default. Same semantics as `chat`:\n * warns at 80%, refuses next turn at 100%. Mid-session adjustable\n * via `/budget <usd>` slash command.\n */\n budgetUsd?: number;\n /** Suppress the auto-launched embedded web dashboard. */\n noDashboard?: boolean;\n /** Inline string appended to the code system prompt after the generated base prompt. */\n systemAppend?: string;\n /** Path to a UTF-8 text file whose contents are appended to the code system prompt. */\n systemAppendFile?: string;\n /** Default true. Pass false (CLI: `--no-alt-screen`) to keep chat output in shell scrollback. */\n altScreen?: boolean;\n /** Default true. Pass false (CLI: `--no-mouse`) to keep terminal-native drag-select unmodified. */\n mouse?: boolean;\n}\n\nexport async function codeCommand(opts: CodeOptions = {}): Promise<void> {\n markPhase(\"code_command_enter\");\n const { codeSystemPrompt } = await import(\"../../code/prompt.js\");\n const rootDir = resolve(opts.dir ?? process.cwd());\n // Per-directory session so switching projects doesn't mix histories.\n // `code-<sanitized-basename>` fits the session name rules without\n // truncating most project names.\n const session = opts.noSession ? undefined : `code-${sanitizeName(basename(rootDir))}`;\n\n // Native filesystem tools. No subprocess, ~50-200 ms faster per call\n // than the MCP server was, and `edit_file` takes a flat SEARCH/REPLACE\n // shape instead of the `string=\"false\"` JSON-in-string array that\n // triggered R1's DSML hallucinations all through 0.4.x.\n const tools = new ToolRegistry();\n // Background-process registry shared between the shell tools and the\n // TUI's /jobs + /kill slashes + exit cleanup. One per `reasonix code`\n // run — orphan prevention on SIGINT / process exit kills everything\n // it owns, so dev servers don't outlive the Reasonix process.\n const jobs = new JobRegistry();\n // Bundled re-registration so `/cwd <path>` can swap every rootDir-\n // dependent tool atomically. ToolRegistry.register is keyed by name\n // and overwrites in-place, so re-calling these against the existing\n // registry replaces the closures cleanly without disturbing tool\n // specs (names/descriptions/params don't reference rootDir, so the\n // prefix cache survives).\n const registerRootedTools = (root: string): void => {\n registerFilesystemTools(tools, { rootDir: root });\n registerShellTools(tools, {\n rootDir: root,\n // Per-project \"always allow\" list persisted from prior ShellConfirm\n // choices; merged on top of the built-in allowlist in shell.ts.\n // GETTER form — re-read every dispatch so a prefix the user adds\n // via ShellConfirm mid-session takes effect on the next shell call\n // instead of waiting for `/new` or a relaunch.\n extraAllowed: () => loadProjectShellAllowed(root),\n // `yolo` edit-mode disables shell confirmations entirely. Re-read\n // from config on each dispatch so /mode yolo (or Shift+Tab cycling\n // through to it) flips the gate live without forcing a relaunch.\n allowAll: () => loadEditMode() === \"yolo\",\n jobs,\n });\n // `remember` / `forget` / `recall_memory` — cross-session user memory.\n // Project scope hashes off rootDir so switching projects gets a fresh\n // per-project memory store; the global scope is shared across runs.\n registerMemoryTools(tools, { projectRoot: root });\n };\n // Async tail to `registerRootedTools`. Kept separate because the FS /\n // shell / memory re-registration above is sync and must happen before\n // the next tool dispatch, while semantic-index probing reads disk and\n // can race ahead in the background. On `/cwd`, App.tsx fires this\n // after the sync swap and surfaces the result via postInfo.\n const reBootstrapSemantic = async (root: string): Promise<{ enabled: boolean }> => {\n const result = await bootstrapSemanticSearchInCodeMode(tools, root);\n if (!result.enabled) tools.unregister(\"semantic_search\");\n return result;\n };\n registerRootedTools(rootDir);\n // `submit_plan` is always in the spec list so the prefix cache stays\n // stable across plan-mode toggles (Pillar 1). The tool itself is a\n // no-op outside plan mode and throws `PlanProposedError` when the\n // user has `/plan`-enabled the session.\n registerPlanTool(tools);\n // `ask_choice` — branching primitive. Independent of plan mode: the\n // model uses it to put a 2–4 way choice in front of the user\n // (strategy, style, library pick) without trying to squeeze the\n // menu into a submit_plan body. Keeping it always-registered\n // preserves the prefix cache across plan-mode toggles.\n registerChoiceTool(tools);\n // `todo_write` — lightweight in-session task tracker, no approval gate.\n // Independent of plan mode (readOnly=true so it stays callable in /plan).\n registerTodoTool(tools);\n // `create_skill` / `add_mcp_server` — let the model scaffold from chat.\n // Both writes go through the same paths the wizard / `/skill new` use,\n // so the on-disk shape stays one source of truth. New servers take\n // effect on next launch (no live client churn).\n registerScaffoldTools(tools, { projectRoot: rootDir });\n // `run_skill` is intentionally NOT registered here — App.tsx wires it\n // up with the subagent runner attached, so `runAs: subagent` skills\n // can spawn isolated child loops. Doing it here would mean the App's\n // re-registration would shadow the no-runner version, which works\n // (last write wins) but obscures the wiring.\n\n // Bootstrap semantic_search. Silent: registers the tool when an\n // on-disk index already exists, skips entirely otherwise. Setup\n // happens via the explicit `reasonix index` command — never\n // by surprise on launch.\n markPhase(\"semantic_bootstrap_start\");\n const semantic = await reBootstrapSemantic(rootDir);\n markPhase(\n semantic.enabled ? \"semantic_bootstrap_done_enabled\" : \"semantic_bootstrap_done_skipped\",\n );\n\n process.stderr.write(\n `▸ reasonix code: rooted at ${rootDir}, session \"${session ?? \"(ephemeral)\"}\" · ${tools.size} native tool(s)${\n semantic.enabled ? \" · semantic_search on\" : \"\"\n }\\n`,\n );\n\n const foreign = detectForeignAgentPlatform(rootDir);\n if (foreign) {\n process.stderr.write(\n `⚠ workspace contains another agent platform's files (${foreign.join(\", \")}). Reasonix Code may read them as project content; relaunch with --dir <your-project> if that's not what you want.\\n`,\n );\n }\n\n // Belt-and-suspenders cleanup: even though spawn(detached:false)\n // should tie child processes to the parent's lifetime, Windows cmd.exe\n // wrappers occasionally leak. We DON'T install SIGINT/SIGTERM\n // handlers here — that overrode Node's default \"exit on Ctrl+C\" with\n // a silent no-op, which made Ctrl+C feel broken in the TUI. App.tsx\n // owns the SIGINT path now (it shows the quit-armed banner and calls\n // exit() on confirmation); this 'exit' hook just guarantees the job\n // registry is drained on the way out, regardless of which exit path\n // fired.\n process.once(\"exit\", () => {\n void jobs.shutdown();\n });\n\n let systemAppendFileContents: string | undefined;\n if (opts.systemAppend !== undefined && opts.systemAppend.trim().length === 0) {\n process.stderr.write(\"--system-append is empty — no prompt text will be appended\\n\");\n }\n if (opts.systemAppendFile) {\n const filePath = resolve(opts.systemAppendFile);\n try {\n systemAppendFileContents = readFileSync(filePath, \"utf8\");\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n process.stderr.write(\n `Error: cannot read --system-append-file \"${filePath}\": ${e.code ? `[${e.code}] ` : \"\"}${e.message}\\n`,\n );\n process.exit(1);\n }\n }\n\n await chatCommand({\n model: opts.model ?? \"deepseek-v4-flash\",\n budgetUsd: opts.budgetUsd,\n system: codeSystemPrompt(rootDir, {\n hasSemanticSearch: semantic.enabled,\n systemAppend: opts.systemAppend,\n systemAppendFile: systemAppendFileContents,\n }),\n transcript: opts.transcript,\n session,\n seedTools: tools,\n codeMode: {\n rootDir,\n jobs,\n reregisterTools: registerRootedTools,\n reBootstrapSemantic,\n },\n mcp: readConfig().mcp,\n forceResume: opts.forceResume,\n forceNew: opts.forceNew,\n noDashboard: opts.noDashboard,\n altScreen: opts.altScreen,\n mouse: opts.mouse,\n });\n}\n","/** Agent-facing tools for scaffolding skills + MCP servers from chat. Persists via the same paths the wizard / `/skill new` use. */\n\nimport { defaultConfigPath, readConfig, writeConfig } from \"../config.js\";\nimport { MCP_CATALOG } from \"../mcp/catalog.js\";\nimport { preflightStdioSpec } from \"../mcp/preflight.js\";\nimport { type McpSpec, parseMcpSpec } from \"../mcp/spec.js\";\nimport { SkillStore } from \"../skills.js\";\nimport type { ToolRegistry } from \"../tools.js\";\n\nexport interface ScaffoldToolsOptions {\n homeDir?: string;\n projectRoot?: string;\n /** Override config path — tests point this at a tmp file. */\n configPath?: string;\n}\n\nconst VALID_SKILL_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/;\nconst VALID_SERVER_NAME = /^[a-zA-Z_][a-zA-Z0-9_-]{0,63}$/;\nconst VALID_TOOL_NAME = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;\n\nexport function registerScaffoldTools(\n registry: ToolRegistry,\n opts: ScaffoldToolsOptions = {},\n): ToolRegistry {\n const configPath = opts.configPath ?? defaultConfigPath();\n\n registry.register({\n name: \"create_skill\",\n description:\n 'Scaffold a new skill (`SKILL.md` in `.reasonix/skills/<name>.md`) the user can invoke later via `/skill <name>`. Use this when the user asks the agent to add a playbook, automate a recurring workflow, or capture a multi-step recipe as a named skill. The frontmatter is filled from the structured args here (description / allowed_tools / run_as / model) so the model never has to write raw YAML. Use `run_as: \"subagent\"` for read-and-synthesize playbooks where only the final answer should come back; default `\"inline\"` appends the body to the parent log so the user sees the steps. Refuses to overwrite an existing skill — pick a different name or ask the user to delete the old one.',\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Skill identifier — letters/digits/`_`/`-`/`.`, 1–64 chars. Becomes the `name` frontmatter and the `<name>.md` filename.\",\n },\n description: {\n type: \"string\",\n description:\n 'One-line summary shown in the pinned skills index. Lead with the verb (\"Run X and …\") so the parent agent can scan it.',\n },\n body: {\n type: \"string\",\n description:\n \"Markdown body of the skill — the playbook the model follows when invoked. Plain prose + bullets; reference tools by name.\",\n },\n scope: {\n type: \"string\",\n enum: [\"project\", \"global\"],\n description:\n \"`project` = `.reasonix/skills/` under the workspace (default, requires `reasonix code`); `global` = `~/.reasonix/skills/` shared across all repos.\",\n },\n allowed_tools: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional whitelist of tool names the subagent registry is scoped to (only meaningful for `run_as: subagent`). Common values: `read_file`, `search_content`, `directory_tree`, `run_command`. Omit to give the subagent the full inherited toolset.\",\n },\n run_as: {\n type: \"string\",\n enum: [\"inline\", \"subagent\"],\n description:\n \"`inline` (default) appends the body to the parent log as a tool result. `subagent` spawns an isolated child loop and only the final answer comes back — use for read-and-synthesize playbooks (explore, research, review).\",\n },\n model: {\n type: \"string\",\n enum: [\"deepseek-v4-flash\", \"deepseek-v4-pro\"],\n description:\n \"Subagent model override (only meaningful for `run_as: subagent`). Default is the same as `spawn_subagent` — `deepseek-v4-flash`. Set to `deepseek-v4-pro` only when the playbook empirically needs the stronger model.\",\n },\n },\n required: [\"name\", \"description\", \"body\"],\n },\n fn: async (args: {\n name?: unknown;\n description?: unknown;\n body?: unknown;\n scope?: unknown;\n allowed_tools?: unknown;\n run_as?: unknown;\n model?: unknown;\n }) => {\n const name = typeof args.name === \"string\" ? args.name.trim() : \"\";\n if (!VALID_SKILL_NAME.test(name)) {\n return JSON.stringify({\n error: `invalid skill name: ${JSON.stringify(name)} — use letters, digits, _, -, .`,\n });\n }\n const description =\n typeof args.description === \"string\" ? args.description.trim().replace(/\\n+/g, \" \") : \"\";\n if (!description) {\n return JSON.stringify({\n error: \"create_skill requires a non-empty 'description'\",\n });\n }\n const body = typeof args.body === \"string\" ? args.body : \"\";\n if (!body.trim()) {\n return JSON.stringify({ error: \"create_skill requires a non-empty 'body'\" });\n }\n const scope: \"project\" | \"global\" =\n args.scope === \"global\" ? \"global\" : opts.projectRoot ? \"project\" : \"global\";\n const runAs: \"inline\" | \"subagent\" = args.run_as === \"subagent\" ? \"subagent\" : \"inline\";\n const allowedTools = parseAllowedTools(args.allowed_tools);\n if (allowedTools && \"error\" in allowedTools) {\n return JSON.stringify({ error: allowedTools.error });\n }\n const model =\n typeof args.model === \"string\" && args.model.startsWith(\"deepseek-\")\n ? args.model\n : undefined;\n\n const content = serializeSkill({\n name,\n description,\n runAs,\n allowedTools: allowedTools ?? undefined,\n model,\n body,\n });\n\n const store = new SkillStore({\n homeDir: opts.homeDir,\n projectRoot: opts.projectRoot,\n });\n const result = store.createWithContent(name, scope, content);\n if (\"error\" in result) {\n return JSON.stringify({ error: result.error });\n }\n return JSON.stringify({\n success: true,\n path: result.path,\n scope,\n name,\n run_as: runAs,\n });\n },\n });\n\n registry.register({\n name: \"add_mcp_server\",\n description:\n 'Register a new MCP server in the user\\'s Reasonix config (`mcp` array). Takes effect on the next session — does NOT spawn the server now. Use stdio for local commands (npx packages, local binaries), `sse` or `streamable-http` for remote endpoints. Pass `from_catalog: \"<name>\"` (e.g. `\"filesystem\"`, `\"memory\"`, `\"github\"`) to auto-fill `command` + `args` from the bundled catalog — the user still has to supply user-args (filesystem: a sandbox dir; github: GITHUB_PERSONAL_ACCESS_TOKEN in env). Refuses to add a server whose name collides with an existing entry.',\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Server name — used as the namespace prefix on every tool the server exposes. Letters/digits/`_`/`-`, must start with a letter or `_`.\",\n },\n transport: {\n type: \"string\",\n enum: [\"stdio\", \"sse\", \"streamable-http\"],\n description:\n \"`stdio` = spawn a local command and pipe MCP over stdin/stdout. `sse` = HTTP+SSE remote. `streamable-http` = Streamable HTTP remote. Required unless `from_catalog` is set.\",\n },\n command: {\n type: \"string\",\n description:\n 'Argv[0] for stdio servers — typically `npx` or a binary path. Required when `transport: \"stdio\"` (and no `from_catalog`).',\n },\n args: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n 'Remaining argv for stdio servers — e.g. `[\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/path/to/dir\"]`. The dir at the tail is enforced to exist by the preflight check.',\n },\n url: {\n type: \"string\",\n description:\n \"Endpoint URL for `sse` / `streamable-http` transports. Must be `http://` or `https://`.\",\n },\n from_catalog: {\n type: \"string\",\n description:\n \"Optional shortcut — name out of the bundled catalog (`filesystem`, `memory`, `github`, `puppeteer`, `everything`). When set, fills `command` + `args` from the catalog entry; you still supply `name` (defaults to the catalog name) and any user-args via `args`.\",\n },\n },\n required: [\"name\"],\n },\n fn: async (args: {\n name?: unknown;\n transport?: unknown;\n command?: unknown;\n args?: unknown;\n url?: unknown;\n from_catalog?: unknown;\n }) => {\n const name = typeof args.name === \"string\" ? args.name.trim() : \"\";\n if (!VALID_SERVER_NAME.test(name)) {\n return JSON.stringify({\n error: `invalid server name: ${JSON.stringify(name)} — must match [a-zA-Z_][a-zA-Z0-9_-]*`,\n });\n }\n\n const specStr = buildSpecString({\n name,\n transport: typeof args.transport === \"string\" ? args.transport : undefined,\n command: typeof args.command === \"string\" ? args.command : undefined,\n argv: Array.isArray(args.args)\n ? (args.args.filter((a) => typeof a === \"string\") as string[])\n : undefined,\n url: typeof args.url === \"string\" ? args.url : undefined,\n fromCatalog: typeof args.from_catalog === \"string\" ? args.from_catalog : undefined,\n });\n if (\"error\" in specStr) {\n return JSON.stringify({ error: specStr.error });\n }\n\n let parsed: McpSpec;\n try {\n parsed = parseMcpSpec(specStr.spec);\n } catch (err) {\n return JSON.stringify({ error: (err as Error).message });\n }\n if (parsed.transport === \"stdio\") {\n try {\n preflightStdioSpec(parsed);\n } catch (err) {\n return JSON.stringify({ error: (err as Error).message });\n }\n }\n\n const cfg = readConfig(configPath);\n const existing = cfg.mcp ?? [];\n const collision = existing.find((s) => parseSpecName(s) === name);\n if (collision) {\n return JSON.stringify({\n error: `MCP server ${JSON.stringify(name)} already registered: ${collision}`,\n });\n }\n cfg.mcp = [...existing, specStr.spec];\n writeConfig(cfg, configPath);\n return JSON.stringify({\n success: true,\n name,\n transport: parsed.transport,\n spec: specStr.spec,\n config_path: configPath,\n active_on_next_launch: true,\n });\n },\n });\n\n return registry;\n}\n\ninterface SerializeSkillArgs {\n name: string;\n description: string;\n runAs: \"inline\" | \"subagent\";\n allowedTools?: readonly string[];\n model?: string;\n body: string;\n}\n\nexport function serializeSkill(args: SerializeSkillArgs): string {\n const lines: string[] = [\"---\", `name: ${args.name}`, `description: ${args.description}`];\n if (args.runAs === \"subagent\") {\n lines.push(\"runAs: subagent\");\n }\n if (args.allowedTools && args.allowedTools.length > 0) {\n lines.push(`allowed-tools: ${args.allowedTools.join(\", \")}`);\n }\n if (args.model) {\n lines.push(`model: ${args.model}`);\n }\n lines.push(\"---\", \"\");\n return `${lines.join(\"\\n\")}\\n${args.body.trim()}\\n`;\n}\n\nfunction parseAllowedTools(raw: unknown): readonly string[] | { error: string } | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!Array.isArray(raw)) {\n return { error: \"'allowed_tools' must be an array of tool-name strings\" };\n }\n const out: string[] = [];\n for (const v of raw) {\n if (typeof v !== \"string\") {\n return { error: \"'allowed_tools' entries must be strings\" };\n }\n const trimmed = v.trim();\n if (!trimmed) continue;\n if (!VALID_TOOL_NAME.test(trimmed)) {\n return { error: `invalid tool name in allowed_tools: ${JSON.stringify(trimmed)}` };\n }\n out.push(trimmed);\n }\n return out.length > 0 ? out : undefined;\n}\n\ninterface BuildSpecInput {\n name: string;\n transport?: string;\n command?: string;\n argv?: string[];\n url?: string;\n fromCatalog?: string;\n}\n\nfunction buildSpecString(input: BuildSpecInput): { spec: string } | { error: string } {\n if (input.fromCatalog) {\n const entry = MCP_CATALOG.find((e) => e.name === input.fromCatalog);\n if (!entry) {\n const known = MCP_CATALOG.map((e) => e.name).join(\", \");\n return {\n error: `unknown catalog entry: ${JSON.stringify(input.fromCatalog)} — known: ${known}`,\n };\n }\n const userArgs = input.argv ?? [];\n if (entry.userArgs && userArgs.length === 0) {\n return {\n error: `catalog entry \"${entry.name}\" needs ${entry.userArgs} — pass it via the 'args' parameter`,\n };\n }\n const tail = userArgs.map(quoteIfNeeded).join(\" \");\n const body = `npx -y ${entry.package}${tail ? ` ${tail}` : \"\"}`;\n return { spec: `${input.name}=${body}` };\n }\n\n const transport = input.transport;\n if (!transport) {\n return { error: \"add_mcp_server requires 'transport' (or 'from_catalog')\" };\n }\n if (transport === \"stdio\") {\n if (!input.command || !input.command.trim()) {\n return { error: \"stdio transport requires 'command'\" };\n }\n const tail = (input.argv ?? []).map(quoteIfNeeded).join(\" \");\n const body = `${quoteIfNeeded(input.command.trim())}${tail ? ` ${tail}` : \"\"}`;\n return { spec: `${input.name}=${body}` };\n }\n if (transport === \"sse\" || transport === \"streamable-http\") {\n if (!input.url || !/^https?:\\/\\//i.test(input.url)) {\n return { error: `${transport} transport requires an http(s):// 'url'` };\n }\n const prefix = transport === \"streamable-http\" ? \"streamable+\" : \"\";\n return { spec: `${input.name}=${prefix}${input.url.trim()}` };\n }\n return { error: `unknown transport: ${JSON.stringify(transport)}` };\n}\n\nfunction parseSpecName(spec: string): string | null {\n const m = spec.trim().match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=/);\n return m ? (m[1] ?? null) : null;\n}\n\nfunction quoteIfNeeded(s: string): string {\n return /\\s|\"/.test(s) ? `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"` : s;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/replay.ts","../../src/cli/ui/ReplayApp.tsx","../../src/cli/ui/StatsPanel.tsx"],"sourcesContent":["import { render } from \"ink\";\nimport React from \"react\";\nimport type { TranscriptRecord } from \"../../transcript/log.js\";\nimport { groupRecordsByTurn, replayFromFile } from \"../../transcript/replay.js\";\nimport { ReplayApp } from \"../ui/ReplayApp.js\";\n\nexport interface ReplayOptions {\n path: string;\n head?: number;\n tail?: number;\n /** Force stdout pretty-print mode (no Ink TUI). Also auto-enabled when stdout is not a TTY. */\n print?: boolean;\n}\n\nexport async function replayCommand(opts: ReplayOptions): Promise<void> {\n const wantPrint =\n opts.print || !process.stdout.isTTY || opts.head !== undefined || opts.tail !== undefined;\n if (wantPrint) {\n printReplay(opts);\n return;\n }\n\n const { parsed } = replayFromFile(opts.path);\n const pages = groupRecordsByTurn(parsed.records);\n const { waitUntilExit } = render(React.createElement(ReplayApp, { meta: parsed.meta, pages }), {\n exitOnCtrlC: true,\n patchConsole: false,\n });\n await waitUntilExit();\n}\n\n// stdout pretty-print path (original behavior, preserved for piping / CI)\n\nfunction printReplay(opts: ReplayOptions): void {\n const { parsed, stats } = replayFromFile(opts.path);\n\n if (parsed.meta) {\n const m = parsed.meta;\n const bits: string[] = [`source=${m.source}`];\n if (m.model) bits.push(`model=${m.model}`);\n if (m.task) bits.push(`task=${m.task}`);\n if (m.mode) bits.push(`mode=${m.mode}`);\n if (m.repeat !== undefined) bits.push(`repeat=${m.repeat}`);\n bits.push(`started=${m.startedAt}`);\n console.log(`[meta] ${bits.join(\" \")}`);\n console.log(\"\");\n }\n\n const records = sliceRecords(parsed.records, opts);\n for (const rec of records) {\n renderRecord(rec);\n }\n\n console.log(\"\");\n console.log(\"── summary ─────────────────────────────────────────\");\n console.log(`model calls: ${stats.turns}`);\n console.log(`user turns: ${stats.userTurns}`);\n console.log(`tool calls: ${stats.toolCalls}`);\n console.log(`cache hit: ${(stats.cacheHitRatio * 100).toFixed(1)}%`);\n console.log(`cost: $${stats.totalCostUsd.toFixed(6)}`);\n console.log(`claude equivalent: $${stats.claudeEquivalentUsd.toFixed(6)}`);\n console.log(`savings vs claude: ${stats.savingsVsClaudePct.toFixed(1)}%`);\n console.log(`models: ${stats.models.join(\", \") || \"—\"}`);\n console.log(`prefix hashes: ${stats.prefixHashes.length} distinct`);\n if (stats.prefixHashes.length === 1) {\n console.log(` (byte-stable prefix: ${stats.prefixHashes[0]?.slice(0, 16)}…)`);\n } else if (stats.prefixHashes.length > 1) {\n console.log(\" (prefix churned — cache-hostile session)\");\n }\n}\n\nfunction sliceRecords(records: TranscriptRecord[], opts: ReplayOptions): TranscriptRecord[] {\n if (opts.head !== undefined && opts.head > 0) return records.slice(0, opts.head);\n if (opts.tail !== undefined && opts.tail > 0) return records.slice(-opts.tail);\n return records;\n}\n\nfunction renderRecord(rec: TranscriptRecord): void {\n const turn = `[t${rec.turn}]`;\n if (rec.role === \"user\") {\n console.log(`${turn} USER: ${oneLine(rec.content)}`);\n } else if (rec.role === \"assistant_final\") {\n const cost = rec.cost !== undefined ? ` $${rec.cost.toFixed(6)}` : \"\";\n const cache =\n rec.usage &&\n (rec.usage.prompt_cache_hit_tokens !== undefined ||\n rec.usage.prompt_cache_miss_tokens !== undefined)\n ? (() => {\n const hit = rec.usage!.prompt_cache_hit_tokens ?? 0;\n const miss = rec.usage!.prompt_cache_miss_tokens ?? 0;\n const total = hit + miss;\n return total > 0 ? ` cache=${((hit / total) * 100).toFixed(1)}%` : \"\";\n })()\n : \"\";\n console.log(`${turn} AGENT:${cost}${cache} ${oneLine(rec.content)}`);\n } else if (rec.role === \"tool\") {\n const args = rec.args ? ` args=${oneLine(rec.args, 80)}` : \"\";\n console.log(`${turn} TOOL ${rec.tool ?? \"?\"}:${args} → ${oneLine(rec.content, 120)}`);\n } else if (rec.role === \"error\") {\n console.log(`${turn} ERROR: ${rec.error ?? rec.content}`);\n } else if (rec.role === \"done\") {\n // Suppress — visually noisy, not informative in replay.\n } else {\n console.log(`${turn} ${rec.role}: ${oneLine(rec.content)}`);\n }\n}\n\nfunction oneLine(s: string, max = 200): string {\n const collapsed = s.replace(/\\s+/g, \" \").trim();\n return collapsed.length > max ? `${collapsed.slice(0, max)}…` : collapsed;\n}\n","/**\n * Ink TUI for `reasonix replay`. Read-only: no input box, no loop.\n * j/k navigation across turn-pages, cumulative stats sidebar updates\n * as you move through time.\n *\n * The navigation logic (grouping records into pages, computing cumulative\n * stats) lives in src/replay.ts as pure functions; this file is just\n * presentation + key bindings.\n */\n\nimport { Box, Static, Text, useApp, useInput } from \"ink\";\nimport React, { useMemo, useState } from \"react\";\nimport type { TranscriptMeta } from \"../../transcript/log.js\";\nimport { type TurnPage, computeCumulativeStats } from \"../../transcript/replay.js\";\nimport { RecordView } from \"./RecordView.js\";\nimport { StatsPanel } from \"./StatsPanel.js\";\n\nexport interface ReplayAppProps {\n meta: TranscriptMeta | null;\n pages: TurnPage[];\n}\n\nexport function ReplayApp({ meta, pages }: ReplayAppProps) {\n const { exit } = useApp();\n const maxIdx = Math.max(0, pages.length - 1);\n // Start at the last page — more useful than \"start from the beginning\"\n // in practice: users mostly want to see the summary + last turn first.\n const [idx, setIdx] = useState(maxIdx);\n\n useInput((input, key) => {\n if (input === \"q\" || (key.ctrl && input === \"c\")) {\n exit();\n return;\n }\n if (input === \"j\" || key.downArrow || input === \" \" || key.return) {\n setIdx((i) => Math.min(maxIdx, i + 1));\n } else if (input === \"k\" || key.upArrow) {\n setIdx((i) => Math.max(0, i - 1));\n } else if (input === \"g\") {\n setIdx(0);\n } else if (input === \"G\") {\n setIdx(maxIdx);\n } else if (input === \"h\" || key.leftArrow) {\n setIdx(0);\n } else if (input === \"l\" || key.rightArrow) {\n setIdx(maxIdx);\n }\n });\n\n const cumStats = useMemo(() => computeCumulativeStats(pages, idx), [pages, idx]);\n\n const summary = {\n turns: cumStats.turns,\n totalCostUsd: cumStats.totalCostUsd,\n totalInputCostUsd: cumStats.totalInputCostUsd,\n totalOutputCostUsd: cumStats.totalOutputCostUsd,\n claudeEquivalentUsd: cumStats.claudeEquivalentUsd,\n savingsVsClaudePct: cumStats.savingsVsClaudePct,\n cacheHitRatio: cumStats.cacheHitRatio,\n // Replay is read-only — no live last-turn prompt tokens to show.\n lastPromptTokens: 0,\n lastTurnCostUsd: 0,\n };\n\n const prefixHash =\n cumStats.prefixHashes.length === 1\n ? cumStats.prefixHashes[0]!.slice(0, 16)\n : cumStats.prefixHashes.length === 0\n ? \"(untracked)\"\n : `(churned ×${cumStats.prefixHashes.length})`;\n\n const currentPage = pages[idx];\n const progressLabel =\n pages.length === 0 ? \"empty transcript\" : `turn ${idx + 1} / ${pages.length}`;\n\n return (\n <Box flexDirection=\"column\">\n <StatsPanel summary={summary} />\n\n <Box flexDirection=\"column\" marginTop={1} paddingX={1}>\n <Box justifyContent=\"space-between\">\n <Text color=\"cyan\" bold>\n {progressLabel}\n </Text>\n {meta ? (\n <Text dimColor>\n {meta.source}\n {meta.task ? ` · ${meta.task}` : \"\"}\n {meta.mode ? ` · ${meta.mode}` : \"\"}\n </Text>\n ) : null}\n </Box>\n\n {currentPage ? (\n <Static items={currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec }))}>\n {({ key, rec }) => <RecordView key={key} rec={rec} />}\n </Static>\n ) : (\n <Text dimColor italic>\n no records\n </Text>\n )}\n </Box>\n\n <Box marginTop={1} paddingX={1} borderStyle=\"single\" borderColor=\"gray\">\n <Text dimColor>\n <Text bold>j</Text>/<Text bold>↓</Text>/<Text bold>space</Text> next · <Text bold>k</Text>\n /<Text bold>↑</Text> prev · <Text bold>g</Text> first · <Text bold>G</Text> last ·{\" \"}\n <Text bold>q</Text> quit\n </Text>\n </Box>\n </Box>\n );\n}\n","import { basename } from \"node:path\";\nimport { Box, Text, useStdout } from \"ink\";\nimport React from \"react\";\nimport stringWidth from \"string-width\";\nimport type { EditMode } from \"../../config.js\";\nimport type { SessionSummary } from \"../../telemetry/stats.js\";\nimport { Bar, ChromeRule } from \"./primitives.js\";\nimport { COLOR, GRADIENT } from \"./theme.js\";\nimport { formatBalance, formatCost } from \"./theme/tokens.js\";\n\nconst COLD_START_TURNS = 3;\n\nexport interface StatsPanelProps {\n summary: SessionSummary;\n planMode?: boolean;\n editMode?: EditMode;\n balance?: { currency: string; total: number } | null;\n updateAvailable?: string | null;\n proArmed?: boolean;\n escalated?: boolean;\n budgetUsd?: number | null;\n rootDir?: string;\n sessionName?: string | null;\n}\n\nexport function StatsPanel({\n summary,\n planMode,\n editMode,\n balance,\n updateAvailable,\n proArmed,\n escalated,\n budgetUsd,\n rootDir,\n sessionName,\n}: StatsPanelProps) {\n const coldStart = summary.turns <= COLD_START_TURNS;\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <ChromeRow\n editMode={editMode}\n planMode={planMode}\n proArmed={proArmed ?? false}\n escalated={escalated ?? false}\n summary={summary}\n coldStart={coldStart}\n rootDir={rootDir}\n sessionName={sessionName ?? null}\n updateAvailable={updateAvailable}\n balance={balance ?? null}\n />\n <ChromeRule />\n {budgetUsd !== null && budgetUsd !== undefined ? (\n <BudgetRow spent={summary.totalCostUsd} cap={budgetUsd} />\n ) : null}\n </Box>\n );\n}\n\nfunction ChromeRow({\n editMode,\n planMode,\n proArmed,\n escalated,\n summary,\n coldStart,\n rootDir,\n sessionName,\n updateAvailable,\n balance,\n}: {\n editMode?: EditMode;\n planMode?: boolean;\n proArmed: boolean;\n escalated: boolean;\n summary: SessionSummary;\n coldStart: boolean;\n rootDir?: string;\n sessionName?: string | null;\n updateAvailable?: string | null;\n balance?: { currency: string; total: number } | null;\n}) {\n const modePill = pickModePill(planMode, editMode);\n const proPill = escalated\n ? { label: \"⇧ pro\", color: COLOR.err }\n : proArmed\n ? { label: \"⇧ pro\", color: COLOR.warn }\n : null;\n const projectName = rootDir ? basename(rootDir) : null;\n const cachePct = (summary.cacheHitRatio * 100).toFixed(1);\n const cacheColor =\n summary.cacheHitRatio >= 0.7 ? COLOR.ok : summary.cacheHitRatio >= 0.4 ? COLOR.warn : COLOR.err;\n const balanceLabel = balance\n ? `[${formatBalance(balance.total, balance.currency, { label: true })}]`\n : \"\";\n const costLabel = `[${formatCost(summary.totalCostUsd, balance?.currency)}]`;\n const cacheLabel = \"[c ▰▰▰▰▰▰ 100%]\";\n const updateLabel = updateAvailable ? `↑ ${updateAvailable}` : \"\";\n\n // Greedy width-aware fit. Layout (every gap = 2 cells, applied as suffix\n // to update/mode/pro and as prefix to balance/cache):\n // [brand][·project][›session]<spacer>[update][mode][pro][cost][balance][cache]\n // Always shown: brand, project (if rootDir), mode (if set), pro (if armed),\n // cost. These carve fixedLeft / fixedRight first.\n // Optional, dropped greedy by priority: balance > cache > session > update.\n // The flexbox spacer can shrink to 0, so no minimum reserve.\n const { stdout } = useStdout();\n const cols = (stdout?.columns ?? 80) - 2; // subtract paddingX={1} on both sides\n const SEP_DOT = stringWidth(\" · \");\n const SEP_ARROW = stringWidth(\" › \");\n const GAP = 2;\n\n const fixedLeft =\n stringWidth(\"◈ reasonix\") + (projectName ? SEP_DOT + stringWidth(projectName) : 0);\n const modeW = modePill ? GAP + stringWidth(`[${modePill.label}]`) : 0;\n const proW = proPill ? GAP + stringWidth(`[${proPill.label}]`) : 0;\n const fixedRight = modeW + proW + stringWidth(costLabel);\n let budget = cols - fixedLeft - fixedRight;\n\n const balW = balance ? GAP + stringWidth(balanceLabel) : 0;\n const cacheW = GAP + stringWidth(cacheLabel);\n const sessionW = sessionName ? SEP_ARROW + stringWidth(sessionName) : 0;\n const updateW = updateLabel ? GAP + stringWidth(updateLabel) : 0;\n\n const showBalance = balW > 0 && budget >= balW;\n if (showBalance) budget -= balW;\n const showCache = budget >= cacheW;\n if (showCache) budget -= cacheW;\n const showSession = sessionW > 0 && budget >= sessionW;\n if (showSession) budget -= sessionW;\n const showUpdate = updateW > 0 && budget >= updateW;\n if (showUpdate) budget -= updateW;\n\n return (\n <Box>\n <Text bold color={GRADIENT[0]}>\n {\"◈ \"}\n </Text>\n <Text color={COLOR.brand} bold>\n reasonix\n </Text>\n {projectName ? (\n <>\n <Text color={COLOR.info} dimColor>\n {\" · \"}\n </Text>\n <Text>{projectName}</Text>\n {showSession && sessionName ? (\n <>\n <Text color={COLOR.info} dimColor>\n {\" › \"}\n </Text>\n <Text color={COLOR.info}>{sessionName}</Text>\n </>\n ) : null}\n </>\n ) : null}\n\n <Box flexGrow={1} />\n\n {showUpdate ? (\n <>\n <Text color={COLOR.warn} bold>\n {updateLabel}\n </Text>\n <Text>{\" \"}</Text>\n </>\n ) : null}\n {modePill ? (\n <>\n <Text color={modePill.color} bold>\n {`[${modePill.label}]`}\n </Text>\n <Text>{\" \"}</Text>\n </>\n ) : null}\n {proPill ? (\n <>\n <Text color={proPill.color} bold>\n {`[${proPill.label}]`}\n </Text>\n <Text>{\" \"}</Text>\n </>\n ) : null}\n <Text\n color={\n summary.turns === 0 || coldStart ? COLOR.info : sessionCostColor(summary.totalCostUsd)\n }\n bold={summary.turns > 0 && !coldStart}\n dimColor={summary.turns === 0 || coldStart}\n >\n {costLabel}\n </Text>\n {showBalance && balance ? (\n <>\n <Text>{\" \"}</Text>\n <Text color={balance.total < 1 ? COLOR.err : balance.total < 5 ? COLOR.warn : COLOR.ok}>\n {balanceLabel}\n </Text>\n </>\n ) : null}\n {showCache ? (\n <>\n <Text>{\" \"}</Text>\n <Text dimColor>{\"[\"}</Text>\n <Text dimColor>{\"c \"}</Text>\n <Bar\n ratio={summary.cacheHitRatio}\n color={coldStart ? COLOR.info : cacheColor}\n cells={6}\n dim={coldStart}\n />\n <Text> </Text>\n <Text color={coldStart ? undefined : cacheColor} dimColor={coldStart}>\n {coldStart && summary.turns === 0 ? \"—\" : `${cachePct}%`}\n </Text>\n <Text dimColor>{\"]\"}</Text>\n </>\n ) : null}\n </Box>\n );\n}\n\nfunction pickModePill(\n planMode: boolean | undefined,\n editMode: EditMode | undefined,\n): { label: string; color: string } | null {\n if (planMode) return { label: \"PLAN\", color: COLOR.err };\n if (editMode === \"yolo\") return { label: \"yolo\", color: COLOR.err };\n if (editMode === \"auto\") return { label: \"auto\", color: COLOR.primary };\n if (editMode === \"review\") return { label: \"review\", color: COLOR.info };\n return null;\n}\n\nfunction BudgetRow({ spent, cap }: { spent: number; cap: number }) {\n const pct = Math.max(0, (spent / cap) * 100);\n const color = pct >= 100 ? \"#f87171\" : pct >= 80 ? \"#fbbf24\" : \"#94a3b8\";\n return (\n <Box>\n <Text dimColor>{\" budget \"}</Text>\n <Text color={color}>\n {`$${spent.toFixed(4)} / $${cap.toFixed(2)}`}\n <Text dimColor>{` (${pct.toFixed(0)}%)`}</Text>\n </Text>\n </Box>\n );\n}\n\nfunction sessionCostColor(cost: number): string | undefined {\n if (cost <= 0) return undefined;\n if (cost >= 5) return COLOR.err;\n if (cost >= 0.5) return COLOR.warn;\n return COLOR.ok;\n}\n"],"mappings":"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","names":["React","Box","Text","React","React","Box","Text","React"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/setup.tsx","../../src/cli/ui/Wizard.tsx"],"sourcesContent":["/**\n * `reasonix setup` — re-mount the first-run wizard on demand so users\n * can reconfigure (add/remove MCP servers, switch preset) without\n * editing JSON by hand.\n *\n * Invoked both explicitly (`reasonix setup`) and implicitly (the no-args\n * entry point when `setupCompleted` is false).\n */\n\nimport { render } from \"ink\";\nimport React from \"react\";\nimport { loadApiKey, readConfig } from \"../../config.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { Wizard } from \"../ui/Wizard.js\";\n\nexport interface SetupOptions {\n /**\n * When true, bypass the API-key step even if no key is saved — useful\n * from test harnesses. Normal CLI use always pushes through the key\n * step when missing.\n */\n skipKeyStep?: boolean;\n}\n\nexport async function setupCommand(_opts: SetupOptions = {}): Promise<void> {\n loadDotenv();\n const existingKey = loadApiKey();\n const existing = readConfig();\n\n const { waitUntilExit, unmount } = render(\n <Wizard\n existingApiKey={existingKey}\n initial={{ preset: existing.preset, mcp: existing.mcp, theme: existing.theme }}\n onComplete={() => {\n // Ink handles its own enter-to-exit inside the \"saved\" step; we\n // just wait for the app to exit naturally.\n }}\n onCancel={() => {\n unmount();\n }}\n />,\n { exitOnCtrlC: true, patchConsole: false },\n );\n await waitUntilExit();\n}\n","/**\n * First-run / re-configure wizard.\n *\n * Walks a new user through: language → theme → API key → preset pick → MCP\n * server pick → per-server args → save. Saved output lives in\n * `~/.reasonix/config.json` so the next `reasonix chat` starts with\n * everything already wired.\n */\n\nimport { mkdirSync, statSync } from \"node:fs\";\nimport { Box, Text, useApp, useInput } from \"ink\";\nimport TextInput from \"ink-text-input\";\n// biome-ignore lint/style/useImportType: JSX (jsx: \"react\") needs React as a value at runtime\nimport React, { useEffect, useState } from \"react\";\nimport {\n type PresetName,\n type ReasonixConfig,\n defaultConfigPath,\n isPlausibleKey,\n loadTheme,\n readConfig,\n redactKey,\n resolveThemePreference,\n writeConfig,\n} from \"../../config.js\";\nimport {\n detectSystemLanguage,\n getLanguage,\n getSupportedLanguages,\n notifyLanguageChange,\n onLanguageChange,\n setLanguage,\n t,\n} from \"../../i18n/index.js\";\nimport type { LanguageCode } from \"../../i18n/types.js\";\nimport { type CatalogEntry, MCP_CATALOG } from \"../../mcp/catalog.js\";\nimport { MultiSelect, type SelectItem, SingleSelect } from \"./Select.js\";\nimport { PRESET_DESCRIPTIONS } from \"./presets.js\";\nimport { ThemeProvider, useTheme } from \"./theme/context.js\";\nimport { type ThemeName, listThemeNames } from \"./theme/tokens.js\";\n\nexport interface WizardProps {\n /** Called once the config has been saved. */\n onComplete: (cfg: ReasonixConfig) => void;\n /** Called if the user presses Esc to abort. */\n onCancel?: () => void;\n /** Skip the API-key step if a key already exists (env or config). */\n existingApiKey?: string;\n /** Pre-fill selections when re-running (reconfigure flow). */\n initial?: {\n preset?: PresetName;\n mcp?: string[];\n theme?: ThemeName | \"auto\";\n };\n}\n\ntype Step = \"language\" | \"theme\" | \"apiKey\" | \"preset\" | \"mcp\" | \"mcpArgs\" | \"review\" | \"saved\";\n\ninterface WizardData {\n language: LanguageCode;\n theme: ThemeName;\n apiKey: string;\n preset: PresetName;\n selectedCatalog: string[];\n catalogArgs: Record<string, string>;\n}\n\nconst CATALOG_BY_NAME = new Map(MCP_CATALOG.map((e) => [e.name, e]));\n\nconst LANGUAGE_LABELS: Record<LanguageCode, string> = {\n EN: \"English\",\n \"zh-CN\": \"简体中文\",\n};\n\nexport function Wizard({ onComplete, onCancel, existingApiKey, initial }: WizardProps) {\n const { exit } = useApp();\n const [, setLanguageVersion] = useState(0);\n useEffect(() => onLanguageChange(() => setLanguageVersion((v) => v + 1)), []);\n\n const [previewTheme, setPreviewTheme] = useState<ThemeName>(() =>\n resolveThemePreference(initial?.theme ?? loadTheme(), process.env.REASONIX_THEME),\n );\n\n const [step, setStep] = useState<Step>(\"language\");\n const [data, setData] = useState<WizardData>(() => ({\n language: getLanguage(),\n theme: resolveThemePreference(initial?.theme ?? loadTheme(), process.env.REASONIX_THEME),\n apiKey: existingApiKey ?? \"\",\n preset: initial?.preset ?? \"auto\",\n selectedCatalog: deriveInitialCatalog(initial?.mcp ?? []),\n catalogArgs: {},\n }));\n const [error, setError] = useState<string | null>(null);\n\n useInput((_input, key) => {\n if (key.escape && step !== \"saved\" && onCancel) onCancel();\n });\n\n const content = (() => {\n if (step === \"language\") {\n return (\n <LanguageStep\n initialValue={data.language}\n onSubmit={(lang) => {\n setLanguage(lang);\n notifyLanguageChange();\n setData((d) => ({ ...d, language: lang }));\n setStep(\"theme\");\n }}\n />\n );\n }\n\n if (step === \"theme\") {\n return (\n <ThemeStep\n initialValue={data.theme}\n onPreview={setPreviewTheme}\n onSubmit={(theme) => {\n setData((d) => ({ ...d, theme }));\n setStep(existingApiKey ? \"preset\" : \"apiKey\");\n }}\n />\n );\n }\n\n if (step === \"apiKey\") {\n return (\n <ApiKeyStep\n onSubmit={(key) => {\n setData((d) => ({ ...d, apiKey: key }));\n setError(null);\n setStep(\"preset\");\n }}\n error={error}\n onError={setError}\n />\n );\n }\n\n if (step === \"preset\") {\n return (\n <StepFrame title={t(\"wizard.presetTitle\")} step={1} total={3}>\n <SingleSelect<PresetName>\n items={presetItems()}\n initialValue={data.preset}\n onSubmit={(preset) => {\n setData((d) => ({ ...d, preset }));\n setStep(\"mcp\");\n }}\n />\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.selectFooter\")}</Text>\n </Box>\n </StepFrame>\n );\n }\n\n if (step === \"mcp\") {\n return (\n <StepFrame title={t(\"wizard.mcpTitle\")} step={2} total={3}>\n <MultiSelect\n items={mcpItems()}\n initialSelected={data.selectedCatalog}\n onSubmit={(selected) => {\n setData((d) => ({ ...d, selectedCatalog: selected }));\n const needsArgs = selected.some((name) => CATALOG_BY_NAME.get(name)?.userArgs);\n setStep(needsArgs ? \"mcpArgs\" : \"review\");\n }}\n footer={t(\"wizard.mcpFooterMulti\")}\n />\n </StepFrame>\n );\n }\n\n if (step === \"mcpArgs\") {\n const pending = data.selectedCatalog.filter((name) => {\n const entry = CATALOG_BY_NAME.get(name);\n return entry?.userArgs && !data.catalogArgs[name];\n });\n if (pending.length === 0) {\n setStep(\"review\");\n return null;\n }\n const currentName = pending[0]!;\n const entry = CATALOG_BY_NAME.get(currentName)!;\n return (\n <McpArgsStep\n entry={entry}\n error={error}\n onSubmit={(value) => {\n setData((d) => ({\n ...d,\n catalogArgs: { ...d.catalogArgs, [currentName]: value },\n }));\n setError(null);\n }}\n onError={setError}\n />\n );\n }\n\n if (step === \"review\") {\n const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));\n return (\n <StepFrame title={t(\"wizard.reviewTitle\")} step={3} total={3}>\n <Box flexDirection=\"column\">\n <SummaryLine\n label={t(\"wizard.reviewLabelLanguage\")}\n value={LANGUAGE_LABELS[data.language]}\n />\n <SummaryLine label={t(\"wizard.reviewLabelApiKey\")} value={redactKey(data.apiKey)} />\n <SummaryLine label={t(\"wizard.reviewLabelTheme\")} value={data.theme} />\n <SummaryLine label={t(\"wizard.reviewLabelPreset\")} value={data.preset} />\n <SummaryLine\n label={t(\"wizard.reviewLabelMcp\")}\n value={\n specs.length === 0\n ? t(\"wizard.reviewMcpNone\")\n : t(\"wizard.reviewMcpServers\", { count: specs.length })\n }\n />\n {specs.map((spec, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed\n <Box key={i} paddingLeft={14}>\n <Text dimColor>· {spec}</Text>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text>{t(\"wizard.reviewSavesTo\", { path: defaultConfigPath() })}</Text>\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : null}\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.reviewFooter\")}</Text>\n </Box>\n </Box>\n <ReviewConfirm\n onConfirm={() => {\n try {\n const specsNow = data.selectedCatalog.map((name) =>\n buildSpec(name, data.catalogArgs),\n );\n const prev = readConfig();\n const next: ReasonixConfig = {\n ...prev,\n apiKey: data.apiKey,\n preset: data.preset,\n theme: data.theme,\n mcp: specsNow,\n setupCompleted: true,\n };\n writeConfig(next);\n setStep(\"saved\");\n onComplete(next);\n } catch (e) {\n setError(t(\"wizard.reviewSaveError\", { message: (e as Error).message }));\n }\n }}\n />\n </StepFrame>\n );\n }\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"green\" paddingX={1}>\n <Text bold color=\"green\">\n {t(\"wizard.savedTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text>{t(\"ui.welcome\")}</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.savedFooter\")}</Text>\n </Box>\n <ExitOnEnter onExit={exit} />\n </Box>\n );\n })();\n\n return <ThemeProvider name={previewTheme}>{content}</ThemeProvider>;\n}\n\nconst THEME_NAMES = listThemeNames();\n\nfunction ThemeStep({\n initialValue,\n onPreview,\n onSubmit,\n}: {\n initialValue: ThemeName;\n onPreview: (theme: ThemeName) => void;\n onSubmit: (theme: ThemeName) => void;\n}) {\n const initialIndex = Math.max(0, THEME_NAMES.indexOf(initialValue));\n const [index, setIndex] = useState(initialIndex);\n const theme = useTheme();\n\n useInput((_input, key) => {\n if (key.upArrow) {\n const next = (index - 1 + THEME_NAMES.length) % THEME_NAMES.length;\n setIndex(next);\n onPreview(THEME_NAMES[next]!);\n } else if (key.downArrow) {\n const next = (index + 1) % THEME_NAMES.length;\n setIndex(next);\n onPreview(THEME_NAMES[next]!);\n } else if (key.return) {\n onSubmit(THEME_NAMES[index]!);\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={theme.tone.brand} paddingX={1}>\n <Text bold color={theme.tone.brand}>\n {t(\"wizard.themeTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.themeSubtitle\")}</Text>\n </Box>\n <Box marginTop={1} flexDirection=\"column\">\n {THEME_NAMES.map((name, i) => (\n <Box key={name}>\n <Text color={i === index ? theme.tone.brand : undefined}>\n {i === index ? \"▸ \" : \" \"}\n </Text>\n <Text bold={i === index} color={i === index ? theme.fg.strong : theme.fg.body}>\n {name}\n </Text>\n <Text color={theme.fg.meta}>{\" — \"}</Text>\n <Text color={theme.fg.meta}>{t(`wizard.themeCaption.${name}`)}</Text>\n </Box>\n ))}\n </Box>\n <Box\n marginTop={1}\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={theme.fg.faint}\n paddingX={1}\n >\n <Text color={theme.fg.meta}>{t(\"wizard.themeSampleHeading\")}</Text>\n <Box marginTop={1}>\n <Text color={theme.tone.accent}>{\"◆ \"}</Text>\n <Text color={theme.tone.accent}>Reasoning</Text>\n </Box>\n <Box>\n <Text color={theme.tone.info}>{\"▣ \"}</Text>\n <Text color={theme.fg.body}>{\"fs.readFile(\"}</Text>\n <Text color={theme.tone.ok}>{'\"main.ts\"'}</Text>\n <Text color={theme.fg.body}>{\")\"}</Text>\n </Box>\n <Box>\n <Text color={theme.fg.meta}>~/project/main.ts:42</Text>\n </Box>\n <Box marginTop={1}>\n <Text color={theme.tone.ok}>ok</Text>\n <Text color={theme.fg.faint}>{\" · \"}</Text>\n <Text color={theme.tone.warn}>warn</Text>\n <Text color={theme.fg.faint}>{\" · \"}</Text>\n <Text color={theme.tone.err}>err</Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.themeFooter\")}</Text>\n </Box>\n </Box>\n );\n}\n\n// ---------- step components ----------\n\nfunction LanguageStep({\n initialValue,\n onSubmit,\n}: {\n initialValue: LanguageCode;\n onSubmit: (lang: LanguageCode) => void;\n}) {\n const items: SelectItem<LanguageCode>[] = getSupportedLanguages().map((code) => ({\n value: code,\n label: LANGUAGE_LABELS[code],\n hint: code === detectSystemLanguage() ? \"(detected)\" : undefined,\n }));\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n {t(\"wizard.languageTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.languageSubtitle\")}</Text>\n </Box>\n <Box marginTop={1}>\n <SingleSelect<LanguageCode>\n items={items}\n initialValue={initialValue}\n onSubmit={onSubmit}\n footer={t(\"wizard.selectFooter\")}\n />\n </Box>\n </Box>\n );\n}\n\nfunction ApiKeyStep({\n onSubmit,\n error,\n onError,\n}: {\n onSubmit: (key: string) => void;\n error: string | null;\n onError: (e: string | null) => void;\n}) {\n const [value, setValue] = useState(\"\");\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n {t(\"wizard.welcomeTitle\")}\n </Text>\n <Box marginTop={1}>\n <Text>{t(\"wizard.apiKeyPrompt\")}</Text>\n </Box>\n <Text dimColor>{t(\"wizard.apiKeyGetOne\")}</Text>\n <Text dimColor>{t(\"wizard.apiKeySavedLocally\", { path: defaultConfigPath() })}</Text>\n <Box marginTop={1}>\n <Text bold color=\"cyan\">\n {t(\"wizard.apiKeyInputLabel\")}\n </Text>\n <TextInput\n value={value}\n onChange={setValue}\n onSubmit={(raw) => {\n const trimmed = raw.trim();\n if (!isPlausibleKey(trimmed)) {\n onError(t(\"wizard.apiKeyInvalid\"));\n setValue(\"\");\n return;\n }\n onSubmit(trimmed);\n }}\n mask=\"•\"\n placeholder=\"sk-...\"\n />\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : value ? (\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.apiKeyPreview\", { redacted: redactKey(value) })}</Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\nfunction McpArgsStep({\n entry,\n error,\n onSubmit,\n onError,\n}: {\n entry: CatalogEntry;\n error: string | null;\n onSubmit: (value: string) => void;\n onError: (e: string | null) => void;\n}) {\n const [value, setValue] = useState(\"\");\n const [pendingCreate, setPendingCreate] = useState<string | null>(null);\n\n useInput((input, key) => {\n if (!pendingCreate) return;\n const ch = input.toLowerCase();\n if (ch === \"y\" || key.return) {\n try {\n mkdirSync(pendingCreate, { recursive: true });\n const created = pendingCreate;\n setPendingCreate(null);\n setValue(\"\");\n onError(null);\n onSubmit(created);\n } catch (e) {\n onError(\n t(\"wizard.mcpArgsDirCreateFailed\", {\n path: pendingCreate,\n message: (e as Error).message,\n }),\n );\n setPendingCreate(null);\n }\n } else if (ch === \"n\" || key.escape) {\n setPendingCreate(null);\n onError(null);\n }\n });\n\n if (pendingCreate) {\n return (\n <StepFrame title={t(\"wizard.mcpArgsTitle\", { name: entry.name })} step={2} total={3}>\n <Box flexDirection=\"column\">\n <Text>{t(\"wizard.mcpArgsDirMissing\", { path: pendingCreate })}</Text>\n <Box marginTop={1}>\n <Text dimColor>{t(\"wizard.mcpArgsDirCreateHint\")}</Text>\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : null}\n </Box>\n </StepFrame>\n );\n }\n\n return (\n <StepFrame title={t(\"wizard.mcpArgsTitle\", { name: entry.name })} step={2} total={3}>\n <Box flexDirection=\"column\">\n <Text>{entry.summary}</Text>\n {entry.note ? (\n <Box marginTop={1}>\n <Text dimColor>{entry.note}</Text>\n </Box>\n ) : null}\n <Box marginTop={1}>\n <Text>{t(\"wizard.mcpArgsRequiredParam\")}</Text>\n <Text bold>{entry.userArgs}</Text>\n </Box>\n <Box marginTop={1}>\n <Text bold color=\"cyan\">\n {entry.userArgs}\n {\" › \"}\n </Text>\n <TextInput\n value={value}\n onChange={setValue}\n onSubmit={(raw) => {\n const trimmed = raw.trim();\n if (!trimmed) {\n onError(t(\"wizard.mcpArgsEmpty\", { name: entry.name }));\n return;\n }\n if (entry.name === \"filesystem\") {\n const check = checkFilesystemPath(trimmed);\n if (check.kind === \"missing\") {\n setPendingCreate(trimmed);\n return;\n }\n if (check.kind === \"not-a-dir\") {\n onError(t(\"wizard.mcpArgsNotADir\", { path: trimmed }));\n return;\n }\n }\n onSubmit(trimmed);\n setValue(\"\");\n }}\n placeholder={placeholderFor(entry)}\n />\n </Box>\n {error ? (\n <Box marginTop={1}>\n <Text color=\"red\">{error}</Text>\n </Box>\n ) : null}\n </Box>\n </StepFrame>\n );\n}\n\nfunction checkFilesystemPath(p: string): { kind: \"ok\" | \"missing\" | \"not-a-dir\" } {\n try {\n return { kind: statSync(p).isDirectory() ? \"ok\" : \"not-a-dir\" };\n } catch {\n return { kind: \"missing\" };\n }\n}\n\nfunction ReviewConfirm({ onConfirm }: { onConfirm: () => void }) {\n useInput((_i, key) => {\n if (key.return) onConfirm();\n });\n return null;\n}\n\nfunction ExitOnEnter({ onExit }: { onExit: () => void }) {\n useInput((_i, key) => {\n if (key.return) onExit();\n });\n return null;\n}\n\nfunction StepFrame({\n title,\n step,\n total,\n children,\n}: {\n title: string;\n step: number;\n total: number;\n children: React.ReactNode;\n}) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Box>\n <Text dimColor>{t(\"wizard.stepCounter\", { step, total })}</Text>\n <Text bold color=\"cyan\">\n {title}\n </Text>\n </Box>\n <Box marginTop={1} flexDirection=\"column\">\n {children}\n </Box>\n </Box>\n );\n}\n\nfunction SummaryLine({ label, value }: { label: string; value: string }) {\n return (\n <Box>\n <Text>{label.padEnd(12)}</Text>\n <Text bold>{value}</Text>\n </Box>\n );\n}\n\nfunction presetItems(): SelectItem<PresetName>[] {\n return ([\"auto\", \"flash\", \"pro\"] as const).map((name) => ({\n value: name as PresetName,\n label: `${name} — ${PRESET_DESCRIPTIONS[name].headline}`,\n hint: PRESET_DESCRIPTIONS[name].cost,\n }));\n}\n\nfunction mcpItems(): SelectItem<string>[] {\n return MCP_CATALOG.map((entry) => {\n const hintParts: string[] = [entry.summary];\n if (entry.userArgs) hintParts.push(t(\"wizard.mcpUserArgsHint\", { arg: entry.userArgs }));\n if (entry.note) hintParts.push(entry.note);\n return {\n value: entry.name,\n label: entry.name,\n hint: hintParts.join(\" · \"),\n };\n });\n}\n\nfunction placeholderFor(entry: CatalogEntry): string {\n if (entry.name === \"filesystem\") return \"e.g. /tmp/reasonix-sandbox\";\n if (entry.name === \"sqlite\") return \"e.g. ./notes.sqlite\";\n return entry.userArgs ?? \"\";\n}\n\nfunction deriveInitialCatalog(existingSpecs: string[]): string[] {\n const packageToName = new Map(MCP_CATALOG.map((e) => [e.package, e.name]));\n const out: string[] = [];\n for (const spec of existingSpecs) {\n for (const [pkg, name] of packageToName) {\n if (spec.includes(pkg)) {\n out.push(name);\n break;\n }\n }\n }\n return out;\n}\n\n/**\n * Build the `--mcp` spec string for a catalog entry. Same format\n * `mcpCommandFor` produces for `reasonix mcp list`, minus the leading\n * `--mcp \"...\"` wrapper — we store the inner spec directly.\n */\nexport function buildSpec(name: string, argsByName: Record<string, string>): string {\n const entry = CATALOG_BY_NAME.get(name);\n if (!entry) return name;\n const userArg = entry.userArgs ? argsByName[name] : undefined;\n const tail = userArg ? ` ${quoteIfNeeded(userArg)}` : \"\";\n return `${entry.name}=npx -y ${entry.package}${tail}`;\n}\n\nfunction quoteIfNeeded(s: string): string {\n // Escape backslashes BEFORE quotes — otherwise a trailing `\\` in the\n // input would consume the closing quote when a downstream parser\n // un-escapes the output (CodeQL js/incomplete-sanitization).\n return /\\s|\"/.test(s) ? `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"` : s;\n}\n"],"mappings":"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","names":["React","entry","React"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|