jinzd-ai-cli 0.4.118 → 0.4.119

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.
@@ -6,7 +6,7 @@ import { platform } from "os";
6
6
  import chalk from "chalk";
7
7
 
8
8
  // src/core/constants.ts
9
- var VERSION = "0.4.117";
9
+ var VERSION = "0.4.119";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ CONFIG_DIR_NAME,
4
+ VERSION
5
+ } from "./chunk-BS7EUZSO.js";
6
+
7
+ // src/diagnostics/crash-log.ts
8
+ import {
9
+ existsSync,
10
+ mkdirSync,
11
+ readdirSync,
12
+ readFileSync,
13
+ statSync,
14
+ unlinkSync,
15
+ writeFileSync
16
+ } from "fs";
17
+ import { join } from "path";
18
+ import { homedir, platform, release, arch } from "os";
19
+ var LOGS_DIR_NAME = "logs";
20
+ var CRASH_LOG_PREFIX = "crash-";
21
+ var MAX_CRASH_FILES = 20;
22
+ function getLogsDir(configDir) {
23
+ const base = configDir ?? join(homedir(), CONFIG_DIR_NAME);
24
+ return join(base, LOGS_DIR_NAME);
25
+ }
26
+ function ensureLogsDir(configDir) {
27
+ const dir = getLogsDir(configDir);
28
+ if (!existsSync(dir)) {
29
+ mkdirSync(dir, { recursive: true });
30
+ }
31
+ return dir;
32
+ }
33
+ function isoTimestampForFilename(d = /* @__PURE__ */ new Date()) {
34
+ return d.toISOString().replace(/[:.]/g, "-");
35
+ }
36
+ function writeCrashLog(err, context, configDir) {
37
+ try {
38
+ const dir = ensureLogsDir(configDir);
39
+ const ts = /* @__PURE__ */ new Date();
40
+ const file = join(dir, `${CRASH_LOG_PREFIX}${isoTimestampForFilename(ts)}.log`);
41
+ const errMessage = err instanceof Error ? err.message : String(err);
42
+ const errStack = err instanceof Error ? err.stack ?? "(no stack)" : "(non-Error thrown)";
43
+ const lines = [
44
+ `# ai-cli crash log`,
45
+ `timestamp: ${ts.toISOString()}`,
46
+ `kind: ${context.kind}`,
47
+ `version: ${VERSION}`,
48
+ `node: ${process.version}`,
49
+ `platform: ${platform()} ${release()} (${arch()})`,
50
+ `pid: ${process.pid}`,
51
+ context.provider ? `provider: ${context.provider}` : "",
52
+ context.model ? `model: ${context.model}` : "",
53
+ context.lastAction ? `lastAction: ${truncate(context.lastAction, 500)}` : "",
54
+ "",
55
+ `## message`,
56
+ errMessage,
57
+ "",
58
+ `## stack`,
59
+ errStack,
60
+ ""
61
+ ].filter(Boolean);
62
+ writeFileSync(file, lines.join("\n"), "utf-8");
63
+ pruneOldCrashes(configDir);
64
+ return file;
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+ function truncate(s, n) {
70
+ return s.length <= n ? s : s.slice(0, n) + "\u2026";
71
+ }
72
+ function pruneOldCrashes(configDir) {
73
+ try {
74
+ const dir = getLogsDir(configDir);
75
+ if (!existsSync(dir)) return;
76
+ const entries = readdirSync(dir).filter((f) => f.startsWith(CRASH_LOG_PREFIX) && f.endsWith(".log")).map((f) => {
77
+ const full = join(dir, f);
78
+ let mtime = 0;
79
+ try {
80
+ mtime = statSync(full).mtimeMs;
81
+ } catch {
82
+ }
83
+ return { file: full, mtime };
84
+ }).sort((a, b) => b.mtime - a.mtime);
85
+ for (const e of entries.slice(MAX_CRASH_FILES)) {
86
+ try {
87
+ unlinkSync(e.file);
88
+ } catch {
89
+ }
90
+ }
91
+ } catch {
92
+ }
93
+ }
94
+ function listRecentCrashes(limit = 10, configDir) {
95
+ const dir = getLogsDir(configDir);
96
+ if (!existsSync(dir)) return [];
97
+ const files = [];
98
+ let names;
99
+ try {
100
+ names = readdirSync(dir);
101
+ } catch {
102
+ return [];
103
+ }
104
+ for (const name of names) {
105
+ if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
106
+ const full = join(dir, name);
107
+ try {
108
+ const st = statSync(full);
109
+ const head = readFileSync(full, "utf-8").split("\n").slice(0, 20);
110
+ const tsLine = head.find((l) => l.startsWith("timestamp:"));
111
+ const kindLine = head.find((l) => l.startsWith("kind:"));
112
+ const msgIdx = head.findIndex((l) => l.trim() === "## message");
113
+ const message = msgIdx >= 0 && head[msgIdx + 1] ? head[msgIdx + 1] : "";
114
+ files.push({
115
+ file: full,
116
+ timestamp: tsLine ? tsLine.replace("timestamp:", "").trim() : st.mtime.toISOString(),
117
+ kind: kindLine ? kindLine.replace("kind:", "").trim() : "unknown",
118
+ message: truncate(message, 200),
119
+ sizeBytes: st.size
120
+ });
121
+ } catch {
122
+ }
123
+ }
124
+ files.sort((a, b) => a.timestamp < b.timestamp ? 1 : -1);
125
+ return files.slice(0, limit);
126
+ }
127
+ function getConfigDirUsage(configDir) {
128
+ const base = configDir ?? join(homedir(), CONFIG_DIR_NAME);
129
+ if (!existsSync(base)) return { totalBytes: 0, entries: [] };
130
+ const entries = [];
131
+ let total = 0;
132
+ let names;
133
+ try {
134
+ names = readdirSync(base);
135
+ } catch {
136
+ return { totalBytes: 0, entries: [] };
137
+ }
138
+ for (const name of names) {
139
+ const full = join(base, name);
140
+ const bytes = dirSize(full);
141
+ entries.push({ name, bytes });
142
+ total += bytes;
143
+ }
144
+ entries.sort((a, b) => b.bytes - a.bytes);
145
+ return { totalBytes: total, entries };
146
+ }
147
+ function dirSize(path) {
148
+ try {
149
+ const st = statSync(path);
150
+ if (st.isFile()) return st.size;
151
+ if (!st.isDirectory()) return 0;
152
+ let sum = 0;
153
+ for (const name of readdirSync(path)) {
154
+ sum += dirSize(join(path, name));
155
+ }
156
+ return sum;
157
+ } catch {
158
+ return 0;
159
+ }
160
+ }
161
+
162
+ export {
163
+ writeCrashLog,
164
+ listRecentCrashes,
165
+ getConfigDirUsage
166
+ };
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-LO4MSGGO.js";
11
+ } from "./chunk-BS7EUZSO.js";
12
12
 
13
13
  // src/config/config-manager.ts
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -5,7 +5,12 @@ import {
5
5
  } from "./chunk-3BICTI5M.js";
6
6
  import {
7
7
  runTestsTool
8
- } from "./chunk-W622HYR2.js";
8
+ } from "./chunk-4QMGQO4P.js";
9
+ import {
10
+ getDangerLevel,
11
+ isFileWriteTool,
12
+ runTool
13
+ } from "./chunk-2OMBLQP6.js";
9
14
  import {
10
15
  EnvLoader,
11
16
  NetworkError,
@@ -18,7 +23,7 @@ import {
18
23
  SUBAGENT_ALLOWED_TOOLS,
19
24
  SUBAGENT_DEFAULT_MAX_ROUNDS,
20
25
  SUBAGENT_MAX_ROUNDS_LIMIT
21
- } from "./chunk-LO4MSGGO.js";
26
+ } from "./chunk-BS7EUZSO.js";
22
27
  import {
23
28
  fileCheckpoints
24
29
  } from "./chunk-4BKXL7SM.js";
@@ -33,61 +38,6 @@ import {
33
38
  loadIndex
34
39
  } from "./chunk-6VRJGH25.js";
35
40
 
36
- // src/tools/types.ts
37
- function isFileWriteTool(name) {
38
- return name === "write_file" || name === "edit_file" || name === "notebook_edit";
39
- }
40
- function getDangerLevel(toolName, args) {
41
- if (toolName.startsWith("mcp__")) return "safe";
42
- if (toolName === "bash") {
43
- const cmd = String(args["command"] ?? "");
44
- if (/\brm\s+[^\n]*(?:-\w*[rRfF]\w*|--recursive|--force)\b/.test(cmd)) return "destructive";
45
- if (/\brm\s+\S/.test(cmd)) return "destructive";
46
- if (/\brmdir\b|\bformat\b|\bmkfs\b|\bdd\s+if=|\bshred\b|\bfdisk\b|\bparted\b/.test(cmd)) return "destructive";
47
- if (/\bshutdown\b|\breboot\b|\bhalt\b|\bpoweroff\b/.test(cmd)) return "destructive";
48
- if (/\bkill\s+-9\b|\bkillall\b/.test(cmd)) return "destructive";
49
- if (/\bRemove-Item\b|\bri\s+\S/i.test(cmd)) return "destructive";
50
- if (/\brd\s+\/s\b|\brmdir\s+\/s\b/i.test(cmd)) return "destructive";
51
- if (/\bdel\s+\S/.test(cmd)) return "destructive";
52
- if (/\bShutdown(-Computer)?\b|\bRestart-Computer\b/i.test(cmd)) return "destructive";
53
- if (/(?:^|[\s|;&])>>?\s*\S/.test(cmd)) return "write";
54
- if (/\btee\b|\bcp\b|\bmv\b|\bln\s+-s/.test(cmd)) return "write";
55
- if (/\bchmod\b|\bchown\b/.test(cmd)) return "write";
56
- if (/\bSet-Content\b|\bOut-File\b|\bAdd-Content\b|\bCopy-Item\b|\bMove-Item\b|\bSet-ItemProperty\b|\bNew-ItemProperty\b/i.test(cmd)) return "write";
57
- return "safe";
58
- }
59
- if (toolName === "write_file") return "write";
60
- if (toolName === "edit_file") return "write";
61
- if (toolName === "save_last_response") return "write";
62
- if (toolName === "run_interactive") {
63
- const exe = String(args["executable"] ?? "").toLowerCase();
64
- if (/\b(rm|rmdir|del|format|mkfs|Remove-Item)\b/i.test(exe)) return "destructive";
65
- if (/\b(bash|sh|zsh|cmd|powershell|pwsh|python|node|ruby|perl)\b/i.test(exe)) return "write";
66
- return "write";
67
- }
68
- if (toolName === "task_create" || toolName === "task_stop") return "write";
69
- if (toolName === "task_list") return "safe";
70
- if (toolName === "git_commit") return "write";
71
- if (toolName === "git_status" || toolName === "git_diff" || toolName === "git_log") return "safe";
72
- if (toolName === "notebook_edit") return "write";
73
- if (toolName === "read_file" || toolName === "list_dir" || toolName === "grep_files" || toolName === "glob_files" || toolName === "web_fetch" || toolName === "save_memory" || toolName === "ask_user" || toolName === "write_todos" || toolName === "google_search" || toolName === "spawn_agent" || toolName === "run_tests") return "safe";
74
- return "write";
75
- }
76
- function schemaToJsonSchema(schema) {
77
- const result = {
78
- type: schema.type,
79
- description: schema.description
80
- };
81
- if (schema.enum) result["enum"] = schema.enum;
82
- if (schema.items) result["items"] = schemaToJsonSchema(schema.items);
83
- if (schema.properties) {
84
- result["properties"] = Object.fromEntries(
85
- Object.entries(schema.properties).map(([k, v]) => [k, schemaToJsonSchema(v)])
86
- );
87
- }
88
- return result;
89
- }
90
-
91
41
  // src/tools/builtin/bash.ts
92
42
  import { spawn } from "child_process";
93
43
  import { existsSync as existsSync2, readdirSync, statSync } from "fs";
@@ -1548,7 +1498,7 @@ var ToolExecutor = class {
1548
1498
  if (action === "auto-approve") {
1549
1499
  this.printToolCall(call);
1550
1500
  try {
1551
- const rawContent = await tool.execute(call.arguments);
1501
+ const rawContent = await runTool(tool, call.arguments, call.name);
1552
1502
  const content = truncateOutput(rawContent, call.name);
1553
1503
  const wasTruncated = content !== rawContent;
1554
1504
  this.printToolResult(call.name, rawContent, false, wasTruncated);
@@ -1567,7 +1517,7 @@ var ToolExecutor = class {
1567
1517
  if (dangerLevel === "write") this.printDiffPreview(call);
1568
1518
  console.log(theme.warning(" \u26A1 Auto-approved (session /yolo mode)"));
1569
1519
  try {
1570
- const rawContent = await tool.execute(call.arguments);
1520
+ const rawContent = await runTool(tool, call.arguments, call.name);
1571
1521
  const content = truncateOutput(rawContent, call.name);
1572
1522
  const wasTruncated = content !== rawContent;
1573
1523
  this.printToolResult(call.name, rawContent, false, wasTruncated);
@@ -1605,7 +1555,7 @@ var ToolExecutor = class {
1605
1555
  this.printToolCall(call);
1606
1556
  }
1607
1557
  try {
1608
- const rawContent = await tool.execute(call.arguments);
1558
+ const rawContent = await runTool(tool, call.arguments, call.name);
1609
1559
  const content = truncateOutput(rawContent, call.name);
1610
1560
  const wasTruncated = content !== rawContent;
1611
1561
  this.printToolResult(call.name, rawContent, false, wasTruncated);
@@ -1688,7 +1638,7 @@ var ToolExecutor = class {
1688
1638
  return;
1689
1639
  }
1690
1640
  try {
1691
- const rawContent = await tool.execute(call.arguments);
1641
+ const rawContent = await runTool(tool, call.arguments, call.name);
1692
1642
  const content = truncateOutput(rawContent, call.name);
1693
1643
  const wasTruncated = content !== rawContent;
1694
1644
  this.printToolResult(call.name, rawContent, false, wasTruncated);
@@ -3849,7 +3799,7 @@ var SubAgentExecutor = class {
3849
3799
  }
3850
3800
  this.printToolCall(call, dangerLevel);
3851
3801
  try {
3852
- const rawContent = await tool.execute(call.arguments);
3802
+ const rawContent = await runTool(tool, call.arguments, call.name);
3853
3803
  const content = truncateOutput(rawContent, call.name);
3854
3804
  const wasTruncated = content !== rawContent;
3855
3805
  this.printToolResult(call.name, rawContent, false, wasTruncated);
@@ -5263,8 +5213,6 @@ var ToolRegistry = class {
5263
5213
  };
5264
5214
 
5265
5215
  export {
5266
- getDangerLevel,
5267
- schemaToJsonSchema,
5268
5216
  initTheme,
5269
5217
  theme,
5270
5218
  undoStack,
@@ -5272,6 +5220,7 @@ export {
5272
5220
  isInterrupted,
5273
5221
  requestInterrupt,
5274
5222
  resetInterrupt,
5223
+ runWithSessionKey,
5275
5224
  rlInternal,
5276
5225
  groupCallsByPhase,
5277
5226
  runSafePhases,
@@ -36,7 +36,7 @@ import {
36
36
  TEST_TIMEOUT,
37
37
  VERSION,
38
38
  buildUserIdentityPrompt
39
- } from "./chunk-LO4MSGGO.js";
39
+ } from "./chunk-BS7EUZSO.js";
40
40
  import "./chunk-PDX44BCA.js";
41
41
  export {
42
42
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getConfigDirUsage,
4
+ listRecentCrashes
5
+ } from "./chunk-SYF3BPZK.js";
6
+ import {
7
+ ProviderRegistry
8
+ } from "./chunk-M36KRNHE.js";
9
+ import {
10
+ ConfigManager
11
+ } from "./chunk-UVKO7T4I.js";
12
+ import {
13
+ getStatsSnapshot,
14
+ getTopFailingTools,
15
+ getTopUsedTools,
16
+ resetStats
17
+ } from "./chunk-2OMBLQP6.js";
18
+ import "./chunk-2ZD3YTVM.js";
19
+ import {
20
+ DEV_STATE_FILE_NAME,
21
+ MEMORY_FILE_NAME,
22
+ VERSION
23
+ } from "./chunk-BS7EUZSO.js";
24
+ import "./chunk-PDX44BCA.js";
25
+
26
+ // src/diagnostics/doctor-cli.ts
27
+ import { existsSync, statSync } from "fs";
28
+ import { join } from "path";
29
+ import { platform, release, arch } from "os";
30
+ async function collect() {
31
+ const config = new ConfigManager();
32
+ const registry = new ProviderRegistry();
33
+ await registry.initialize(
34
+ (id) => config.getApiKey(id),
35
+ (id) => ({
36
+ baseUrl: config.get("customBaseUrls")[id],
37
+ timeout: config.get("timeouts")[id]
38
+ }),
39
+ config.get("customProviders")
40
+ );
41
+ const providers = registry.listAll().map((p) => ({
42
+ id: p.id,
43
+ displayName: p.displayName,
44
+ configured: p.configured
45
+ }));
46
+ const configDir = config.getConfigDir();
47
+ const checkFile = (label, path) => {
48
+ const exists = existsSync(path);
49
+ let sizeBytes = null;
50
+ if (exists) {
51
+ try {
52
+ sizeBytes = statSync(path).size;
53
+ } catch {
54
+ }
55
+ }
56
+ return { label, path, exists, sizeBytes };
57
+ };
58
+ return {
59
+ version: VERSION,
60
+ node: process.version,
61
+ platform: `${platform()} ${release()} (${arch()})`,
62
+ configDir,
63
+ providers,
64
+ files: [
65
+ checkFile("config.json", join(configDir, "config.json")),
66
+ checkFile("memory.md", join(configDir, MEMORY_FILE_NAME)),
67
+ checkFile("dev-state.md", join(configDir, DEV_STATE_FILE_NAME))
68
+ ],
69
+ recentCrashes: listRecentCrashes(5, configDir),
70
+ diskUsage: getConfigDirUsage(configDir),
71
+ toolStats: (() => {
72
+ const all = getStatsSnapshot();
73
+ const totalCalls = all.reduce((a, b) => a + b.calls, 0);
74
+ const totalFailures = all.reduce((a, b) => a + b.failures, 0);
75
+ return {
76
+ totalCalls,
77
+ totalFailures,
78
+ topUsed: getTopUsedTools(5),
79
+ topFailing: getTopFailingTools(5)
80
+ };
81
+ })()
82
+ };
83
+ }
84
+ function formatBytes(n) {
85
+ if (n < 1024) return `${n} B`;
86
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
87
+ if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
88
+ return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
89
+ }
90
+ async function runDoctorCli(options = {}) {
91
+ if (options.resetStats) {
92
+ resetStats();
93
+ process.stdout.write("Tool stats reset.\n");
94
+ return;
95
+ }
96
+ const report = await collect();
97
+ if (options.json) {
98
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
99
+ return;
100
+ }
101
+ const B = "\x1B[1m";
102
+ const D = "\x1B[2m";
103
+ const G = "\x1B[32m";
104
+ const Y = "\x1B[33m";
105
+ const R_ = "\x1B[31m";
106
+ const RESET = "\x1B[0m";
107
+ const out = [];
108
+ out.push("");
109
+ out.push(`${B}\u{1FA7A} AI-CLI Health Check${RESET}`);
110
+ out.push("");
111
+ out.push(` version: ${report.version}`);
112
+ out.push(` node: ${report.node}`);
113
+ out.push(` platform: ${report.platform}`);
114
+ out.push(` config: ${report.configDir}`);
115
+ out.push("");
116
+ out.push(`${B}API Keys:${RESET}`);
117
+ for (const p of report.providers) {
118
+ const icon = p.configured ? `${G}\u2713${RESET}` : `${D}\u25CB${RESET}`;
119
+ const status = p.configured ? `${G}configured${RESET}` : `${D}not configured${RESET}`;
120
+ out.push(` ${icon} ${p.id.padEnd(14)} ${status}`);
121
+ }
122
+ out.push("");
123
+ out.push(`${B}Config Files:${RESET}`);
124
+ for (const f of report.files) {
125
+ const icon = f.exists ? `${G}\u2713${RESET}` : `${D}\u2013${RESET}`;
126
+ const extra = f.exists && f.sizeBytes !== null ? ` ${D}(${formatBytes(f.sizeBytes)})${RESET}` : "";
127
+ out.push(` ${icon} ${f.label.padEnd(14)} ${f.exists ? f.path : `${D}(not found)${RESET}`}${extra}`);
128
+ }
129
+ out.push("");
130
+ out.push(`${B}Recent Crashes (last 5):${RESET}`);
131
+ if (report.recentCrashes.length === 0) {
132
+ out.push(` ${D}(none \u2014 clean!)${RESET}`);
133
+ } else {
134
+ for (const c of report.recentCrashes) {
135
+ out.push(` ${R_}\u2717${RESET} ${c.timestamp} ${Y}${c.kind}${RESET}`);
136
+ out.push(` ${D}${c.message}${RESET}`);
137
+ out.push(` ${D}${c.file}${RESET}`);
138
+ }
139
+ }
140
+ out.push("");
141
+ out.push(`${B}Tool Usage:${RESET}`);
142
+ const ts = report.toolStats;
143
+ out.push(` total: ${ts.totalCalls} calls \xB7 ${ts.totalFailures} failures (${ts.totalCalls ? (ts.totalFailures * 100 / ts.totalCalls).toFixed(1) : "0.0"}%)`);
144
+ if (ts.topUsed.length > 0) {
145
+ out.push(` ${D}top used:${RESET}`);
146
+ for (const t of ts.topUsed) {
147
+ const avg = t.calls ? (t.totalDurationMs / t.calls).toFixed(0) : "0";
148
+ out.push(` ${t.name.padEnd(20)} ${String(t.calls).padStart(6)} calls \xB7 avg ${avg}ms`);
149
+ }
150
+ }
151
+ if (ts.topFailing.length > 0) {
152
+ out.push(` ${D}top failing:${RESET}`);
153
+ for (const t of ts.topFailing) {
154
+ const rate = (t.failures * 100 / Math.max(1, t.calls)).toFixed(1);
155
+ out.push(` ${R_}${t.name.padEnd(20)}${RESET} ${t.failures}/${t.calls} (${rate}%) ${D}${t.lastFailureMessage ?? ""}${RESET}`.slice(0, 200));
156
+ }
157
+ }
158
+ out.push("");
159
+ out.push(`${B}Disk Usage (~/.aicli):${RESET}`);
160
+ out.push(` total: ${formatBytes(report.diskUsage.totalBytes)}`);
161
+ for (const e of report.diskUsage.entries.slice(0, 8)) {
162
+ out.push(` ${e.name.padEnd(18)} ${formatBytes(e.bytes)}`);
163
+ }
164
+ out.push("");
165
+ out.push(`${G}\u2713 Health check complete${RESET}`);
166
+ out.push("");
167
+ process.stdout.write(out.join("\n"));
168
+ }
169
+ export {
170
+ runDoctorCli
171
+ };