@ia-ccun/code-agent-cli 0.0.57-beta.3 → 0.0.58-beta.1

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.
@@ -1,12 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // Post-install script for aicode-cli
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, readdirSync, statSync, createWriteStream } from 'fs';
5
- import { symlink as fsSymlink } from 'fs/promises';
6
- import { join, dirname, relative } from 'path';
7
- import { homedir } from 'os';
8
- import { fileURLToPath } from 'url';
9
- import { spawn } from 'child_process';
4
+ import {
5
+ existsSync,
6
+ mkdirSync,
7
+ readFileSync,
8
+ writeFileSync,
9
+ copyFileSync,
10
+ readdirSync,
11
+ statSync,
12
+ createWriteStream,
13
+ } from "fs";
14
+ import { symlink as fsSymlink } from "fs/promises";
15
+ import { join, dirname, relative } from "path";
16
+ import { homedir } from "os";
17
+ import { fileURLToPath } from "url";
18
+ import { spawn } from "child_process";
10
19
 
11
20
  // Get __dirname equivalent for ES modules
12
21
  const __filename = fileURLToPath(import.meta.url);
@@ -15,8 +24,8 @@ const __dirname = dirname(__filename);
15
24
  // ============================================================================
16
25
  // Security Logger (inline for postinstall script)
17
26
  // ============================================================================
18
- const LOG_DIR = join(homedir(), '.aicode-cli', 'logs');
19
- const SECURITY_LOG = join(LOG_DIR, 'security.log');
27
+ const LOG_DIR = join(homedir(), ".aicode-cli", "logs");
28
+ const SECURITY_LOG = join(LOG_DIR, "security.log");
20
29
 
21
30
  function ensureLogDir() {
22
31
  if (!existsSync(LOG_DIR)) {
@@ -24,7 +33,7 @@ function ensureLogDir() {
24
33
  }
25
34
  }
26
35
 
27
- function logSecurity(event, details, level = 'info') {
36
+ function logSecurity(event, details, level = "info") {
28
37
  ensureLogDir();
29
38
  const entry = {
30
39
  timestamp: new Date().toISOString(),
@@ -34,15 +43,15 @@ function logSecurity(event, details, level = 'info') {
34
43
  details,
35
44
  pid: process.pid,
36
45
  };
37
-
46
+
38
47
  try {
39
- const stream = createWriteStream(SECURITY_LOG, { flags: 'a', mode: 0o600 });
40
- stream.write(JSON.stringify(entry) + '\n');
48
+ const stream = createWriteStream(SECURITY_LOG, { flags: "a", mode: 0o600 });
49
+ stream.write(JSON.stringify(entry) + "\n");
41
50
  stream.end();
42
51
  } catch (e) {
43
52
  // Ignore logging errors
44
53
  }
45
-
54
+
46
55
  if (process.env.DEBUG) {
47
56
  console.error(`[🔒 安全] ${event}:`, details);
48
57
  }
@@ -52,64 +61,86 @@ function logSecurity(event, details, level = 'info') {
52
61
  // Main Installation Logic
53
62
  // ============================================================================
54
63
 
55
- console.log('\n🚀 Setting up aicode-cli...');
64
+ console.log("\n🚀 Setting up aicode-cli...");
56
65
 
57
66
  // Record installation start
58
- logSecurity('install_start', {
59
- version: '0.0.51-beta.1',
67
+ logSecurity("install_start", {
68
+ version: "0.0.51-beta.1",
60
69
  homeDir: homedir(),
61
70
  timestamp: new Date().toISOString(),
62
71
  });
63
72
 
64
73
  // Get the current user's home directory
65
74
  const homeDir = homedir();
66
- const aicodeCliDir = join(homeDir, '.aicode-cli');
67
- const piDir = join(homeDir, '.pi');
75
+ const aicodeCliDir = join(homeDir, ".aicode-cli");
76
+ const piDir = join(homeDir, ".pi");
68
77
 
69
78
  // ============================================================================
70
79
  // Fix pi-coding-agent APP_NAME
71
80
  // ============================================================================
72
- const piAgentPackageJson = join(__dirname, '..', 'node_modules', '@earendil-works', 'pi-coding-agent', 'package.json');
81
+ const piAgentPackageJson = join(
82
+ __dirname,
83
+ "..",
84
+ "node_modules",
85
+ "@earendil-works",
86
+ "pi-coding-agent",
87
+ "package.json",
88
+ );
73
89
  if (existsSync(piAgentPackageJson)) {
74
90
  try {
75
- const piPkg = JSON.parse(readFileSync(piAgentPackageJson, 'utf-8'));
91
+ const piPkg = JSON.parse(readFileSync(piAgentPackageJson, "utf-8"));
76
92
  if (!piPkg.piConfig) {
77
93
  piPkg.piConfig = {};
78
94
  }
79
- const oldName = piPkg.piConfig.name || 'pi';
80
- piPkg.piConfig.name = 'aicode-cli';
81
- piPkg.piConfig.configDir = '.aicode-cli';
82
- writeFileSync(piAgentPackageJson, JSON.stringify(piPkg, null, 2) + '\n');
95
+ const oldName = piPkg.piConfig.name || "pi";
96
+ piPkg.piConfig.name = "aicode-cli";
97
+ piPkg.piConfig.configDir = ".aicode-cli";
98
+ writeFileSync(piAgentPackageJson, JSON.stringify(piPkg, null, 2) + "\n");
83
99
  console.log(`✓ Updated pi-coding-agent app name: ${oldName} -> aicode-cli`);
84
-
85
- logSecurity('file_modified', {
100
+
101
+ logSecurity("file_modified", {
86
102
  file: piAgentPackageJson,
87
- action: 'Updated piConfig',
88
- changes: ['name', 'configDir'],
103
+ action: "Updated piConfig",
104
+ changes: ["name", "configDir"],
89
105
  });
90
106
  } catch (e) {
91
107
  console.log(`⚠ Could not update pi-coding-agent config: ${e.message}`);
92
- logSecurity('file_modified', {
93
- file: piAgentPackageJson,
94
- action: 'Update failed',
95
- error: e.message,
96
- }, 'warn');
108
+ logSecurity(
109
+ "file_modified",
110
+ {
111
+ file: piAgentPackageJson,
112
+ action: "Update failed",
113
+ error: e.message,
114
+ },
115
+ "warn",
116
+ );
97
117
  }
98
118
  }
99
119
 
100
120
  // Fix pi-coding-agent cli.js process.title
101
- const piAgentCliJs = join(__dirname, '..', 'node_modules', '@earendil-works', 'pi-coding-agent', 'dist', 'cli.js');
121
+ const piAgentCliJs = join(
122
+ __dirname,
123
+ "..",
124
+ "node_modules",
125
+ "@earendil-works",
126
+ "pi-coding-agent",
127
+ "dist",
128
+ "cli.js",
129
+ );
102
130
  if (existsSync(piAgentCliJs)) {
103
131
  try {
104
- let cliContent = readFileSync(piAgentCliJs, 'utf-8');
132
+ let cliContent = readFileSync(piAgentCliJs, "utf-8");
105
133
  if (cliContent.includes('process.title = "pi"')) {
106
- cliContent = cliContent.replace(/process\.title = "pi"/g, 'process.title = "aicode-cli"');
134
+ cliContent = cliContent.replace(
135
+ /process\.title = "pi"/g,
136
+ 'process.title = "aicode-cli"',
137
+ );
107
138
  writeFileSync(piAgentCliJs, cliContent);
108
139
  console.log(`✓ Updated pi-coding-agent process.title`);
109
-
110
- logSecurity('file_modified', {
140
+
141
+ logSecurity("file_modified", {
111
142
  file: piAgentCliJs,
112
- action: 'Updated process.title',
143
+ action: "Updated process.title",
113
144
  });
114
145
  }
115
146
  } catch (e) {
@@ -118,18 +149,29 @@ if (existsSync(piAgentCliJs)) {
118
149
  }
119
150
 
120
151
  // Fix pi-coding-agent config.js APP_NAME default
121
- const piAgentConfigJs = join(__dirname, '..', 'node_modules', '@earendil-works', 'pi-coding-agent', 'dist', 'config.js');
152
+ const piAgentConfigJs = join(
153
+ __dirname,
154
+ "..",
155
+ "node_modules",
156
+ "@earendil-works",
157
+ "pi-coding-agent",
158
+ "dist",
159
+ "config.js",
160
+ );
122
161
  if (existsSync(piAgentConfigJs)) {
123
162
  try {
124
- let configContent = readFileSync(piAgentConfigJs, 'utf-8');
163
+ let configContent = readFileSync(piAgentConfigJs, "utf-8");
125
164
  if (configContent.includes('pkg.piConfig?.name || "pi"')) {
126
- configContent = configContent.replace(/pkg\.piConfig\?\.name \|\| "pi"/g, 'pkg.piConfig?.name || "aicode-cli"');
165
+ configContent = configContent.replace(
166
+ /pkg\.piConfig\?\.name \|\| "pi"/g,
167
+ 'pkg.piConfig?.name || "aicode-cli"',
168
+ );
127
169
  writeFileSync(piAgentConfigJs, configContent);
128
170
  console.log(`✓ Updated pi-coding-agent config.js APP_NAME`);
129
-
130
- logSecurity('file_modified', {
171
+
172
+ logSecurity("file_modified", {
131
173
  file: piAgentConfigJs,
132
- action: 'Updated APP_NAME',
174
+ action: "Updated APP_NAME",
133
175
  });
134
176
  }
135
177
  } catch (e) {
@@ -138,18 +180,27 @@ if (existsSync(piAgentConfigJs)) {
138
180
  }
139
181
 
140
182
  // Fix pi-coding-agent slash commands - change "Quit pi" to "Quit aicode-cli"
141
- const slashCommandsJs = join(__dirname, '..', 'node_modules', '@earendil-works', 'pi-coding-agent', 'dist', 'core', 'slash-commands.js');
183
+ const slashCommandsJs = join(
184
+ __dirname,
185
+ "..",
186
+ "node_modules",
187
+ "@earendil-works",
188
+ "pi-coding-agent",
189
+ "dist",
190
+ "core",
191
+ "slash-commands.js",
192
+ );
142
193
  if (existsSync(slashCommandsJs)) {
143
194
  try {
144
- let content = readFileSync(slashCommandsJs, 'utf-8');
145
- if (content.includes('Quit pi')) {
146
- content = content.replace(/Quit pi/g, 'Quit aicode-cli');
195
+ let content = readFileSync(slashCommandsJs, "utf-8");
196
+ if (content.includes("Quit pi")) {
197
+ content = content.replace(/Quit pi/g, "Quit aicode-cli");
147
198
  writeFileSync(slashCommandsJs, content);
148
199
  console.log(`✓ Updated slash command description`);
149
-
150
- logSecurity('file_modified', {
200
+
201
+ logSecurity("file_modified", {
151
202
  file: slashCommandsJs,
152
- action: 'Updated slash commands',
203
+ action: "Updated slash commands",
153
204
  });
154
205
  }
155
206
  } catch (e) {
@@ -164,7 +215,7 @@ if (!existsSync(aicodeCliDir)) {
164
215
  }
165
216
 
166
217
  // Create agent subdirectory
167
- const agentDir = join(aicodeCliDir, 'agent');
218
+ const agentDir = join(aicodeCliDir, "agent");
168
219
  if (!existsSync(agentDir)) {
169
220
  mkdirSync(agentDir, { recursive: true });
170
221
  console.log(`✓ Created directory: ${agentDir}`);
@@ -182,7 +233,7 @@ function copyDirRecursive(src, dest) {
182
233
  }
183
234
 
184
235
  const files = readdirSync(src);
185
- files.forEach(function(file) {
236
+ files.forEach(function (file) {
186
237
  const srcPath = join(src, file);
187
238
  const destPath = join(dest, file);
188
239
  copyDirRecursive(srcPath, destPath);
@@ -203,13 +254,13 @@ function copyDirRecursive(src, dest) {
203
254
  // Force copy directory recursively (always overwrite destination)
204
255
  function forceCopyDirRecursive(src, dest) {
205
256
  if (!existsSync(src)) return;
206
-
257
+
207
258
  const stats = statSync(src);
208
259
  if (stats.isDirectory()) {
209
260
  if (!existsSync(dest)) {
210
261
  mkdirSync(dest, { recursive: true });
211
262
  }
212
- readdirSync(src).forEach(file => {
263
+ readdirSync(src).forEach((file) => {
213
264
  forceCopyDirRecursive(join(src, file), join(dest, file));
214
265
  });
215
266
  } else {
@@ -222,53 +273,54 @@ function forceCopyDirRecursive(src, dest) {
222
273
  }
223
274
 
224
275
  // Copy config.json if it doesn't exist
225
- const packageConfigFile = join(__dirname, '..', 'config.json');
226
- const userConfigFile = join(aicodeCliDir, 'config.json');
276
+ const packageConfigFile = join(__dirname, "..", "config.json");
277
+ const userConfigFile = join(aicodeCliDir, "config.json");
227
278
  if (existsSync(packageConfigFile) && !existsSync(userConfigFile)) {
228
- console.log(`📁 Copying config.json from ${packageConfigFile} to ${userConfigFile}`);
279
+ console.log(
280
+ `📁 Copying config.json from ${packageConfigFile} to ${userConfigFile}`,
281
+ );
229
282
  copyFileSync(packageConfigFile, userConfigFile);
230
- console.log('✓ config.json copied successfully');
283
+ console.log("✓ config.json copied successfully");
231
284
  } else if (!existsSync(packageConfigFile)) {
232
- console.log('⚠ config.json not found in package');
285
+ console.log("⚠ config.json not found in package");
233
286
  }
234
287
 
235
288
  // ============================================================================
236
289
  // Files/folders that must be force-overwritten on every install
237
290
  // ============================================================================
238
- const packageConfigDir = join(__dirname, '..', 'config', 'agent');
291
+ const packageConfigDir = join(__dirname, "..", "config", "agent");
239
292
 
240
293
  const FORCE_OVERWRITE_LIST = [
241
- 'APPEND_SYSTEM.md',
242
- 'SYSTEM.md',
243
- 'dangerous-patterns.json',
244
- 'help.md',
245
- 'extensions/*.ts',
246
- 'prompts/*.md',
247
- 'skills/*/SKILL.md',
248
- 'skills/*/*/SKILL.md',
294
+ "APPEND_SYSTEM.md",
295
+ "SYSTEM.md",
296
+ "help.md",
297
+ "extensions/*.ts",
298
+ "prompts/*.md",
299
+ "skills/*/SKILL.md",
300
+ "skills/*/*/SKILL.md",
249
301
  ];
250
302
 
251
303
  // Function to expand glob patterns
252
304
  function expandGlob(pattern) {
253
305
  const results = [];
254
-
255
- if (pattern.includes('*')) {
256
- const parts = pattern.split('/');
306
+
307
+ if (pattern.includes("*")) {
308
+ const parts = pattern.split("/");
257
309
  let currentPaths = [packageConfigDir];
258
-
310
+
259
311
  for (let i = 0; i < parts.length; i++) {
260
312
  const part = parts[i];
261
313
  const nextPaths = [];
262
314
  const isLastPart = i === parts.length - 1;
263
- const hasWildcard = part.includes('*');
264
-
315
+ const hasWildcard = part.includes("*");
316
+
265
317
  for (const cp of currentPaths) {
266
318
  if (!existsSync(cp)) continue;
267
-
319
+
268
320
  if (hasWildcard) {
269
321
  const entries = readdirSync(cp);
270
- const regex = new RegExp('^' + part.replace(/\*/g, '.*') + '$');
271
-
322
+ const regex = new RegExp("^" + part.replace(/\*/g, ".*") + "$");
323
+
272
324
  for (const entry of entries) {
273
325
  if (regex.test(entry)) {
274
326
  const fullPath = join(cp, entry);
@@ -289,7 +341,7 @@ function expandGlob(pattern) {
289
341
  }
290
342
  currentPaths = nextPaths;
291
343
  }
292
-
344
+
293
345
  for (const p of currentPaths) {
294
346
  if (existsSync(p)) {
295
347
  results.push(relative(packageConfigDir, p));
@@ -298,7 +350,7 @@ function expandGlob(pattern) {
298
350
  } else {
299
351
  results.push(pattern);
300
352
  }
301
-
353
+
302
354
  return results;
303
355
  }
304
356
 
@@ -308,11 +360,11 @@ function forceOverwriteList(relativePaths) {
308
360
  for (const relativePath of relativePaths) {
309
361
  expandedPaths.push(...expandGlob(relativePath));
310
362
  }
311
-
312
- expandedPaths.forEach(relativePath => {
363
+
364
+ expandedPaths.forEach((relativePath) => {
313
365
  const srcPath = join(packageConfigDir, relativePath);
314
366
  const destPath = join(agentDir, relativePath);
315
-
367
+
316
368
  if (existsSync(srcPath)) {
317
369
  try {
318
370
  const stats = statSync(srcPath);
@@ -331,7 +383,9 @@ function forceOverwriteList(relativePaths) {
331
383
  console.log(`✓ Force overwritten: ${relativePath}`);
332
384
  }
333
385
  } catch (e) {
334
- console.log(`⚠ Could not force overwrite ${relativePath}: ${e.message}`);
386
+ console.log(
387
+ `⚠ Could not force overwrite ${relativePath}: ${e.message}`,
388
+ );
335
389
  }
336
390
  } else {
337
391
  console.log(`⚠ Source path does not exist: ${relativePath}`);
@@ -341,66 +395,67 @@ function forceOverwriteList(relativePaths) {
341
395
 
342
396
  // Copy config/agent contents to ~/.aicode-cli/agent
343
397
  if (existsSync(packageConfigDir)) {
344
- console.log(`📁 Syncing default config files to ${agentDir} (preserving user customizations)`);
398
+ console.log(
399
+ `📁 Syncing default config files to ${agentDir} (preserving user customizations)`,
400
+ );
345
401
 
346
402
  copyDirRecursive(packageConfigDir, agentDir);
347
- console.log('✓ Default config files synced successfully');
403
+ console.log("✓ Default config files synced successfully");
348
404
 
349
405
  if (FORCE_OVERWRITE_LIST.length > 0) {
350
406
  forceOverwriteList(FORCE_OVERWRITE_LIST);
351
407
  }
352
408
 
353
- const extensionsDir = join(agentDir, 'extensions');
409
+ const extensionsDir = join(agentDir, "extensions");
354
410
  if (existsSync(extensionsDir)) {
355
411
  try {
356
- const extFiles = readdirSync(extensionsDir).filter(f => f.endsWith('.ts'));
412
+ const extFiles = readdirSync(extensionsDir).filter((f) =>
413
+ f.endsWith(".ts"),
414
+ );
357
415
  if (extFiles.length > 0) {
358
- console.log(`✓ Found ${extFiles.length} extension(s): ${extFiles.join(', ')}`);
416
+ console.log(
417
+ `✓ Found ${extFiles.length} extension(s): ${extFiles.join(", ")}`,
418
+ );
359
419
  }
360
420
  } catch (e) {
361
421
  // ignore
362
422
  }
363
423
  }
364
424
  } else {
365
- console.log('⚠ Configuration directory not found in package');
425
+ console.log("⚠ Configuration directory not found in package");
366
426
  }
367
427
 
368
428
  // ============================================================================
369
429
  // Reset User-Agent placeholder in models.json
370
430
  // ============================================================================
371
- const modelsPath = join(agentDir, 'models.json');
431
+ const modelsPath = join(agentDir, "models.json");
372
432
  if (existsSync(modelsPath)) {
373
433
  try {
374
- let content = readFileSync(modelsPath, 'utf-8');
434
+ let content = readFileSync(modelsPath, "utf-8");
375
435
  try {
376
436
  const config = JSON.parse(content);
377
437
  for (const provider of Object.values(config.providers || {})) {
378
- if (provider.headers && provider.headers['User-Agent']) {
379
- const ua = provider.headers['User-Agent'];
380
- if (ua && ua.startsWith('aicode-cli/')) {
381
- provider.headers['User-Agent'] = '${VERSION}';
438
+ if (provider.headers && provider.headers["User-Agent"]) {
439
+ const ua = provider.headers["User-Agent"];
440
+ if (ua && ua.startsWith("aicode-cli/")) {
441
+ provider.headers["User-Agent"] = "${VERSION}";
382
442
  }
383
443
  }
384
444
  }
385
445
  const newContent = JSON.stringify(config, null, 2);
386
-
446
+
387
447
  if (newContent !== content) {
388
- writeFileSync(modelsPath, newContent, 'utf-8');
389
- console.log('✓ Reset User-Agent placeholder in models.json');
390
-
391
- logSecurity('file_modified', {
448
+ writeFileSync(modelsPath, newContent, "utf-8");
449
+ console.log("✓ Reset User-Agent placeholder in models.json");
450
+
451
+ logSecurity("file_modified", {
392
452
  file: modelsPath,
393
- action: 'Reset User-Agent placeholder',
453
+ action: "Reset User-Agent placeholder",
394
454
  });
395
455
  }
396
456
  } catch (e) {
397
457
  console.log(`⚠ Could not reset User-Agent placeholder: ${e.message}`);
398
458
  }
399
-
400
- if (newContent !== content) {
401
- writeFileSync(modelsPath, newContent, 'utf-8');
402
- console.log('✓ Reset User-Agent placeholder in models.json');
403
- }
404
459
  } catch (e) {
405
460
  console.log(`⚠ Could not reset User-Agent placeholder: ${e.message}`);
406
461
  }
@@ -410,10 +465,10 @@ if (existsSync(modelsPath)) {
410
465
  (async () => {
411
466
  try {
412
467
  if (!existsSync(piDir)) {
413
- await fsSymlink(aicodeCliDir, piDir, 'dir');
468
+ await fsSymlink(aicodeCliDir, piDir, "dir");
414
469
  console.log(`✓ Created symbolic link: ${piDir} -> ${aicodeCliDir}`);
415
-
416
- logSecurity('symlink_create', {
470
+
471
+ logSecurity("symlink_create", {
417
472
  target: piDir,
418
473
  source: aicodeCliDir,
419
474
  success: true,
@@ -422,20 +477,26 @@ if (existsSync(modelsPath)) {
422
477
  console.log(`✓ ${piDir} already exists`);
423
478
  }
424
479
  } catch (e) {
425
- if (e.code === 'EEXIST') {
480
+ if (e.code === "EEXIST") {
426
481
  console.log(`✓ Symbolic link already exists: ${piDir}`);
427
482
  } else {
428
483
  console.log(`⚠ Could not create symbolic link: ${e.message}`);
429
- console.log('\n📌 To fix this, please run manually:');
430
- console.log(' ln -s ~/.aicode-cli ~/.pi');
431
- console.log('\n (If ~/.pi exists, run: rm -rf ~/.pi && ln -s ~/.aicode-cli ~/.pi)');
432
-
433
- logSecurity('symlink_create', {
434
- target: piDir,
435
- source: aicodeCliDir,
436
- success: false,
437
- error: e.message,
438
- }, 'warn');
484
+ console.log("\n📌 To fix this, please run manually:");
485
+ console.log(" ln -s ~/.aicode-cli ~/.pi");
486
+ console.log(
487
+ "\n (If ~/.pi exists, run: rm -rf ~/.pi && ln -s ~/.aicode-cli ~/.pi)",
488
+ );
489
+
490
+ logSecurity(
491
+ "symlink_create",
492
+ {
493
+ target: piDir,
494
+ source: aicodeCliDir,
495
+ success: false,
496
+ error: e.message,
497
+ },
498
+ "warn",
499
+ );
439
500
  }
440
501
  }
441
502
  })();
@@ -443,7 +504,7 @@ if (existsSync(modelsPath)) {
443
504
  // Check and display models config
444
505
  if (existsSync(modelsPath)) {
445
506
  try {
446
- const models = JSON.parse(readFileSync(modelsPath, 'utf-8'));
507
+ const models = JSON.parse(readFileSync(modelsPath, "utf-8"));
447
508
  if (models.providers) {
448
509
  const providerCount = Object.keys(models.providers).length;
449
510
  console.log(`✓ Found ${providerCount} configured provider(s)`);
@@ -456,7 +517,7 @@ if (existsSync(modelsPath)) {
456
517
  }
457
518
 
458
519
  // Record installation complete
459
- logSecurity('install_complete', {
520
+ logSecurity("install_complete", {
460
521
  success: true,
461
522
  aicodeCliDir,
462
523
  agentDir,
@@ -467,51 +528,61 @@ logSecurity('install_complete', {
467
528
  // Auto-install codegraph (optional dependency)
468
529
  // ============================================================================
469
530
 
470
- const CODEGRAPH_PKG = '@colbymchenry/codegraph@0.9.7';
531
+ const CODEGRAPH_PKG = "@colbymchenry/codegraph@0.9.7";
471
532
 
472
533
  async function installCodegraph() {
473
534
  return new Promise((resolve) => {
474
- const child = spawn('npm', ['i', '-g', CODEGRAPH_PKG], {
475
- stdio: 'pipe',
476
- shell: process.platform === 'win32',
535
+ const child = spawn("npm", ["i", "-g", CODEGRAPH_PKG], {
536
+ stdio: "pipe",
537
+ shell: process.platform === "win32",
477
538
  });
478
-
479
- let stderr = '';
480
-
481
- child.stderr.on('data', (data) => {
539
+
540
+ let stderr = "";
541
+
542
+ child.stderr.on("data", (data) => {
482
543
  stderr += data.toString();
483
544
  });
484
-
485
- child.on('close', (code) => {
545
+
546
+ child.on("close", (code) => {
486
547
  if (code === 0) {
487
- console.log('✓ Installed codegraph globally,See UniDoc《2026.5 aicode+codegraph 安装与使用》');
488
- logSecurity('codegraph_install', {
489
- package: CODEGRAPH_PKG,
490
- success: true
548
+ console.log(
549
+ "✓ Installed codegraph globally,See UniDoc《2026.5 aicode+codegraph 安装与使用》",
550
+ );
551
+ logSecurity("codegraph_install", {
552
+ package: CODEGRAPH_PKG,
553
+ success: true,
491
554
  });
492
555
  } else {
493
556
  // 静默失败,不中断主流程
494
557
  if (process.env.DEBUG) {
495
558
  console.log(`⚠ Could not install codegraph: ${stderr.slice(0, 100)}`);
496
559
  }
497
- logSecurity('codegraph_install', {
498
- package: CODEGRAPH_PKG,
499
- success: false,
500
- error: stderr.slice(0, 200)
501
- }, 'warn');
560
+ logSecurity(
561
+ "codegraph_install",
562
+ {
563
+ package: CODEGRAPH_PKG,
564
+ success: false,
565
+ error: stderr.slice(0, 200),
566
+ },
567
+ "warn",
568
+ );
502
569
  }
503
570
  resolve();
504
571
  });
505
-
506
- child.on('error', (err) => {
572
+
573
+ child.on("error", (err) => {
507
574
  if (process.env.DEBUG) {
508
575
  console.log(`⚠ Could not install codegraph: ${err.message}`);
509
576
  }
510
- logSecurity('codegraph_install', {
511
- package: CODEGRAPH_PKG,
512
- success: false,
513
- error: err.message
514
- }, 'warn');
577
+ logSecurity(
578
+ "codegraph_install",
579
+ {
580
+ package: CODEGRAPH_PKG,
581
+ success: false,
582
+ error: err.message,
583
+ },
584
+ "warn",
585
+ );
515
586
  resolve();
516
587
  });
517
588
  });
@@ -520,8 +591,12 @@ async function installCodegraph() {
520
591
  // Execute codegraph installation
521
592
  await installCodegraph();
522
593
 
523
- console.log('\n✨ Setup complete!');
524
- console.log('📝 Configuration files are in ~/.aicode-cli/');
525
- console.log('🔗 ~/.pi is linked to ~/.aicode-cli (ensuring model configs work)');
526
- console.log('🚀 Run with: aicode-cli');
527
- console.log('\n📖 For more information, see: https://www.npmjs.com/package/@ia-ccun/code-agent-cli');
594
+ console.log("\n✨ Setup complete!");
595
+ console.log("📝 Configuration files are in ~/.aicode-cli/");
596
+ console.log(
597
+ "🔗 ~/.pi is linked to ~/.aicode-cli (ensuring model configs work)",
598
+ );
599
+ console.log("🚀 Run with: aicode-cli");
600
+ console.log(
601
+ "\n📖 For more information, see: https://www.npmjs.com/package/@ia-ccun/code-agent-cli",
602
+ );