jinzd-ai-cli 0.4.217 → 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 +5 -2
  2. package/dist/{batch-YCOVKTXD.js → batch-CHAPYRVM.js} +2 -2
  3. package/dist/chunk-3I4RZYYO.js +638 -0
  4. package/dist/{chunk-KOPUCJXM.js → chunk-4ZN6L6K5.js} +3 -3
  5. package/dist/{chunk-VTH7BLXK.js → chunk-64NUW3WL.js} +1 -1
  6. package/dist/{chunk-QAYOI57M.js → chunk-EGMORH5W.js} +1 -1
  7. package/dist/{chunk-MGBMNCHG.js → chunk-GEN4O5QH.js} +94 -270
  8. package/dist/chunk-GGKQHPB3.js +604 -0
  9. package/dist/{chunk-WKOQ5CYC.js → chunk-KIEZBTVD.js} +1 -1
  10. package/dist/{chunk-OUAZOE5U.js → chunk-QUFYBR6Q.js} +47 -206
  11. package/dist/{chunk-XJGEQIYS.js → chunk-U7KVU25H.js} +1 -1
  12. package/dist/{chunk-WZ3VKLF3.js → chunk-VADHBW7T.js} +1 -1
  13. package/dist/{ci-52RZIYWB.js → ci-QPP66T53.js} +4 -4
  14. package/dist/{ci-format-73UXKE65.js → ci-format-5S3EEYRK.js} +2 -2
  15. package/dist/{constants-DIXAD35W.js → constants-FJOLBABC.js} +1 -1
  16. package/dist/doctor-cli-KB2LUDF3.js +17 -0
  17. package/dist/electron-server.js +921 -274
  18. package/dist/{hub-GIGBITZN.js → hub-DIM7SKKY.js} +1 -1
  19. package/dist/index.js +192 -200
  20. package/dist/{pr-KPQ5RPKB.js → pr-YQGH72N6.js} +4 -4
  21. package/dist/{run-tests-ZDSA3QES.js → run-tests-GEZSSNJM.js} +2 -2
  22. package/dist/{run-tests-K7QR5QN4.js → run-tests-O76JIBCW.js} +1 -1
  23. package/dist/{server-QT3SC2KI.js → server-5E2AIXVX.js} +108 -80
  24. package/dist/{server-22YF3U34.js → server-Z6O3G2LY.js} +9 -9
  25. package/dist/{task-orchestrator-BHQQCVTY.js → task-orchestrator-5HBW4O64.js} +9 -9
  26. package/dist/{usage-WZZFSFLM.js → usage-BMK6M5U3.js} +2 -2
  27. package/package.json +1 -1
  28. package/dist/chunk-524WZOKS.js +0 -166
  29. package/dist/chunk-SNJAOXFT.js +0 -129
  30. package/dist/doctor-cli-7GOQPULZ.js +0 -226
@@ -1,180 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-MGBMNCHG.js";
4
+ } from "./chunk-GEN4O5QH.js";
5
5
  import {
6
6
  APP_NAME,
7
7
  CONFIG_DIR_NAME,
8
- CONTEXT_FILE_CANDIDATES,
9
- CONTEXT_FILE_MAX_BYTES,
10
8
  DEV_STATE_FILE_NAME,
11
9
  MCP_CALL_TIMEOUT,
12
10
  MCP_CONNECT_TIMEOUT,
13
11
  MCP_PROTOCOL_VERSION,
14
12
  MCP_TOOL_PREFIX,
15
13
  VERSION
16
- } from "./chunk-XJGEQIYS.js";
14
+ } from "./chunk-U7KVU25H.js";
17
15
  import {
18
16
  atomicWriteFileSync
19
17
  } from "./chunk-IW3Q7AE5.js";
20
18
 
21
- // src/core/context-files.ts
22
- import { existsSync, readFileSync } from "fs";
23
- import { join, relative, resolve } from "path";
24
- function uniqueNonEmpty(values) {
25
- const seen = /* @__PURE__ */ new Set();
26
- const out = [];
27
- for (const value of values) {
28
- const trimmed = value.trim();
29
- if (!trimmed || seen.has(trimmed)) continue;
30
- seen.add(trimmed);
31
- out.push(trimmed);
32
- }
33
- return out;
34
- }
35
- function buildContextFileCandidates(fallbackFilenames = []) {
36
- return uniqueNonEmpty([...CONTEXT_FILE_CANDIDATES, ...fallbackFilenames]);
37
- }
38
- function displayPath(filePath, cwd) {
39
- const rel = relative(cwd, filePath);
40
- if (rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.startsWith("\\")) {
41
- return rel;
42
- }
43
- return filePath;
44
- }
45
- function isInsideOrEqual(parent, child) {
46
- const rel = relative(resolve(parent), resolve(child));
47
- return rel === "" || !!rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.startsWith("\\");
48
- }
49
- function readContextFile(level, filePath, cwd, maxBytes) {
50
- const name = filePath.split(/[\\/]/).pop() ?? filePath;
51
- const shown = displayPath(filePath, cwd);
52
- try {
53
- const raw = readFileSync(filePath);
54
- const byteCount = raw.byteLength;
55
- if (byteCount === 0) {
56
- return {
57
- layer: null,
58
- skipped: { level, filePath, displayPath: shown, fileName: name, reason: "empty" }
59
- };
60
- }
61
- const truncated = byteCount > maxBytes;
62
- const bytes = truncated ? raw.subarray(0, maxBytes) : raw;
63
- const content = bytes.toString("utf-8").trim();
64
- if (!content) {
65
- return {
66
- layer: null,
67
- skipped: { level, filePath, displayPath: shown, fileName: name, reason: "empty" }
68
- };
69
- }
70
- return {
71
- layer: {
72
- level: level === "single" ? "project" : level,
73
- filePath,
74
- displayPath: shown,
75
- fileName: name,
76
- content,
77
- charCount: content.length,
78
- byteCount,
79
- truncated
80
- },
81
- skipped: truncated ? { level, filePath, displayPath: shown, fileName: name, reason: "too-large", message: `truncated to ${maxBytes} bytes` } : null
82
- };
83
- } catch (err) {
84
- return {
85
- layer: null,
86
- skipped: {
87
- level,
88
- filePath,
89
- displayPath: shown,
90
- fileName: name,
91
- reason: "read-error",
92
- message: err instanceof Error ? err.message : String(err)
93
- }
94
- };
95
- }
96
- }
97
- function findFirstContextFile(level, dir, cwd, candidates, maxBytes) {
98
- const skipped = [];
99
- for (const candidate of candidates) {
100
- const filePath = join(dir, candidate);
101
- if (!existsSync(filePath)) continue;
102
- const result = readContextFile(level, filePath, cwd, maxBytes);
103
- if (result.skipped) skipped.push(result.skipped);
104
- if (result.layer) return { layer: result.layer, skipped };
105
- }
106
- return { layer: null, skipped };
107
- }
108
- function loadContextFiles(options) {
109
- const cwd = resolve(options.cwd);
110
- const maxBytes = options.maxBytes ?? CONTEXT_FILE_MAX_BYTES;
111
- const candidates = options.candidates ?? buildContextFileCandidates(options.fallbackFilenames);
112
- const skipped = [];
113
- if (options.setting === false) {
114
- return { layers: [], mergedContent: "", skipped, totalChars: 0, totalBytes: 0, maxBytes, candidates };
115
- }
116
- if (options.setting && options.setting !== "auto") {
117
- const filePath = resolve(cwd, String(options.setting));
118
- if (!isInsideOrEqual(cwd, filePath)) {
119
- skipped.push({
120
- level: "single",
121
- filePath,
122
- displayPath: filePath,
123
- fileName: String(options.setting),
124
- reason: "outside-cwd"
125
- });
126
- return { layers: [], mergedContent: "", skipped, totalChars: 0, totalBytes: 0, maxBytes, candidates };
127
- }
128
- if (!existsSync(filePath)) {
129
- skipped.push({
130
- level: "single",
131
- filePath,
132
- displayPath: displayPath(filePath, cwd),
133
- fileName: String(options.setting),
134
- reason: "missing"
135
- });
136
- return { layers: [], mergedContent: "", skipped, totalChars: 0, totalBytes: 0, maxBytes, candidates };
137
- }
138
- const result = readContextFile("single", filePath, cwd, maxBytes);
139
- if (result.skipped) skipped.push(result.skipped);
140
- const layers2 = result.layer ? [result.layer] : [];
141
- const mergedContent2 = layers2.map((l) => l.content).join("\n\n---\n\n");
142
- return {
143
- layers: layers2,
144
- mergedContent: mergedContent2,
145
- skipped,
146
- totalChars: layers2.reduce((sum, l) => sum + l.charCount, 0),
147
- totalBytes: layers2.reduce((sum, l) => sum + l.byteCount, 0),
148
- maxBytes,
149
- candidates
150
- };
151
- }
152
- const layers = [];
153
- for (const [level, dir] of [
154
- ["global", options.configDir],
155
- ["project", options.projectRoot]
156
- ]) {
157
- const result = findFirstContextFile(level, dir, cwd, candidates, maxBytes);
158
- skipped.push(...result.skipped);
159
- if (result.layer) layers.push(result.layer);
160
- }
161
- if (resolve(options.cwd) !== resolve(options.projectRoot)) {
162
- const result = findFirstContextFile("local", options.cwd, cwd, candidates, maxBytes);
163
- skipped.push(...result.skipped);
164
- if (result.layer) layers.push(result.layer);
165
- }
166
- const mergedContent = layers.map((l) => l.content).join("\n\n---\n\n");
167
- return {
168
- layers,
169
- mergedContent,
170
- skipped,
171
- totalChars: layers.reduce((sum, l) => sum + l.charCount, 0),
172
- totalBytes: layers.reduce((sum, l) => sum + l.byteCount, 0),
173
- maxBytes,
174
- candidates
175
- };
176
- }
177
-
178
19
  // src/mcp/client.ts
179
20
  import { spawn } from "child_process";
180
21
  var McpClient = class {
@@ -310,7 +151,7 @@ var McpClient = class {
310
151
  // 内部方法:JSON-RPC 通信
311
152
  // ══════════════════════════════════════════════════════════════════
312
153
  sendRequest(method, params) {
313
- return new Promise((resolve2, reject) => {
154
+ return new Promise((resolve, reject) => {
314
155
  if (!this.process?.stdin?.writable) {
315
156
  return reject(new Error(`MCP server [${this.serverId}] stdin not writable`));
316
157
  }
@@ -334,7 +175,7 @@ var McpClient = class {
334
175
  this.pendingRequests.set(id, {
335
176
  resolve: (result) => {
336
177
  cleanup();
337
- resolve2(result);
178
+ resolve(result);
338
179
  },
339
180
  reject: (error) => {
340
181
  cleanup();
@@ -411,13 +252,13 @@ var McpClient = class {
411
252
  }
412
253
  /** Promise 超时包装 */
413
254
  withTimeout(promise, ms, label) {
414
- return new Promise((resolve2, reject) => {
255
+ return new Promise((resolve, reject) => {
415
256
  const timer = setTimeout(() => {
416
257
  reject(new Error(`MCP [${this.serverId}] ${label} timed out after ${ms}ms`));
417
258
  }, ms);
418
259
  promise.then((val) => {
419
260
  clearTimeout(timer);
420
- resolve2(val);
261
+ resolve(val);
421
262
  }).catch((err) => {
422
263
  clearTimeout(timer);
423
264
  reject(err);
@@ -694,11 +535,11 @@ var McpManager = class {
694
535
  };
695
536
 
696
537
  // src/skills/manager.ts
697
- import { existsSync as existsSync2, readdirSync, mkdirSync, statSync } from "fs";
698
- import { join as join2 } from "path";
538
+ import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
539
+ import { join } from "path";
699
540
 
700
541
  // src/skills/types.ts
701
- import { readFileSync as readFileSync2 } from "fs";
542
+ import { readFileSync } from "fs";
702
543
  import { basename } from "path";
703
544
  function parseSimpleYaml(yaml) {
704
545
  const result = {};
@@ -720,7 +561,7 @@ function parseYamlArray(value) {
720
561
  function parseSkillFile(filePath) {
721
562
  let raw;
722
563
  try {
723
- raw = readFileSync2(filePath, "utf-8");
564
+ raw = readFileSync(filePath, "utf-8");
724
565
  } catch {
725
566
  return null;
726
567
  }
@@ -760,36 +601,40 @@ var SkillManager = class {
760
601
  this.skillsDir = skillsDir;
761
602
  this.warnThreshold = warnThreshold ?? SKILL_CONTENT_WARN_CHARS_DEFAULT;
762
603
  }
763
- /** 发现并加载 skillsDir 下所有 .md 文件,返回加载数量 */
764
- loadSkills() {
604
+ /** 发现并加载 skillsDir 以及额外插件目录下的技能,返回加载数量 */
605
+ loadSkills(extraDirs = []) {
765
606
  this.skills.clear();
766
- if (!existsSync2(this.skillsDir)) {
767
- try {
768
- mkdirSync(this.skillsDir, { recursive: true });
769
- } catch {
607
+ this.loadSkillDir(this.skillsDir, true);
608
+ for (const dir of extraDirs) this.loadSkillDir(dir, false);
609
+ return this.skills.size;
610
+ }
611
+ loadSkillDir(dir, createIfMissing) {
612
+ if (!existsSync(dir)) {
613
+ if (createIfMissing) {
614
+ try {
615
+ mkdirSync(dir, { recursive: true });
616
+ } catch {
617
+ }
770
618
  }
771
- return 0;
619
+ return;
772
620
  }
773
621
  let entries;
774
622
  try {
775
- entries = readdirSync(this.skillsDir);
623
+ entries = readdirSync(dir);
776
624
  } catch {
777
- return 0;
625
+ return;
778
626
  }
779
627
  for (const entry of entries) {
780
628
  let filePath;
781
- const fullPath = join2(this.skillsDir, entry);
629
+ const fullPath = join(dir, entry);
782
630
  if (entry.endsWith(".md")) {
783
631
  filePath = fullPath;
784
632
  } else {
785
633
  try {
786
634
  if (statSync(fullPath).isDirectory()) {
787
- const skillMd = join2(fullPath, "SKILL.md");
788
- if (existsSync2(skillMd)) {
789
- filePath = skillMd;
790
- } else {
791
- continue;
792
- }
635
+ const skillMd = join(fullPath, "SKILL.md");
636
+ if (existsSync(skillMd)) filePath = skillMd;
637
+ else continue;
793
638
  } else {
794
639
  continue;
795
640
  }
@@ -799,13 +644,10 @@ var SkillManager = class {
799
644
  }
800
645
  const skill = parseSkillFile(filePath);
801
646
  if (skill) {
802
- if (skill.meta.name === "SKILL" && !entry.endsWith(".md")) {
803
- skill.meta.name = entry;
804
- }
805
- this.skills.set(skill.meta.name, skill);
647
+ if (skill.meta.name === "SKILL" && !entry.endsWith(".md")) skill.meta.name = entry;
648
+ if (!this.skills.has(skill.meta.name)) this.skills.set(skill.meta.name, skill);
806
649
  }
807
650
  }
808
- return this.skills.size;
809
651
  }
810
652
  /** 列出所有已加载的技能 */
811
653
  listSkills() {
@@ -859,8 +701,8 @@ async function setupProxy(configProxy) {
859
701
  }
860
702
 
861
703
  // src/repl/commands/project-init.ts
862
- import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
863
- import { join as join3 } from "path";
704
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
705
+ import { join as join2 } from "path";
864
706
  var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
865
707
  "node_modules",
866
708
  ".git",
@@ -904,11 +746,11 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
904
746
  const sorted = filtered.sort((a, b) => {
905
747
  let aIsDir = false, bIsDir = false;
906
748
  try {
907
- aIsDir = statSync2(join3(d, a)).isDirectory();
749
+ aIsDir = statSync2(join2(d, a)).isDirectory();
908
750
  } catch {
909
751
  }
910
752
  try {
911
- bIsDir = statSync2(join3(d, b)).isDirectory();
753
+ bIsDir = statSync2(join2(d, b)).isDirectory();
912
754
  } catch {
913
755
  }
914
756
  if (aIsDir !== bIsDir) return aIsDir ? -1 : 1;
@@ -916,7 +758,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
916
758
  });
917
759
  for (let i = 0; i < sorted.length && count < maxEntries; i++) {
918
760
  const name = sorted[i];
919
- const fullPath = join3(d, name);
761
+ const fullPath = join2(d, name);
920
762
  const isLast = i === sorted.length - 1;
921
763
  const connector = isLast ? "+-- " : "|-- ";
922
764
  let isDir;
@@ -943,7 +785,7 @@ function scanProject(cwd) {
943
785
  configFiles: [],
944
786
  directoryStructure: ""
945
787
  };
946
- const check = (file) => existsSync3(join3(cwd, file));
788
+ const check = (file) => existsSync2(join2(cwd, file));
947
789
  const configCandidates = [
948
790
  "package.json",
949
791
  "tsconfig.json",
@@ -970,7 +812,7 @@ function scanProject(cwd) {
970
812
  info.type = "node";
971
813
  info.language = check("tsconfig.json") ? "TypeScript" : "JavaScript";
972
814
  try {
973
- const pkg = JSON.parse(readFileSync3(join3(cwd, "package.json"), "utf-8"));
815
+ const pkg = JSON.parse(readFileSync2(join2(cwd, "package.json"), "utf-8"));
974
816
  const scripts = pkg.scripts ?? {};
975
817
  info.buildCommand = scripts.build ? "npm run build" : void 0;
976
818
  info.testCommand = scripts.test ? "npm test" : void 0;
@@ -1146,8 +988,8 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
1146
988
  }
1147
989
 
1148
990
  // src/repl/dev-state.ts
1149
- import { existsSync as existsSync4, readFileSync as readFileSync4, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
1150
- import { join as join4 } from "path";
991
+ import { existsSync as existsSync3, readFileSync as readFileSync3, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
992
+ import { join as join3 } from "path";
1151
993
  import { homedir } from "os";
1152
994
  var DEV_STATE_MAX_CHARS = 6e3;
1153
995
  var SNAPSHOT_PROMPT = `You are about to be replaced by a different AI model. Please generate a structured development state snapshot so the next model can continue seamlessly.
@@ -1201,11 +1043,11 @@ function sessionHasMeaningfulContent(messages) {
1201
1043
  return hasUser && hasAssistant;
1202
1044
  }
1203
1045
  function getDevStatePath() {
1204
- return join4(homedir(), CONFIG_DIR_NAME, DEV_STATE_FILE_NAME);
1046
+ return join3(homedir(), CONFIG_DIR_NAME, DEV_STATE_FILE_NAME);
1205
1047
  }
1206
1048
  function saveDevState(content) {
1207
- const configDir = join4(homedir(), CONFIG_DIR_NAME);
1208
- if (!existsSync4(configDir)) {
1049
+ const configDir = join3(homedir(), CONFIG_DIR_NAME);
1050
+ if (!existsSync3(configDir)) {
1209
1051
  mkdirSync2(configDir, { recursive: true });
1210
1052
  }
1211
1053
  let trimmed = content.trim();
@@ -1221,13 +1063,13 @@ function saveDevState(content) {
1221
1063
  }
1222
1064
  function loadDevState() {
1223
1065
  const path = getDevStatePath();
1224
- if (!existsSync4(path)) return null;
1225
- const content = readFileSync4(path, "utf-8").trim();
1066
+ if (!existsSync3(path)) return null;
1067
+ const content = readFileSync3(path, "utf-8").trim();
1226
1068
  return content || null;
1227
1069
  }
1228
1070
  function clearDevState() {
1229
1071
  const path = getDevStatePath();
1230
- if (existsSync4(path)) {
1072
+ if (existsSync3(path)) {
1231
1073
  try {
1232
1074
  unlinkSync(path);
1233
1075
  } catch {
@@ -1243,7 +1085,6 @@ export {
1243
1085
  parseSimpleYaml,
1244
1086
  persistToolRound,
1245
1087
  autoTrimSessionIfNeeded,
1246
- loadContextFiles,
1247
1088
  SNAPSHOT_PROMPT,
1248
1089
  sessionHasMeaningfulContent,
1249
1090
  saveDevState,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.217";
4
+ var VERSION = "0.4.219";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-XJGEQIYS.js";
4
+ } from "./chunk-U7KVU25H.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -3,14 +3,14 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-KOPUCJXM.js";
7
- import "./chunk-WZ3VKLF3.js";
6
+ } from "./chunk-4ZN6L6K5.js";
7
+ import "./chunk-VADHBW7T.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
9
  import "./chunk-QMXC327F.js";
10
10
  import "./chunk-XPBEJB27.js";
11
- import "./chunk-WKOQ5CYC.js";
11
+ import "./chunk-KIEZBTVD.js";
12
12
  import "./chunk-TZQHYZKT.js";
13
- import "./chunk-XJGEQIYS.js";
13
+ import "./chunk-U7KVU25H.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
  export {
16
16
  CI_COMMENT_MARKER,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-WZ3VKLF3.js";
10
- import "./chunk-XJGEQIYS.js";
9
+ } from "./chunk-VADHBW7T.js";
10
+ import "./chunk-U7KVU25H.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-XJGEQIYS.js";
41
+ } from "./chunk-U7KVU25H.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ formatDoctorReport,
4
+ runDoctorCli
5
+ } from "./chunk-3I4RZYYO.js";
6
+ import "./chunk-QMXC327F.js";
7
+ import "./chunk-GGKQHPB3.js";
8
+ import "./chunk-XPBEJB27.js";
9
+ import "./chunk-KIEZBTVD.js";
10
+ import "./chunk-TZQHYZKT.js";
11
+ import "./chunk-U7KVU25H.js";
12
+ import "./chunk-HOSJZMQS.js";
13
+ import "./chunk-IW3Q7AE5.js";
14
+ export {
15
+ formatDoctorReport,
16
+ runDoctorCli
17
+ };