jinzd-ai-cli 0.4.23 → 0.4.25
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/dist/chunk-4BKXL7SM.js +98 -0
- package/dist/{chunk-PDVX5QJA.js → chunk-5GZQLJAY.js} +1068 -201
- package/dist/{chunk-UA4BVWKV.js → chunk-AHH5I2U6.js} +1 -1
- package/dist/{chunk-XMTMCMAP.js → chunk-ETMUP3CY.js} +1 -1
- package/dist/chunk-SKET65WZ.js +96 -0
- package/dist/{chunk-GBMVHLPA.js → chunk-SS7BQZ5R.js} +2 -198
- package/dist/{hub-YN245LMP.js → hub-JOYPSPR2.js} +1 -1
- package/dist/index.js +170 -500
- package/dist/{run-tests-2S6SYL2M.js → run-tests-25BZE3KQ.js} +1 -1
- package/dist/{run-tests-7ZBI4ZTU.js → run-tests-L3JNRB6X.js} +1 -1
- package/dist/{server-SD5ICBFP.js → server-V3IZSAMO.js} +126 -7
- package/dist/{task-orchestrator-C472QXTJ.js → task-orchestrator-4N5UUA6L.js} +3 -2
- package/dist/web/client/app.js +16 -3
- package/package.json +1 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/tools/file-checkpoint.ts
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
3
|
+
var MAX_SNAPSHOTS = 200;
|
|
4
|
+
var FileCheckpointStore = class {
|
|
5
|
+
snapshots = [];
|
|
6
|
+
/**
|
|
7
|
+
* 在文件写入前调用,保存当前文件内容。
|
|
8
|
+
* 同一 messageIndex 下同一文件只记录首次快照。
|
|
9
|
+
*/
|
|
10
|
+
snapshot(filePath, messageIndex) {
|
|
11
|
+
const exists = this.snapshots.some(
|
|
12
|
+
(s) => s.filePath === filePath && s.messageIndex === messageIndex
|
|
13
|
+
);
|
|
14
|
+
if (exists) return;
|
|
15
|
+
let content = null;
|
|
16
|
+
if (existsSync(filePath)) {
|
|
17
|
+
try {
|
|
18
|
+
content = readFileSync(filePath, "utf-8");
|
|
19
|
+
} catch {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
this.snapshots.push({
|
|
24
|
+
filePath,
|
|
25
|
+
content,
|
|
26
|
+
messageIndex,
|
|
27
|
+
timestamp: Date.now()
|
|
28
|
+
});
|
|
29
|
+
if (this.snapshots.length > MAX_SNAPSHOTS) {
|
|
30
|
+
this.snapshots = this.snapshots.slice(-MAX_SNAPSHOTS);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 恢复所有在指定消息索引之后被修改的文件到该索引时的状态。
|
|
35
|
+
* @returns 恢复和删除的文件数量
|
|
36
|
+
*/
|
|
37
|
+
restoreToMessageIndex(targetIndex) {
|
|
38
|
+
const modifiedAfter = this.snapshots.filter((s) => s.messageIndex > targetIndex);
|
|
39
|
+
const uniqueFiles = [...new Set(modifiedAfter.map((s) => s.filePath))];
|
|
40
|
+
let restored = 0;
|
|
41
|
+
let deleted = 0;
|
|
42
|
+
const files = [];
|
|
43
|
+
for (const filePath of uniqueFiles) {
|
|
44
|
+
const beforeSnapshots = this.snapshots.filter((s) => s.filePath === filePath && s.messageIndex <= targetIndex).sort((a, b) => b.messageIndex - a.messageIndex);
|
|
45
|
+
const restoreTo = beforeSnapshots[0];
|
|
46
|
+
try {
|
|
47
|
+
if (restoreTo) {
|
|
48
|
+
if (restoreTo.content === null) {
|
|
49
|
+
if (existsSync(filePath)) {
|
|
50
|
+
unlinkSync(filePath);
|
|
51
|
+
deleted++;
|
|
52
|
+
files.push(filePath);
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
writeFileSync(filePath, restoreTo.content, "utf-8");
|
|
56
|
+
restored++;
|
|
57
|
+
files.push(filePath);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
const earliest = this.snapshots.filter((s) => s.filePath === filePath).sort((a, b) => a.messageIndex - b.messageIndex)[0];
|
|
61
|
+
if (earliest && earliest.content === null) {
|
|
62
|
+
if (existsSync(filePath)) {
|
|
63
|
+
unlinkSync(filePath);
|
|
64
|
+
deleted++;
|
|
65
|
+
files.push(filePath);
|
|
66
|
+
}
|
|
67
|
+
} else if (earliest) {
|
|
68
|
+
writeFileSync(filePath, earliest.content, "utf-8");
|
|
69
|
+
restored++;
|
|
70
|
+
files.push(filePath);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
this.snapshots = this.snapshots.filter((s) => s.messageIndex <= targetIndex);
|
|
77
|
+
return { restored, deleted, files };
|
|
78
|
+
}
|
|
79
|
+
/** 获取所有快照(供调试/显示) */
|
|
80
|
+
getSnapshots() {
|
|
81
|
+
return this.snapshots;
|
|
82
|
+
}
|
|
83
|
+
/** 获取有快照的消息索引列表(去重排序) */
|
|
84
|
+
getMessageIndices() {
|
|
85
|
+
return [...new Set(this.snapshots.map((s) => s.messageIndex))].sort((a, b) => a - b);
|
|
86
|
+
}
|
|
87
|
+
/** 清空所有快照(新会话/清除时调用) */
|
|
88
|
+
clear() {
|
|
89
|
+
this.snapshots = [];
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var fileCheckpoints = new FileCheckpointStore();
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
fileCheckpoints
|
|
96
|
+
};
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
ProviderNotFoundError,
|
|
8
8
|
RateLimitError,
|
|
9
9
|
schemaToJsonSchema
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5GZQLJAY.js";
|
|
11
11
|
import {
|
|
12
12
|
APP_NAME,
|
|
13
13
|
CONFIG_DIR_NAME,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
MCP_TOOL_PREFIX,
|
|
21
21
|
PLUGINS_DIR_NAME,
|
|
22
22
|
VERSION
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-AHH5I2U6.js";
|
|
24
24
|
|
|
25
25
|
// src/config/config-manager.ts
|
|
26
26
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -3239,159 +3239,6 @@ async function setupProxy(configProxy) {
|
|
|
3239
3239
|
}
|
|
3240
3240
|
}
|
|
3241
3241
|
|
|
3242
|
-
// src/tools/diff-utils.ts
|
|
3243
|
-
import chalk from "chalk";
|
|
3244
|
-
function renderDiff(oldText, newText, opts = {}) {
|
|
3245
|
-
const contextLines = opts.contextLines ?? 3;
|
|
3246
|
-
const maxLines = opts.maxLines ?? 120;
|
|
3247
|
-
const filePath = opts.filePath ?? "";
|
|
3248
|
-
const oldLines = oldText.split("\n");
|
|
3249
|
-
const newLines = newText.split("\n");
|
|
3250
|
-
const hunks = computeHunks(oldLines, newLines, contextLines);
|
|
3251
|
-
if (hunks.length === 0) {
|
|
3252
|
-
return chalk.dim(" (no changes)");
|
|
3253
|
-
}
|
|
3254
|
-
const output = [];
|
|
3255
|
-
if (filePath) {
|
|
3256
|
-
output.push(chalk.bold.white(`--- ${filePath} (before)`));
|
|
3257
|
-
output.push(chalk.bold.white(`+++ ${filePath} (after)`));
|
|
3258
|
-
}
|
|
3259
|
-
let totalDisplayed = 0;
|
|
3260
|
-
for (const hunk of hunks) {
|
|
3261
|
-
if (totalDisplayed >= maxLines) {
|
|
3262
|
-
output.push(chalk.dim(` ... (diff truncated, too many changes)`));
|
|
3263
|
-
break;
|
|
3264
|
-
}
|
|
3265
|
-
output.push(
|
|
3266
|
-
chalk.cyan(
|
|
3267
|
-
`@@ -${hunk.oldStart + 1},${hunk.oldCount} +${hunk.newStart + 1},${hunk.newCount} @@`
|
|
3268
|
-
)
|
|
3269
|
-
);
|
|
3270
|
-
for (const line of hunk.lines) {
|
|
3271
|
-
if (totalDisplayed >= maxLines) break;
|
|
3272
|
-
totalDisplayed++;
|
|
3273
|
-
if (line.type === "context") {
|
|
3274
|
-
output.push(chalk.dim(` ${line.text}`));
|
|
3275
|
-
} else if (line.type === "remove") {
|
|
3276
|
-
output.push(chalk.red(`- ${line.text}`));
|
|
3277
|
-
} else {
|
|
3278
|
-
output.push(chalk.green(`+ ${line.text}`));
|
|
3279
|
-
}
|
|
3280
|
-
}
|
|
3281
|
-
}
|
|
3282
|
-
return output.join("\n");
|
|
3283
|
-
}
|
|
3284
|
-
function computeHunks(oldLines, newLines, contextLines) {
|
|
3285
|
-
const edits = diffLines(oldLines, newLines);
|
|
3286
|
-
if (edits.every((e) => e.type === "context")) return [];
|
|
3287
|
-
const hunks = [];
|
|
3288
|
-
let i = 0;
|
|
3289
|
-
while (i < edits.length) {
|
|
3290
|
-
if (edits[i].type === "context") {
|
|
3291
|
-
i++;
|
|
3292
|
-
continue;
|
|
3293
|
-
}
|
|
3294
|
-
const start = Math.max(0, i - contextLines);
|
|
3295
|
-
let end = i;
|
|
3296
|
-
while (end < edits.length) {
|
|
3297
|
-
if (edits[end].type !== "context") {
|
|
3298
|
-
end++;
|
|
3299
|
-
} else {
|
|
3300
|
-
let hasMoreChange = false;
|
|
3301
|
-
for (let j = end + 1; j < Math.min(edits.length, end + contextLines * 2 + 1); j++) {
|
|
3302
|
-
if (edits[j].type !== "context") {
|
|
3303
|
-
hasMoreChange = true;
|
|
3304
|
-
break;
|
|
3305
|
-
}
|
|
3306
|
-
}
|
|
3307
|
-
if (hasMoreChange) {
|
|
3308
|
-
end++;
|
|
3309
|
-
} else {
|
|
3310
|
-
break;
|
|
3311
|
-
}
|
|
3312
|
-
}
|
|
3313
|
-
}
|
|
3314
|
-
end = Math.min(edits.length, end + contextLines);
|
|
3315
|
-
const hunkEdits = edits.slice(start, end);
|
|
3316
|
-
let oldStart = 0;
|
|
3317
|
-
let newStart = 0;
|
|
3318
|
-
for (let k = 0; k < start; k++) {
|
|
3319
|
-
if (edits[k].type !== "add") oldStart++;
|
|
3320
|
-
if (edits[k].type !== "remove") newStart++;
|
|
3321
|
-
}
|
|
3322
|
-
let oldCount = 0;
|
|
3323
|
-
let newCount = 0;
|
|
3324
|
-
for (const e of hunkEdits) {
|
|
3325
|
-
if (e.type !== "add") oldCount++;
|
|
3326
|
-
if (e.type !== "remove") newCount++;
|
|
3327
|
-
}
|
|
3328
|
-
hunks.push({
|
|
3329
|
-
oldStart,
|
|
3330
|
-
oldCount,
|
|
3331
|
-
newStart,
|
|
3332
|
-
newCount,
|
|
3333
|
-
lines: hunkEdits.map((e) => ({ type: e.type, text: e.text }))
|
|
3334
|
-
});
|
|
3335
|
-
i = end;
|
|
3336
|
-
}
|
|
3337
|
-
return hunks;
|
|
3338
|
-
}
|
|
3339
|
-
function diffLines(oldLines, newLines) {
|
|
3340
|
-
const n = oldLines.length;
|
|
3341
|
-
const m = newLines.length;
|
|
3342
|
-
if (n * m > 25e4) {
|
|
3343
|
-
return simpleDiff(oldLines, newLines);
|
|
3344
|
-
}
|
|
3345
|
-
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
3346
|
-
for (let i2 = 1; i2 <= n; i2++) {
|
|
3347
|
-
for (let j2 = 1; j2 <= m; j2++) {
|
|
3348
|
-
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
3349
|
-
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
3350
|
-
} else {
|
|
3351
|
-
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
3352
|
-
}
|
|
3353
|
-
}
|
|
3354
|
-
}
|
|
3355
|
-
const result = [];
|
|
3356
|
-
let i = n;
|
|
3357
|
-
let j = m;
|
|
3358
|
-
while (i > 0 || j > 0) {
|
|
3359
|
-
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
|
|
3360
|
-
result.unshift({ type: "context", text: oldLines[i - 1] });
|
|
3361
|
-
i--;
|
|
3362
|
-
j--;
|
|
3363
|
-
} else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
|
3364
|
-
result.unshift({ type: "add", text: newLines[j - 1] });
|
|
3365
|
-
j--;
|
|
3366
|
-
} else {
|
|
3367
|
-
result.unshift({ type: "remove", text: oldLines[i - 1] });
|
|
3368
|
-
i--;
|
|
3369
|
-
}
|
|
3370
|
-
}
|
|
3371
|
-
return result;
|
|
3372
|
-
}
|
|
3373
|
-
function simpleDiff(oldLines, newLines) {
|
|
3374
|
-
const result = [];
|
|
3375
|
-
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
3376
|
-
for (let i = 0; i < maxLen; i++) {
|
|
3377
|
-
const o = oldLines[i];
|
|
3378
|
-
const n = newLines[i];
|
|
3379
|
-
if (o !== void 0 && n !== void 0) {
|
|
3380
|
-
if (o === n) {
|
|
3381
|
-
result.push({ type: "context", text: o });
|
|
3382
|
-
} else {
|
|
3383
|
-
result.push({ type: "remove", text: o });
|
|
3384
|
-
result.push({ type: "add", text: n });
|
|
3385
|
-
}
|
|
3386
|
-
} else if (o !== void 0) {
|
|
3387
|
-
result.push({ type: "remove", text: o });
|
|
3388
|
-
} else if (n !== void 0) {
|
|
3389
|
-
result.push({ type: "add", text: n });
|
|
3390
|
-
}
|
|
3391
|
-
}
|
|
3392
|
-
return result;
|
|
3393
|
-
}
|
|
3394
|
-
|
|
3395
3242
|
// src/repl/dev-state.ts
|
|
3396
3243
|
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "fs";
|
|
3397
3244
|
import { join as join5 } from "path";
|
|
@@ -3482,46 +3329,6 @@ function clearDevState() {
|
|
|
3482
3329
|
}
|
|
3483
3330
|
}
|
|
3484
3331
|
|
|
3485
|
-
// src/tools/hooks.ts
|
|
3486
|
-
import { execSync as execSync2 } from "child_process";
|
|
3487
|
-
function shellEscape(value) {
|
|
3488
|
-
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
3489
|
-
}
|
|
3490
|
-
function runHook(template, vars) {
|
|
3491
|
-
if (!template) return;
|
|
3492
|
-
let cmd = template;
|
|
3493
|
-
cmd = cmd.replace(/\{tool\}/g, shellEscape(vars.tool));
|
|
3494
|
-
cmd = cmd.replace(/\{dangerLevel\}/g, shellEscape(vars.dangerLevel ?? ""));
|
|
3495
|
-
cmd = cmd.replace(/\{args\}/g, shellEscape(vars.args ?? ""));
|
|
3496
|
-
cmd = cmd.replace(/\{status\}/g, shellEscape(vars.status ?? ""));
|
|
3497
|
-
try {
|
|
3498
|
-
execSync2(cmd, {
|
|
3499
|
-
timeout: 5e3,
|
|
3500
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
3501
|
-
encoding: "utf-8"
|
|
3502
|
-
});
|
|
3503
|
-
} catch {
|
|
3504
|
-
process.stderr.write(`\u26A0 Hook failed: ${cmd.slice(0, 100)}
|
|
3505
|
-
`);
|
|
3506
|
-
}
|
|
3507
|
-
}
|
|
3508
|
-
|
|
3509
|
-
// src/tools/permissions.ts
|
|
3510
|
-
function checkPermission(toolName, args, dangerLevel, rules, defaultAction = "confirm") {
|
|
3511
|
-
for (const rule of rules) {
|
|
3512
|
-
if (rule.tool !== "*" && rule.tool !== toolName) continue;
|
|
3513
|
-
if (rule.when) {
|
|
3514
|
-
if (rule.when.dangerLevel && rule.when.dangerLevel !== dangerLevel) continue;
|
|
3515
|
-
if (rule.when.pathPattern) {
|
|
3516
|
-
const path = String(args["path"] ?? args["command"] ?? "");
|
|
3517
|
-
if (!path.includes(rule.when.pathPattern)) continue;
|
|
3518
|
-
}
|
|
3519
|
-
}
|
|
3520
|
-
return rule.action;
|
|
3521
|
-
}
|
|
3522
|
-
return defaultAction;
|
|
3523
|
-
}
|
|
3524
|
-
|
|
3525
3332
|
export {
|
|
3526
3333
|
ConfigManager,
|
|
3527
3334
|
detectsHallucinatedFileOp,
|
|
@@ -3534,9 +3341,6 @@ export {
|
|
|
3534
3341
|
getGitRoot,
|
|
3535
3342
|
getGitContext,
|
|
3536
3343
|
formatGitContextForPrompt,
|
|
3537
|
-
renderDiff,
|
|
3538
|
-
runHook,
|
|
3539
|
-
checkPermission,
|
|
3540
3344
|
parseSimpleYaml,
|
|
3541
3345
|
SNAPSHOT_PROMPT,
|
|
3542
3346
|
sessionHasMeaningfulContent,
|
|
@@ -387,7 +387,7 @@ ${content}`);
|
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
390
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
390
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-4N5UUA6L.js");
|
|
391
391
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
392
392
|
let interrupted = false;
|
|
393
393
|
const onSigint = () => {
|