#!/usr/bin/env node /** * init.ts —— 灵枢一键配置生成器(独立 CLI 入口:`lingshu-init`) * * 用户痛点:部署灵枢要手工做多步——选记忆根目录、手写各端 mcp.json 的 * env(MDCG_ROOT / MDCG_PYTHON 等)、理解令牌签发。本命令把「生成配置」 * 这一步自动化:三问(接入端 / 记忆根目录 / Python 解释器)后打印所选端 * 的 mcp.json 配置片段、把片段落盘成可复制的文件、并给出各端后续步骤 * (片段放哪 / 令牌签发命令——后者指向 README「写入凭据」节)。 * * 边界(刻意设计,勿越界): * · init **只生成配置**——不创建记忆目录、不启动 md_cg 服务、不写库; * 重跑(同参数)输出逐字节一致(无时间戳等易变内容),可放心重复执行。 * · 与插件运行时的数据根缺省(`~/.dsh/.dsh-memory/data/mdcg`,见 * `src/lib/datapath.ts`)不同,本命令的缺省记忆根是 `~/.lingshu/memory` * ——它会被**显式写进**片段的 MDCG_ROOT,两侧不靠默契、无歧义。 * * env 片段口径与 `mdcgChildEnv()`(src/lib/mdcg_client.ts)对齐: * PYTHONIOENCODING/PYTHONUTF8 两条编码注入是硬约束(中文记忆场景, * 详见该函数头注的 2026-09-20 读线程崩溃现场);MDCG_MCP_SURFACE=kernel * 与各端 mcp.json 样例(claude/lingshu-memory/mcp.json.example 等)同口径。 * MDCG_PYTHON 对直挂端是文档性键(解释器由 command 决定),对 DSH 插件端 * 真实生效(`defaultPython()` 读它,src/lib/python_path.ts:42)。 * * 零运行时依赖:只用 Node 内置模块(node:readline/promises / node:fs / * node:path)——与全仓「CLI 不加第三方依赖」纪律一致。 */ import type { Readable, Writable } from 'node:stream'; /** 接入端:1=DSH 插件 2=Claude Code 3=Codex CLI 4=通用 MCP。 */ export type InitEnd = 'dsh' | 'claude' | 'codex' | 'generic'; interface EndSpec { id: InitEnd; /** 问答菜单里的展示名。 */ label: string; /** MDCG_ACTOR(与既有各端样例/插件配置同口径;私有内容按 (tenant, actor) 派生 DEK)。 */ actor: string; /** 片段该放到哪(打印给用户)。 */ configTarget: string; /** 令牌签发指引里说明的角色语境(保持 README 口径,仅按端换 actor)。 */ tokenActor: string; } /** 缺省记忆根:/.lingshu/memory(home 可注入,供测试)。 */ export declare function defaultMemoryRoot(home?: string): string; /** 生成的 mcp.json 片段(键序固定 → 序列化稳定 → 幂等)。 */ export declare function buildSnippet(end: EndSpec, root: string, python: string): { mcpServers: { mdcg: { command: string; args: string[]; env: Record; }; }; }; /** runInit 可注入的 IO(测试注入;缺省 = 真实 stdin/stdout/cwd/home/平台)。 */ export interface InitOptions { /** 交互模式的 stdin(注入 PassThrough 即可 mock)。 */ input?: Readable; /** 输出收集处(缺省 process.stdout)。 */ output?: Writable; /** 片段文件落盘目录(缺省 process.cwd())。 */ cwd?: string; /** 缺省记忆根的 home(缺省 os.homedir())。 */ home?: string; /** 平台缺省解释器判定(缺省 process.platform)。 */ platform?: NodeJS.Platform; /** 覆盖 TTY 判定(缺省 process.stdin.isTTY):决定「无参数时」走交互还是 * 报错。测试注入 false 即可确定性触发非交互分支,不依赖测试宿主的 stdin * 形态(管道/终端两态都会让测试结果漂移——显式注入消除这个自由度)。 */ tty?: boolean; } export interface InitResult { end: InitEnd; endLabel: string; root: string; python: string; snippetPath: string; snippet: ReturnType; /** 本次打印到 output 的完整文本(幂等断言用)。 */ output: string; /** 片段文件字节(= JSON.stringify(snippet, null, 2) + 换行)。 */ snippetFile: string; } /** * 一键配置主流程:非交互(参数齐)跳过问答;无参数走交互三问。 * 只生成配置(打印 + 片段落盘),不创建目录、不启动服务、不写库。 */ export declare function runInit(argv: string[], opts?: InitOptions): Promise; export {};