@24klynx/cli 0.1.3 → 0.1.5
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/LICENSE +21 -0
- package/dist/{config-Braj-aBw.mjs → config-B-iYJluO.mjs} +11 -4
- package/dist/config-B-iYJluO.mjs.map +1 -0
- package/dist/config-C6StrUyB.mjs +2 -0
- package/dist/git-branch-Dn1CP6An.mjs.map +1 -1
- package/dist/{headless-launcher-CnSrw3bm.mjs → headless-launcher-faY5GV9T.mjs} +3 -3
- package/dist/headless-launcher-faY5GV9T.mjs.map +1 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +12 -8
- package/dist/index.mjs.map +1 -1
- package/dist/privacy-B6Rm1Xck.mjs.map +1 -1
- package/dist/{process-lifecycle-kdV53L3o.mjs → process-lifecycle-Xy1A3HFe.mjs} +22 -3
- package/dist/process-lifecycle-Xy1A3HFe.mjs.map +1 -0
- package/dist/sandbox-toggle-9akjTw3h.mjs.map +1 -1
- package/dist/upgrade-CREWRNeC.mjs.map +1 -1
- package/package.json +19 -19
- package/dist/config-Braj-aBw.mjs.map +0 -1
- package/dist/config-D9DbomLt.mjs +0 -2
- package/dist/headless-launcher-CnSrw3bm.mjs.map +0 -1
- package/dist/process-lifecycle-kdV53L3o.mjs.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 24K
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -82,6 +82,7 @@ function resolveConfigEnv(config) {
|
|
|
82
82
|
*
|
|
83
83
|
* @throws 找不到对应 API key 时抛出中文错误。
|
|
84
84
|
*/
|
|
85
|
+
/** Select and construct an LLM provider from config — dispatches by model name prefix (claude→Anthropic, gpt→OpenAI, etc.). */
|
|
85
86
|
function resolveProvider(config) {
|
|
86
87
|
const model = process.env.LYNX_MODEL ?? config.model ?? "deepseek-v4-pro";
|
|
87
88
|
if (model.includes("claude")) {
|
|
@@ -97,10 +98,16 @@ function resolveProvider(config) {
|
|
|
97
98
|
if (!token) throw new Error("未配置 OpenAI API 密钥。请在 config.json 的 env.OPENAI_API_KEY 中设置,或设置环境变量 OPENAI_API_KEY。");
|
|
98
99
|
return createOpenAiProvider({ apiKey: token });
|
|
99
100
|
}
|
|
100
|
-
const
|
|
101
|
-
|
|
101
|
+
const anthropicToken = process.env.ANTHROPIC_AUTH_TOKEN ?? process.env.ANTHROPIC_API_KEY;
|
|
102
|
+
const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL;
|
|
103
|
+
if (model.includes("deepseek") && anthropicToken && anthropicBaseUrl) return createAnthropicProvider({
|
|
104
|
+
apiKey: anthropicToken,
|
|
105
|
+
baseUrl: anthropicBaseUrl
|
|
106
|
+
});
|
|
107
|
+
const deepseekToken = process.env.DEEPSEEK_API_KEY;
|
|
108
|
+
if (!deepseekToken) throw new Error("未配置 DeepSeek API 密钥。请在 config.json 的 env.DEEPSEEK_API_KEY 中设置,或设置环境变量 DEEPSEEK_API_KEY。");
|
|
102
109
|
return createDeepSeekProvider({
|
|
103
|
-
apiKey:
|
|
110
|
+
apiKey: deepseekToken,
|
|
104
111
|
baseUrl: process.env.DEEPSEEK_BASE_URL
|
|
105
112
|
});
|
|
106
113
|
}
|
|
@@ -144,4 +151,4 @@ async function handleConfigCommand(opts) {
|
|
|
144
151
|
//#endregion
|
|
145
152
|
export { saveConfig as a, resolveProvider as i, loadConfig as n, resolveConfigEnv as r, handleConfigCommand as t };
|
|
146
153
|
|
|
147
|
-
//# sourceMappingURL=config-
|
|
154
|
+
//# sourceMappingURL=config-B-iYJluO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-B-iYJluO.mjs","names":[],"sources":["../src/commands/config.ts"],"sourcesContent":["/**\n * Config command — 统一配置文件管理与 Provider 工厂。\n *\n * 读取 ~/.lynx/config.json,提供类型安全的结构化配置。\n * 同时输出 resolveConfigEnv(env 注入)和 resolveProvider(按模型名自动选型)。\n */\n\nimport { readFileSync, writeFileSync, existsSync, renameSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { resolvePaths } from \"@24klynx/core\";\nimport type { LlmProvider } from \"@24klynx/llm\";\nimport {\n createDeepSeekProvider,\n createAnthropicProvider,\n createOpenAiProvider,\n} from \"@24klynx/llm\";\n\n// ── Types ────────────────────────────────────────────\n\n/** Lynx 完整配置结构。对应 ~/.lynx/config.json。 */\nexport interface LynxConfig {\n /** 模型标识符(如 deepseek-v4-pro、claude-sonnet-4-6)。 */\n model: string;\n /** UI 主题(dark / light)。 */\n theme: string;\n /** 环境变量注入 — key 不存在于 process.env 时自动设置。 */\n env: Record<string, string>;\n /** 权限白/黑名单。格式 \"ToolName(args)\"。 */\n permissions: {\n allow: string[];\n deny: string[];\n };\n}\n\n/** Options for the config command — get/set/list/import configuration values. */\nexport interface ConfigCommandOptions {\n show?: boolean;\n set?: string;\n value?: string;\n path?: boolean;\n}\n\n// ── Defaults ─────────────────────────────────────────\n\nconst DEFAULT_CONFIG: LynxConfig = {\n model: \"deepseek-v4-pro\",\n theme: \"dark\",\n env: {},\n permissions: { allow: [], deny: [] },\n};\n\n// ── Helpers ──────────────────────────────────────────\n\nfunction configPath(): string {\n const paths = resolvePaths();\n return paths.configFile;\n}\n\n// ── Public API ───────────────────────────────────────\n\n/**\n * 从磁盘加载配置,缺失字段填默认值。\n * 文件损坏时自动备份为 .bak 并返回默认配置。\n */\nexport function loadConfig(): LynxConfig {\n const path = configPath();\n if (!existsSync(path))\n return { ...DEFAULT_CONFIG, env: {}, permissions: { allow: [], deny: [] } };\n try {\n const raw = JSON.parse(readFileSync(path, \"utf-8\")) as Partial<LynxConfig>;\n return {\n model: raw.model ?? DEFAULT_CONFIG.model,\n theme: raw.theme ?? DEFAULT_CONFIG.theme,\n env: raw.env ?? {},\n permissions: {\n allow: raw.permissions?.allow ?? [],\n deny: raw.permissions?.deny ?? [],\n },\n };\n } catch {\n const backupPath = path + \".bak\";\n try {\n renameSync(path, backupPath);\n } catch {\n // 备份失败不阻塞\n }\n process.stderr.write(\n `[lynx] 警告:配置文件已损坏,已备份到 ${backupPath}。正在使用默认配置。\\n`,\n );\n return { ...DEFAULT_CONFIG, env: {}, permissions: { allow: [], deny: [] } };\n }\n}\n\n/**\n * 将 config.env 中的键注入 process.env(仅补未设的 key,不覆盖已有环境变量)。\n *\n * 优先级:已存在的 process.env > config.json env\n */\nexport function resolveConfigEnv(config: LynxConfig): void {\n for (const [key, value] of Object.entries(config.env)) {\n if (process.env[key] === undefined && value !== undefined && value !== \"\") {\n process.env[key] = value;\n }\n }\n}\n\n/**\n * 按模型名自动匹配 LLM Provider。\n *\n * 匹配规则:\n * - 含 `claude` → Anthropic(需 ANTHROPIC_AUTH_TOKEN 或 ANTHROPIC_API_KEY)\n * - 含 `gpt` 或 `o1`/`o3` → OpenAI(需 OPENAI_API_KEY)\n * - 其他 → DeepSeek(需 DEEPSEEK_API_KEY)\n *\n * 环境变量优先于 config.json env(resolveConfigEnv 已处理)。\n *\n * @throws 找不到对应 API key 时抛出中文错误。\n */\n/** Select and construct an LLM provider from config — dispatches by model name prefix (claude→Anthropic, gpt→OpenAI, etc.). */\nexport function resolveProvider(config: LynxConfig): LlmProvider {\n const model = process.env.LYNX_MODEL ?? config.model ?? \"deepseek-v4-pro\";\n\n if (model.includes(\"claude\")) {\n const token = process.env.ANTHROPIC_AUTH_TOKEN ?? process.env.ANTHROPIC_API_KEY;\n if (!token) {\n throw new Error(\n \"未配置 Anthropic API 密钥。请在 config.json 的 env.ANTHROPIC_AUTH_TOKEN 中设置,\" +\n \"或设置环境变量 ANTHROPIC_API_KEY。\",\n );\n }\n return createAnthropicProvider({\n apiKey: token,\n baseUrl: process.env.ANTHROPIC_BASE_URL,\n });\n }\n\n if (model.includes(\"gpt\") || model.includes(\"o1\") || model.includes(\"o3\")) {\n const token = process.env.OPENAI_API_KEY;\n if (!token) {\n throw new Error(\n \"未配置 OpenAI API 密钥。请在 config.json 的 env.OPENAI_API_KEY 中设置,\" +\n \"或设置环境变量 OPENAI_API_KEY。\",\n );\n }\n return createOpenAiProvider({ apiKey: token });\n }\n\n // 含 deepseek 但在 Anthropic 兼容端点 → 走 Anthropic provider\n const anthropicToken = process.env.ANTHROPIC_AUTH_TOKEN ?? process.env.ANTHROPIC_API_KEY;\n const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL;\n if (model.includes(\"deepseek\") && anthropicToken && anthropicBaseUrl) {\n return createAnthropicProvider({\n apiKey: anthropicToken,\n baseUrl: anthropicBaseUrl,\n });\n }\n\n // 默认:DeepSeek\n const deepseekToken = process.env.DEEPSEEK_API_KEY;\n if (!deepseekToken) {\n throw new Error(\n \"未配置 DeepSeek API 密钥。请在 config.json 的 env.DEEPSEEK_API_KEY 中设置,\" +\n \"或设置环境变量 DEEPSEEK_API_KEY。\",\n );\n }\n return createDeepSeekProvider({\n apiKey: deepseekToken,\n baseUrl: process.env.DEEPSEEK_BASE_URL,\n });\n}\n\n/** 原子写入配置到磁盘(temp file + rename)。 */\nexport function saveConfig(config: LynxConfig): void {\n const path = configPath();\n const dir = dirname(path);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\n const tmpPath = path + \".tmp\";\n // 排序键以保证 diff 友好\n const ordered = {\n model: config.model,\n theme: config.theme,\n env: config.env,\n permissions: config.permissions,\n };\n writeFileSync(tmpPath, JSON.stringify(ordered, null, 2) + \"\\n\", \"utf-8\");\n renameSync(tmpPath, path);\n}\n\n// ── CLI handler ──────────────────────────────────────\n\n/** 处理 `lynx config` 命令。 */\nexport async function handleConfigCommand(opts: ConfigCommandOptions): Promise<void> {\n if (opts.path) {\n process.stdout.write(`${configPath()}\\n`);\n return;\n }\n\n if (opts.set) {\n const config = loadConfig();\n // 简单顶层 key 直写;嵌套 key 暂不支持\n const key = opts.set as keyof LynxConfig;\n if (key === \"model\" || key === \"theme\") {\n config[key] = opts.value ?? \"\";\n } else if (key === \"env\" || key === \"permissions\") {\n process.stderr.write(`[lynx] 警告:${opts.set} 是嵌套对象,请直接编辑 config.json。\\n`);\n return;\n }\n saveConfig(config);\n process.stdout.write(`${opts.set} = ${opts.value ?? \"\"}\\n`);\n return;\n }\n\n // Default: --show\n const config = loadConfig();\n const keys = Object.keys(config);\n if (keys.length === 0) {\n process.stdout.write(\"No configuration values set.\\n\");\n } else {\n for (const [key, val] of Object.entries(config)) {\n process.stdout.write(`${key} = ${JSON.stringify(val)}\\n`);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-branch-Dn1CP6An.mjs","names":[],"sources":["../src/commands/git-branch.ts"],"sourcesContent":["/**\n * /branch 命令 — Git 分支管理。\n *\n * 生成中文指令,引导模型执行分支操作:\n * - list:列出所有分支并高亮当前分支\n * - create:从指定基准创建新分支\n * - switch:切换到指定分支\n * - delete:删除分支(未合并时警告)\n */\n\n// ── Types ────────────────────────────────────────────\n\nexport interface BranchCommandArgs {\n /** 操作类型:列出 / 创建 / 切换 / 删除。默认为 list。 */\n action?: \"list\" | \"create\" | \"switch\" | \"delete\";\n /** 分支名称(create / switch / delete 时必填)。 */\n name?: string;\n /** 创建分支时的基准分支(仅 create 时有效)。 */\n base?: string;\n}\n\n// ── Public API ───────────────────────────────────────\n\n/**\n * 处理 /branch 命令,返回一段中文指令引导模型完成分支操作。\n */\nexport function handleBranchCommand(args: BranchCommandArgs): { instruction: string } {\n const { action = \"list\", name, base } = args;\n\n switch (action) {\n case \"list\":\n return { instruction: buildListInstruction() };\n case \"create\":\n return { instruction: buildCreateInstruction(name, base) };\n case \"switch\":\n return { instruction: buildSwitchInstruction(name) };\n case \"delete\":\n return { instruction: buildDeleteInstruction(name) };\n default:\n return {\n instruction: `未知操作:${action}。可选操作:list、create、switch、delete`,\n };\n }\n}\n\n// ── Instruction Builders ─────────────────────────────\n\n/** 构建列出分支的指令。 */\nfunction buildListInstruction(): string {\n const steps: string[] = [\n \"# Git 分支列表\",\n \"\",\n \"请执行以下步骤列出所有分支:\",\n \"\",\n \"1. 运行 `git branch -a` 列出所有本地和远程分支\",\n \"2. 运行 `git branch --show-current` 获取当前分支名\",\n \"3. 格式化输出:\",\n \" - 当前分支用 `*` 或特殊标记高亮显示\",\n \" - 本地分支和远程分支分组显示\",\n \" - 如果分支很多,可以只显示最近的活跃分支(用 `--sort=-committerdate` 排序并限制数量)\",\n \"4. 向用户展示格式化后的分支列表,清楚标明当前所在分支\",\n \"\",\n \"可选增强:\",\n \"- 运行 `git branch -v` 显示每个分支的最新提交摘要\",\n \"- 用表格形式展示,包含:分支名、最新提交、是否已合并到主分支\",\n ];\n\n return steps.join(\"\\n\");\n}\n\n/** 构建创建分支的指令。 */\nfunction buildCreateInstruction(name?: string, base?: string): string {\n if (!name || name.trim().length === 0) {\n return \"错误:创建分支需要指定分支名称。用法:/branch create <name> [base]\";\n }\n\n const baseRef = base && base.trim().length > 0 ? base.trim() : \"\";\n const baseDesc = baseRef ? `(基于 ${baseRef})` : \"(基于当前分支)\";\n\n const steps: string[] = [\n `# 创建 Git 分支:${name.trim()} ${baseDesc}`,\n \"\",\n \"请按以下步骤创建新分支:\",\n \"\",\n baseRef\n ? `1. 运行 \\`git checkout -b ${name.trim()} ${baseRef}\\` 创建并切换到新分支`\n : `1. 运行 \\`git checkout -b ${name.trim()}\\` 创建并切换到新分支`,\n \"2. 确认当前已切换到新分支:运行 `git branch --show-current`\",\n \"3. 向用户报告:已创建并切换到分支 `${name.trim()}`\",\n ];\n\n return steps.join(\"\\n\");\n}\n\n/** 构建切换分支的指令。 */\nfunction buildSwitchInstruction(name?: string): string {\n if (!name || name.trim().length === 0) {\n return \"错误:切换分支需要指定分支名称。用法:/branch switch <name>\";\n }\n\n const steps: string[] = [\n `# 切换到分支:${name.trim()}`,\n \"\",\n \"请按以下步骤切换分支:\",\n \"\",\n \"1. 先运行 `git status` 检查当前工作区是否有未提交的变更\",\n \"2. 如果有未提交变更:\",\n \" - 运行 `git stash` 暂存当前变更,或\",\n \" - 提示用户是否需要先提交或放弃变更\",\n `3. 运行 \\`git checkout ${name.trim()}\\`(或 \\`git switch ${name.trim()}\\`)切换到目标分支`,\n \"4. 运行 `git branch --show-current` 确认切换成功\",\n \"5. 如果之前有 stash,提示用户可用 `git stash pop` 恢复\",\n \"\",\n \"注意事项:\",\n \"- 如果分支不存在,检查远程分支:`git branch -r | grep ${name.trim()}`\",\n \"- 远程分支存在时,用 `git checkout -b ${name.trim()} origin/${name.trim()}` 创建本地跟踪分支\",\n ];\n\n return steps.join(\"\\n\");\n}\n\n/** 构建删除分支的指令。 */\nfunction buildDeleteInstruction(name?: string): string {\n if (!name || name.trim().length === 0) {\n return \"错误:删除分支需要指定分支名称。用法:/branch delete <name>\";\n }\n\n const steps: string[] = [\n `# 删除 Git 分支:${name.trim()}`,\n \"\",\n \"请按以下步骤删除分支:\",\n \"\",\n \"1. 先确认当前不在目标分支上(运行 `git branch --show-current`)\",\n \" - 如果当前在目标分支上,先切换到其他分支(如 master)\",\n `2. 运行 \\`git branch -d ${name.trim()}\\` 删除本地分支`,\n \"3. 如果提示「未合并」:\",\n \" - 警告用户该分支还有未合并的提交,列出未合并的提交\",\n \" - 询问用户确认后才使用 `git branch -D ${name.trim()}` 强制删除\",\n \"4. 删除成功后向用户报告\",\n \"\",\n \"注意事项:\",\n \"- 安全删除(-d)优先,只有用户明确确认后才用强制删除(-D)\",\n \"- 删除前展示该分支的最后 3 条提交记录,帮助用户确认\",\n \"- 如果有对应的远程分支,询问用户是否也需要删除:`git push origin --delete ${name.trim()}`\",\n ];\n\n return steps.join(\"\\n\");\n}\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"git-branch-Dn1CP6An.mjs","names":[],"sources":["../src/commands/git-branch.ts"],"sourcesContent":["/**\n * /branch 命令 — Git 分支管理。\n *\n * 生成中文指令,引导模型执行分支操作:\n * - list:列出所有分支并高亮当前分支\n * - create:从指定基准创建新分支\n * - switch:切换到指定分支\n * - delete:删除分支(未合并时警告)\n */\n\n// ── Types ────────────────────────────────────────────\n\n/** Arguments for /branch — action (list/create/switch/delete), branch name, and base ref. */\nexport interface BranchCommandArgs {\n /** 操作类型:列出 / 创建 / 切换 / 删除。默认为 list。 */\n action?: \"list\" | \"create\" | \"switch\" | \"delete\";\n /** 分支名称(create / switch / delete 时必填)。 */\n name?: string;\n /** 创建分支时的基准分支(仅 create 时有效)。 */\n base?: string;\n}\n\n// ── Public API ───────────────────────────────────────\n\n/**\n * 处理 /branch 命令,返回一段中文指令引导模型完成分支操作。\n */\nexport function handleBranchCommand(args: BranchCommandArgs): { instruction: string } {\n const { action = \"list\", name, base } = args;\n\n switch (action) {\n case \"list\":\n return { instruction: buildListInstruction() };\n case \"create\":\n return { instruction: buildCreateInstruction(name, base) };\n case \"switch\":\n return { instruction: buildSwitchInstruction(name) };\n case \"delete\":\n return { instruction: buildDeleteInstruction(name) };\n default:\n return {\n instruction: `未知操作:${action}。可选操作:list、create、switch、delete`,\n };\n }\n}\n\n// ── Instruction Builders ─────────────────────────────\n\n/** 构建列出分支的指令。 */\nfunction buildListInstruction(): string {\n const steps: string[] = [\n \"# Git 分支列表\",\n \"\",\n \"请执行以下步骤列出所有分支:\",\n \"\",\n \"1. 运行 `git branch -a` 列出所有本地和远程分支\",\n \"2. 运行 `git branch --show-current` 获取当前分支名\",\n \"3. 格式化输出:\",\n \" - 当前分支用 `*` 或特殊标记高亮显示\",\n \" - 本地分支和远程分支分组显示\",\n \" - 如果分支很多,可以只显示最近的活跃分支(用 `--sort=-committerdate` 排序并限制数量)\",\n \"4. 向用户展示格式化后的分支列表,清楚标明当前所在分支\",\n \"\",\n \"可选增强:\",\n \"- 运行 `git branch -v` 显示每个分支的最新提交摘要\",\n \"- 用表格形式展示,包含:分支名、最新提交、是否已合并到主分支\",\n ];\n\n return steps.join(\"\\n\");\n}\n\n/** 构建创建分支的指令。 */\nfunction buildCreateInstruction(name?: string, base?: string): string {\n if (!name || name.trim().length === 0) {\n return \"错误:创建分支需要指定分支名称。用法:/branch create <name> [base]\";\n }\n\n const baseRef = base && base.trim().length > 0 ? base.trim() : \"\";\n const baseDesc = baseRef ? `(基于 ${baseRef})` : \"(基于当前分支)\";\n\n const steps: string[] = [\n `# 创建 Git 分支:${name.trim()} ${baseDesc}`,\n \"\",\n \"请按以下步骤创建新分支:\",\n \"\",\n baseRef\n ? `1. 运行 \\`git checkout -b ${name.trim()} ${baseRef}\\` 创建并切换到新分支`\n : `1. 运行 \\`git checkout -b ${name.trim()}\\` 创建并切换到新分支`,\n \"2. 确认当前已切换到新分支:运行 `git branch --show-current`\",\n \"3. 向用户报告:已创建并切换到分支 `${name.trim()}`\",\n ];\n\n return steps.join(\"\\n\");\n}\n\n/** 构建切换分支的指令。 */\nfunction buildSwitchInstruction(name?: string): string {\n if (!name || name.trim().length === 0) {\n return \"错误:切换分支需要指定分支名称。用法:/branch switch <name>\";\n }\n\n const steps: string[] = [\n `# 切换到分支:${name.trim()}`,\n \"\",\n \"请按以下步骤切换分支:\",\n \"\",\n \"1. 先运行 `git status` 检查当前工作区是否有未提交的变更\",\n \"2. 如果有未提交变更:\",\n \" - 运行 `git stash` 暂存当前变更,或\",\n \" - 提示用户是否需要先提交或放弃变更\",\n `3. 运行 \\`git checkout ${name.trim()}\\`(或 \\`git switch ${name.trim()}\\`)切换到目标分支`,\n \"4. 运行 `git branch --show-current` 确认切换成功\",\n \"5. 如果之前有 stash,提示用户可用 `git stash pop` 恢复\",\n \"\",\n \"注意事项:\",\n \"- 如果分支不存在,检查远程分支:`git branch -r | grep ${name.trim()}`\",\n \"- 远程分支存在时,用 `git checkout -b ${name.trim()} origin/${name.trim()}` 创建本地跟踪分支\",\n ];\n\n return steps.join(\"\\n\");\n}\n\n/** 构建删除分支的指令。 */\nfunction buildDeleteInstruction(name?: string): string {\n if (!name || name.trim().length === 0) {\n return \"错误:删除分支需要指定分支名称。用法:/branch delete <name>\";\n }\n\n const steps: string[] = [\n `# 删除 Git 分支:${name.trim()}`,\n \"\",\n \"请按以下步骤删除分支:\",\n \"\",\n \"1. 先确认当前不在目标分支上(运行 `git branch --show-current`)\",\n \" - 如果当前在目标分支上,先切换到其他分支(如 master)\",\n `2. 运行 \\`git branch -d ${name.trim()}\\` 删除本地分支`,\n \"3. 如果提示「未合并」:\",\n \" - 警告用户该分支还有未合并的提交,列出未合并的提交\",\n \" - 询问用户确认后才使用 `git branch -D ${name.trim()}` 强制删除\",\n \"4. 删除成功后向用户报告\",\n \"\",\n \"注意事项:\",\n \"- 安全删除(-d)优先,只有用户明确确认后才用强制删除(-D)\",\n \"- 删除前展示该分支的最后 3 条提交记录,帮助用户确认\",\n \"- 如果有对应的远程分支,询问用户是否也需要删除:`git push origin --delete ${name.trim()}`\",\n ];\n\n return steps.join(\"\\n\");\n}\n"],"mappings":";;;;AA2BA,SAAgB,oBAAoB,MAAkD;CACpF,MAAM,EAAE,SAAS,QAAQ,MAAM,SAAS;CAExC,QAAQ,QAAR;EACE,KAAK,QACH,OAAO,EAAE,aAAa,qBAAqB,EAAE;EAC/C,KAAK,UACH,OAAO,EAAE,aAAa,uBAAuB,MAAM,IAAI,EAAE;EAC3D,KAAK,UACH,OAAO,EAAE,aAAa,uBAAuB,IAAI,EAAE;EACrD,KAAK,UACH,OAAO,EAAE,aAAa,uBAAuB,IAAI,EAAE;EACrD,SACE,OAAO,EACL,aAAa,QAAQ,OAAO,iCAC9B;CACJ;AACF;;AAKA,SAAS,uBAA+B;CAmBtC,OAAO;EAjBL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAGS,CAAC,CAAC,KAAK,IAAI;AACxB;;AAGA,SAAS,uBAAuB,MAAe,MAAuB;CACpE,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,WAAW,GAClC,OAAO;CAGT,MAAM,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI;CAC/D,MAAM,WAAW,UAAU,OAAO,QAAQ,KAAK;CAc/C,OAAO;EAXL,eAAe,KAAK,KAAK,EAAE,GAAG;EAC9B;EACA;EACA;EACA,UACI,2BAA2B,KAAK,KAAK,EAAE,GAAG,QAAQ,gBAClD,2BAA2B,KAAK,KAAK,EAAE;EAC3C;EACA;CAGS,CAAC,CAAC,KAAK,IAAI;AACxB;;AAGA,SAAS,uBAAuB,MAAuB;CACrD,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,WAAW,GAClC,OAAO;CAqBT,OAAO;EAjBL,WAAW,KAAK,KAAK;EACrB;EACA;EACA;EACA;EACA;EACA;EACA;EACA,wBAAwB,KAAK,KAAK,EAAE,oBAAoB,KAAK,KAAK,EAAE;EACpE;EACA;EACA;EACA;EACA;EACA;CAGS,CAAC,CAAC,KAAK,IAAI;AACxB;;AAGA,SAAS,uBAAuB,MAAuB;CACrD,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,WAAW,GAClC,OAAO;CAsBT,OAAO;EAlBL,eAAe,KAAK,KAAK;EACzB;EACA;EACA;EACA;EACA;EACA,yBAAyB,KAAK,KAAK,EAAE;EACrC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAGS,CAAC,CAAC,KAAK,IAAI;AACxB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as runPhase2WithContext, f as bootstrap, t as installProcessLifecycle } from "./process-lifecycle-
|
|
2
|
-
import { i as resolveProvider, n as loadConfig, r as resolveConfigEnv } from "./config-
|
|
1
|
+
import { d as runPhase2WithContext, f as bootstrap, t as installProcessLifecycle } from "./process-lifecycle-Xy1A3HFe.mjs";
|
|
2
|
+
import { i as resolveProvider, n as loadConfig, r as resolveConfigEnv } from "./config-B-iYJluO.mjs";
|
|
3
3
|
import { asMessageId, resolvePaths } from "@24klynx/core";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import "node:os";
|
|
@@ -168,4 +168,4 @@ async function startHeadless(config = {}) {
|
|
|
168
168
|
//#endregion
|
|
169
169
|
export { startHeadless };
|
|
170
170
|
|
|
171
|
-
//# sourceMappingURL=headless-launcher-
|
|
171
|
+
//# sourceMappingURL=headless-launcher-faY5GV9T.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-launcher-faY5GV9T.mjs","names":[],"sources":["../src/headless-launcher.ts"],"sourcesContent":["/**\n * headless-launcher — non-interactive mode for Lynx.\n *\n * Used when `lynx start --headless` is invoked. Starts the agent engine\n * and optionally a messaging channel (飞书 etc.) for remote interaction.\n * No TUI is rendered — all I/O goes through the channel adapter.\n *\n * Responsibility:\n * 1. Bootstrap the application (same as tui-launcher)\n * 2. Register channel adapters (飞书 etc.)\n * 3. Process incoming messages through the engine\n * 4. Stream responses back through the channel\n */\n\nimport { resolvePaths, asMessageId } from \"@24klynx/core\";\nimport { loadConfig, resolveConfigEnv, resolveProvider } from \"./commands/config.js\";\nimport { bootstrap } from \"./bootstrap.js\";\nimport { runPhase2WithContext } from \"./startup.js\";\nimport { installProcessLifecycle } from \"./process-lifecycle.js\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { homedir } from \"node:os\";\n\n// ── Types ────────────────────────────────────────────\n\n/** Non-interactive CLI configuration — model override, verbosity, and channel config. */\nexport interface HeadlessConfig {\n /** Model to use (overrides LYNX_MODEL env var). */\n model?: string;\n /** Enable verbose logging. */\n verbose?: boolean;\n /** 飞书 channel configuration. */\n feishu?: { appId: string; appSecret: string };\n}\n\n// ── Public API ───────────────────────────────────────\n\n/**\n * Start Lynx in headless (non-interactive) mode.\n *\n * If a 飞书 configuration is provided, the agent listens for\n * incoming messages from the 飞书 channel and responds via\n * the same channel. Otherwise, runs a simple REPL on stdin/stdout.\n */\nexport async function startHeadless(config: HeadlessConfig = {}): Promise<void> {\n const paths = resolvePaths();\n\n // 加载配置 → 注入 env → 按模型名自动选 Provider\n const appConfig = loadConfig();\n resolveConfigEnv(appConfig);\n const provider = resolveProvider(appConfig);\n\n // Resolve built‑in skills directory relative to the lynx-agent package\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const builtinSkillsDir = join(__dirname, \"..\", \"..\", \"lynx-agent\", \"skills\");\n\n const ctx = bootstrap({\n homeDir: paths.home,\n provider,\n model: config.model ?? process.env.LYNX_MODEL ?? appConfig.model,\n skillsDir: builtinSkillsDir,\n workspace: process.cwd(),\n feishu: config.feishu,\n });\n\n const sessions = ctx.sessionMgr.list();\n const activeSession =\n sessions.length > 0 ? sessions[0]! : ctx.sessionMgr.create(\"default\", process.cwd());\n\n // ── Abort layer state ────────────────────────────\n let abortLayer = 0;\n let isStreaming = false;\n\n const getAbortLayer = () => abortLayer;\n const incrementAbortLayer = () => {\n abortLayer++;\n return abortLayer;\n };\n const resetAbortLayer = () => {\n abortLayer = 0;\n };\n\n // ── Process lifecycle ───────────────────────────\n installProcessLifecycle({\n ctx,\n onAbortLl: () => ctx.engine.abort(),\n onAbortTool: () => ctx.engine.abort(),\n getAbortLayer,\n incrementAbortLayer,\n resetAbortLayer,\n isStreaming: () => isStreaming,\n });\n\n // ── Phase 2: background tasks ───────────────────\n runPhase2WithContext(ctx, paths).catch(() => {\n // Errors are already logged by the task runner\n });\n\n // ── Message handler (shared across all channels) ─\n async function processMessage(msg: { text: string }): Promise<string> {\n isStreaming = true;\n resetAbortLayer();\n\n const userMsg = {\n id: asMessageId(crypto.randomUUID()),\n role: \"user\" as const,\n content: [{ type: \"text\" as const, text: msg.text }],\n timestamp: Date.now(),\n turnIndex: activeSession.messages.length,\n };\n\n // Add user message to the session\n activeSession.messages.push(userMsg);\n\n const controller = new AbortController();\n let responseText = \"\";\n\n try {\n for await (const event of ctx.engine.submit(activeSession, userMsg, controller.signal)) {\n switch (event.type) {\n case \"text_delta\":\n responseText += event.text;\n break;\n case \"reasoning_delta\":\n // Reasoning tokens — skip in headless mode (not sent to channel)\n break;\n case \"tool_use_start\":\n if (config.verbose) {\n process.stderr.write(`[headless] Tool call: ${event.name}\\n`);\n }\n break;\n case \"tool_result\":\n if (config.verbose) {\n const truncated =\n event.content.length > 200 ? event.content.slice(0, 200) + \"...\" : event.content;\n process.stderr.write(`[headless] Tool result: ${truncated}\\n`);\n }\n break;\n case \"error\":\n responseText += `\\nError: ${event.message}`;\n break;\n case \"done\":\n break;\n }\n }\n } catch (err) {\n responseText += `\\nError: ${err instanceof Error ? err.message : String(err)}`;\n } finally {\n isStreaming = false;\n }\n\n // Add assistant response to the session\n if (responseText) {\n const reply = {\n id: asMessageId(crypto.randomUUID()),\n role: \"assistant\" as const,\n content: [{ type: \"text\" as const, text: responseText }],\n timestamp: Date.now(),\n turnIndex: activeSession.messages.length,\n };\n activeSession.messages.push(reply);\n }\n\n return responseText;\n }\n\n // ── Channel or stdin mode ───────────────────────\n const channelIds = ctx.channelRegistry.list();\n\n if (channelIds.length > 0) {\n // Channel mode — use the first registered channel for I/O.\n // The registry wires each adapter's onMessage() to the centralized handler.\n // Since Message doesn't carry a channelId, we get the adapter directly\n // and bypass the centralized handler for request/response pairing.\n process.stderr.write(`[headless] Listening on channels: ${channelIds.join(\", \")}\\n`);\n\n const primaryChannelId = channelIds[0]!;\n const adapter = ctx.channelRegistry.get(primaryChannelId);\n\n if (!adapter) {\n process.stderr.write(`[headless] Channel \"${primaryChannelId}\" not found\\n`);\n process.exitCode = 1;\n return;\n }\n\n // Listen for incoming messages on the primary channel\n adapter.onMessage((msg) => {\n const textContent = msg.content\n .filter((c) => c.type === \"text\")\n .map((c) => (c as { text: string }).text)\n .join(\"\\n\");\n\n if (!textContent) return;\n\n processMessage({ text: textContent })\n .then(async (replyText) => {\n if (replyText) {\n const replyMsg = {\n id: asMessageId(crypto.randomUUID()),\n role: \"assistant\" as const,\n content: [{ type: \"text\" as const, text: replyText }],\n timestamp: Date.now(),\n turnIndex: activeSession.messages.length,\n };\n await adapter.sendMessage(replyMsg);\n }\n })\n .catch((err) => {\n process.stderr.write(\n `[headless] Channel message processing failed: ` +\n `${err instanceof Error ? err.message : String(err)}\\n`,\n );\n });\n });\n\n // Keep process alive — channels run indefinitely\n await new Promise<void>(() => {\n // Never resolves — process runs until SIGTERM/SIGINT\n });\n } else {\n // Stdin mode — read one message and respond\n process.stderr.write(\"[headless] No channels configured — stdin mode\\n\");\n process.stderr.write(\"[headless] Enter your message (Ctrl+D to end):\\n\");\n\n const chunks: string[] = [];\n process.stdin.setEncoding(\"utf-8\");\n\n for await (const chunk of process.stdin) {\n chunks.push(chunk as string);\n }\n\n const text = chunks.join(\"\").trim();\n if (!text) {\n process.stderr.write(\"[headless] Empty input — exiting\\n\");\n process.exitCode = 1;\n return;\n }\n\n const replyText = await processMessage({ text });\n process.stdout.write(replyText + \"\\n\");\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -34,6 +34,7 @@ interface PermissionBridge {
|
|
|
34
34
|
safety: "Safe" | "WorkspaceSafe" | "RequiresApproval" | "Dangerous";
|
|
35
35
|
}) => void) | null): void;
|
|
36
36
|
}
|
|
37
|
+
/** Assembled application context — all singletons and services after Phase 1 + Phase 2 boot. */
|
|
37
38
|
interface AppContext {
|
|
38
39
|
db: Database;
|
|
39
40
|
sessionMgr: SessionManager;
|
|
@@ -69,6 +70,7 @@ interface AppContext {
|
|
|
69
70
|
/** Destroy all resources (close DB, stop timers, etc.). */
|
|
70
71
|
destroy(): void;
|
|
71
72
|
}
|
|
73
|
+
/** Bootstrap configuration — the minimal inputs needed to assemble the full AppContext. */
|
|
72
74
|
interface BootstrapConfig {
|
|
73
75
|
homeDir: string;
|
|
74
76
|
provider: LlmProvider;
|
|
@@ -98,12 +100,14 @@ declare function createProgram(): Command;
|
|
|
98
100
|
declare function runCli(argv?: string[]): Promise<void>;
|
|
99
101
|
//#endregion
|
|
100
102
|
//#region src/startup.d.ts
|
|
103
|
+
/** Phase 1 blocking result — paths, open database handle, and resolved config for immediate use. */
|
|
101
104
|
interface Phase1Result {
|
|
102
105
|
paths: LynxPaths;
|
|
103
106
|
db: Database;
|
|
104
107
|
/** Wall‑clock ms for Phase 1. */
|
|
105
108
|
elapsedMs: number;
|
|
106
109
|
}
|
|
110
|
+
/** Full startup result — Phase 1 state plus assembled AppContext and Phase 2 task outcomes. */
|
|
107
111
|
interface StartupResult extends Phase1Result {
|
|
108
112
|
/** Wall‑clock ms for Phase 2. */
|
|
109
113
|
phase2ElapsedMs: number;
|
|
@@ -142,6 +146,7 @@ declare function runPhase2(result: Phase1Result): Promise<Phase2TaskResult[]>;
|
|
|
142
146
|
* of policies that control how the agent behaves while executing
|
|
143
147
|
* that command.
|
|
144
148
|
*/
|
|
149
|
+
/** Per-command execution policy — permission mode, tool whitelist, and write access control. */
|
|
145
150
|
interface CommandPolicy {
|
|
146
151
|
/** Permission mode for this command. */
|
|
147
152
|
permissionMode: "default" | "auto" | "yolo" | "headless" | "plan";
|
|
@@ -150,6 +155,7 @@ interface CommandPolicy {
|
|
|
150
155
|
/** Can this command modify files? */
|
|
151
156
|
allowWrites: boolean;
|
|
152
157
|
}
|
|
158
|
+
/** Registered command entry — name, description, execution policy, and lazy-loaded handler path. */
|
|
153
159
|
interface CommandEntry {
|
|
154
160
|
name: string;
|
|
155
161
|
description: string;
|
|
@@ -170,7 +176,9 @@ declare function findCommand(name: string): CommandEntry | undefined;
|
|
|
170
176
|
* Uses pino for formatting and rotation. Production logs are
|
|
171
177
|
* JSONL with daily rotation; development uses pino‑pretty.
|
|
172
178
|
*/
|
|
179
|
+
/** Valid log levels for the debug logger — pino-compatible severity ordering. */
|
|
173
180
|
type LogLevel = "trace" | "debug" | "info" | "warn" | "error";
|
|
181
|
+
/** Structured debug logger interface — JSONL output with five severity levels. */
|
|
174
182
|
interface DebugLogger {
|
|
175
183
|
trace(msg: string, data?: unknown): void;
|
|
176
184
|
debug(msg: string, data?: unknown): void;
|
|
@@ -193,11 +201,13 @@ declare function createDebugLogger(logDir: string, minLevel?: LogLevel): DebugLo
|
|
|
193
201
|
* Runs a series of diagnostic checks and prints a report.
|
|
194
202
|
* Each check returns pass/fail with an optional detail message.
|
|
195
203
|
*/
|
|
204
|
+
/** A single diagnostic check result — name, pass/fail status, and optional detail text. */
|
|
196
205
|
interface CheckResult {
|
|
197
206
|
name: string;
|
|
198
207
|
passed: boolean;
|
|
199
208
|
detail?: string;
|
|
200
209
|
}
|
|
210
|
+
/** Complete diagnostic report — a list of checks plus an all-passed aggregate. */
|
|
201
211
|
interface DoctorReport {
|
|
202
212
|
checks: CheckResult[];
|
|
203
213
|
allPassed: boolean;
|
|
@@ -234,6 +244,7 @@ declare function runCrestodian(message: string, _model?: string): Promise<void>;
|
|
|
234
244
|
* Uses SessionManager for persistence and SessionPicker for
|
|
235
245
|
* interactive selection when no ID is provided.
|
|
236
246
|
*/
|
|
247
|
+
/** Options for the session command — action (list/resume/fork/delete), optional session ID, and optional label. */
|
|
237
248
|
interface SessionCommandOptions {
|
|
238
249
|
action: string;
|
|
239
250
|
id?: string;
|
|
@@ -243,6 +254,7 @@ interface SessionCommandOptions {
|
|
|
243
254
|
declare function handleSessionCommand(opts: SessionCommandOptions): Promise<void>;
|
|
244
255
|
//#endregion
|
|
245
256
|
//#region src/commands/config.d.ts
|
|
257
|
+
/** Options for the config command — get/set/list/import configuration values. */
|
|
246
258
|
interface ConfigCommandOptions {
|
|
247
259
|
show?: boolean;
|
|
248
260
|
set?: string;
|
|
@@ -285,6 +297,7 @@ declare function main(argv?: string[]): Promise<void>;
|
|
|
285
297
|
declare function launchTui(): Promise<void>;
|
|
286
298
|
//#endregion
|
|
287
299
|
//#region src/process-lifecycle.d.ts
|
|
300
|
+
/** Configuration for graceful shutdown — context, abort callbacks, and signal handlers. */
|
|
288
301
|
interface LifecycleConfig {
|
|
289
302
|
/** AppContext for graceful cleanup. */
|
|
290
303
|
ctx: AppContext;
|
|
@@ -334,7 +347,9 @@ declare function uninstallProcessLifecycle(): void;
|
|
|
334
347
|
declare function enterFullscreen(): void;
|
|
335
348
|
/** Exit fullscreen mode: restore main buffer. */
|
|
336
349
|
declare function exitFullscreen(): void;
|
|
350
|
+
/** Enter synchronous terminal mode — flushes stdout and begins screen sync protocol (DCS). */
|
|
337
351
|
declare function beginSync(): void;
|
|
352
|
+
/** Exit synchronous terminal mode — ends the screen sync protocol and restores normal output. */
|
|
338
353
|
declare function endSync(): void;
|
|
339
354
|
/**
|
|
340
355
|
* Execute a callback within a DEC synchronized update region.
|
|
@@ -487,6 +502,7 @@ interface MemorySnapshot {
|
|
|
487
502
|
* monitor.start();
|
|
488
503
|
* ```
|
|
489
504
|
*/
|
|
505
|
+
/** Periodically samples heap usage and emits alerts at warning/threshold/fatal levels. */
|
|
490
506
|
declare class MemoryMonitor extends EventEmitter {
|
|
491
507
|
private config;
|
|
492
508
|
private timer;
|
|
@@ -600,6 +616,7 @@ declare function clearUpdateCache(): void;
|
|
|
600
616
|
* install <path> — install a plugin from a local path
|
|
601
617
|
* remove <name> — uninstall a plugin
|
|
602
618
|
*/
|
|
619
|
+
/** Options for the plugin command — list/enable/disable/install/remove sub-commands. */
|
|
603
620
|
interface PluginCommandOptions {
|
|
604
621
|
list?: boolean;
|
|
605
622
|
enable?: string;
|
|
@@ -620,6 +637,7 @@ declare function handlePluginCommand(opts: PluginCommandOptions): Promise<void>;
|
|
|
620
637
|
* 3. git add → git commit → git push
|
|
621
638
|
* 4. --all 标志表示暂存所有变更
|
|
622
639
|
*/
|
|
640
|
+
/** Arguments for /commit — custom message and --all flag for staging all changes. */
|
|
623
641
|
interface CommitCommandArgs {
|
|
624
642
|
/** 用户自定义的提交消息(可选,省略时自动生成)。 */
|
|
625
643
|
message?: string;
|
|
@@ -643,6 +661,7 @@ declare function handleCommitCommand(args: CommitCommandArgs): {
|
|
|
643
661
|
* 3. 系统化分析:bug、风格、测试、安全
|
|
644
662
|
* 4. 输出结构化审查报告
|
|
645
663
|
*/
|
|
664
|
+
/** Arguments for /review — optional PR number and target base branch filter. */
|
|
646
665
|
interface ReviewCommandArgs {
|
|
647
666
|
/** PR 编号(可选,省略时列出所有待审查的 PR)。 */
|
|
648
667
|
number?: number;
|
|
@@ -665,6 +684,7 @@ declare function handleReviewCommand(args: ReviewCommandArgs): {
|
|
|
665
684
|
* 2. 处理未解决的评论(修改代码)
|
|
666
685
|
* 3. 回复已解决的评论(确认)
|
|
667
686
|
*/
|
|
687
|
+
/** Arguments for /pr-comments — optional PR number for fetching review comments. */
|
|
668
688
|
interface PrCommentsCommandArgs {
|
|
669
689
|
/** PR 编号(可选,省略时从最近 PR 推断)。 */
|
|
670
690
|
number?: number;
|
|
@@ -685,6 +705,7 @@ declare function handlePrCommentsCommand(args: PrCommentsCommandArgs): {
|
|
|
685
705
|
* list — 列出仓库 Issue
|
|
686
706
|
* view — 查看指定 Issue 详情
|
|
687
707
|
*/
|
|
708
|
+
/** Arguments for /issue — action (create/list/view), title, and issue number. */
|
|
688
709
|
interface IssueCommandArgs {
|
|
689
710
|
/** 操作类型:create 创建、list 列出、view 查看。 */
|
|
690
711
|
action?: "create" | "list" | "view";
|
|
@@ -732,6 +753,7 @@ declare function handleAutoFixCommand(_args: AutoFixCommandArgs): {
|
|
|
732
753
|
* 2. 运行 git diff --staged 获取已暂存变更
|
|
733
754
|
* 3. 以结构化格式展示,高亮关键变更
|
|
734
755
|
*/
|
|
756
|
+
/** Arguments for /diff — optional staged-only flag and file filter list. */
|
|
735
757
|
interface DiffCommandArgs {
|
|
736
758
|
/** 是否仅显示已暂存的变更(git diff --staged)。 */
|
|
737
759
|
staged?: boolean;
|
|
@@ -754,6 +776,7 @@ declare function handleDiffCommand(args: DiffCommandArgs): {
|
|
|
754
776
|
*
|
|
755
777
|
* 用法:/ant-trace [--session <id>] 默认追踪当前会话。
|
|
756
778
|
*/
|
|
779
|
+
/** Options for the /ant-trace command — optional session ID to trace tool call chains. */
|
|
757
780
|
interface AntTraceOptions {
|
|
758
781
|
/** 可选:要追踪的会话 ID,默认当前会话。 */
|
|
759
782
|
sessionId?: string;
|
|
@@ -780,6 +803,7 @@ declare function handleAntTraceCommand(opts: AntTraceOptions): {
|
|
|
780
803
|
* /debug-tool-call --tool <name> 查看指定工具的最后一次调用
|
|
781
804
|
* /debug-tool-call --step <index> 查看指定步骤索引处的工具调用
|
|
782
805
|
*/
|
|
806
|
+
/** Options for /debug-tool-call — filter by tool name or step index for single-step debugging. */
|
|
783
807
|
interface DebugToolCallOptions {
|
|
784
808
|
/** 按工具名称过滤,查看该工具的最后一次调用详情。 */
|
|
785
809
|
tool?: string;
|
|
@@ -811,6 +835,7 @@ declare function handleDebugToolCall(opts: DebugToolCallOptions): {
|
|
|
811
835
|
* /tasks --action cancel --taskId <id> 取消任务
|
|
812
836
|
* /tasks --action detail --taskId <id> 查看任务详情
|
|
813
837
|
*/
|
|
838
|
+
/** Options for /tasks — action (list/cancel/detail) and optional task ID for background task monitoring. */
|
|
814
839
|
interface TasksCommandOptions {
|
|
815
840
|
/** 操作类型:list(默认)、cancel、detail。 */
|
|
816
841
|
action?: string;
|
|
@@ -858,6 +883,7 @@ declare function handleHeapdumpCommand(): Promise<{
|
|
|
858
883
|
* /perf-issue 通用性能健康检查
|
|
859
884
|
* /perf-issue --issue <描述> 针对具体问题的诊断
|
|
860
885
|
*/
|
|
886
|
+
/** Options for /perf-issue — optional issue description for targeted performance diagnosis. */
|
|
861
887
|
interface PerfIssueOptions {
|
|
862
888
|
/** 可选:用户描述的具体性能问题。不提供则执行通用健康检查。 */
|
|
863
889
|
issue?: string;
|
|
@@ -878,6 +904,7 @@ declare function handlePerfIssueCommand(opts: PerfIssueOptions): {
|
|
|
878
904
|
* 从 ~/.lynx/sessions/{sessionId}.json 读取消息,
|
|
879
905
|
* 格式化为干净的 Markdown 后写入 ~/.lynx/exports/ 目录。
|
|
880
906
|
*/
|
|
907
|
+
/** Options for /share — optional session ID and output file path for exporting to Markdown. */
|
|
881
908
|
interface ShareCommandOptions {
|
|
882
909
|
sessionId?: string;
|
|
883
910
|
output?: string;
|
|
@@ -901,6 +928,7 @@ declare function handleShareCommand(opts: ShareCommandOptions): Promise<{
|
|
|
901
928
|
* - json:导出原始消息数组(格式化 JSON)
|
|
902
929
|
* - html:将 Markdown 包裹在基础 HTML 模板中
|
|
903
930
|
*/
|
|
931
|
+
/** Options for /export — session ID, output format (markdown/json/html), and output path. */
|
|
904
932
|
interface ExportCommandOptions {
|
|
905
933
|
sessionId?: string;
|
|
906
934
|
format?: "markdown" | "json" | "html";
|
|
@@ -926,6 +954,7 @@ declare function handleExportCommand(opts: ExportCommandOptions): Promise<{
|
|
|
926
954
|
* - remove:移除指定标签
|
|
927
955
|
* - list:列出所有带标签的会话,或指定会话的所有标签
|
|
928
956
|
*/
|
|
957
|
+
/** Options for /tag — session ID, tag name, and action (add/remove/list) for session categorization. */
|
|
929
958
|
interface TagCommandOptions {
|
|
930
959
|
sessionId?: string;
|
|
931
960
|
tag?: string;
|
|
@@ -951,6 +980,7 @@ declare function handleTagCommand(opts: TagCommandOptions): Promise<{
|
|
|
951
980
|
* 支持平台:Windows(PowerShell)、macOS(pbcopy)、
|
|
952
981
|
* Linux(xclip 或 wl-copy)。
|
|
953
982
|
*/
|
|
983
|
+
/** Options for /copy — session ID and message index (counting from the end). */
|
|
954
984
|
interface CopyCommandOptions {
|
|
955
985
|
sessionId?: string;
|
|
956
986
|
/** 从末尾倒数第几条消息(0 = 最后一条,默认 0)。 */
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/bootstrap.ts","../src/args.ts","../src/startup.ts","../src/catalog.ts","../src/debug.ts","../src/doctor/runner.ts","../src/crestodian/runner.ts","../src/commands/session.ts","../src/commands/config.ts","../src/entry.ts","../src/tui-launcher.ts","../src/process-lifecycle.ts","../src/terminal-mode.ts","../src/worker-pool.ts","../src/memory-monitor.ts","../src/update-check.ts","../src/commands/plugin.ts","../src/commands/git-commit.ts","../src/commands/git-review.ts","../src/commands/git-pr-comments.ts","../src/commands/git-issue.ts","../src/commands/git-autofix.ts","../src/commands/git-diff.ts","../src/commands/ant-trace.ts","../src/commands/debug-tool-call.ts","../src/commands/tasks.ts","../src/commands/heapdump.ts","../src/commands/perf-issue.ts","../src/commands/share.ts","../src/commands/export.ts","../src/commands/tag.ts","../src/commands/copy.ts"],"mappings":";;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/bootstrap.ts","../src/args.ts","../src/startup.ts","../src/catalog.ts","../src/debug.ts","../src/doctor/runner.ts","../src/crestodian/runner.ts","../src/commands/session.ts","../src/commands/config.ts","../src/entry.ts","../src/tui-launcher.ts","../src/process-lifecycle.ts","../src/terminal-mode.ts","../src/worker-pool.ts","../src/memory-monitor.ts","../src/update-check.ts","../src/commands/plugin.ts","../src/commands/git-commit.ts","../src/commands/git-review.ts","../src/commands/git-pr-comments.ts","../src/commands/git-issue.ts","../src/commands/git-autofix.ts","../src/commands/git-diff.ts","../src/commands/ant-trace.ts","../src/commands/debug-tool-call.ts","../src/commands/tasks.ts","../src/commands/heapdump.ts","../src/commands/perf-issue.ts","../src/commands/share.ts","../src/commands/export.ts","../src/commands/tag.ts","../src/commands/copy.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as endSync, c as withSync, d as runPhase2WithContext, f as bootstrap, i as beginSync, l as runPhase1, n as onCleanup, o as enterFullscreen, r as uninstallProcessLifecycle, s as exitFullscreen, t as installProcessLifecycle, u as runPhase2 } from "./process-lifecycle-
|
|
2
|
-
import { a as saveConfig, i as resolveProvider, n as loadConfig, r as resolveConfigEnv, t as handleConfigCommand } from "./config-
|
|
1
|
+
import { a as endSync, c as withSync, d as runPhase2WithContext, f as bootstrap, i as beginSync, l as runPhase1, n as onCleanup, o as enterFullscreen, r as uninstallProcessLifecycle, s as exitFullscreen, t as installProcessLifecycle, u as runPhase2 } from "./process-lifecycle-Xy1A3HFe.mjs";
|
|
2
|
+
import { a as saveConfig, i as resolveProvider, n as loadConfig, r as resolveConfigEnv, t as handleConfigCommand } from "./config-B-iYJluO.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { asSessionId, migrate, openDatabase, resolvePaths } from "@24klynx/core";
|
|
5
5
|
import { createSessionManager, getLastSession } from "@24klynx/session";
|
|
@@ -38,8 +38,8 @@ var args_exports = /* @__PURE__ */ __exportAll({
|
|
|
38
38
|
createProgram: () => createProgram,
|
|
39
39
|
runCli: () => runCli
|
|
40
40
|
});
|
|
41
|
-
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
42
|
-
const version = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
41
|
+
const pkgPath$1 = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
42
|
+
const version = JSON.parse(readFileSync(pkgPath$1, "utf-8")).version;
|
|
43
43
|
/** Create the full CLI program with all sub‑commands registered. */
|
|
44
44
|
function createProgram() {
|
|
45
45
|
const program = new Command();
|
|
@@ -57,7 +57,7 @@ function createProgram() {
|
|
|
57
57
|
await handleSessionCommand(opts);
|
|
58
58
|
});
|
|
59
59
|
program.command("config").description("显示或设置配置项").option("--show", "Show current configuration").option("--set <key>", "Set a configuration key").option("--value <value>", "Value for --set").option("--path", "Show config file path").action(async (opts) => {
|
|
60
|
-
const { handleConfigCommand } = await import("./config-
|
|
60
|
+
const { handleConfigCommand } = await import("./config-C6StrUyB.mjs");
|
|
61
61
|
await handleConfigCommand(opts);
|
|
62
62
|
});
|
|
63
63
|
program.command("start").description("以无头后台模式启动(无 TUI)").option("--headless", "以无头模式运行(守护进程模式必需)").option("--feishu-app-id <id>", "飞书 App ID(覆盖 FEISHU_APP_ID 环境变量)").option("--feishu-app-secret <secret>", "飞书 App Secret(覆盖 FEISHU_APP_SECRET 环境变量)").option("--model <model>", "要使用的模型").option("--verbose", "启用详细日志").action(async (opts) => {
|
|
@@ -67,7 +67,7 @@ function createProgram() {
|
|
|
67
67
|
process.exitCode = 1;
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
const { startHeadless } = await import("./headless-launcher-
|
|
70
|
+
const { startHeadless } = await import("./headless-launcher-faY5GV9T.mjs");
|
|
71
71
|
const feishu = opts.feishuAppId && opts.feishuAppSecret ? {
|
|
72
72
|
appId: opts.feishuAppId,
|
|
73
73
|
appSecret: opts.feishuAppSecret
|
|
@@ -747,7 +747,7 @@ async function runCrestodian(message, _model) {
|
|
|
747
747
|
}];
|
|
748
748
|
const controller = new AbortController();
|
|
749
749
|
try {
|
|
750
|
-
const stream = provider.stream(
|
|
750
|
+
const stream = provider.stream(config.model, messages, systemPrompt, [], controller.signal);
|
|
751
751
|
for await (const event of stream) if (event.type === "text_delta") process.stdout.write(event.text);
|
|
752
752
|
process.stdout.write("\n");
|
|
753
753
|
} catch (err) {
|
|
@@ -908,6 +908,7 @@ const DEFAULT_FATAL_MB = 950;
|
|
|
908
908
|
* monitor.start();
|
|
909
909
|
* ```
|
|
910
910
|
*/
|
|
911
|
+
/** Periodically samples heap usage and emits alerts at warning/threshold/fatal levels. */
|
|
911
912
|
var MemoryMonitor = class extends EventEmitter {
|
|
912
913
|
config;
|
|
913
914
|
timer = null;
|
|
@@ -1336,6 +1337,8 @@ function createSnapshotStore(snapshotsDir) {
|
|
|
1336
1337
|
* interactive mode (no sub‑command given).
|
|
1337
1338
|
*/
|
|
1338
1339
|
var tui_launcher_exports = /* @__PURE__ */ __exportAll({ launchTui: () => launchTui });
|
|
1340
|
+
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
1341
|
+
const currentVersion = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
1339
1342
|
/** Approximate USD per 1M input tokens. */
|
|
1340
1343
|
const INPUT_PRICE_PER_1M = {
|
|
1341
1344
|
"deepseek-chat": .27,
|
|
@@ -1729,6 +1732,7 @@ async function launchTui() {
|
|
|
1729
1732
|
currentModel: ctx.agentConfig.model,
|
|
1730
1733
|
columns: process.stdout.columns ?? 80,
|
|
1731
1734
|
rows: process.stdout.rows ?? 24,
|
|
1735
|
+
version: currentVersion,
|
|
1732
1736
|
showWelcome: true,
|
|
1733
1737
|
onPermissionReady: (handler) => {
|
|
1734
1738
|
ctx.permissionBridge.setTuiHandler(handler);
|
|
@@ -1756,7 +1760,7 @@ async function launchTui() {
|
|
|
1756
1760
|
process.stderr.write(`[lynx] Memory ${alert.level}: ${Math.round(alert.heapUsed / 1024 / 1024)}MB (${alert.percentage}% of threshold)\n`);
|
|
1757
1761
|
});
|
|
1758
1762
|
memoryMonitor.start();
|
|
1759
|
-
checkForUpdates({ currentVersion
|
|
1763
|
+
checkForUpdates({ currentVersion }).then((result) => {
|
|
1760
1764
|
if (result.hasUpdate) process.stderr.write(`[lynx] Update available: ${result.current} → ${result.latest} (${result.releaseUrl})\n`);
|
|
1761
1765
|
}).catch(() => {});
|
|
1762
1766
|
await waitUntilExit();
|