jinzd-ai-cli 0.4.205 → 0.4.207
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 -1
- package/dist/{batch-RBPABHS7.js → batch-6PORMJWT.js} +2 -2
- package/dist/{chunk-XIYSFN4U.js → chunk-2WV6AGHM.js} +1 -1
- package/dist/{chunk-43H3D2PK.js → chunk-BQIV4ZQT.js} +1 -1
- package/dist/{chunk-JVYH66N2.js → chunk-KJHMRAJU.js} +1 -1
- package/dist/{chunk-ZSC4YLEJ.js → chunk-KOU4KX7J.js} +2 -2
- package/dist/{chunk-UZISJ3KZ.js → chunk-QMXC327F.js} +3 -3
- package/dist/{chunk-3RET7PL7.js → chunk-QNUVZO5X.js} +1 -1
- package/dist/{chunk-43MWRT2C.js → chunk-QQYSZMET.js} +20 -17
- package/dist/{chunk-VOV2PWZU.js → chunk-SFCNFX42.js} +1 -1
- package/dist/{chunk-TZ7SNVSG.js → chunk-TW47X5AO.js} +1 -1
- package/dist/{chunk-SMFRJCXB.js → chunk-XPBEJB27.js} +8 -1
- package/dist/{ci-ABE74AXH.js → ci-AYMV66P3.js} +9 -9
- package/dist/{constants-GMQMJRIO.js → constants-NHGTSHKT.js} +1 -1
- package/dist/{doctor-cli-M5PPO3L3.js → doctor-cli-WKH7T4AW.js} +6 -6
- package/dist/electron-server.js +46 -41
- package/dist/{hub-NCU5JNCK.js → hub-6R3M3NTC.js} +1 -1
- package/dist/index.js +102 -98
- package/dist/{run-tests-ZFAEFEYK.js → run-tests-5F2OBWIK.js} +2 -2
- package/dist/{run-tests-FGRWBNVF.js → run-tests-NBCA4KEG.js} +1 -1
- package/dist/{server-RKP7JRRE.js → server-37EXC4EB.js} +5 -5
- package/dist/{server-ML6ZL3J5.js → server-L2MXWYF7.js} +26 -26
- package/dist/{task-orchestrator-LJP5XZSC.js → task-orchestrator-2DTDVCMR.js} +5 -5
- package/dist/{usage-YX2235W5.js → usage-SZWZFX3T.js} +2 -2
- package/dist/web/client/actions.js +84 -0
- package/dist/web/client/app.js +23 -205
- package/dist/web/client/index.html +27 -42
- package/dist/web/client/sw.js +1 -1
- package/dist/web/client/templates.js +188 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
saveDevState,
|
|
16
16
|
sessionHasMeaningfulContent,
|
|
17
17
|
setupProxy
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-KOU4KX7J.js";
|
|
19
19
|
import {
|
|
20
20
|
ToolExecutor,
|
|
21
21
|
ToolRegistry,
|
|
@@ -35,10 +35,10 @@ import {
|
|
|
35
35
|
spawnAgentContext,
|
|
36
36
|
theme,
|
|
37
37
|
undoStack
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-QQYSZMET.js";
|
|
39
39
|
import "./chunk-T2NL5ZIA.js";
|
|
40
40
|
import "./chunk-BXP6YZ2P.js";
|
|
41
|
-
import "./chunk-
|
|
41
|
+
import "./chunk-SFCNFX42.js";
|
|
42
42
|
import {
|
|
43
43
|
SessionManager,
|
|
44
44
|
getContentText
|
|
@@ -55,16 +55,16 @@ import {
|
|
|
55
55
|
getConfigDirUsage,
|
|
56
56
|
listRecentCrashes,
|
|
57
57
|
writeCrashLog
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-KJHMRAJU.js";
|
|
59
59
|
import {
|
|
60
60
|
ProviderRegistry
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-QMXC327F.js";
|
|
62
62
|
import {
|
|
63
63
|
getStatsSnapshot,
|
|
64
64
|
getTopFailingTools,
|
|
65
65
|
getTopUsedTools,
|
|
66
66
|
installFlushOnExit
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-2WV6AGHM.js";
|
|
68
68
|
import {
|
|
69
69
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
70
70
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -83,10 +83,10 @@ import {
|
|
|
83
83
|
stripOuterCodeFence,
|
|
84
84
|
stripToolCallReminder,
|
|
85
85
|
teeStreamErrorSummary
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-XPBEJB27.js";
|
|
87
87
|
import {
|
|
88
88
|
ConfigManager
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-TW47X5AO.js";
|
|
90
90
|
import {
|
|
91
91
|
AuthError,
|
|
92
92
|
ProviderError,
|
|
@@ -113,7 +113,7 @@ import {
|
|
|
113
113
|
SKILLS_DIR_NAME,
|
|
114
114
|
VERSION,
|
|
115
115
|
buildUserIdentityPrompt
|
|
116
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-QNUVZO5X.js";
|
|
117
117
|
import {
|
|
118
118
|
formatGitContextForPrompt,
|
|
119
119
|
getGitContext,
|
|
@@ -135,15 +135,17 @@ import {
|
|
|
135
135
|
} from "./chunk-SLSWPBK3.js";
|
|
136
136
|
import "./chunk-O6UFCEUZ.js";
|
|
137
137
|
import "./chunk-CKH4KQ4E.js";
|
|
138
|
-
import
|
|
138
|
+
import {
|
|
139
|
+
atomicWriteFileSync
|
|
140
|
+
} from "./chunk-IW3Q7AE5.js";
|
|
139
141
|
|
|
140
142
|
// src/index.ts
|
|
141
143
|
import { program } from "commander";
|
|
142
144
|
|
|
143
145
|
// src/repl/repl.ts
|
|
144
146
|
import * as readline from "readline";
|
|
145
|
-
import { existsSync as
|
|
146
|
-
import { join as
|
|
147
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
148
|
+
import { join as join5, resolve as resolve2, extname as extname2, dirname as dirname3, basename as basename2 } from "path";
|
|
147
149
|
import chalk4 from "chalk";
|
|
148
150
|
|
|
149
151
|
// src/session/title-generator.ts
|
|
@@ -635,10 +637,10 @@ Error${typeName}: ${lines.join("\n")}
|
|
|
635
637
|
};
|
|
636
638
|
|
|
637
639
|
// src/repl/commands/index.ts
|
|
638
|
-
import { writeFileSync, mkdirSync as mkdirSync2, existsSync as
|
|
640
|
+
import { writeFileSync, mkdirSync as mkdirSync2, existsSync as existsSync3, readFileSync as readFileSync2, statSync as statSync3, appendFileSync } from "fs";
|
|
639
641
|
import { execSync as execSync2 } from "child_process";
|
|
640
642
|
import { platform } from "os";
|
|
641
|
-
import { resolve, dirname as dirname2, join as
|
|
643
|
+
import { resolve, dirname as dirname2, join as join3, basename } from "path";
|
|
642
644
|
import chalk2 from "chalk";
|
|
643
645
|
|
|
644
646
|
// src/repl/clipboard.ts
|
|
@@ -728,12 +730,9 @@ function getClipboardHint() {
|
|
|
728
730
|
return "";
|
|
729
731
|
}
|
|
730
732
|
|
|
731
|
-
// src/repl/commands/
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
if (tokens >= 1e3) return `${Math.round(tokens / 1024)}K`;
|
|
735
|
-
return `${tokens}`;
|
|
736
|
-
}
|
|
733
|
+
// src/repl/commands/project-init.ts
|
|
734
|
+
import { existsSync as existsSync2, readFileSync, readdirSync, statSync as statSync2 } from "fs";
|
|
735
|
+
import { join as join2 } from "path";
|
|
737
736
|
var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
738
737
|
"node_modules",
|
|
739
738
|
".git",
|
|
@@ -791,7 +790,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
|
|
|
791
790
|
const name = sorted[i];
|
|
792
791
|
const fullPath = join2(d, name);
|
|
793
792
|
const isLast = i === sorted.length - 1;
|
|
794
|
-
const connector = isLast ? "
|
|
793
|
+
const connector = isLast ? "+-- " : "|-- ";
|
|
795
794
|
let isDir;
|
|
796
795
|
try {
|
|
797
796
|
isDir = statSync2(fullPath).isDirectory();
|
|
@@ -801,7 +800,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
|
|
|
801
800
|
lines.push(prefix + connector + name + (isDir ? "/" : ""));
|
|
802
801
|
count++;
|
|
803
802
|
if (isDir) {
|
|
804
|
-
walk(fullPath, prefix + (isLast ? " " : "
|
|
803
|
+
walk(fullPath, prefix + (isLast ? " " : "| "), depth + 1);
|
|
805
804
|
}
|
|
806
805
|
}
|
|
807
806
|
};
|
|
@@ -845,9 +844,9 @@ function scanProject(cwd) {
|
|
|
845
844
|
try {
|
|
846
845
|
const pkg = JSON.parse(readFileSync(join2(cwd, "package.json"), "utf-8"));
|
|
847
846
|
const scripts = pkg.scripts ?? {};
|
|
848
|
-
info.buildCommand = scripts.build ?
|
|
849
|
-
info.testCommand = scripts.test ?
|
|
850
|
-
info.devCommand = scripts.dev ?
|
|
847
|
+
info.buildCommand = scripts.build ? "npm run build" : void 0;
|
|
848
|
+
info.testCommand = scripts.test ? "npm test" : void 0;
|
|
849
|
+
info.devCommand = scripts.dev ? "npm run dev" : void 0;
|
|
851
850
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
852
851
|
if (allDeps["react"]) info.framework = "React";
|
|
853
852
|
else if (allDeps["vue"]) info.framework = "Vue";
|
|
@@ -889,10 +888,8 @@ function scanProject(cwd) {
|
|
|
889
888
|
}
|
|
890
889
|
function buildInitPrompt(info, cwd) {
|
|
891
890
|
const parts = [
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
## Project Info
|
|
895
|
-
`,
|
|
891
|
+
"Please generate an AICLI.md context file (Markdown format) for the following project. This file will be injected into the AI conversation system prompt to help the AI understand the project structure and coding conventions.",
|
|
892
|
+
"\n## Project Info\n",
|
|
896
893
|
`- Working directory: ${cwd}`,
|
|
897
894
|
`- Type: ${info.type}`,
|
|
898
895
|
`- Language: ${info.language}`
|
|
@@ -921,6 +918,13 @@ Please generate a structured Markdown file containing:
|
|
|
921
918
|
Output the Markdown content directly, do not wrap the entire file in a code block. Keep it concise, within 200 lines.`);
|
|
922
919
|
return parts.join("\n");
|
|
923
920
|
}
|
|
921
|
+
|
|
922
|
+
// src/repl/commands/index.ts
|
|
923
|
+
function fmtCtx(tokens) {
|
|
924
|
+
if (tokens >= 1e6) return `${Math.round(tokens / 1e5) / 10}M`;
|
|
925
|
+
if (tokens >= 1e3) return `${Math.round(tokens / 1024)}K`;
|
|
926
|
+
return `${tokens}`;
|
|
927
|
+
}
|
|
924
928
|
function copyToClipboard(text) {
|
|
925
929
|
const plat = platform();
|
|
926
930
|
if (plat === "win32") {
|
|
@@ -1825,16 +1829,16 @@ No tools match "${filter}".
|
|
|
1825
1829
|
usage: "/mcp [reconnect [serverId] | trust-project]",
|
|
1826
1830
|
async execute(args, ctx) {
|
|
1827
1831
|
if (args[0] === "trust-project") {
|
|
1828
|
-
const { join:
|
|
1829
|
-
const { existsSync:
|
|
1832
|
+
const { join: join6 } = await import("path");
|
|
1833
|
+
const { existsSync: existsSync6 } = await import("fs");
|
|
1830
1834
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
|
|
1831
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
1835
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-NHGTSHKT.js");
|
|
1832
1836
|
const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
|
|
1833
1837
|
const cwd = process.cwd();
|
|
1834
1838
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
1835
|
-
const mcpPath =
|
|
1839
|
+
const mcpPath = join6(projectRoot, MCP_PROJECT_CONFIG_NAME2);
|
|
1836
1840
|
console.log();
|
|
1837
|
-
if (!
|
|
1841
|
+
if (!existsSync6(mcpPath)) {
|
|
1838
1842
|
console.log(theme.dim(` No .mcp.json in ${projectRoot}.`));
|
|
1839
1843
|
console.log();
|
|
1840
1844
|
return;
|
|
@@ -2167,9 +2171,9 @@ No tools match "${filter}".
|
|
|
2167
2171
|
usage: "/init [--force]",
|
|
2168
2172
|
async execute(args, ctx) {
|
|
2169
2173
|
const cwd = process.cwd();
|
|
2170
|
-
const targetPath =
|
|
2174
|
+
const targetPath = join3(cwd, "AICLI.md");
|
|
2171
2175
|
const force = args.includes("--force");
|
|
2172
|
-
if (
|
|
2176
|
+
if (existsSync3(targetPath) && !force) {
|
|
2173
2177
|
ctx.renderer.printInfo(`AICLI.md already exists at ${targetPath}`);
|
|
2174
2178
|
ctx.renderer.printInfo("Use /init --force to overwrite, or edit it manually.");
|
|
2175
2179
|
return;
|
|
@@ -2889,7 +2893,7 @@ ${hint}` : "")
|
|
|
2889
2893
|
usage: "/test [command|filter]",
|
|
2890
2894
|
async execute(args, ctx) {
|
|
2891
2895
|
try {
|
|
2892
|
-
const { executeTests } = await import("./run-tests-
|
|
2896
|
+
const { executeTests } = await import("./run-tests-5F2OBWIK.js");
|
|
2893
2897
|
const argStr = args.join(" ").trim();
|
|
2894
2898
|
let testArgs = {};
|
|
2895
2899
|
if (argStr) {
|
|
@@ -3047,7 +3051,7 @@ ${hint}` : "")
|
|
|
3047
3051
|
description: "Persistent memory (memory.md) + chat memory recall index (v0.4.89+)",
|
|
3048
3052
|
usage: "/memory [show|add <text>|clear|path|rebuild|refresh|status|recall <query>|index-clear]",
|
|
3049
3053
|
async execute(args, ctx) {
|
|
3050
|
-
const memoryFile =
|
|
3054
|
+
const memoryFile = join3(ctx.config.getConfigDir(), MEMORY_FILE_NAME);
|
|
3051
3055
|
const sub = args[0] ?? "show";
|
|
3052
3056
|
if (sub === "rebuild" || sub === "refresh") {
|
|
3053
3057
|
const full = sub === "rebuild";
|
|
@@ -3131,11 +3135,11 @@ ${hint}` : "")
|
|
|
3131
3135
|
return;
|
|
3132
3136
|
}
|
|
3133
3137
|
if (sub === "show" || sub === "view") {
|
|
3134
|
-
if (!
|
|
3138
|
+
if (!existsSync3(memoryFile)) {
|
|
3135
3139
|
ctx.renderer.printInfo("Memory is empty (memory.md not found)");
|
|
3136
3140
|
return;
|
|
3137
3141
|
}
|
|
3138
|
-
const content =
|
|
3142
|
+
const content = readFileSync2(memoryFile, "utf-8").trim();
|
|
3139
3143
|
if (!content) {
|
|
3140
3144
|
ctx.renderer.printInfo("Memory is empty");
|
|
3141
3145
|
return;
|
|
@@ -3166,7 +3170,7 @@ ${text}
|
|
|
3166
3170
|
ctx.renderer.renderError(`Failed to write memory: ${err instanceof Error ? err.message : String(err)}`);
|
|
3167
3171
|
}
|
|
3168
3172
|
} else if (sub === "clear") {
|
|
3169
|
-
if (!
|
|
3173
|
+
if (!existsSync3(memoryFile)) {
|
|
3170
3174
|
ctx.renderer.printInfo("Memory is already empty");
|
|
3171
3175
|
return;
|
|
3172
3176
|
}
|
|
@@ -3202,20 +3206,20 @@ ${text}
|
|
|
3202
3206
|
console.log(theme.heading("Config Files:"));
|
|
3203
3207
|
console.log(` Dir: ${theme.accent(configDir)}`);
|
|
3204
3208
|
const checkFile = (label, filePath) => {
|
|
3205
|
-
const exists =
|
|
3209
|
+
const exists = existsSync3(filePath);
|
|
3206
3210
|
const icon = exists ? theme.success("\u2713") : theme.dim("\u2013");
|
|
3207
3211
|
let extra = "";
|
|
3208
3212
|
if (exists) {
|
|
3209
3213
|
try {
|
|
3210
|
-
extra = theme.dim(` (${
|
|
3214
|
+
extra = theme.dim(` (${statSync3(filePath).size} bytes)`);
|
|
3211
3215
|
} catch {
|
|
3212
3216
|
}
|
|
3213
3217
|
}
|
|
3214
3218
|
console.log(` ${icon} ${label.padEnd(14)} ${exists ? filePath : theme.dim("(not found)")}${extra}`);
|
|
3215
3219
|
};
|
|
3216
|
-
checkFile("config.json",
|
|
3217
|
-
checkFile("memory.md",
|
|
3218
|
-
checkFile("dev-state.md",
|
|
3220
|
+
checkFile("config.json", join3(configDir, "config.json"));
|
|
3221
|
+
checkFile("memory.md", join3(configDir, MEMORY_FILE_NAME));
|
|
3222
|
+
checkFile("dev-state.md", join3(configDir, "dev-state.md"));
|
|
3219
3223
|
console.log();
|
|
3220
3224
|
const mcpManager = ctx.getMcpManager();
|
|
3221
3225
|
if (mcpManager) {
|
|
@@ -3379,9 +3383,9 @@ ${text}
|
|
|
3379
3383
|
let newFiles = 0;
|
|
3380
3384
|
let modifiedFiles = 0;
|
|
3381
3385
|
for (const [filePath, { earliest }] of fileMap) {
|
|
3382
|
-
const currentContent =
|
|
3386
|
+
const currentContent = existsSync3(filePath) ? (() => {
|
|
3383
3387
|
try {
|
|
3384
|
-
return
|
|
3388
|
+
return readFileSync2(filePath, "utf-8");
|
|
3385
3389
|
} catch {
|
|
3386
3390
|
return null;
|
|
3387
3391
|
}
|
|
@@ -3507,12 +3511,12 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
|
|
|
3507
3511
|
if (scanAll) {
|
|
3508
3512
|
const metas = ctx.sessions.listSessions();
|
|
3509
3513
|
console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
|
|
3510
|
-
const { readFileSync:
|
|
3511
|
-
const { join:
|
|
3514
|
+
const { readFileSync: readFileSync5 } = await import("fs");
|
|
3515
|
+
const { join: join6 } = await import("path");
|
|
3512
3516
|
const historyDir = ctx.config.getHistoryDir();
|
|
3513
3517
|
for (const m of metas) {
|
|
3514
3518
|
try {
|
|
3515
|
-
const content =
|
|
3519
|
+
const content = readFileSync5(join6(historyDir, `${m.id}.json`), "utf-8");
|
|
3516
3520
|
const hits2 = scanString(content, opts);
|
|
3517
3521
|
if (hits2.length) {
|
|
3518
3522
|
filesWithHits++;
|
|
@@ -3567,7 +3571,7 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
|
|
|
3567
3571
|
console.log(theme.info(" \u{1F512} Auto-approve disabled \u2014 confirmations restored for this session."));
|
|
3568
3572
|
} else {
|
|
3569
3573
|
executor.sessionAutoApprove = true;
|
|
3570
|
-
console.log(theme.warning(" \u26A1 YOLO mode ON \u2014
|
|
3574
|
+
console.log(theme.warning(" \u26A1 YOLO mode ON \u2014 write tools auto-approved; destructive tools still require confirmation."));
|
|
3571
3575
|
console.log(theme.dim(" Use /yolo off to re-enable confirmations."));
|
|
3572
3576
|
}
|
|
3573
3577
|
console.log();
|
|
@@ -4047,11 +4051,11 @@ Managing ${displayName} API Key`);
|
|
|
4047
4051
|
console.log(" alwaysYolo: " + (current ? theme.warning("ON") : theme.dim("off")));
|
|
4048
4052
|
console.log(
|
|
4049
4053
|
theme.dim(
|
|
4050
|
-
" When ON, REPL starts with sessionAutoApprove enabled \u2014
|
|
4054
|
+
" When ON, REPL starts with sessionAutoApprove enabled \u2014 write\n tools (write_file/edit_file, etc.) run without confirmation prompts. Destructive tools still require confirmation. Only enable this\n if you fully trust the working directory you run aicli in.\n"
|
|
4051
4055
|
)
|
|
4052
4056
|
);
|
|
4053
4057
|
const next = await confirm({
|
|
4054
|
-
message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip
|
|
4058
|
+
message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip write confirmations; destructive still confirms)?",
|
|
4055
4059
|
default: current
|
|
4056
4060
|
});
|
|
4057
4061
|
if (next === current) {
|
|
@@ -4197,13 +4201,13 @@ Managing ${displayName} API Key`);
|
|
|
4197
4201
|
};
|
|
4198
4202
|
|
|
4199
4203
|
// src/repl/custom-commands.ts
|
|
4200
|
-
import { existsSync as
|
|
4201
|
-
import { join as
|
|
4204
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
4205
|
+
import { join as join4, extname } from "path";
|
|
4202
4206
|
import { execSync as execSync3 } from "child_process";
|
|
4203
4207
|
function parseCommandFile(filePath) {
|
|
4204
4208
|
let content;
|
|
4205
4209
|
try {
|
|
4206
|
-
content =
|
|
4210
|
+
content = readFileSync3(filePath, "utf-8");
|
|
4207
4211
|
} catch {
|
|
4208
4212
|
return null;
|
|
4209
4213
|
}
|
|
@@ -4227,7 +4231,7 @@ function expandTemplate(template, args) {
|
|
|
4227
4231
|
result = result.replace(/\{\{input\}\}/g, args.join(" "));
|
|
4228
4232
|
result = result.replace(/\{\{file:([^}]+)\}\}/g, (_m, p) => {
|
|
4229
4233
|
try {
|
|
4230
|
-
return
|
|
4234
|
+
return readFileSync3(p.trim(), "utf-8");
|
|
4231
4235
|
} catch {
|
|
4232
4236
|
return `[Error: cannot read ${p.trim()}]`;
|
|
4233
4237
|
}
|
|
@@ -4252,14 +4256,14 @@ var CustomCommandManager = class {
|
|
|
4252
4256
|
commands = /* @__PURE__ */ new Map();
|
|
4253
4257
|
loadCommands() {
|
|
4254
4258
|
this.commands.clear();
|
|
4255
|
-
if (!
|
|
4259
|
+
if (!existsSync4(this.commandsDir)) {
|
|
4256
4260
|
mkdirSync3(this.commandsDir, { recursive: true });
|
|
4257
4261
|
return 0;
|
|
4258
4262
|
}
|
|
4259
4263
|
let count = 0;
|
|
4260
4264
|
for (const file of readdirSync2(this.commandsDir)) {
|
|
4261
4265
|
if (extname(file) !== ".md") continue;
|
|
4262
|
-
const cmd = parseCommandFile(
|
|
4266
|
+
const cmd = parseCommandFile(join4(this.commandsDir, file));
|
|
4263
4267
|
if (cmd) {
|
|
4264
4268
|
this.commands.set(cmd.meta.name, cmd);
|
|
4265
4269
|
count++;
|
|
@@ -4564,17 +4568,17 @@ function parseAtReferences(input2, cwd) {
|
|
|
4564
4568
|
const absPath = resolve2(cwd, rawPath);
|
|
4565
4569
|
const ext = extname2(rawPath).toLowerCase();
|
|
4566
4570
|
const mime = IMAGE_MIME[ext];
|
|
4567
|
-
if (!
|
|
4571
|
+
if (!existsSync5(absPath)) {
|
|
4568
4572
|
refs.push({ path: rawPath, type: "notfound" });
|
|
4569
4573
|
continue;
|
|
4570
4574
|
}
|
|
4571
4575
|
if (mime) {
|
|
4572
|
-
const fileSize =
|
|
4576
|
+
const fileSize = statSync4(absPath).size;
|
|
4573
4577
|
if (fileSize > MAX_IMAGE_BYTES) {
|
|
4574
4578
|
refs.push({ path: rawPath, type: "toolarge" });
|
|
4575
4579
|
continue;
|
|
4576
4580
|
}
|
|
4577
|
-
const data =
|
|
4581
|
+
const data = readFileSync4(absPath).toString("base64");
|
|
4578
4582
|
imageParts.push({
|
|
4579
4583
|
type: "image_url",
|
|
4580
4584
|
image_url: { url: `data:${mime};base64,${data}` }
|
|
@@ -4582,7 +4586,7 @@ function parseAtReferences(input2, cwd) {
|
|
|
4582
4586
|
refs.push({ path: rawPath, type: "image" });
|
|
4583
4587
|
textBody = textBody.replace(match[0], "").trim();
|
|
4584
4588
|
} else {
|
|
4585
|
-
const content =
|
|
4589
|
+
const content = readFileSync4(absPath, "utf-8");
|
|
4586
4590
|
const inlined = `
|
|
4587
4591
|
|
|
4588
4592
|
[File: ${rawPath}]
|
|
@@ -4807,12 +4811,12 @@ var Repl = class {
|
|
|
4807
4811
|
const filtered = entries.filter((e) => !SKIP_DIRS_SET.has(e));
|
|
4808
4812
|
for (let i = 0; i < filtered.length && entryCount < MAX_TREE_ENTRIES; i++) {
|
|
4809
4813
|
const name = filtered[i];
|
|
4810
|
-
const fullPath =
|
|
4814
|
+
const fullPath = join5(dir, name);
|
|
4811
4815
|
const isLast = i === filtered.length - 1;
|
|
4812
4816
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
4813
4817
|
let isDir;
|
|
4814
4818
|
try {
|
|
4815
|
-
isDir =
|
|
4819
|
+
isDir = statSync4(fullPath).isDirectory();
|
|
4816
4820
|
} catch {
|
|
4817
4821
|
continue;
|
|
4818
4822
|
}
|
|
@@ -4841,10 +4845,10 @@ ${treeLines.join("\n")}`
|
|
|
4841
4845
|
for (const name of entries) {
|
|
4842
4846
|
if (totalChars >= MAX_TOTAL_CHARS) break;
|
|
4843
4847
|
if (SKIP_DIRS_SET.has(name)) continue;
|
|
4844
|
-
const fullPath =
|
|
4848
|
+
const fullPath = join5(dir, name);
|
|
4845
4849
|
let st;
|
|
4846
4850
|
try {
|
|
4847
|
-
st =
|
|
4851
|
+
st = statSync4(fullPath);
|
|
4848
4852
|
} catch {
|
|
4849
4853
|
continue;
|
|
4850
4854
|
}
|
|
@@ -4856,7 +4860,7 @@ ${treeLines.join("\n")}`
|
|
|
4856
4860
|
if (!TEXT_EXTS.has(ext) && !isSpecial) continue;
|
|
4857
4861
|
if (st.size > MAX_FILE_CHARS * 3) continue;
|
|
4858
4862
|
try {
|
|
4859
|
-
let content =
|
|
4863
|
+
let content = readFileSync4(fullPath, "utf-8");
|
|
4860
4864
|
if (content.length > MAX_FILE_CHARS) {
|
|
4861
4865
|
content = content.slice(0, MAX_FILE_CHARS) + `
|
|
4862
4866
|
... (truncated, ${content.length} chars total)`;
|
|
@@ -4886,12 +4890,12 @@ ${content}
|
|
|
4886
4890
|
*/
|
|
4887
4891
|
addExtraContextDir(dirPath) {
|
|
4888
4892
|
const absPath = resolve2(dirPath);
|
|
4889
|
-
if (!
|
|
4893
|
+
if (!existsSync5(absPath)) {
|
|
4890
4894
|
return { success: false, charCount: 0, added: false, error: `Directory not found: ${dirPath}` };
|
|
4891
4895
|
}
|
|
4892
4896
|
let isDir;
|
|
4893
4897
|
try {
|
|
4894
|
-
isDir =
|
|
4898
|
+
isDir = statSync4(absPath).isDirectory();
|
|
4895
4899
|
} catch {
|
|
4896
4900
|
return { success: false, charCount: 0, added: false, error: `Cannot access: ${dirPath}` };
|
|
4897
4901
|
}
|
|
@@ -4920,9 +4924,9 @@ ${content}
|
|
|
4920
4924
|
*/
|
|
4921
4925
|
findContextFile(dir, candidates = CONTEXT_FILE_CANDIDATES) {
|
|
4922
4926
|
for (const candidate of candidates) {
|
|
4923
|
-
const fullPath =
|
|
4924
|
-
if (
|
|
4925
|
-
const content =
|
|
4927
|
+
const fullPath = join5(dir, candidate);
|
|
4928
|
+
if (existsSync5(fullPath)) {
|
|
4929
|
+
const content = readFileSync4(fullPath, "utf-8").trim();
|
|
4926
4930
|
if (content) return { filePath: fullPath, content };
|
|
4927
4931
|
}
|
|
4928
4932
|
}
|
|
@@ -4950,10 +4954,10 @@ ${content}
|
|
|
4950
4954
|
const cwd = process.cwd();
|
|
4951
4955
|
const gitRoot = getGitRoot(cwd);
|
|
4952
4956
|
const projectRoot = gitRoot ?? cwd;
|
|
4953
|
-
const mcpPath =
|
|
4954
|
-
if (!
|
|
4957
|
+
const mcpPath = join5(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
4958
|
+
if (!existsSync5(mcpPath)) return null;
|
|
4955
4959
|
try {
|
|
4956
|
-
const raw = JSON.parse(
|
|
4960
|
+
const raw = JSON.parse(readFileSync4(mcpPath, "utf-8"));
|
|
4957
4961
|
const servers = raw?.mcpServers;
|
|
4958
4962
|
if (!servers || typeof servers !== "object") {
|
|
4959
4963
|
process.stderr.write(
|
|
@@ -4999,8 +5003,8 @@ ${content}
|
|
|
4999
5003
|
);
|
|
5000
5004
|
return { layers: [], mergedContent: "" };
|
|
5001
5005
|
}
|
|
5002
|
-
if (
|
|
5003
|
-
const content =
|
|
5006
|
+
if (existsSync5(fullPath)) {
|
|
5007
|
+
const content = readFileSync4(fullPath, "utf-8").trim();
|
|
5004
5008
|
if (content) {
|
|
5005
5009
|
const layer = {
|
|
5006
5010
|
level: "project",
|
|
@@ -5057,9 +5061,9 @@ ${content}
|
|
|
5057
5061
|
* 超过 MEMORY_MAX_CHARS 时只取末尾最新部分。
|
|
5058
5062
|
*/
|
|
5059
5063
|
loadMemoryContent() {
|
|
5060
|
-
const memoryPath =
|
|
5061
|
-
if (!
|
|
5062
|
-
let content =
|
|
5064
|
+
const memoryPath = join5(this.config.getConfigDir(), MEMORY_FILE_NAME);
|
|
5065
|
+
if (!existsSync5(memoryPath)) return null;
|
|
5066
|
+
let content = readFileSync4(memoryPath, "utf-8").trim();
|
|
5063
5067
|
if (!content) return null;
|
|
5064
5068
|
if (content.length > MEMORY_MAX_CHARS) {
|
|
5065
5069
|
content = content.slice(-MEMORY_MAX_CHARS);
|
|
@@ -5391,7 +5395,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5391
5395
|
this.renderer.printWelcome(this.currentProvider, this.currentModel, welcomeModelInfo?.contextWindow, profileNickname);
|
|
5392
5396
|
if (this.toolExecutor.sessionAutoApprove && this.config.get("alwaysYolo") === true) {
|
|
5393
5397
|
process.stdout.write(
|
|
5394
|
-
theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014
|
|
5398
|
+
theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014 write tools auto-approved; destructive tools still require confirmation.\n")
|
|
5395
5399
|
);
|
|
5396
5400
|
}
|
|
5397
5401
|
const cfgOutputCap = this.config.get("maxToolOutputChars");
|
|
@@ -5447,14 +5451,14 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5447
5451
|
process.stdout.write(theme.dim(` \u{1F50C} Plugins loaded: ${pluginCount} tool(s) from plugins/
|
|
5448
5452
|
`));
|
|
5449
5453
|
}
|
|
5450
|
-
const skillsDir =
|
|
5454
|
+
const skillsDir = join5(this.config.getConfigDir(), SKILLS_DIR_NAME);
|
|
5451
5455
|
this.skillManager = new SkillManager(skillsDir, this.config.get("ui").skillSizeWarn);
|
|
5452
5456
|
const skillCount = this.skillManager.loadSkills();
|
|
5453
5457
|
if (skillCount > 0) {
|
|
5454
5458
|
process.stdout.write(theme.dim(` \u{1F3AF} Skills: ${skillCount} available (use /skill to manage)
|
|
5455
5459
|
`));
|
|
5456
5460
|
}
|
|
5457
|
-
const commandsDir =
|
|
5461
|
+
const commandsDir = join5(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
|
|
5458
5462
|
this.customCommandManager = new CustomCommandManager(commandsDir);
|
|
5459
5463
|
const customCmdCount = this.customCommandManager.loadCommands();
|
|
5460
5464
|
if (customCmdCount > 0) {
|
|
@@ -6090,15 +6094,15 @@ Session '${this.resumeSessionId}' not found.
|
|
|
6090
6094
|
const dir = normalized.includes("/") ? dirname3(normalized) : ".";
|
|
6091
6095
|
const prefix = normalized.includes("/") ? basename2(normalized) : normalized;
|
|
6092
6096
|
const absDir = resolve2(process.cwd(), dir);
|
|
6093
|
-
if (!
|
|
6097
|
+
if (!existsSync5(absDir)) return [];
|
|
6094
6098
|
const entries = readdirSync3(absDir);
|
|
6095
6099
|
const results = [];
|
|
6096
6100
|
for (const entry of entries) {
|
|
6097
6101
|
if (entry.startsWith(".")) continue;
|
|
6098
6102
|
if (!entry.toLowerCase().startsWith(prefix.toLowerCase())) continue;
|
|
6099
6103
|
try {
|
|
6100
|
-
const fullPath =
|
|
6101
|
-
const stat =
|
|
6104
|
+
const fullPath = join5(absDir, entry);
|
|
6105
|
+
const stat = statSync4(fullPath);
|
|
6102
6106
|
const rel = dir === "." ? entry : `${dir}/${entry}`;
|
|
6103
6107
|
results.push(stat.isDirectory() ? `${rel}/` : rel);
|
|
6104
6108
|
} catch {
|
|
@@ -6642,7 +6646,7 @@ ${decision.displayMessage}
|
|
|
6642
6646
|
try {
|
|
6643
6647
|
mkdirSync4(dirname3(pendingTeeSave), { recursive: true });
|
|
6644
6648
|
const bodyToSave = stripOuterCodeFence(content);
|
|
6645
|
-
|
|
6649
|
+
atomicWriteFileSync(pendingTeeSave, bodyToSave);
|
|
6646
6650
|
undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
|
|
6647
6651
|
const lines = bodyToSave.split("\n").length;
|
|
6648
6652
|
process.stdout.write(theme.success(
|
|
@@ -6911,7 +6915,7 @@ Tip: You can continue the conversation by asking the AI to proceed.`
|
|
|
6911
6915
|
}
|
|
6912
6916
|
if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
|
|
6913
6917
|
try {
|
|
6914
|
-
|
|
6918
|
+
atomicWriteFileSync(saveToFile, verdict.content);
|
|
6915
6919
|
const banner = verdict.kind === "fallback" ? `
|
|
6916
6920
|
\u26A0 Fallback save: fresh stream had no usable body (matched: ${verdict.matched})
|
|
6917
6921
|
${saveToFile} now holds the response you previously saw (${verdict.content.length} chars).
|
|
@@ -7267,7 +7271,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
7267
7271
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
7268
7272
|
process.exit(1);
|
|
7269
7273
|
}
|
|
7270
|
-
const { startWebServer } = await import("./server-
|
|
7274
|
+
const { startWebServer } = await import("./server-L2MXWYF7.js");
|
|
7271
7275
|
await startWebServer({ port, host: options.host });
|
|
7272
7276
|
});
|
|
7273
7277
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -7434,16 +7438,16 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
7434
7438
|
console.log(footer + "\n");
|
|
7435
7439
|
});
|
|
7436
7440
|
program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
|
|
7437
|
-
const { runUsageCli } = await import("./usage-
|
|
7441
|
+
const { runUsageCli } = await import("./usage-SZWZFX3T.js");
|
|
7438
7442
|
await runUsageCli(options);
|
|
7439
7443
|
});
|
|
7440
7444
|
program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
|
|
7441
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
7445
|
+
const { runDoctorCli } = await import("./doctor-cli-WKH7T4AW.js");
|
|
7442
7446
|
await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
|
|
7443
7447
|
});
|
|
7444
7448
|
program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
|
|
7445
7449
|
try {
|
|
7446
|
-
const batch = await import("./batch-
|
|
7450
|
+
const batch = await import("./batch-6PORMJWT.js");
|
|
7447
7451
|
switch (action) {
|
|
7448
7452
|
case "submit":
|
|
7449
7453
|
if (!arg) {
|
|
@@ -7486,7 +7490,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
7486
7490
|
}
|
|
7487
7491
|
});
|
|
7488
7492
|
program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
|
|
7489
|
-
const { startMcpServer } = await import("./server-
|
|
7493
|
+
const { startMcpServer } = await import("./server-37EXC4EB.js");
|
|
7490
7494
|
await startMcpServer({
|
|
7491
7495
|
allowDestructive: !!options.allowDestructive,
|
|
7492
7496
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7495,7 +7499,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
|
|
|
7495
7499
|
});
|
|
7496
7500
|
});
|
|
7497
7501
|
program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number; diff fetched via `gh pr diff <num>`", (v) => parseInt(v, 10)).option("--base <ref>", "Base ref for `git diff <ref>...HEAD` (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").action(async (options) => {
|
|
7498
|
-
const { runCi } = await import("./ci-
|
|
7502
|
+
const { runCi } = await import("./ci-AYMV66P3.js");
|
|
7499
7503
|
const result = await runCi({
|
|
7500
7504
|
pr: options.pr,
|
|
7501
7505
|
base: options.base,
|
|
@@ -7593,7 +7597,7 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
|
|
|
7593
7597
|
` ${M}/checkpoint${R} ${M}/fork${R} Save/restore/fork session state`,
|
|
7594
7598
|
` ${M}/branch${R} List/create/switch/delete conversation branches (B2)`,
|
|
7595
7599
|
` ${M}/undo${R} Undo file operations`,
|
|
7596
|
-
` ${M}/yolo${R} Skip
|
|
7600
|
+
` ${M}/yolo${R} Skip write confirmations`,
|
|
7597
7601
|
` ${M}/mcp${R} Manage MCP server connections`,
|
|
7598
7602
|
` ${M}/skill${R} Manage agent skills`,
|
|
7599
7603
|
` ${M}/memory${R} View/edit persistent memory`,
|
|
@@ -7641,7 +7645,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7641
7645
|
}),
|
|
7642
7646
|
config.get("customProviders")
|
|
7643
7647
|
);
|
|
7644
|
-
const { startHub } = await import("./hub-
|
|
7648
|
+
const { startHub } = await import("./hub-6R3M3NTC.js");
|
|
7645
7649
|
await startHub(
|
|
7646
7650
|
{
|
|
7647
7651
|
topic: topic ?? "",
|