@ia-ccun/code-agent-cli 0.0.54-beta.1 → 0.0.54-beta.4
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/bin/cli.js +116 -74
- package/config/agent/extensions/aicode-advisor.ts +187 -64
- package/config/agent/extensions/aicode-banner.ts +101 -0
- package/config/agent/extensions/aicode-btw.ts +619 -182
- package/config/agent/extensions/aicode-cd.ts +246 -63
- package/config/agent/extensions/aicode-pets.ts +0 -11
- package/config/agent/extensions/aicode-plan.ts +2 -0
- package/config/agent/extensions/aicode-safety-guard.ts +3 -0
- package/config/agent/extensions/aicode-tips.ts +1 -16
- package/config/agent/extensions/context-monitor.ts +30 -15
- package/config/agent/extensions/context.ts +132 -60
- package/config/agent/extensions/custom-footer.ts +42 -24
- package/config/agent/extensions/custom.ts +41 -29
- package/config/agent/extensions/error-monitor.ts +37 -33
- package/config/agent/extensions/goal.ts +8 -6
- package/config/agent/extensions/msg-debug.ts +103 -112
- package/config/agent/extensions/review.ts +365 -164
- package/config/agent/extensions/working-msg.ts +2 -4
- package/config/agent/settings.json +15 -14
- package/config/agent/skills/hello/SKILL.md +1 -1
- package/config/agent/skills/refactor/SKILL.md +40 -0
- package/dist/banner.d.ts.map +1 -1
- package/dist/banner.js +8 -1
- package/dist/banner.js.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +9 -2
- package/dist/config-loader.js.map +1 -1
- package/package.json +6 -7
- package/scripts/regression/README.md +224 -0
- package/scripts/regression/cases/01-version-and-deps.sh +94 -0
- package/scripts/regression/cases/02-extension-loading.sh +130 -0
- package/scripts/regression/cases/03-rpc-protocol.sh +259 -0
- package/scripts/regression/cases/04-prompt-stream.sh +130 -0
- package/scripts/regression/cases/05-slash-commands-and-skills.sh +119 -0
- package/scripts/regression/cases/06-tool-execution.sh +115 -0
- package/scripts/regression/cases/07-pi-new-features.sh +141 -0
- package/scripts/regression/cases/08-cwd-resilience.sh +84 -0
- package/scripts/regression/lib/common.sh +287 -0
- package/scripts/regression/results/.last_pid +1 -0
- package/scripts/regression/results/.last_workdir +1 -0
- package/scripts/regression/results/02-extension-loading.log +19 -0
- package/scripts/regression/results/03-prompt-stream.log +16 -0
- package/scripts/regression/results/03-rpc-protocol.log +28 -0
- package/scripts/regression/results/04-slash-commands-and-skills.log +11 -0
- package/scripts/regression/results/05-tool-execution.log +8 -0
- package/scripts/regression/results/06-pi-new-features.log +27 -0
- package/scripts/regression/results/08-cwd-resilience.log +1 -0
- package/scripts/regression/run-all.sh +187 -0
- package/config/agent/bin/fd.exe +0 -0
- package/config/agent/bin/rg.exe +0 -0
- package/config/agent/extensions/aicode-filter-outputs.ts +0 -131
- package/config/agent/extensions/aicode-snake.ts +0 -354
- /package/config/agent/{skills_bak → skills}/csv-data-summarizer/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/csv-data-summarizer/analyze.py +0 -0
- /package/config/agent/{skills_bak → skills}/csv-data-summarizer/examples/showcase_financial_pl_data.csv +0 -0
- /package/config/agent/{skills_bak → skills}/csv-data-summarizer/requirements.txt +0 -0
- /package/config/agent/{skills_bak → skills}/csv-data-summarizer/resources/sample.csv +0 -0
- /package/config/agent/{skills_bak → skills}/dispatching-parallel-agents/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/find-skills/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/finishing-a-development-branch/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/LICENSE +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/README.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/README.zh.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/agentloop-core.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/agents/openai.yaml +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style1-flat.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style2-dark.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style3-blueprint.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style4-notion.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style5-glass.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style6-claude.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/assets/samples/sample-style7-openai.png +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/agent-memory-types-style4.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/api-flow-style7.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/mem0-style1.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/microservices-style3.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/multi-agent-style5.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/system-architecture-style6.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/fixtures/tool-call-style2.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/package.json +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/icons.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-1-flat-icon.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-2-dark-terminal.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-3-blueprint.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-4-notion-clean.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-5-glassmorphism.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-6-claude-official.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-7-openai.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/style-diagram-matrix.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/references/svg-layout-best-practices.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/scripts/README.md +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/scripts/generate-diagram.sh +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/scripts/generate-from-template.py +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/scripts/test-all-styles.sh +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/scripts/validate-svg.sh +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/agent-architecture.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/architecture.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/comparison-matrix.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/data-flow.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/er-diagram.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/flowchart.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/sequence.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/state-machine.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/timeline.svg +0 -0
- /package/config/agent/{skills_bak → skills}/fireworks-tech-graph/templates/use-case.svg +0 -0
- /package/config/agent/{skills_bak → skills}/librarian/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/markdown-to-html/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/LICENSE +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/README.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/collection.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/database.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/index.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/partition.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/patterns.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/user-role.md +0 -0
- /package/config/agent/{skills_bak → skills}/milvus-skill/references/vector.md +0 -0
- /package/config/agent/{skills_bak → skills}/pr/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/receiving-code-review/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/requesting-code-review/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/requesting-code-review/code-reviewer.md +0 -0
- /package/config/agent/{skills_bak → skills}/subagent-driven-development/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/subagent-driven-development/code-quality-reviewer-prompt.md +0 -0
- /package/config/agent/{skills_bak → skills}/subagent-driven-development/implementer-prompt.md +0 -0
- /package/config/agent/{skills_bak → skills}/subagent-driven-development/spec-reviewer-prompt.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/CREATION-LOG.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/condition-based-waiting-example.ts +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/condition-based-waiting.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/defense-in-depth.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/find-polluter.sh +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/root-cause-tracing.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/test-academic.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/test-pressure-1.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/test-pressure-2.md +0 -0
- /package/config/agent/{skills_bak → skills}/systematic-debugging/test-pressure-3.md +0 -0
- /package/config/agent/{skills_bak → skills}/test-driven-development/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/test-driven-development/testing-anti-patterns.md +0 -0
- /package/config/agent/{skills_bak → skills}/unit-test/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/using-git-worktrees/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/zread/README.md +0 -0
- /package/config/agent/{skills_bak → skills}/zread/SKILL.md +0 -0
- /package/config/agent/{skills_bak → skills}/zread/references/stdio-protocol.md +0 -0
package/bin/cli.js
CHANGED
|
@@ -6,15 +6,30 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// 设置终端标题
|
|
9
|
-
process.title =
|
|
9
|
+
process.title = "aicode-cli";
|
|
10
10
|
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
// 防御 CWD 被删: 在所有 import 之前 chdir (node ESM 解析 import 时会读 cwd)
|
|
12
|
+
// 不 import os.homedir() 因为那需要模块解析, 此时 cwd 还没改
|
|
13
|
+
// 用 process.env.PWD 优先 (用户启动目录) → HOME fallback (防 PWD 缺失 ENOENT)
|
|
14
|
+
// 先 PWD 试 (用户启动目录), 失败 fallback HOME (cwd 被删时 PWD 也指向已删目录, chdir 会抛 ENOENT)
|
|
15
|
+
// catch 后再退一步: HOME 也失败则 chdir 到 / (绝对保证不会 ENOENT)
|
|
16
|
+
try {
|
|
17
|
+
process.chdir(process.env.PWD);
|
|
18
|
+
} catch {
|
|
19
|
+
try {
|
|
20
|
+
process.chdir(process.env.HOME || "/");
|
|
21
|
+
} catch {
|
|
22
|
+
try {
|
|
23
|
+
process.chdir("/");
|
|
24
|
+
} catch {}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
17
27
|
|
|
28
|
+
import { spawn } from "child_process";
|
|
29
|
+
import { fileURLToPath } from "url";
|
|
30
|
+
import { dirname, join } from "path";
|
|
31
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
32
|
+
import { getConfig, loadConfig } from "../dist/config-loader.js";
|
|
18
33
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
34
|
const __dirname = dirname(__filename);
|
|
20
35
|
|
|
@@ -22,9 +37,13 @@ const __dirname = dirname(__filename);
|
|
|
22
37
|
function getLocalVersion() {
|
|
23
38
|
let rootDir = __dirname;
|
|
24
39
|
while (rootDir !== dirname(rootDir)) {
|
|
25
|
-
const pkgPath = join(rootDir,
|
|
40
|
+
const pkgPath = join(rootDir, "package.json");
|
|
26
41
|
if (existsSync(pkgPath)) {
|
|
27
|
-
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
28
47
|
}
|
|
29
48
|
rootDir = dirname(rootDir);
|
|
30
49
|
}
|
|
@@ -33,33 +52,38 @@ function getLocalVersion() {
|
|
|
33
52
|
|
|
34
53
|
// 获取版本缓存文件路径
|
|
35
54
|
function getVersionCachePath() {
|
|
36
|
-
return join(
|
|
55
|
+
return join(
|
|
56
|
+
process.env.HOME || process.env.USERPROFILE,
|
|
57
|
+
".aicode-cli",
|
|
58
|
+
".version-cache.json",
|
|
59
|
+
);
|
|
37
60
|
}
|
|
38
61
|
|
|
39
62
|
// 解析命令行参数
|
|
40
63
|
function parseArgs() {
|
|
41
64
|
const args = process.argv.slice(2);
|
|
42
65
|
let configDir;
|
|
43
|
-
|
|
66
|
+
|
|
44
67
|
// 处理 --version 参数,显示 CLI 自己的版本
|
|
45
|
-
if (args.includes(
|
|
46
|
-
const pkgPath = join(__dirname,
|
|
68
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
69
|
+
const pkgPath = join(__dirname, "..", "package.json");
|
|
47
70
|
if (existsSync(pkgPath)) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
71
|
+
try {
|
|
72
|
+
const { version } = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
73
|
+
console.log(version);
|
|
74
|
+
} catch (_e) {
|
|
51
75
|
process.exit(0);
|
|
52
76
|
}
|
|
53
|
-
|
|
77
|
+
|
|
54
78
|
for (let i = 0; i < args.length; i++) {
|
|
55
79
|
const arg = args[i];
|
|
56
|
-
if (arg ===
|
|
80
|
+
if (arg === "--config" || arg === "-c") {
|
|
57
81
|
configDir = args[i + 1];
|
|
58
82
|
args.splice(i, 2);
|
|
59
83
|
break;
|
|
60
84
|
}
|
|
61
85
|
}
|
|
62
|
-
|
|
86
|
+
|
|
63
87
|
return { remainingArgs: args, configDir };
|
|
64
88
|
}
|
|
65
89
|
|
|
@@ -86,41 +110,41 @@ function replaceCLIVersionPlaceholder() {
|
|
|
86
110
|
// 找到项目根目录的 package.json
|
|
87
111
|
let rootDir = __dirname;
|
|
88
112
|
while (rootDir !== dirname(rootDir)) {
|
|
89
|
-
const pkgPath = join(rootDir,
|
|
113
|
+
const pkgPath = join(rootDir, "package.json");
|
|
90
114
|
if (existsSync(pkgPath)) {
|
|
91
|
-
const { version } = JSON.parse(readFileSync(pkgPath,
|
|
115
|
+
const { version } = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
92
116
|
const versionString = `aicode-cli/${version}`;
|
|
93
|
-
|
|
117
|
+
|
|
94
118
|
// 查找配置目录下的 models.json
|
|
95
119
|
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
96
120
|
const configDirs = [
|
|
97
|
-
join(homeDir,
|
|
98
|
-
join(homeDir,
|
|
121
|
+
join(homeDir, ".aicode-cli", "agent"),
|
|
122
|
+
join(homeDir, ".pi", "agent"),
|
|
99
123
|
];
|
|
100
|
-
|
|
124
|
+
|
|
101
125
|
for (const dir of configDirs) {
|
|
102
|
-
const modelsPath = join(dir,
|
|
126
|
+
const modelsPath = join(dir, "models.json");
|
|
103
127
|
if (!existsSync(modelsPath)) continue;
|
|
104
|
-
|
|
128
|
+
|
|
105
129
|
try {
|
|
106
|
-
let content = readFileSync(modelsPath,
|
|
130
|
+
let content = readFileSync(modelsPath, "utf-8");
|
|
107
131
|
const config = JSON.parse(content);
|
|
108
|
-
|
|
132
|
+
|
|
109
133
|
// 遍历所有 provider,替换 headers.User-Agent 中的占位符
|
|
110
134
|
for (const provider of Object.values(config.providers || {})) {
|
|
111
|
-
if (provider.headers && provider.headers[
|
|
112
|
-
const ua = provider.headers[
|
|
113
|
-
if (ua && ua.startsWith(
|
|
114
|
-
provider.headers[
|
|
135
|
+
if (provider.headers && provider.headers["User-Agent"]) {
|
|
136
|
+
const ua = provider.headers["User-Agent"];
|
|
137
|
+
if (ua && ua.startsWith("${") && ua.endsWith("}")) {
|
|
138
|
+
provider.headers["User-Agent"] = versionString;
|
|
115
139
|
}
|
|
116
140
|
}
|
|
117
141
|
}
|
|
118
|
-
|
|
142
|
+
|
|
119
143
|
const newContent = JSON.stringify(config, null, 2);
|
|
120
144
|
if (newContent !== content) {
|
|
121
|
-
writeFileSync(modelsPath, newContent,
|
|
145
|
+
writeFileSync(modelsPath, newContent, "utf-8");
|
|
122
146
|
}
|
|
123
|
-
} catch
|
|
147
|
+
} catch {
|
|
124
148
|
// 忽略错误
|
|
125
149
|
}
|
|
126
150
|
}
|
|
@@ -128,7 +152,7 @@ function replaceCLIVersionPlaceholder() {
|
|
|
128
152
|
}
|
|
129
153
|
rootDir = dirname(rootDir);
|
|
130
154
|
}
|
|
131
|
-
} catch
|
|
155
|
+
} catch {
|
|
132
156
|
// 忽略错误
|
|
133
157
|
}
|
|
134
158
|
}
|
|
@@ -138,24 +162,21 @@ replaceCLIVersionPlaceholder();
|
|
|
138
162
|
|
|
139
163
|
// 提前获取版本号(用于 banner 显示)
|
|
140
164
|
const localVersion = getLocalVersion();
|
|
141
|
-
process.env.AICODE_CLI_VERSION = localVersion ||
|
|
165
|
+
process.env.AICODE_CLI_VERSION = localVersion || "";
|
|
142
166
|
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
console.log(generateBanner(config.themeColor));
|
|
146
|
-
}
|
|
167
|
+
// banner 启动后打印已移交给 config/agent/extensions/aicode-banner.ts
|
|
168
|
+
// 理由: 1) 避免 RPC 父进程的 stdout JSON-RPC 污染; 2) chdir 到 homedir 后再触发更稳
|
|
147
169
|
|
|
148
|
-
// 检查新版本
|
|
149
170
|
async function checkForUpdates() {
|
|
150
171
|
try {
|
|
151
|
-
const { execFileSync } = await import(
|
|
172
|
+
const { execFileSync } = await import("child_process");
|
|
152
173
|
// 读取本地版本 - 向上查找 package.json
|
|
153
174
|
let rootDir = __dirname;
|
|
154
175
|
let localVersion = null;
|
|
155
176
|
while (rootDir !== dirname(rootDir)) {
|
|
156
|
-
const pkgPath = join(rootDir,
|
|
177
|
+
const pkgPath = join(rootDir, "package.json");
|
|
157
178
|
if (existsSync(pkgPath)) {
|
|
158
|
-
localVersion = JSON.parse(readFileSync(pkgPath,
|
|
179
|
+
localVersion = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
159
180
|
break;
|
|
160
181
|
}
|
|
161
182
|
rootDir = dirname(rootDir);
|
|
@@ -163,42 +184,56 @@ async function checkForUpdates() {
|
|
|
163
184
|
if (!localVersion) return;
|
|
164
185
|
|
|
165
186
|
// 🔒 Security: Use execFileSync instead of execSync to prevent command injection
|
|
166
|
-
const registry = execFileSync(
|
|
167
|
-
|
|
187
|
+
const registry = execFileSync("npm", ["config", "get", "registry"], {
|
|
188
|
+
encoding: "utf8",
|
|
189
|
+
stdio: "pipe",
|
|
190
|
+
}).trim();
|
|
191
|
+
const latestVersion = execFileSync(
|
|
192
|
+
"npm",
|
|
193
|
+
["view", "@ia-ccun/code-agent-cli", "version", "--registry=" + registry],
|
|
194
|
+
{ encoding: "utf8", stdio: "pipe" },
|
|
195
|
+
).trim();
|
|
168
196
|
|
|
169
197
|
// 比较版本号
|
|
170
|
-
const localParts = localVersion.split(
|
|
171
|
-
const latestParts = latestVersion.split(
|
|
172
|
-
const needsUpdate =
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
198
|
+
const localParts = localVersion.split(".").map(Number);
|
|
199
|
+
const latestParts = latestVersion.split(".").map(Number);
|
|
200
|
+
const needsUpdate =
|
|
201
|
+
latestParts[0] > localParts[0] ||
|
|
202
|
+
(latestParts[0] === localParts[0] && latestParts[1] > localParts[1]) ||
|
|
203
|
+
(latestParts[0] === localParts[0] &&
|
|
204
|
+
latestParts[1] === localParts[1] &&
|
|
205
|
+
latestParts[2] > localParts[2]);
|
|
177
206
|
|
|
178
207
|
// 写入版本缓存
|
|
179
208
|
try {
|
|
180
|
-
const cacheDir = join(
|
|
209
|
+
const cacheDir = join(
|
|
210
|
+
process.env.HOME || process.env.USERPROFILE,
|
|
211
|
+
".aicode-cli",
|
|
212
|
+
);
|
|
181
213
|
if (!existsSync(cacheDir)) {
|
|
182
214
|
// 🔒 Security: Use execFileSync for mkdir instead of execSync
|
|
183
|
-
execFileSync(
|
|
215
|
+
execFileSync("mkdir", ["-p", cacheDir], { stdio: "pipe" });
|
|
184
216
|
}
|
|
185
217
|
const cacheData = {
|
|
186
218
|
localVersion,
|
|
187
219
|
latestVersion,
|
|
188
220
|
needsUpdate,
|
|
189
|
-
timestamp: Date.now()
|
|
221
|
+
timestamp: Date.now(),
|
|
190
222
|
};
|
|
191
223
|
writeFileSync(versionCachePath, JSON.stringify(cacheData, null, 2));
|
|
192
|
-
} catch
|
|
224
|
+
} catch {
|
|
193
225
|
// 忽略缓存写入失败
|
|
194
226
|
}
|
|
195
|
-
} catch
|
|
227
|
+
} catch {
|
|
196
228
|
// 忽略检查失败
|
|
197
229
|
}
|
|
198
230
|
}
|
|
199
231
|
checkForUpdates();
|
|
200
232
|
|
|
201
|
-
const piAgentPathUrl = new URL(
|
|
233
|
+
const piAgentPathUrl = new URL(
|
|
234
|
+
"../node_modules/@earendil-works/pi-coding-agent/dist/cli.js",
|
|
235
|
+
import.meta.url,
|
|
236
|
+
);
|
|
202
237
|
const piAgentPath = fileURLToPath(piAgentPathUrl); // 解码中文路径
|
|
203
238
|
|
|
204
239
|
// 获取版本缓存文件路径
|
|
@@ -209,30 +244,37 @@ const env = {
|
|
|
209
244
|
...process.env,
|
|
210
245
|
AICODE_CLI_CONFIG_DIR: config.configDir,
|
|
211
246
|
AICODE_CLI_NAME: config.name,
|
|
212
|
-
AICODE_CLI_VERSION: localVersion ||
|
|
247
|
+
AICODE_CLI_VERSION: localVersion || "",
|
|
213
248
|
AICODE_CLI_VERSION_CACHE: versionCachePath,
|
|
214
|
-
PI_SKIP_VERSION_CHECK:
|
|
215
|
-
PI_OFFLINE:
|
|
249
|
+
PI_SKIP_VERSION_CHECK: "1",
|
|
250
|
+
PI_OFFLINE: "1", // 禁用包更新检查
|
|
216
251
|
};
|
|
217
252
|
|
|
218
253
|
// 传递配置目录给 pi
|
|
219
|
-
// pi 使用
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
254
|
+
// pi 使用 ${APP_NAME.toUpperCase()}_CODING_AGENT_DIR 环境变量识别 agent 目录
|
|
255
|
+
// 注意 "aicode-cli".toUpperCase() = "AICODE-CLI"(连字符,不是下划线)
|
|
256
|
+
// 所以 pi 0.85+ 读的是 AICODE-CLI_CODING_AGENT_DIR(连字符),不是 AICODE_CLI_CODING_AGENT_DIR(下划线)
|
|
257
|
+
// 下划线版本保留向后兼容 0.80~0.84
|
|
258
|
+
const fullPath = join(
|
|
259
|
+
process.env.HOME || process.env.USERPROFILE,
|
|
260
|
+
config.configDir,
|
|
261
|
+
);
|
|
262
|
+
const agentDir = join(fullPath, "agent");
|
|
263
|
+
env["AICODE-CLI_CODING_AGENT_DIR"] = agentDir;
|
|
223
264
|
env.AICODE_CLI_CODING_AGENT_DIR = agentDir;
|
|
265
|
+
env.PI_CODING_AGENT_DIR = agentDir;
|
|
224
266
|
|
|
225
267
|
// 启动 pi-coding-agent
|
|
226
|
-
const child = spawn(
|
|
227
|
-
stdio:
|
|
228
|
-
env
|
|
268
|
+
const child = spawn("node", [piAgentPath, ...remainingArgs], {
|
|
269
|
+
stdio: "inherit",
|
|
270
|
+
env,
|
|
229
271
|
});
|
|
230
272
|
|
|
231
|
-
child.on(
|
|
273
|
+
child.on("exit", (code) => {
|
|
232
274
|
process.exit(code ?? 0);
|
|
233
275
|
});
|
|
234
276
|
|
|
235
|
-
child.on(
|
|
236
|
-
console.error(
|
|
277
|
+
child.on("error", (err) => {
|
|
278
|
+
console.error("Failed to start agent:", err);
|
|
237
279
|
process.exit(1);
|
|
238
280
|
});
|