jinzd-ai-cli 0.4.306 → 0.4.308
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/README.md +1 -0
- package/THIRD_PARTY_NOTICES.md +3 -0
- package/dist/{agent-client-6GX6QQDU.js → agent-client-TIEAYZXV.js} +4 -1
- package/dist/{auth-PE3Z5OHS.js → auth-QTQNZ6IX.js} +2 -2
- package/dist/{batch-JLGWQ7HU.js → batch-S7XLEEOH.js} +3 -3
- package/dist/{chat-index-2D5GK2DB.js → chat-index-7CLR4CBG.js} +4 -3
- package/dist/{chat-index-DGUOUUQW.js → chat-index-RLVLQRRC.js} +3 -2
- package/dist/{chunk-JDT6UG6R.js → chunk-2DYQDLLF.js} +1 -1
- package/dist/{chunk-T6WQEQI4.js → chunk-2MNUMLN4.js} +1 -1
- package/dist/chunk-2XMUCC42.js +67 -0
- package/dist/{chunk-7SSCSSC6.js → chunk-3537CQ5M.js} +2 -2
- package/dist/{chunk-OAXLMF3U.js → chunk-3YVNDYOY.js} +1 -1
- package/dist/{chunk-RYQBBEMM.js → chunk-4PR5AVJ5.js} +115 -19
- package/dist/{chunk-GHWZVPUV.js → chunk-6JHACXB3.js} +7 -5
- package/dist/{chunk-WZWRA7R2.js → chunk-7OHXFTZO.js} +2 -2
- package/dist/{chunk-IUVDZVZ4.js → chunk-AXTLYOA7.js} +24 -17
- package/dist/{chunk-XJOK5353.js → chunk-B3MPYI4E.js} +2 -2
- package/dist/{chunk-3RDJEYF7.js → chunk-BGZN4K7Q.js} +4 -4
- package/dist/chunk-BMLQPSHP.js +69 -0
- package/dist/{chunk-NRSYBKWA.js → chunk-C7CKDFJS.js} +1 -1
- package/dist/{chunk-JFNBJHR6.js → chunk-E2PNXNKI.js} +4 -4
- package/dist/chunk-FVXNEZEW.js +161 -0
- package/dist/{chunk-YKJO3SI4.js → chunk-G6DVGQ4I.js} +1 -1
- package/dist/{chunk-AYLK4EGA.js → chunk-HC33C4U3.js} +18 -18
- package/dist/chunk-JJFJWD35.js +162 -0
- package/dist/{chunk-W6PLV3EY.js → chunk-JJNUASMJ.js} +263 -55
- package/dist/{chunk-NYNSYLFY.js → chunk-JL44HGZC.js} +1 -1
- package/dist/{chunk-NUJTNH76.js → chunk-LBWKMTT3.js} +1 -1
- package/dist/{chunk-LAP7TPPK.js → chunk-LR3TGZWQ.js} +2 -2
- package/dist/{chunk-WQ3OMEC4.js → chunk-M6HLYG33.js} +1 -1
- package/dist/{chunk-I4GQRMFV.js → chunk-M6YV5KSS.js} +6 -4
- package/dist/{chunk-K5SDDTN7.js → chunk-NLK45GUS.js} +1 -1
- package/dist/{chunk-KBDKKHXB.js → chunk-O6CGOVD4.js} +2 -2
- package/dist/chunk-QMFMST2T.js +39 -0
- package/dist/{chunk-MI4SFZGX.js → chunk-RMEJR3AW.js} +5 -2
- package/dist/{chunk-UFW4S3RU.js → chunk-RVMCY6DP.js} +1 -1
- package/dist/{chunk-LF67HWWR.js → chunk-RWRZVQCB.js} +1 -1
- package/dist/chunk-SXIJLSVF.js +41 -0
- package/dist/chunk-TDQW2YHK.js +65 -0
- package/dist/{chunk-VLDB2SVN.js → chunk-TPTFV3Y6.js} +383 -513
- package/dist/{chunk-45UVJXFQ.js → chunk-W2UOVGRC.js} +1 -1
- package/dist/{chunk-VXEF2SWG.js → chunk-WT252ZDV.js} +2 -2
- package/dist/{chunk-NLB7JZSO.js → chunk-WVEIUSXE.js} +246 -55
- package/dist/{chunk-OC2XHG5L.js → chunk-YBZM7PHI.js} +4 -4
- package/dist/{ci-6PHEL3C7.js → ci-5HONSUAS.js} +7 -7
- package/dist/{ci-format-AZYUP6BL.js → ci-format-URUH3ZZ5.js} +2 -2
- package/dist/{constants-CPNWIUGZ.js → constants-BLDBI7IG.js} +1 -1
- package/dist/{constants-AXBD2EEB.js → constants-FG27DQMS.js} +1 -1
- package/dist/doctor-cli-QQLMNJN7.js +18 -0
- package/dist/electron-server.js +1003 -829
- package/dist/file-checkpoint-64A2AXHE.js +7 -0
- package/dist/{file-checkpoint-NKBHGC7L.js → file-checkpoint-VVPUJNCI.js} +2 -1
- package/dist/{hub-DDYAWLF2.js → hub-GGFW3DCC.js} +3 -3
- package/dist/{hub-server-CBKCP5VD.js → hub-server-JLC7CNP7.js} +55 -17
- package/dist/index.js +42 -40
- package/dist/{indexer-P3FPRTPJ.js → indexer-GKIWSSRP.js} +3 -3
- package/dist/indexer-VRXDZ74A.js +10 -0
- package/dist/{persist-S77WRVLD.js → persist-ZZXRWFBX.js} +4 -4
- package/dist/{persistent-memory-XZISXRWT.js → persistent-memory-UNLCXUWH.js} +3 -3
- package/dist/{persistent-memory-6XYYOMSC.js → persistent-memory-YYWIN6BG.js} +3 -3
- package/dist/{pr-UY4ZCZNI.js → pr-YCFGPFI7.js} +7 -7
- package/dist/{project-trust-MUG325AW.js → project-trust-6CJB5ZMX.js} +1 -1
- package/dist/{project-trust-NKYHL3VZ.js → project-trust-KGG2BWKC.js} +1 -1
- package/dist/run-tests-GHY4BYDE.js +13 -0
- package/dist/run-tests-KRNMFXAN.js +12 -0
- package/dist/{semantic-7GM5M4MU.js → semantic-N227CLSC.js} +4 -4
- package/dist/{semantic-QOBAXEQ4.js → semantic-TRQAZSRY.js} +4 -4
- package/dist/{server-6IC33CJK.js → server-73UBHSFV.js} +16 -14
- package/dist/{server-DBHLVQVP.js → server-QRAWSG4Z.js} +231 -103
- package/dist/{store-SIKHCUYJ.js → store-2N6PPPBP.js} +2 -2
- package/dist/{store-CMSSWZF7.js → store-76VVFDXM.js} +2 -2
- package/dist/{task-orchestrator-RDDETDW2.js → task-orchestrator-GI3RGLZI.js} +15 -14
- package/dist/{usage-D473ZVIP.js → usage-GWTIGZF5.js} +4 -4
- package/dist/{vector-store-JAXWDZYW.js → vector-store-T2DVUMY4.js} +2 -2
- package/dist/{vector-store-PWIOQFTP.js → vector-store-V6UGEYWK.js} +2 -2
- package/dist/web/client/app.js +7 -0
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/dist/web/client/util.js +14 -23
- package/dist/web/client/util.js.br +0 -0
- package/dist/web/client/util.js.gz +0 -0
- package/dist/web/client/vendor/DOMPurify-LICENSE.txt +202 -0
- package/dist/web/client/vendor/purify.es.mjs +2722 -0
- package/dist/web/client/vendor/purify.es.mjs.br +0 -0
- package/dist/web/client/vendor/purify.es.mjs.gz +0 -0
- package/package.json +4 -2
- package/dist/chunk-4BKXL7SM.js +0 -98
- package/dist/chunk-6BUTA5VW.js +0 -38
- package/dist/chunk-IW3Q7AE5.js +0 -40
- package/dist/chunk-SKET65WZ.js +0 -96
- package/dist/doctor-cli-DDHHDMMJ.js +0 -18
- package/dist/file-checkpoint-CGH6OJVI.js +0 -6
- package/dist/indexer-FPKY7LCT.js +0 -10
- package/dist/run-tests-BAMLVLO6.js +0 -10
- package/dist/run-tests-UEE3OMLS.js +0 -9
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateCiGate,
|
|
4
4
|
normalizeCiThresholds
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NLK45GUS.js";
|
|
6
6
|
import {
|
|
7
7
|
buildReviewPrompt,
|
|
8
8
|
buildSecurityReviewPrompt,
|
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
} from "./chunk-6YZEZFX5.js";
|
|
14
14
|
import {
|
|
15
15
|
ProviderRegistry
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-WT252ZDV.js";
|
|
17
17
|
import {
|
|
18
18
|
ConfigManager
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-YBZM7PHI.js";
|
|
20
20
|
import {
|
|
21
21
|
VERSION
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2MNUMLN4.js";
|
|
23
23
|
|
|
24
24
|
// src/cli/ci.ts
|
|
25
25
|
import { execFileSync } from "child_process";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/core/atomic-write.ts
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { randomUUID } from "crypto";
|
|
6
|
+
import { setTimeout as delay } from "timers/promises";
|
|
7
|
+
function modeFor(target, options) {
|
|
8
|
+
if (options.mode !== void 0) return options.mode;
|
|
9
|
+
try {
|
|
10
|
+
return fs.statSync(target).mode & 511;
|
|
11
|
+
} catch {
|
|
12
|
+
return 384;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function atomicWriteFileSync(target, data, options = {}) {
|
|
16
|
+
const tmp = `${target}.${process.pid}.${randomUUID()}.tmp`;
|
|
17
|
+
try {
|
|
18
|
+
fs.writeFileSync(tmp, data, { flag: "wx", mode: modeFor(target, options) });
|
|
19
|
+
fs.renameSync(tmp, target);
|
|
20
|
+
} finally {
|
|
21
|
+
try {
|
|
22
|
+
fs.unlinkSync(tmp);
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
var pending = /* @__PURE__ */ new Map();
|
|
28
|
+
async function atomicWriteFile(target, data, options = {}) {
|
|
29
|
+
const previous = pending.get(target) ?? Promise.resolve();
|
|
30
|
+
const operation = previous.catch(() => {
|
|
31
|
+
}).then(async () => {
|
|
32
|
+
const tmp = `${target}.${process.pid}.${randomUUID()}.tmp`;
|
|
33
|
+
try {
|
|
34
|
+
let mode = options.mode ?? 384;
|
|
35
|
+
if (options.mode === void 0) {
|
|
36
|
+
try {
|
|
37
|
+
mode = (await fs.promises.stat(target)).mode & 511;
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
await fs.promises.writeFile(tmp, data, { flag: "wx", mode });
|
|
42
|
+
for (let attempt = 0; ; attempt++) {
|
|
43
|
+
try {
|
|
44
|
+
await fs.promises.rename(tmp, target);
|
|
45
|
+
break;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (attempt >= 10 || !["EPERM", "EBUSY", "EACCES"].includes(error.code ?? "")) throw error;
|
|
48
|
+
await delay(5 * (attempt + 1));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} finally {
|
|
52
|
+
try {
|
|
53
|
+
await fs.promises.unlink(tmp);
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
pending.set(target, operation);
|
|
59
|
+
try {
|
|
60
|
+
await operation;
|
|
61
|
+
} finally {
|
|
62
|
+
if (pending.get(target) === operation) pending.delete(target);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
atomicWriteFileSync,
|
|
68
|
+
atomicWriteFile
|
|
69
|
+
};
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
listHooks,
|
|
9
9
|
listInstalledPlugins,
|
|
10
10
|
resetStats
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-3537CQ5M.js";
|
|
12
12
|
import {
|
|
13
13
|
ProviderRegistry
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WT252ZDV.js";
|
|
15
15
|
import {
|
|
16
16
|
ConfigManager
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-YBZM7PHI.js";
|
|
18
18
|
import {
|
|
19
19
|
getGitRoot
|
|
20
20
|
} from "./chunk-HOSJZMQS.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
MCP_PROJECT_CONFIG_NAME,
|
|
27
27
|
MEMORY_FILE_NAME,
|
|
28
28
|
VERSION
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-2MNUMLN4.js";
|
|
30
30
|
|
|
31
31
|
// src/diagnostics/doctor-report.ts
|
|
32
32
|
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getExecutionConfigDir,
|
|
3
|
+
scopedState
|
|
4
|
+
} from "./chunk-QMFMST2T.js";
|
|
5
|
+
|
|
6
|
+
// src/security/file-access.ts
|
|
7
|
+
import { existsSync, realpathSync, openSync, readSync, closeSync, statSync } from "fs";
|
|
8
|
+
import { basename, dirname, resolve, join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
function canonicalPath(value) {
|
|
11
|
+
let cursor = resolve(value);
|
|
12
|
+
const missing = [];
|
|
13
|
+
while (!existsSync(cursor)) {
|
|
14
|
+
const parent = dirname(cursor);
|
|
15
|
+
if (parent === cursor) throw new Error("Cannot resolve path");
|
|
16
|
+
missing.unshift(basename(cursor));
|
|
17
|
+
cursor = parent;
|
|
18
|
+
}
|
|
19
|
+
return resolve(realpathSync(cursor), ...missing);
|
|
20
|
+
}
|
|
21
|
+
function isCredentialVault(value) {
|
|
22
|
+
const normalize = (p) => process.platform === "win32" ? p.toLowerCase() : p;
|
|
23
|
+
const target = normalize(canonicalPath(value));
|
|
24
|
+
const hostRoot = normalize(canonicalPath(join(homedir(), ".aicli")));
|
|
25
|
+
if (basename(target) === "config.json" && normalize(dirname(dirname(dirname(target)))) === hostRoot && basename(dirname(dirname(target))) === "users") return true;
|
|
26
|
+
return [getExecutionConfigDir(), join(homedir(), ".aicli")].some((root) => ["config.json", "users.json"].some((file) => {
|
|
27
|
+
const vault = canonicalPath(join(root, file));
|
|
28
|
+
if (target === normalize(vault)) return true;
|
|
29
|
+
try {
|
|
30
|
+
const a = statSync(target), b = statSync(vault);
|
|
31
|
+
return a.ino !== 0 && a.dev === b.dev && a.ino === b.ino;
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
function assertReadablePath(value) {
|
|
38
|
+
if (isCredentialVault(value)) throw new Error("[Refused] Credential vault files cannot be read by tools. Use aicli config or an external editor.");
|
|
39
|
+
}
|
|
40
|
+
var MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024;
|
|
41
|
+
var MAX_SNAPSHOT_TOTAL_BYTES = 16 * 1024 * 1024;
|
|
42
|
+
function readSnapshot(value) {
|
|
43
|
+
const fd = openSync(value, "r");
|
|
44
|
+
try {
|
|
45
|
+
const buffer = Buffer.alloc(MAX_SNAPSHOT_BYTES + 1);
|
|
46
|
+
let bytes = 0;
|
|
47
|
+
while (bytes < buffer.length) {
|
|
48
|
+
const n = readSync(fd, buffer, bytes, buffer.length - bytes, null);
|
|
49
|
+
if (!n) break;
|
|
50
|
+
bytes += n;
|
|
51
|
+
}
|
|
52
|
+
if (bytes > MAX_SNAPSHOT_BYTES) throw new Error("File exceeds 2 MiB snapshot limit; edit refused because a complete undo snapshot cannot be kept.");
|
|
53
|
+
return buffer.subarray(0, bytes).toString("utf8");
|
|
54
|
+
} finally {
|
|
55
|
+
closeSync(fd);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/tools/file-checkpoint.ts
|
|
60
|
+
import { existsSync as existsSync2, writeFileSync, unlinkSync } from "fs";
|
|
61
|
+
var MAX_SNAPSHOTS = 200;
|
|
62
|
+
var FileCheckpointStore = class {
|
|
63
|
+
stateKey = /* @__PURE__ */ Symbol("snapshots");
|
|
64
|
+
get snapshots() {
|
|
65
|
+
return scopedState(this.stateKey, () => ({ items: [] })).items;
|
|
66
|
+
}
|
|
67
|
+
set snapshots(items) {
|
|
68
|
+
scopedState(this.stateKey, () => ({ items: [] })).items = items;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 在文件写入前调用,保存当前文件内容。
|
|
72
|
+
* 同一 messageIndex 下同一文件只记录首次快照。
|
|
73
|
+
*/
|
|
74
|
+
snapshot(filePath, messageIndex) {
|
|
75
|
+
const exists = this.snapshots.some(
|
|
76
|
+
(s) => s.filePath === filePath && s.messageIndex === messageIndex
|
|
77
|
+
);
|
|
78
|
+
if (exists) return;
|
|
79
|
+
let content = null;
|
|
80
|
+
if (existsSync2(filePath)) {
|
|
81
|
+
content = readSnapshot(filePath);
|
|
82
|
+
}
|
|
83
|
+
this.snapshots.push({
|
|
84
|
+
filePath,
|
|
85
|
+
content,
|
|
86
|
+
messageIndex,
|
|
87
|
+
timestamp: Date.now()
|
|
88
|
+
});
|
|
89
|
+
while (this.snapshots.length > MAX_SNAPSHOTS || this.snapshots.reduce((n, e) => n + Buffer.byteLength(e.content ?? ""), 0) > MAX_SNAPSHOT_TOTAL_BYTES) {
|
|
90
|
+
this.snapshots.shift();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 恢复所有在指定消息索引之后被修改的文件到该索引时的状态。
|
|
95
|
+
* @returns 恢复和删除的文件数量
|
|
96
|
+
*/
|
|
97
|
+
restoreToMessageIndex(targetIndex) {
|
|
98
|
+
const modifiedAfter = this.snapshots.filter((s) => s.messageIndex > targetIndex);
|
|
99
|
+
const uniqueFiles = [...new Set(modifiedAfter.map((s) => s.filePath))];
|
|
100
|
+
let restored = 0;
|
|
101
|
+
let deleted = 0;
|
|
102
|
+
const files = [];
|
|
103
|
+
for (const filePath of uniqueFiles) {
|
|
104
|
+
const beforeSnapshots = this.snapshots.filter((s) => s.filePath === filePath && s.messageIndex <= targetIndex).sort((a, b) => b.messageIndex - a.messageIndex);
|
|
105
|
+
const restoreTo = beforeSnapshots[0];
|
|
106
|
+
try {
|
|
107
|
+
if (restoreTo) {
|
|
108
|
+
if (restoreTo.content === null) {
|
|
109
|
+
if (existsSync2(filePath)) {
|
|
110
|
+
unlinkSync(filePath);
|
|
111
|
+
deleted++;
|
|
112
|
+
files.push(filePath);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
writeFileSync(filePath, restoreTo.content, "utf-8");
|
|
116
|
+
restored++;
|
|
117
|
+
files.push(filePath);
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
const earliest = this.snapshots.filter((s) => s.filePath === filePath).sort((a, b) => a.messageIndex - b.messageIndex)[0];
|
|
121
|
+
if (earliest && earliest.content === null) {
|
|
122
|
+
if (existsSync2(filePath)) {
|
|
123
|
+
unlinkSync(filePath);
|
|
124
|
+
deleted++;
|
|
125
|
+
files.push(filePath);
|
|
126
|
+
}
|
|
127
|
+
} else if (earliest) {
|
|
128
|
+
writeFileSync(filePath, earliest.content, "utf-8");
|
|
129
|
+
restored++;
|
|
130
|
+
files.push(filePath);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
this.snapshots = this.snapshots.filter((s) => s.messageIndex <= targetIndex);
|
|
137
|
+
return { restored, deleted, files };
|
|
138
|
+
}
|
|
139
|
+
/** 获取所有快照(供调试/显示) */
|
|
140
|
+
getSnapshots() {
|
|
141
|
+
return this.snapshots;
|
|
142
|
+
}
|
|
143
|
+
/** 获取有快照的消息索引列表(去重排序) */
|
|
144
|
+
getMessageIndices() {
|
|
145
|
+
return [...new Set(this.snapshots.map((s) => s.messageIndex))].sort((a, b) => a - b);
|
|
146
|
+
}
|
|
147
|
+
/** 清空所有快照(新会话/清除时调用) */
|
|
148
|
+
clear() {
|
|
149
|
+
this.snapshots = [];
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
var fileCheckpoints = new FileCheckpointStore();
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
canonicalPath,
|
|
156
|
+
isCredentialVault,
|
|
157
|
+
assertReadablePath,
|
|
158
|
+
MAX_SNAPSHOT_TOTAL_BYTES,
|
|
159
|
+
readSnapshot,
|
|
160
|
+
fileCheckpoints
|
|
161
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
computeCost,
|
|
4
4
|
formatCost
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-G6DVGQ4I.js";
|
|
6
6
|
import {
|
|
7
7
|
clearRecentlyDeniedAutoActions,
|
|
8
8
|
estimateTokens,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
setPreferredAgentName,
|
|
17
17
|
truncateForPersist,
|
|
18
18
|
undoStack
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-TPTFV3Y6.js";
|
|
20
20
|
import {
|
|
21
21
|
buildReviewPrompt,
|
|
22
22
|
buildSecurityReviewPrompt
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
clearChatIndex,
|
|
27
27
|
getChatIndexStatus,
|
|
28
28
|
searchChatMemory
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-6JHACXB3.js";
|
|
30
30
|
import {
|
|
31
31
|
addMemoryEntry,
|
|
32
32
|
backupMemoryStore,
|
|
@@ -51,13 +51,13 @@ import {
|
|
|
51
51
|
touchMemoryReferences,
|
|
52
52
|
updateMemoryApproval,
|
|
53
53
|
updateMemoryEntry
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-LR3TGZWQ.js";
|
|
55
55
|
import {
|
|
56
56
|
theme
|
|
57
57
|
} from "./chunk-5C76XDDF.js";
|
|
58
58
|
import {
|
|
59
59
|
getContentText
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-AXTLYOA7.js";
|
|
61
61
|
import {
|
|
62
62
|
DEFAULT_PATTERNS,
|
|
63
63
|
scanString
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
import {
|
|
66
66
|
buildDoctorReport,
|
|
67
67
|
formatDoctorReport
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-E2PNXNKI.js";
|
|
69
69
|
import {
|
|
70
70
|
describePlugin,
|
|
71
71
|
getActivePluginAssets,
|
|
@@ -80,24 +80,24 @@ import {
|
|
|
80
80
|
trustHook,
|
|
81
81
|
trustPlugin,
|
|
82
82
|
untrustHook
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-3537CQ5M.js";
|
|
84
84
|
import {
|
|
85
85
|
isCleanDocumentBody,
|
|
86
86
|
stripOuterCodeFence
|
|
87
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-RMEJR3AW.js";
|
|
88
88
|
import {
|
|
89
89
|
formatGitContextForPrompt,
|
|
90
90
|
getGitContext
|
|
91
91
|
} from "./chunk-HOSJZMQS.js";
|
|
92
92
|
import {
|
|
93
93
|
atomicWriteFileSync
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-BMLQPSHP.js";
|
|
95
95
|
import {
|
|
96
96
|
applyConfigCommand
|
|
97
97
|
} from "./chunk-XNFIYS7G.js";
|
|
98
98
|
import {
|
|
99
99
|
fileCheckpoints
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-JJFJWD35.js";
|
|
101
101
|
import {
|
|
102
102
|
APP_NAME,
|
|
103
103
|
CONFIG_DIR_NAME,
|
|
@@ -109,7 +109,7 @@ import {
|
|
|
109
109
|
MCP_TOOL_PREFIX,
|
|
110
110
|
REPO_URL,
|
|
111
111
|
VERSION
|
|
112
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-2MNUMLN4.js";
|
|
113
113
|
|
|
114
114
|
// src/skills/manager.ts
|
|
115
115
|
import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
|
|
@@ -2426,8 +2426,8 @@ No tools match "${filter}".
|
|
|
2426
2426
|
const { join: join6 } = await import("path");
|
|
2427
2427
|
const { existsSync: existsSync6 } = await import("fs");
|
|
2428
2428
|
const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
|
|
2429
|
-
const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-
|
|
2430
|
-
const { approveProject, hashMcpFile } = await import("./project-trust-
|
|
2429
|
+
const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-BLDBI7IG.js");
|
|
2430
|
+
const { approveProject, hashMcpFile } = await import("./project-trust-KGG2BWKC.js");
|
|
2431
2431
|
const cwd = process.cwd();
|
|
2432
2432
|
const projectRoot = getGitRoot(cwd) ?? cwd;
|
|
2433
2433
|
const mcpPath = join6(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
@@ -3534,7 +3534,7 @@ function createReviewCommands() {
|
|
|
3534
3534
|
usage: "/test [command|filter]",
|
|
3535
3535
|
async execute(args, ctx) {
|
|
3536
3536
|
try {
|
|
3537
|
-
const { executeTests } = await import("./run-tests-
|
|
3537
|
+
const { executeTests } = await import("./run-tests-GHY4BYDE.js");
|
|
3538
3538
|
const argStr = args.join(" ").trim();
|
|
3539
3539
|
let testArgs = {};
|
|
3540
3540
|
if (argStr) {
|
|
@@ -3900,9 +3900,9 @@ function createMemoryCommands() {
|
|
|
3900
3900
|
async execute(args, ctx) {
|
|
3901
3901
|
const sub = (args[0] ?? "status").toLowerCase();
|
|
3902
3902
|
const root = process.cwd();
|
|
3903
|
-
const { loadIndex, clearIndex } = await import("./store-
|
|
3904
|
-
const { indexProject } = await import("./indexer-
|
|
3905
|
-
const { loadVectorStore, clearVectorStore } = await import("./vector-store-
|
|
3903
|
+
const { loadIndex, clearIndex } = await import("./store-76VVFDXM.js");
|
|
3904
|
+
const { indexProject } = await import("./indexer-GKIWSSRP.js");
|
|
3905
|
+
const { loadVectorStore, clearVectorStore } = await import("./vector-store-V6UGEYWK.js");
|
|
3906
3906
|
if (sub === "status") {
|
|
3907
3907
|
const idx = loadIndex(root);
|
|
3908
3908
|
const vec = loadVectorStore(root);
|
|
@@ -3962,7 +3962,7 @@ function createMemoryCommands() {
|
|
|
3962
3962
|
}
|
|
3963
3963
|
console.log(theme.dim(` Building semantic index for ${idx.symbolCount} symbols\u2026`));
|
|
3964
3964
|
console.log(theme.dim(" (First run downloads ~117 MB embedding model to ~/.aicli/models/)"));
|
|
3965
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
3965
|
+
const { rebuildSemanticIndex } = await import("./semantic-N227CLSC.js");
|
|
3966
3966
|
try {
|
|
3967
3967
|
const stats = await rebuildSemanticIndex(root, {
|
|
3968
3968
|
onProgress: (done, total) => {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getExecutionConfigDir,
|
|
4
|
+
scopedState
|
|
5
|
+
} from "./chunk-SXIJLSVF.js";
|
|
6
|
+
|
|
7
|
+
// src/security/file-access.ts
|
|
8
|
+
import { existsSync, realpathSync, openSync, readSync, closeSync, statSync } from "fs";
|
|
9
|
+
import { basename, dirname, resolve, join } from "path";
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
function canonicalPath(value) {
|
|
12
|
+
let cursor = resolve(value);
|
|
13
|
+
const missing = [];
|
|
14
|
+
while (!existsSync(cursor)) {
|
|
15
|
+
const parent = dirname(cursor);
|
|
16
|
+
if (parent === cursor) throw new Error("Cannot resolve path");
|
|
17
|
+
missing.unshift(basename(cursor));
|
|
18
|
+
cursor = parent;
|
|
19
|
+
}
|
|
20
|
+
return resolve(realpathSync(cursor), ...missing);
|
|
21
|
+
}
|
|
22
|
+
function isCredentialVault(value) {
|
|
23
|
+
const normalize = (p) => process.platform === "win32" ? p.toLowerCase() : p;
|
|
24
|
+
const target = normalize(canonicalPath(value));
|
|
25
|
+
const hostRoot = normalize(canonicalPath(join(homedir(), ".aicli")));
|
|
26
|
+
if (basename(target) === "config.json" && normalize(dirname(dirname(dirname(target)))) === hostRoot && basename(dirname(dirname(target))) === "users") return true;
|
|
27
|
+
return [getExecutionConfigDir(), join(homedir(), ".aicli")].some((root) => ["config.json", "users.json"].some((file) => {
|
|
28
|
+
const vault = canonicalPath(join(root, file));
|
|
29
|
+
if (target === normalize(vault)) return true;
|
|
30
|
+
try {
|
|
31
|
+
const a = statSync(target), b = statSync(vault);
|
|
32
|
+
return a.ino !== 0 && a.dev === b.dev && a.ino === b.ino;
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
function assertReadablePath(value) {
|
|
39
|
+
if (isCredentialVault(value)) throw new Error("[Refused] Credential vault files cannot be read by tools. Use aicli config or an external editor.");
|
|
40
|
+
}
|
|
41
|
+
var MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024;
|
|
42
|
+
var MAX_SNAPSHOT_TOTAL_BYTES = 16 * 1024 * 1024;
|
|
43
|
+
function readSnapshot(value) {
|
|
44
|
+
const fd = openSync(value, "r");
|
|
45
|
+
try {
|
|
46
|
+
const buffer = Buffer.alloc(MAX_SNAPSHOT_BYTES + 1);
|
|
47
|
+
let bytes = 0;
|
|
48
|
+
while (bytes < buffer.length) {
|
|
49
|
+
const n = readSync(fd, buffer, bytes, buffer.length - bytes, null);
|
|
50
|
+
if (!n) break;
|
|
51
|
+
bytes += n;
|
|
52
|
+
}
|
|
53
|
+
if (bytes > MAX_SNAPSHOT_BYTES) throw new Error("File exceeds 2 MiB snapshot limit; edit refused because a complete undo snapshot cannot be kept.");
|
|
54
|
+
return buffer.subarray(0, bytes).toString("utf8");
|
|
55
|
+
} finally {
|
|
56
|
+
closeSync(fd);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/tools/file-checkpoint.ts
|
|
61
|
+
import { existsSync as existsSync2, writeFileSync, unlinkSync } from "fs";
|
|
62
|
+
var MAX_SNAPSHOTS = 200;
|
|
63
|
+
var FileCheckpointStore = class {
|
|
64
|
+
stateKey = /* @__PURE__ */ Symbol("snapshots");
|
|
65
|
+
get snapshots() {
|
|
66
|
+
return scopedState(this.stateKey, () => ({ items: [] })).items;
|
|
67
|
+
}
|
|
68
|
+
set snapshots(items) {
|
|
69
|
+
scopedState(this.stateKey, () => ({ items: [] })).items = items;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 在文件写入前调用,保存当前文件内容。
|
|
73
|
+
* 同一 messageIndex 下同一文件只记录首次快照。
|
|
74
|
+
*/
|
|
75
|
+
snapshot(filePath, messageIndex) {
|
|
76
|
+
const exists = this.snapshots.some(
|
|
77
|
+
(s) => s.filePath === filePath && s.messageIndex === messageIndex
|
|
78
|
+
);
|
|
79
|
+
if (exists) return;
|
|
80
|
+
let content = null;
|
|
81
|
+
if (existsSync2(filePath)) {
|
|
82
|
+
content = readSnapshot(filePath);
|
|
83
|
+
}
|
|
84
|
+
this.snapshots.push({
|
|
85
|
+
filePath,
|
|
86
|
+
content,
|
|
87
|
+
messageIndex,
|
|
88
|
+
timestamp: Date.now()
|
|
89
|
+
});
|
|
90
|
+
while (this.snapshots.length > MAX_SNAPSHOTS || this.snapshots.reduce((n, e) => n + Buffer.byteLength(e.content ?? ""), 0) > MAX_SNAPSHOT_TOTAL_BYTES) {
|
|
91
|
+
this.snapshots.shift();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 恢复所有在指定消息索引之后被修改的文件到该索引时的状态。
|
|
96
|
+
* @returns 恢复和删除的文件数量
|
|
97
|
+
*/
|
|
98
|
+
restoreToMessageIndex(targetIndex) {
|
|
99
|
+
const modifiedAfter = this.snapshots.filter((s) => s.messageIndex > targetIndex);
|
|
100
|
+
const uniqueFiles = [...new Set(modifiedAfter.map((s) => s.filePath))];
|
|
101
|
+
let restored = 0;
|
|
102
|
+
let deleted = 0;
|
|
103
|
+
const files = [];
|
|
104
|
+
for (const filePath of uniqueFiles) {
|
|
105
|
+
const beforeSnapshots = this.snapshots.filter((s) => s.filePath === filePath && s.messageIndex <= targetIndex).sort((a, b) => b.messageIndex - a.messageIndex);
|
|
106
|
+
const restoreTo = beforeSnapshots[0];
|
|
107
|
+
try {
|
|
108
|
+
if (restoreTo) {
|
|
109
|
+
if (restoreTo.content === null) {
|
|
110
|
+
if (existsSync2(filePath)) {
|
|
111
|
+
unlinkSync(filePath);
|
|
112
|
+
deleted++;
|
|
113
|
+
files.push(filePath);
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
writeFileSync(filePath, restoreTo.content, "utf-8");
|
|
117
|
+
restored++;
|
|
118
|
+
files.push(filePath);
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
const earliest = this.snapshots.filter((s) => s.filePath === filePath).sort((a, b) => a.messageIndex - b.messageIndex)[0];
|
|
122
|
+
if (earliest && earliest.content === null) {
|
|
123
|
+
if (existsSync2(filePath)) {
|
|
124
|
+
unlinkSync(filePath);
|
|
125
|
+
deleted++;
|
|
126
|
+
files.push(filePath);
|
|
127
|
+
}
|
|
128
|
+
} else if (earliest) {
|
|
129
|
+
writeFileSync(filePath, earliest.content, "utf-8");
|
|
130
|
+
restored++;
|
|
131
|
+
files.push(filePath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.snapshots = this.snapshots.filter((s) => s.messageIndex <= targetIndex);
|
|
138
|
+
return { restored, deleted, files };
|
|
139
|
+
}
|
|
140
|
+
/** 获取所有快照(供调试/显示) */
|
|
141
|
+
getSnapshots() {
|
|
142
|
+
return this.snapshots;
|
|
143
|
+
}
|
|
144
|
+
/** 获取有快照的消息索引列表(去重排序) */
|
|
145
|
+
getMessageIndices() {
|
|
146
|
+
return [...new Set(this.snapshots.map((s) => s.messageIndex))].sort((a, b) => a - b);
|
|
147
|
+
}
|
|
148
|
+
/** 清空所有快照(新会话/清除时调用) */
|
|
149
|
+
clear() {
|
|
150
|
+
this.snapshots = [];
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
var fileCheckpoints = new FileCheckpointStore();
|
|
154
|
+
|
|
155
|
+
export {
|
|
156
|
+
canonicalPath,
|
|
157
|
+
isCredentialVault,
|
|
158
|
+
assertReadablePath,
|
|
159
|
+
MAX_SNAPSHOT_TOTAL_BYTES,
|
|
160
|
+
readSnapshot,
|
|
161
|
+
fileCheckpoints
|
|
162
|
+
};
|