jinzd-ai-cli 0.4.218 → 0.4.219

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.
Files changed (30) hide show
  1. package/README.md +1 -0
  2. package/dist/{batch-7V7OTMUP.js → batch-CHAPYRVM.js} +2 -2
  3. package/dist/chunk-3I4RZYYO.js +638 -0
  4. package/dist/{chunk-L4UREAID.js → chunk-4ZN6L6K5.js} +3 -3
  5. package/dist/{chunk-VGFTM3XT.js → chunk-64NUW3WL.js} +1 -1
  6. package/dist/{chunk-C2Z42DI5.js → chunk-EGMORH5W.js} +1 -1
  7. package/dist/{chunk-GX3HSGJX.js → chunk-GEN4O5QH.js} +165 -637
  8. package/dist/chunk-GGKQHPB3.js +604 -0
  9. package/dist/{chunk-P4VBLXKS.js → chunk-KIEZBTVD.js} +1 -1
  10. package/dist/{chunk-H2UIHGHH.js → chunk-QUFYBR6Q.js} +29 -189
  11. package/dist/{chunk-NTCB7CMT.js → chunk-U7KVU25H.js} +1 -1
  12. package/dist/{chunk-5CA2TJ5F.js → chunk-VADHBW7T.js} +1 -1
  13. package/dist/{ci-L6GH2WVC.js → ci-QPP66T53.js} +4 -4
  14. package/dist/{ci-format-WW7454AY.js → ci-format-5S3EEYRK.js} +2 -2
  15. package/dist/{constants-NCTFSHDU.js → constants-FJOLBABC.js} +1 -1
  16. package/dist/doctor-cli-KB2LUDF3.js +17 -0
  17. package/dist/electron-server.js +419 -116
  18. package/dist/{hub-CDL6T7CP.js → hub-DIM7SKKY.js} +1 -1
  19. package/dist/index.js +71 -181
  20. package/dist/{pr-D6PEKEGK.js → pr-YQGH72N6.js} +4 -4
  21. package/dist/{run-tests-SWU2XEV7.js → run-tests-GEZSSNJM.js} +2 -2
  22. package/dist/{run-tests-NXVVKAK2.js → run-tests-O76JIBCW.js} +1 -1
  23. package/dist/{server-LHYSS6CK.js → server-5E2AIXVX.js} +39 -75
  24. package/dist/{server-WUT7VYTD.js → server-Z6O3G2LY.js} +9 -9
  25. package/dist/{task-orchestrator-C5AA2BI5.js → task-orchestrator-5HBW4O64.js} +9 -9
  26. package/dist/{usage-6ZUUJBI2.js → usage-BMK6M5U3.js} +2 -2
  27. package/package.json +1 -1
  28. package/dist/chunk-MWKE2TNS.js +0 -129
  29. package/dist/chunk-OUC75QCF.js +0 -166
  30. package/dist/doctor-cli-EWMFBP5Q.js +0 -226
@@ -17,14 +17,13 @@ import {
17
17
  SkillManager,
18
18
  autoTrimSessionIfNeeded,
19
19
  buildInitPrompt,
20
- loadContextFiles,
21
20
  loadDevState,
22
21
  persistToolRound,
23
22
  readGitDiff,
24
23
  scanDirTree,
25
24
  scanProject,
26
25
  setupProxy
27
- } from "./chunk-H2UIHGHH.js";
26
+ } from "./chunk-QUFYBR6Q.js";
28
27
  import {
29
28
  buildReviewPrompt,
30
29
  buildSecurityReviewPrompt
@@ -40,49 +39,38 @@ import {
40
39
  clearRecentlyDeniedAutoActions,
41
40
  defaultActionClassifier,
42
41
  deleteMemoryEntry,
43
- describePlugin,
44
42
  estimateTokens,
45
43
  expireMemoryEntry,
46
44
  exportMemoryEntries,
47
45
  formatMemoryForPrompt,
48
46
  formatPermissionProfileWarning,
49
- getActivePluginAssets,
50
- getInstalledPlugin,
51
- getPendingHookTrust,
52
47
  getPreferredAgentName,
53
48
  getRecentlyDeniedAutoActions,
54
49
  googleSearchContext,
55
50
  groupCallsByPhase,
56
- installPlugin,
57
51
  isMemoryExpired,
58
52
  listAgentConfigs,
59
53
  listAgentRuns,
60
- listInstalledPlugins,
61
54
  listMemoryEntries,
62
55
  memoryStorePath,
63
- mergePluginHooks,
64
- pluginRoot,
65
56
  recordRecentlyDeniedAutoAction,
66
57
  renderDiff,
67
58
  requestAgentStop,
68
59
  resolveAgentConfig,
69
- runHook,
70
- runLifecycleHooks,
71
60
  runSafePhases,
72
61
  runWithSessionKey,
73
62
  setContextWindow,
74
63
  setMaxOutputCap,
75
- setPluginEnabled,
76
64
  setPreferredAgentName,
77
65
  spawnAgentContext,
78
66
  truncateOutput,
79
- trustPlugin,
80
67
  undoStack,
81
68
  updateMemoryApproval
82
- } from "./chunk-GX3HSGJX.js";
69
+ } from "./chunk-GEN4O5QH.js";
70
+ import "./chunk-K3CF65QH.js";
83
71
  import "./chunk-T2NL5ZIA.js";
84
72
  import "./chunk-BXP6YZ2P.js";
85
- import "./chunk-VGFTM3XT.js";
73
+ import "./chunk-64NUW3WL.js";
86
74
  import {
87
75
  SessionManager,
88
76
  getContentText
@@ -91,12 +79,35 @@ import {
91
79
  computeCost,
92
80
  formatCost
93
81
  } from "./chunk-E44DTERW.js";
82
+ import "./chunk-4BKXL7SM.js";
83
+ import "./chunk-TB4W4Y4T.js";
84
+ import "./chunk-KHYD3WXE.js";
85
+ import {
86
+ scanString
87
+ } from "./chunk-SLSWPBK3.js";
88
+ import {
89
+ buildDoctorReport,
90
+ formatDoctorReport,
91
+ loadContextFiles
92
+ } from "./chunk-3I4RZYYO.js";
94
93
  import {
95
94
  ProviderRegistry
96
95
  } from "./chunk-QMXC327F.js";
97
96
  import {
98
- runTool
99
- } from "./chunk-MWKE2TNS.js";
97
+ describePlugin,
98
+ getActivePluginAssets,
99
+ getInstalledPlugin,
100
+ getPendingHookTrust,
101
+ installPlugin,
102
+ listInstalledPlugins,
103
+ mergePluginHooks,
104
+ pluginRoot,
105
+ runHook,
106
+ runLifecycleHooks,
107
+ runTool,
108
+ setPluginEnabled,
109
+ trustPlugin
110
+ } from "./chunk-GGKQHPB3.js";
100
111
  import {
101
112
  CONTENT_ONLY_STREAM_REMINDER,
102
113
  TEE_FINAL_USER_NUDGE,
@@ -115,7 +126,7 @@ import {
115
126
  } from "./chunk-XPBEJB27.js";
116
127
  import {
117
128
  ConfigManager
118
- } from "./chunk-P4VBLXKS.js";
129
+ } from "./chunk-KIEZBTVD.js";
119
130
  import "./chunk-TZQHYZKT.js";
120
131
  import {
121
132
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -133,19 +144,12 @@ import {
133
144
  SKILLS_DIR_NAME,
134
145
  VERSION,
135
146
  buildUserIdentityPrompt
136
- } from "./chunk-NTCB7CMT.js";
147
+ } from "./chunk-U7KVU25H.js";
137
148
  import {
138
149
  formatGitContextForPrompt,
139
150
  getGitContext,
140
151
  getGitRoot
141
152
  } from "./chunk-HOSJZMQS.js";
142
- import "./chunk-4BKXL7SM.js";
143
- import "./chunk-TB4W4Y4T.js";
144
- import "./chunk-KHYD3WXE.js";
145
- import {
146
- scanString
147
- } from "./chunk-SLSWPBK3.js";
148
- import "./chunk-K3CF65QH.js";
149
153
  import "./chunk-CKH4KQ4E.js";
150
154
  import {
151
155
  atomicWriteFileSync
@@ -2761,7 +2765,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2761
2765
  case "test": {
2762
2766
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2763
2767
  try {
2764
- const { executeTests } = await import("./run-tests-SWU2XEV7.js");
2768
+ const { executeTests } = await import("./run-tests-GEZSSNJM.js");
2765
2769
  const argStr = args.join(" ").trim();
2766
2770
  let testArgs = {};
2767
2771
  if (argStr) {
@@ -2800,53 +2804,13 @@ Use /context reload to load it.` });
2800
2804
  }
2801
2805
  // ── /doctor ─────────────────────────────────────────────────────
2802
2806
  case "doctor": {
2803
- const lines = ["\u{1FA7A} **AI-CLI Health Check**", ""];
2804
- lines.push("**API Keys:**");
2805
- const providersList = this.providers.listAll();
2806
- for (const p of providersList) {
2807
- const icon = p.configured ? "\u2713" : "\u25CB";
2808
- const status = p.configured ? "configured" : "not configured";
2809
- lines.push(` ${icon} ${p.id.padEnd(14)} ${status}`);
2810
- }
2811
- lines.push("");
2812
- const configDir = this.config.getConfigDir();
2813
- lines.push("**Config Files:**");
2814
- lines.push(` Dir: ${configDir}`);
2815
- const checkFile = (label, filePath) => {
2816
- const exists = existsSync2(filePath);
2817
- let extra = "";
2818
- if (exists) {
2819
- try {
2820
- extra = ` (${statSync(filePath).size} bytes)`;
2821
- } catch {
2822
- }
2823
- }
2824
- lines.push(` ${exists ? "\u2713" : "\u2013"} ${label.padEnd(14)} ${exists ? filePath + extra : "(not found)"}`);
2825
- };
2826
- checkFile("config.json", join(configDir, "config.json"));
2827
- checkFile("memory.md", join(configDir, MEMORY_FILE_NAME));
2828
- checkFile("dev-state.md", join(configDir, "dev-state.md"));
2829
- lines.push("");
2830
- if (this.mcpManager) {
2831
- lines.push("**MCP Servers:**");
2832
- const statuses = this.mcpManager.getStatus();
2833
- if (statuses.length === 0) {
2834
- lines.push(" (no servers configured)");
2835
- } else {
2836
- for (const s of statuses) {
2837
- const state = s.connected ? `connected \xB7 ${s.serverName} \xB7 ${s.toolCount} tools` : `disconnected${s.error ? ` \xB7 ${s.error}` : ""}`;
2838
- lines.push(` ${s.connected ? "\u2713" : "\u2717"} ${s.serverId.padEnd(16)} ${state}`);
2839
- }
2840
- }
2841
- lines.push("");
2842
- }
2843
- lines.push("**Current Session:**");
2844
- lines.push(` Provider: ${this.currentProvider}`);
2845
- lines.push(` Model: ${this.currentModel}`);
2846
- lines.push(` Version: ${VERSION}`);
2847
- lines.push("");
2848
- lines.push("\u2713 Health check complete");
2849
- this.send({ type: "info", message: lines.join("\n") });
2807
+ const report = buildDoctorReport({
2808
+ config: this.config,
2809
+ providers: this.providers,
2810
+ cwd: process.cwd(),
2811
+ mcpStatuses: this.mcpManager?.getStatus() ?? []
2812
+ });
2813
+ this.send({ type: "info", message: formatDoctorReport(report, false) });
2850
2814
  break;
2851
2815
  }
2852
2816
  // ── /about ──────────────────────────────────────────────────────
@@ -1,13 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-GX3HSGJX.js";
4
+ } from "./chunk-GEN4O5QH.js";
5
+ import "./chunk-K3CF65QH.js";
5
6
  import "./chunk-T2NL5ZIA.js";
6
7
  import "./chunk-BXP6YZ2P.js";
7
- import "./chunk-VGFTM3XT.js";
8
+ import "./chunk-64NUW3WL.js";
9
+ import "./chunk-4BKXL7SM.js";
10
+ import "./chunk-TB4W4Y4T.js";
11
+ import "./chunk-KHYD3WXE.js";
12
+ import "./chunk-SLSWPBK3.js";
8
13
  import {
9
14
  runTool
10
- } from "./chunk-MWKE2TNS.js";
15
+ } from "./chunk-GGKQHPB3.js";
11
16
  import {
12
17
  getDangerLevel,
13
18
  schemaToJsonSchema
@@ -15,13 +20,8 @@ import {
15
20
  import "./chunk-TZQHYZKT.js";
16
21
  import {
17
22
  VERSION
18
- } from "./chunk-NTCB7CMT.js";
23
+ } from "./chunk-U7KVU25H.js";
19
24
  import "./chunk-HOSJZMQS.js";
20
- import "./chunk-4BKXL7SM.js";
21
- import "./chunk-TB4W4Y4T.js";
22
- import "./chunk-KHYD3WXE.js";
23
- import "./chunk-SLSWPBK3.js";
24
- import "./chunk-K3CF65QH.js";
25
25
  import "./chunk-CKH4KQ4E.js";
26
26
  import "./chunk-IW3Q7AE5.js";
27
27
 
@@ -3,13 +3,18 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-GX3HSGJX.js";
6
+ } from "./chunk-GEN4O5QH.js";
7
+ import "./chunk-K3CF65QH.js";
7
8
  import "./chunk-T2NL5ZIA.js";
8
9
  import "./chunk-BXP6YZ2P.js";
9
- import "./chunk-VGFTM3XT.js";
10
+ import "./chunk-64NUW3WL.js";
11
+ import "./chunk-4BKXL7SM.js";
12
+ import "./chunk-TB4W4Y4T.js";
13
+ import "./chunk-KHYD3WXE.js";
14
+ import "./chunk-SLSWPBK3.js";
10
15
  import {
11
16
  runTool
12
- } from "./chunk-MWKE2TNS.js";
17
+ } from "./chunk-GGKQHPB3.js";
13
18
  import {
14
19
  getDangerLevel,
15
20
  runLeanAgentLoop
@@ -17,13 +22,8 @@ import {
17
22
  import "./chunk-TZQHYZKT.js";
18
23
  import {
19
24
  SUBAGENT_ALLOWED_TOOLS
20
- } from "./chunk-NTCB7CMT.js";
25
+ } from "./chunk-U7KVU25H.js";
21
26
  import "./chunk-HOSJZMQS.js";
22
- import "./chunk-4BKXL7SM.js";
23
- import "./chunk-TB4W4Y4T.js";
24
- import "./chunk-KHYD3WXE.js";
25
- import "./chunk-SLSWPBK3.js";
26
- import "./chunk-K3CF65QH.js";
27
27
  import "./chunk-CKH4KQ4E.js";
28
28
  import {
29
29
  atomicWriteFileSync
@@ -8,9 +8,9 @@ import {
8
8
  } from "./chunk-E44DTERW.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-P4VBLXKS.js";
11
+ } from "./chunk-KIEZBTVD.js";
12
12
  import "./chunk-TZQHYZKT.js";
13
- import "./chunk-NTCB7CMT.js";
13
+ import "./chunk-U7KVU25H.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
 
16
16
  // src/cli/usage.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.218",
3
+ "version": "0.4.219",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,129 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- CONFIG_DIR_NAME
4
- } from "./chunk-NTCB7CMT.js";
5
- import {
6
- atomicWriteFileSync
7
- } from "./chunk-IW3Q7AE5.js";
8
-
9
- // src/diagnostics/tool-stats.ts
10
- import { existsSync, readFileSync, mkdirSync } from "fs";
11
- import { join, dirname } from "path";
12
- import { homedir } from "os";
13
- var STATS_FILE_NAME = "tool-stats.json";
14
- var STATS_VERSION = 1;
15
- var FLUSH_EVERY_N = 50;
16
- var state = null;
17
- var dirty = false;
18
- var pendingWrites = 0;
19
- var configDirOverride;
20
- function statsFilePath() {
21
- const base = configDirOverride ?? join(homedir(), CONFIG_DIR_NAME);
22
- return join(base, STATS_FILE_NAME);
23
- }
24
- function load() {
25
- const path = statsFilePath();
26
- if (!existsSync(path)) {
27
- return { version: STATS_VERSION, startedAt: (/* @__PURE__ */ new Date()).toISOString(), entries: {} };
28
- }
29
- try {
30
- const raw = JSON.parse(readFileSync(path, "utf-8"));
31
- if (raw.version !== STATS_VERSION || !raw.entries) {
32
- return { version: STATS_VERSION, startedAt: (/* @__PURE__ */ new Date()).toISOString(), entries: {} };
33
- }
34
- return raw;
35
- } catch {
36
- return { version: STATS_VERSION, startedAt: (/* @__PURE__ */ new Date()).toISOString(), entries: {} };
37
- }
38
- }
39
- function ensureLoaded() {
40
- if (state === null) state = load();
41
- return state;
42
- }
43
- function recordToolCall(name, durationMs, ok, errorMessage) {
44
- const s = ensureLoaded();
45
- const now = (/* @__PURE__ */ new Date()).toISOString();
46
- let entry = s.entries[name];
47
- if (!entry) {
48
- entry = {
49
- name,
50
- calls: 0,
51
- failures: 0,
52
- totalDurationMs: 0,
53
- firstSeenAt: now,
54
- lastUsedAt: now
55
- };
56
- s.entries[name] = entry;
57
- }
58
- entry.calls += 1;
59
- entry.totalDurationMs += Math.max(0, Math.round(durationMs));
60
- entry.lastUsedAt = now;
61
- if (!ok) {
62
- entry.failures += 1;
63
- entry.lastFailureAt = now;
64
- if (errorMessage) entry.lastFailureMessage = errorMessage.slice(0, 300);
65
- }
66
- dirty = true;
67
- pendingWrites += 1;
68
- if (pendingWrites >= FLUSH_EVERY_N) {
69
- flush();
70
- }
71
- }
72
- async function runTool(tool, args, name) {
73
- const start = Date.now();
74
- try {
75
- const result = await tool.execute(args);
76
- recordToolCall(name, Date.now() - start, true);
77
- return result;
78
- } catch (err) {
79
- const msg = err instanceof Error ? err.message : String(err);
80
- recordToolCall(name, Date.now() - start, false, msg);
81
- throw err;
82
- }
83
- }
84
- function flush() {
85
- if (!dirty || state === null) return;
86
- const path = statsFilePath();
87
- try {
88
- mkdirSync(dirname(path), { recursive: true });
89
- atomicWriteFileSync(path, JSON.stringify(state, null, 2));
90
- dirty = false;
91
- pendingWrites = 0;
92
- } catch {
93
- }
94
- }
95
- function getStatsSnapshot() {
96
- const s = ensureLoaded();
97
- return Object.values(s.entries).map((e) => ({ ...e }));
98
- }
99
- function getTopFailingTools(limit = 5) {
100
- return getStatsSnapshot().filter((e) => e.failures > 0).sort((a, b) => {
101
- const rateA = a.failures / Math.max(1, a.calls);
102
- const rateB = b.failures / Math.max(1, b.calls);
103
- if (rateB !== rateA) return rateB - rateA;
104
- return b.failures - a.failures;
105
- }).slice(0, limit);
106
- }
107
- function getTopUsedTools(limit = 5) {
108
- return getStatsSnapshot().sort((a, b) => b.calls - a.calls).slice(0, limit);
109
- }
110
- function resetStats() {
111
- state = { version: STATS_VERSION, startedAt: (/* @__PURE__ */ new Date()).toISOString(), entries: {} };
112
- dirty = true;
113
- flush();
114
- }
115
- var exitHookInstalled = false;
116
- function installFlushOnExit() {
117
- if (exitHookInstalled) return;
118
- exitHookInstalled = true;
119
- process.on("exit", () => flush());
120
- }
121
-
122
- export {
123
- runTool,
124
- getStatsSnapshot,
125
- getTopFailingTools,
126
- getTopUsedTools,
127
- resetStats,
128
- installFlushOnExit
129
- };
@@ -1,166 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- CONFIG_DIR_NAME,
4
- VERSION
5
- } from "./chunk-NTCB7CMT.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
- };