jinzd-ai-cli 0.4.24 → 0.4.26
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 +8 -3
- package/README.zh-CN.md +8 -3
- 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 +178 -504
- 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-SZZXQZWY.js} +128 -7
- package/dist/{task-orchestrator-C472QXTJ.js → task-orchestrator-4N5UUA6L.js} +3 -2
- package/package.json +1 -1
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
SessionManager,
|
|
8
8
|
SkillManager,
|
|
9
9
|
TOOL_CALL_REMINDER,
|
|
10
|
-
checkPermission,
|
|
11
10
|
detectsHallucinatedFileOp,
|
|
12
11
|
formatGitContextForPrompt,
|
|
13
12
|
getContentText,
|
|
@@ -15,24 +14,27 @@ import {
|
|
|
15
14
|
getGitRoot,
|
|
16
15
|
hadPreviousWriteToolCalls,
|
|
17
16
|
loadDevState,
|
|
18
|
-
renderDiff,
|
|
19
|
-
runHook,
|
|
20
17
|
setupProxy
|
|
21
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-SS7BQZ5R.js";
|
|
22
19
|
import {
|
|
23
20
|
AuthManager
|
|
24
21
|
} from "./chunk-BYNY5JPB.js";
|
|
25
22
|
import {
|
|
23
|
+
ToolExecutor,
|
|
26
24
|
ToolRegistry,
|
|
27
25
|
askUserContext,
|
|
26
|
+
checkPermission,
|
|
28
27
|
getDangerLevel,
|
|
29
28
|
googleSearchContext,
|
|
30
29
|
isFileWriteTool,
|
|
30
|
+
renderDiff,
|
|
31
|
+
runHook,
|
|
31
32
|
setContextWindow,
|
|
32
33
|
spawnAgentContext,
|
|
33
34
|
truncateOutput,
|
|
34
35
|
undoStack
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-5GZQLJAY.js";
|
|
37
|
+
import "./chunk-4BKXL7SM.js";
|
|
36
38
|
import {
|
|
37
39
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
38
40
|
AUTHOR,
|
|
@@ -50,7 +52,7 @@ import {
|
|
|
50
52
|
SKILLS_DIR_NAME,
|
|
51
53
|
VERSION,
|
|
52
54
|
buildUserIdentityPrompt
|
|
53
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-AHH5I2U6.js";
|
|
54
56
|
|
|
55
57
|
// src/web/server.ts
|
|
56
58
|
import express from "express";
|
|
@@ -815,6 +817,7 @@ You have a maximum of ${MAX_TOOL_ROUNDS} tool call rounds for this task. Plan ef
|
|
|
815
817
|
spawnAgentContext.systemPrompt = systemPrompt;
|
|
816
818
|
spawnAgentContext.modelParams = modelParams;
|
|
817
819
|
spawnAgentContext.configManager = this.config;
|
|
820
|
+
ToolExecutor.currentMessageIndex = this.sessions.current?.messages.length ?? 0;
|
|
818
821
|
const toolResults = await this.toolExecutor.executeAll(result.toolCalls);
|
|
819
822
|
const reasoningContent = result.reasoningContent;
|
|
820
823
|
const newMsgs = provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent);
|
|
@@ -1144,6 +1147,8 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1144
1147
|
" /checkpoint [save|restore|delete] <name> \u2014 Session checkpoints",
|
|
1145
1148
|
" /fork [checkpoint] \u2014 Fork session from checkpoint or current",
|
|
1146
1149
|
" /review [--staged] \u2014 AI code review from git diff",
|
|
1150
|
+
" /security-review \u2014 Security vulnerability scan on git diff",
|
|
1151
|
+
" /rewind [list|<n>] \u2014 Rewind conversation & restore files to checkpoint",
|
|
1147
1152
|
" /test [command] \u2014 Run project tests",
|
|
1148
1153
|
" /init [--force] \u2014 Generate AICLI.md by scanning project",
|
|
1149
1154
|
" /scaffold <desc> \u2014 Generate project scaffolding with AI",
|
|
@@ -1512,11 +1517,96 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1512
1517
|
}
|
|
1513
1518
|
break;
|
|
1514
1519
|
}
|
|
1520
|
+
// ── /security-review ──────────────────────────────────────────────
|
|
1521
|
+
case "security-review": {
|
|
1522
|
+
const gitCtx = getGitContext();
|
|
1523
|
+
if (!gitCtx) {
|
|
1524
|
+
this.send({ type: "error", message: "Not a git repository." });
|
|
1525
|
+
break;
|
|
1526
|
+
}
|
|
1527
|
+
const secStaged = args.includes("--staged");
|
|
1528
|
+
let secDiff;
|
|
1529
|
+
try {
|
|
1530
|
+
const cmd = secStaged ? "git diff --staged" : "git diff";
|
|
1531
|
+
secDiff = execSync(cmd, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
1532
|
+
} catch {
|
|
1533
|
+
this.send({ type: "error", message: "Failed to run git diff." });
|
|
1534
|
+
break;
|
|
1535
|
+
}
|
|
1536
|
+
if (!secDiff) {
|
|
1537
|
+
this.send({ type: "info", message: "No changes to review." + (secStaged ? "" : " Try --staged for staged changes.") });
|
|
1538
|
+
break;
|
|
1539
|
+
}
|
|
1540
|
+
const SEC_MAX_DIFF = 8e3;
|
|
1541
|
+
let secTruncated = false;
|
|
1542
|
+
if (secDiff.length > SEC_MAX_DIFF) {
|
|
1543
|
+
const head = secDiff.slice(0, Math.floor(SEC_MAX_DIFF * 0.7));
|
|
1544
|
+
const tail = secDiff.slice(secDiff.length - Math.floor(SEC_MAX_DIFF * 0.2));
|
|
1545
|
+
secDiff = head + "\n\n... [diff truncated, " + secDiff.length + " chars total] ...\n\n" + tail;
|
|
1546
|
+
secTruncated = true;
|
|
1547
|
+
}
|
|
1548
|
+
const secPrompt = this.buildSecurityReviewPrompt(secDiff, formatGitContextForPrompt(gitCtx));
|
|
1549
|
+
this.send({ type: "info", message: "\u{1F512} Scanning for security vulnerabilities..." });
|
|
1550
|
+
try {
|
|
1551
|
+
const secReview = await this.chatOnce(secPrompt, { temperature: 0.2, maxTokens: 8192 });
|
|
1552
|
+
const secMsg = secTruncated ? secReview + "\n\n\u26A0 Diff was truncated. Consider reviewing smaller changesets." : secReview;
|
|
1553
|
+
this.send({ type: "info", message: secMsg });
|
|
1554
|
+
} catch (err) {
|
|
1555
|
+
this.send({ type: "error", message: `Security review failed: ${err.message}` });
|
|
1556
|
+
}
|
|
1557
|
+
break;
|
|
1558
|
+
}
|
|
1559
|
+
// ── /rewind ────────────────────────────────────────────────────────
|
|
1560
|
+
case "rewind": {
|
|
1561
|
+
const session = this.sessions.current;
|
|
1562
|
+
if (!session || session.messages.length === 0) {
|
|
1563
|
+
this.send({ type: "info", message: "No messages to rewind." });
|
|
1564
|
+
break;
|
|
1565
|
+
}
|
|
1566
|
+
const rewindSub = args[0];
|
|
1567
|
+
if (rewindSub === "list" || !rewindSub) {
|
|
1568
|
+
const lines = [`Conversation messages (${session.messages.length} total):
|
|
1569
|
+
`];
|
|
1570
|
+
const cpIndices = (await import("./file-checkpoint-NKBHGC7L.js")).fileCheckpoints.getMessageIndices();
|
|
1571
|
+
for (let i = 0; i < session.messages.length; i++) {
|
|
1572
|
+
const m = session.messages[i];
|
|
1573
|
+
const text = getContentText(m.content).replace(/\n/g, " ").slice(0, 60);
|
|
1574
|
+
const pin = cpIndices.includes(i) ? " \u{1F4CC}" : "";
|
|
1575
|
+
lines.push(` [${i + 1}] ${m.role.padEnd(10)} ${text}${pin}`);
|
|
1576
|
+
}
|
|
1577
|
+
lines.push("", "Usage: /rewind <n> \u2014 rewind to message N", "\u{1F4CC} = file checkpoint");
|
|
1578
|
+
this.send({ type: "info", message: lines.join("\n") });
|
|
1579
|
+
break;
|
|
1580
|
+
}
|
|
1581
|
+
const rewindN = parseInt(rewindSub, 10);
|
|
1582
|
+
if (isNaN(rewindN) || rewindN < 1 || rewindN > session.messages.length) {
|
|
1583
|
+
this.send({ type: "error", message: `Invalid message number: ${rewindSub}. Range: 1-${session.messages.length}` });
|
|
1584
|
+
break;
|
|
1585
|
+
}
|
|
1586
|
+
const { fileCheckpoints: fc } = await import("./file-checkpoint-NKBHGC7L.js");
|
|
1587
|
+
const rewindRemoved = session.messages.length - rewindN;
|
|
1588
|
+
const rewindResult = fc.restoreToMessageIndex(rewindN);
|
|
1589
|
+
session.messages = session.messages.slice(0, rewindN);
|
|
1590
|
+
session.checkpoints = session.checkpoints.filter((c) => c.messageIndex <= rewindN);
|
|
1591
|
+
session.updated = /* @__PURE__ */ new Date();
|
|
1592
|
+
this.sessions.save();
|
|
1593
|
+
const rewindLines = [`\u2713 Rewound to message ${rewindN}`, ` Messages removed: ${rewindRemoved}`];
|
|
1594
|
+
if (rewindResult.restored > 0 || rewindResult.deleted > 0) {
|
|
1595
|
+
rewindLines.push(` Files restored: ${rewindResult.restored}, deleted: ${rewindResult.deleted}`);
|
|
1596
|
+
for (const f of rewindResult.files) rewindLines.push(` ${f}`);
|
|
1597
|
+
} else {
|
|
1598
|
+
rewindLines.push(" No file changes to revert.");
|
|
1599
|
+
}
|
|
1600
|
+
this.send({ type: "info", message: rewindLines.join("\n") });
|
|
1601
|
+
this.sendSessionMessages();
|
|
1602
|
+
this.sendStatus();
|
|
1603
|
+
break;
|
|
1604
|
+
}
|
|
1515
1605
|
// ── /test ───────────────────────────────────────────────────────
|
|
1516
1606
|
case "test": {
|
|
1517
1607
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
1518
1608
|
try {
|
|
1519
|
-
const { executeTests } = await import("./run-tests-
|
|
1609
|
+
const { executeTests } = await import("./run-tests-L3JNRB6X.js");
|
|
1520
1610
|
const argStr = args.join(" ").trim();
|
|
1521
1611
|
let testArgs = {};
|
|
1522
1612
|
if (argStr) {
|
|
@@ -2320,6 +2410,37 @@ ${diff}
|
|
|
2320
2410
|
4. **Highlights** (if any)
|
|
2321
2411
|
|
|
2322
2412
|
Severity: \u{1F534} Critical / \u{1F7E1} Warning / \u{1F535} Info`;
|
|
2413
|
+
}
|
|
2414
|
+
buildSecurityReviewPrompt(diff, gitContextStr) {
|
|
2415
|
+
return `# Security Vulnerability Review
|
|
2416
|
+
|
|
2417
|
+
Analyze the following code changes **exclusively for security vulnerabilities**.
|
|
2418
|
+
|
|
2419
|
+
## Categories
|
|
2420
|
+
1. Injection (SQL, command, path traversal, XSS)
|
|
2421
|
+
2. Auth & Authorization (hardcoded creds, missing checks)
|
|
2422
|
+
3. Secrets & Sensitive Data (API keys, tokens in code)
|
|
2423
|
+
4. Input Validation (missing validation, unsafe deserialization)
|
|
2424
|
+
5. Cryptography (weak algorithms, hardcoded IVs)
|
|
2425
|
+
6. File System (path traversal, symlink attacks)
|
|
2426
|
+
7. Network (SSRF, insecure protocols)
|
|
2427
|
+
|
|
2428
|
+
## Git Status
|
|
2429
|
+
${gitContextStr}
|
|
2430
|
+
|
|
2431
|
+
## Code Changes
|
|
2432
|
+
\`\`\`diff
|
|
2433
|
+
${diff}
|
|
2434
|
+
\`\`\`
|
|
2435
|
+
|
|
2436
|
+
## Output Format
|
|
2437
|
+
For each finding:
|
|
2438
|
+
- **Severity**: \u{1F534} CRITICAL / \u{1F7E0} HIGH / \u{1F7E1} MEDIUM / \u{1F535} LOW
|
|
2439
|
+
- **Category** + **File:line**
|
|
2440
|
+
- **Description** + exploitation scenario
|
|
2441
|
+
- **Recommended fix**
|
|
2442
|
+
|
|
2443
|
+
If none found: "\u2705 No security vulnerabilities detected"`;
|
|
2323
2444
|
}
|
|
2324
2445
|
loadContextFiles() {
|
|
2325
2446
|
const parts = [];
|
|
@@ -4,10 +4,11 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-5GZQLJAY.js";
|
|
8
|
+
import "./chunk-4BKXL7SM.js";
|
|
8
9
|
import {
|
|
9
10
|
SUBAGENT_ALLOWED_TOOLS
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-AHH5I2U6.js";
|
|
11
12
|
|
|
12
13
|
// src/hub/task-orchestrator.ts
|
|
13
14
|
import { createInterface } from "readline";
|