jinzd-ai-cli 0.4.183 → 0.4.184
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/{batch-V4KR6ENR.js → batch-ROTBHZ56.js} +2 -2
- package/dist/{chunk-A56C3L4P.js → chunk-2DVGTYZG.js} +1 -1
- package/dist/{chunk-G44XZPNZ.js → chunk-4JWMT7XQ.js} +3 -3
- package/dist/chunk-7D67AR56.js +228 -0
- package/dist/chunk-BLRPRWZX.js +102 -0
- package/dist/{chunk-JWT54N7I.js → chunk-HNSN575P.js} +1 -1
- package/dist/{chunk-2AZX76LV.js → chunk-NVCB6SFZ.js} +1 -1
- package/dist/{chunk-ETGCCZBT.js → chunk-PS6S4IIW.js} +1 -1
- package/dist/{chunk-UCPHXAHM.js → chunk-QLHGIWTT.js} +2 -98
- package/dist/{chunk-M5JHEB35.js → chunk-WGJ7LE6T.js} +1 -1
- package/dist/{chunk-3GZ7RYAP.js → chunk-WLMBMRIA.js} +1 -1
- package/dist/{ci-NS7PR27C.js → ci-Y5JKHJPG.js} +2 -2
- package/dist/{constants-EQ7ULMVF.js → constants-UGNL2FJR.js} +1 -1
- package/dist/{doctor-cli-VWYAVULH.js → doctor-cli-6OZTPWTL.js} +4 -4
- package/dist/electron-server.js +4 -2
- package/dist/{hub-DBGEPDIE.js → hub-UMVOJF26.js} +1 -1
- package/dist/index.js +61 -187
- package/dist/{run-tests-3FJMYYIU.js → run-tests-JHICSWKH.js} +2 -2
- package/dist/{run-tests-UM2YUDTP.js → run-tests-L6773UMG.js} +1 -1
- package/dist/{server-3KIQK257.js → server-D2NQLJBH.js} +11 -9
- package/dist/{server-CESWZS3I.js → server-KUJV27ZT.js} +4 -4
- package/dist/{task-orchestrator-2S5WM7GH.js → task-orchestrator-DTX44RG2.js} +4 -4
- package/dist/usage-4724JLXN.js +80 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,16 +9,13 @@ import {
|
|
|
9
9
|
SkillManager,
|
|
10
10
|
autoTrimSessionIfNeeded,
|
|
11
11
|
clearDevState,
|
|
12
|
-
computeCost,
|
|
13
|
-
formatCost,
|
|
14
|
-
getPricing,
|
|
15
12
|
loadDevState,
|
|
16
13
|
parseSimpleYaml,
|
|
17
14
|
persistToolRound,
|
|
18
15
|
saveDevState,
|
|
19
16
|
sessionHasMeaningfulContent,
|
|
20
17
|
setupProxy
|
|
21
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QLHGIWTT.js";
|
|
22
19
|
import {
|
|
23
20
|
ToolExecutor,
|
|
24
21
|
ToolRegistry,
|
|
@@ -37,19 +34,27 @@ import {
|
|
|
37
34
|
spawnAgentContext,
|
|
38
35
|
theme,
|
|
39
36
|
undoStack
|
|
40
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-4JWMT7XQ.js";
|
|
41
38
|
import "./chunk-HDSKW7Q3.js";
|
|
42
39
|
import "./chunk-ZWVIDFGY.js";
|
|
43
|
-
import "./chunk-
|
|
40
|
+
import "./chunk-NVCB6SFZ.js";
|
|
44
41
|
import {
|
|
45
42
|
SessionManager,
|
|
46
43
|
getContentText
|
|
47
44
|
} from "./chunk-RIVZNS3K.js";
|
|
45
|
+
import {
|
|
46
|
+
CostTracker
|
|
47
|
+
} from "./chunk-7D67AR56.js";
|
|
48
|
+
import {
|
|
49
|
+
computeCost,
|
|
50
|
+
formatCost,
|
|
51
|
+
getPricing
|
|
52
|
+
} from "./chunk-BLRPRWZX.js";
|
|
48
53
|
import {
|
|
49
54
|
getConfigDirUsage,
|
|
50
55
|
listRecentCrashes,
|
|
51
56
|
writeCrashLog
|
|
52
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-WGJ7LE6T.js";
|
|
53
58
|
import {
|
|
54
59
|
BudgetWarner,
|
|
55
60
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
@@ -85,11 +90,11 @@ import {
|
|
|
85
90
|
getTopFailingTools,
|
|
86
91
|
getTopUsedTools,
|
|
87
92
|
installFlushOnExit
|
|
88
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-PS6S4IIW.js";
|
|
89
94
|
import "./chunk-HIU2SH4V.js";
|
|
90
95
|
import {
|
|
91
96
|
ConfigManager
|
|
92
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-WLMBMRIA.js";
|
|
93
98
|
import {
|
|
94
99
|
AuthError,
|
|
95
100
|
ProviderError,
|
|
@@ -116,7 +121,7 @@ import {
|
|
|
116
121
|
SKILLS_DIR_NAME,
|
|
117
122
|
VERSION,
|
|
118
123
|
buildUserIdentityPrompt
|
|
119
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-2DVGTYZG.js";
|
|
120
125
|
import {
|
|
121
126
|
formatGitContextForPrompt,
|
|
122
127
|
getGitContext,
|
|
@@ -145,8 +150,8 @@ import { program } from "commander";
|
|
|
145
150
|
|
|
146
151
|
// src/repl/repl.ts
|
|
147
152
|
import * as readline from "readline";
|
|
148
|
-
import { existsSync as
|
|
149
|
-
import { join as
|
|
153
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
154
|
+
import { join as join4, resolve as resolve2, extname as extname2, dirname as dirname3, basename as basename2 } from "path";
|
|
150
155
|
import chalk4 from "chalk";
|
|
151
156
|
|
|
152
157
|
// src/session/title-generator.ts
|
|
@@ -278,7 +283,7 @@ var ABOUT_FEATURES = [
|
|
|
278
283
|
"Session tooling: /checkpoint, /fork, /branch (diff/cherry-pick), /rewind, /session show|page|remove",
|
|
279
284
|
"Session Replay \u{1F3AC} + Web UI: timeline of every message, tool call, reasoning, token usage",
|
|
280
285
|
"Cross-session search (/search) + sensitive-data redaction before anything hits disk",
|
|
281
|
-
"Cost dashboard: /cost
|
|
286
|
+
"Cost dashboard: /cost (session) + aicli usage (cross-session by provider/model) + monthly budget",
|
|
282
287
|
"File operation undo (/undo) for write_file / edit_file / bash-created files",
|
|
283
288
|
"Multi-Agent Hub: aicli hub \u2014 mixed-model debate, --steer, --vote, Web UI room",
|
|
284
289
|
"aicli ci: headless PR review for GitHub Actions (posts/updates one comment, CI gate)",
|
|
@@ -1828,16 +1833,16 @@ No tools match "${filter}".
|
|
|
1828
1833
|
usage: "/mcp [reconnect [serverId] | trust-project]",
|
|
1829
1834
|
async execute(args, ctx) {
|
|
1830
1835
|
if (args[0] === "trust-project") {
|
|
1831
|
-
const { join:
|
|
1832
|
-
const { existsSync:
|
|
1836
|
+
const { join: join5 } = await import("path");
|
|
1837
|
+
const { existsSync: existsSync5 } = await import("fs");
|
|
1833
1838
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-7KIP4X2V.js");
|
|
1834
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
1839
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-UGNL2FJR.js");
|
|
1835
1840
|
const { approveProject, hashMcpFile } = await import("./project-trust-IFM7FXEV.js");
|
|
1836
1841
|
const cwd = process.cwd();
|
|
1837
1842
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
1838
|
-
const mcpPath =
|
|
1843
|
+
const mcpPath = join5(projectRoot, MCP_PROJECT_CONFIG_NAME2);
|
|
1839
1844
|
console.log();
|
|
1840
|
-
if (!
|
|
1845
|
+
if (!existsSync5(mcpPath)) {
|
|
1841
1846
|
console.log(theme.dim(` No .mcp.json in ${projectRoot}.`));
|
|
1842
1847
|
console.log();
|
|
1843
1848
|
return;
|
|
@@ -2892,7 +2897,7 @@ ${hint}` : "")
|
|
|
2892
2897
|
usage: "/test [command|filter]",
|
|
2893
2898
|
async execute(args, ctx) {
|
|
2894
2899
|
try {
|
|
2895
|
-
const { executeTests } = await import("./run-tests-
|
|
2900
|
+
const { executeTests } = await import("./run-tests-JHICSWKH.js");
|
|
2896
2901
|
const argStr = args.join(" ").trim();
|
|
2897
2902
|
let testArgs = {};
|
|
2898
2903
|
if (argStr) {
|
|
@@ -3510,12 +3515,12 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
|
|
|
3510
3515
|
if (scanAll) {
|
|
3511
3516
|
const metas = ctx.sessions.listSessions();
|
|
3512
3517
|
console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
|
|
3513
|
-
const { readFileSync:
|
|
3514
|
-
const { join:
|
|
3518
|
+
const { readFileSync: readFileSync4 } = await import("fs");
|
|
3519
|
+
const { join: join5 } = await import("path");
|
|
3515
3520
|
const historyDir = ctx.config.getHistoryDir();
|
|
3516
3521
|
for (const m of metas) {
|
|
3517
3522
|
try {
|
|
3518
|
-
const content =
|
|
3523
|
+
const content = readFileSync4(join5(historyDir, `${m.id}.json`), "utf-8");
|
|
3519
3524
|
const hits2 = scanString(content, opts);
|
|
3520
3525
|
if (hits2.length) {
|
|
3521
3526
|
filesWithHits++;
|
|
@@ -4278,142 +4283,6 @@ var CustomCommandManager = class {
|
|
|
4278
4283
|
}
|
|
4279
4284
|
};
|
|
4280
4285
|
|
|
4281
|
-
// src/core/cost-tracker.ts
|
|
4282
|
-
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync } from "fs";
|
|
4283
|
-
import { join as join4 } from "path";
|
|
4284
|
-
var CostTracker = class {
|
|
4285
|
-
filePath;
|
|
4286
|
-
records = [];
|
|
4287
|
-
dirty = false;
|
|
4288
|
-
constructor(configDir) {
|
|
4289
|
-
this.filePath = join4(configDir, "cost-history.json");
|
|
4290
|
-
this.load();
|
|
4291
|
-
}
|
|
4292
|
-
load() {
|
|
4293
|
-
try {
|
|
4294
|
-
if (existsSync4(this.filePath)) {
|
|
4295
|
-
const data = JSON.parse(readFileSync3(this.filePath, "utf-8"));
|
|
4296
|
-
if (data.version === 1 && Array.isArray(data.records)) {
|
|
4297
|
-
this.records = [...data.records].sort((a, b) => a.date.localeCompare(b.date));
|
|
4298
|
-
}
|
|
4299
|
-
}
|
|
4300
|
-
} catch {
|
|
4301
|
-
this.records = [];
|
|
4302
|
-
}
|
|
4303
|
-
}
|
|
4304
|
-
/**
|
|
4305
|
-
* Save to disk (atomic write).
|
|
4306
|
-
*
|
|
4307
|
-
* H2: Snapshot records before writing and only clear the dirty flag after
|
|
4308
|
-
* the write succeeds. If writeFileSync/renameSync throws, dirty remains
|
|
4309
|
-
* true so the next save() retries — prevents silent data loss on transient
|
|
4310
|
-
* disk errors. writeFileSync is sync in Node.js so there's no interleaving
|
|
4311
|
-
* risk within a single save() call; the snapshot mainly protects against
|
|
4312
|
-
* future refactors to async I/O.
|
|
4313
|
-
*/
|
|
4314
|
-
save() {
|
|
4315
|
-
if (!this.dirty) return;
|
|
4316
|
-
const snapshot = {
|
|
4317
|
-
version: 1,
|
|
4318
|
-
records: [...this.records]
|
|
4319
|
-
// shallow copy — records are plain data
|
|
4320
|
-
};
|
|
4321
|
-
try {
|
|
4322
|
-
const tmp = this.filePath + ".tmp";
|
|
4323
|
-
writeFileSync2(tmp, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
4324
|
-
renameSync(tmp, this.filePath);
|
|
4325
|
-
this.dirty = false;
|
|
4326
|
-
} catch (err) {
|
|
4327
|
-
console.error("[cost-tracker] Failed to persist cost history:", err);
|
|
4328
|
-
}
|
|
4329
|
-
}
|
|
4330
|
-
/**
|
|
4331
|
-
* Record cost from a completed session/interaction.
|
|
4332
|
-
*/
|
|
4333
|
-
addCost(provider, model, usage) {
|
|
4334
|
-
const cost = computeCost(provider, model, usage);
|
|
4335
|
-
if (cost === null || cost === 0) return;
|
|
4336
|
-
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4337
|
-
let record = this.records.find((r) => r.date === today);
|
|
4338
|
-
if (!record) {
|
|
4339
|
-
record = { date: today, cost: 0, sessions: 0, inputTokens: 0, outputTokens: 0 };
|
|
4340
|
-
this.records.push(record);
|
|
4341
|
-
}
|
|
4342
|
-
record.cost += cost;
|
|
4343
|
-
record.sessions += 1;
|
|
4344
|
-
record.inputTokens += usage.inputTokens;
|
|
4345
|
-
record.outputTokens += usage.outputTokens;
|
|
4346
|
-
this.dirty = true;
|
|
4347
|
-
if (this.records.length > 90) {
|
|
4348
|
-
this.records = this.records.slice(-90);
|
|
4349
|
-
}
|
|
4350
|
-
}
|
|
4351
|
-
/** Get total cost for a given month ("2026-04"). */
|
|
4352
|
-
getMonthlyCost(yearMonth) {
|
|
4353
|
-
const prefix = yearMonth ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
4354
|
-
return this.records.filter((r) => r.date.startsWith(prefix)).reduce((sum, r) => sum + r.cost, 0);
|
|
4355
|
-
}
|
|
4356
|
-
/** Get today's cost. */
|
|
4357
|
-
getTodayCost() {
|
|
4358
|
-
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4359
|
-
return this.records.find((r) => r.date === today)?.cost ?? 0;
|
|
4360
|
-
}
|
|
4361
|
-
/** Get total cost for last N days. */
|
|
4362
|
-
getRecentCost(days) {
|
|
4363
|
-
const cutoff = /* @__PURE__ */ new Date();
|
|
4364
|
-
cutoff.setDate(cutoff.getDate() - days);
|
|
4365
|
-
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
4366
|
-
return this.records.filter((r) => r.date >= cutoffStr).reduce((sum, r) => sum + r.cost, 0);
|
|
4367
|
-
}
|
|
4368
|
-
/** Get all records for display. */
|
|
4369
|
-
getRecords() {
|
|
4370
|
-
return [...this.records];
|
|
4371
|
-
}
|
|
4372
|
-
/**
|
|
4373
|
-
* Check if monthly cost exceeds budget, return warning message or null.
|
|
4374
|
-
*/
|
|
4375
|
-
checkBudget(monthlyBudget) {
|
|
4376
|
-
if (!monthlyBudget || monthlyBudget <= 0) return null;
|
|
4377
|
-
const monthlyCost = this.getMonthlyCost();
|
|
4378
|
-
const ratio = monthlyCost / monthlyBudget;
|
|
4379
|
-
if (ratio >= 1) {
|
|
4380
|
-
return `\u{1F6A8} Monthly budget exceeded: ${formatCost(monthlyCost)} / ${formatCost(monthlyBudget)} (${Math.round(ratio * 100)}%)`;
|
|
4381
|
-
}
|
|
4382
|
-
if (ratio >= 0.8) {
|
|
4383
|
-
return `\u26A0 Monthly budget warning: ${formatCost(monthlyCost)} / ${formatCost(monthlyBudget)} (${Math.round(ratio * 100)}%)`;
|
|
4384
|
-
}
|
|
4385
|
-
return null;
|
|
4386
|
-
}
|
|
4387
|
-
/**
|
|
4388
|
-
* Format a cost summary for display.
|
|
4389
|
-
*/
|
|
4390
|
-
formatSummary(monthlyBudget) {
|
|
4391
|
-
const today = this.getTodayCost();
|
|
4392
|
-
const monthly = this.getMonthlyCost();
|
|
4393
|
-
const yearMonth = (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
4394
|
-
const lines = [
|
|
4395
|
-
`Today: ${formatCost(today)}`,
|
|
4396
|
-
`This month: ${formatCost(monthly)} (${yearMonth})`
|
|
4397
|
-
];
|
|
4398
|
-
if (monthlyBudget && monthlyBudget > 0) {
|
|
4399
|
-
const ratio = monthly / monthlyBudget;
|
|
4400
|
-
const bar = "\u2588".repeat(Math.min(20, Math.round(ratio * 20))) + "\u2591".repeat(Math.max(0, 20 - Math.round(ratio * 20)));
|
|
4401
|
-
lines.push(`Budget: ${formatCost(monthlyBudget)} [${bar}] ${Math.round(ratio * 100)}%`);
|
|
4402
|
-
}
|
|
4403
|
-
const last7 = [];
|
|
4404
|
-
for (let i = 6; i >= 0; i--) {
|
|
4405
|
-
const d = /* @__PURE__ */ new Date();
|
|
4406
|
-
d.setDate(d.getDate() - i);
|
|
4407
|
-
const dateStr = d.toISOString().slice(0, 10);
|
|
4408
|
-
const record = this.records.find((r) => r.date === dateStr);
|
|
4409
|
-
const dayLabel = dateStr.slice(5);
|
|
4410
|
-
last7.push(`${dayLabel}: ${record ? formatCost(record.cost) : "$0.00"}`);
|
|
4411
|
-
}
|
|
4412
|
-
lines.push(`Last 7 days: ${last7.join(" ")}`);
|
|
4413
|
-
return lines.join("\n");
|
|
4414
|
-
}
|
|
4415
|
-
};
|
|
4416
|
-
|
|
4417
4286
|
// src/core/model-router.ts
|
|
4418
4287
|
var TAG_REGEX = /(?:^|\s)#([a-zA-Z][\w-]{0,31})\b/g;
|
|
4419
4288
|
function extractTags(message) {
|
|
@@ -4703,7 +4572,7 @@ function parseAtReferences(input2, cwd) {
|
|
|
4703
4572
|
const absPath = resolve2(cwd, rawPath);
|
|
4704
4573
|
const ext = extname2(rawPath).toLowerCase();
|
|
4705
4574
|
const mime = IMAGE_MIME[ext];
|
|
4706
|
-
if (!
|
|
4575
|
+
if (!existsSync4(absPath)) {
|
|
4707
4576
|
refs.push({ path: rawPath, type: "notfound" });
|
|
4708
4577
|
continue;
|
|
4709
4578
|
}
|
|
@@ -4713,7 +4582,7 @@ function parseAtReferences(input2, cwd) {
|
|
|
4713
4582
|
refs.push({ path: rawPath, type: "toolarge" });
|
|
4714
4583
|
continue;
|
|
4715
4584
|
}
|
|
4716
|
-
const data =
|
|
4585
|
+
const data = readFileSync3(absPath).toString("base64");
|
|
4717
4586
|
imageParts.push({
|
|
4718
4587
|
type: "image_url",
|
|
4719
4588
|
image_url: { url: `data:${mime};base64,${data}` }
|
|
@@ -4721,7 +4590,7 @@ function parseAtReferences(input2, cwd) {
|
|
|
4721
4590
|
refs.push({ path: rawPath, type: "image" });
|
|
4722
4591
|
textBody = textBody.replace(match[0], "").trim();
|
|
4723
4592
|
} else {
|
|
4724
|
-
const content =
|
|
4593
|
+
const content = readFileSync3(absPath, "utf-8");
|
|
4725
4594
|
const inlined = `
|
|
4726
4595
|
|
|
4727
4596
|
[File: ${rawPath}]
|
|
@@ -4946,7 +4815,7 @@ var Repl = class {
|
|
|
4946
4815
|
const filtered = entries.filter((e) => !SKIP_DIRS_SET.has(e));
|
|
4947
4816
|
for (let i = 0; i < filtered.length && entryCount < MAX_TREE_ENTRIES; i++) {
|
|
4948
4817
|
const name = filtered[i];
|
|
4949
|
-
const fullPath =
|
|
4818
|
+
const fullPath = join4(dir, name);
|
|
4950
4819
|
const isLast = i === filtered.length - 1;
|
|
4951
4820
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
4952
4821
|
let isDir;
|
|
@@ -4980,7 +4849,7 @@ ${treeLines.join("\n")}`
|
|
|
4980
4849
|
for (const name of entries) {
|
|
4981
4850
|
if (totalChars >= MAX_TOTAL_CHARS) break;
|
|
4982
4851
|
if (SKIP_DIRS_SET.has(name)) continue;
|
|
4983
|
-
const fullPath =
|
|
4852
|
+
const fullPath = join4(dir, name);
|
|
4984
4853
|
let st;
|
|
4985
4854
|
try {
|
|
4986
4855
|
st = statSync3(fullPath);
|
|
@@ -4995,7 +4864,7 @@ ${treeLines.join("\n")}`
|
|
|
4995
4864
|
if (!TEXT_EXTS.has(ext) && !isSpecial) continue;
|
|
4996
4865
|
if (st.size > MAX_FILE_CHARS * 3) continue;
|
|
4997
4866
|
try {
|
|
4998
|
-
let content =
|
|
4867
|
+
let content = readFileSync3(fullPath, "utf-8");
|
|
4999
4868
|
if (content.length > MAX_FILE_CHARS) {
|
|
5000
4869
|
content = content.slice(0, MAX_FILE_CHARS) + `
|
|
5001
4870
|
... (truncated, ${content.length} chars total)`;
|
|
@@ -5025,7 +4894,7 @@ ${content}
|
|
|
5025
4894
|
*/
|
|
5026
4895
|
addExtraContextDir(dirPath) {
|
|
5027
4896
|
const absPath = resolve2(dirPath);
|
|
5028
|
-
if (!
|
|
4897
|
+
if (!existsSync4(absPath)) {
|
|
5029
4898
|
return { success: false, charCount: 0, added: false, error: `Directory not found: ${dirPath}` };
|
|
5030
4899
|
}
|
|
5031
4900
|
let isDir;
|
|
@@ -5059,9 +4928,9 @@ ${content}
|
|
|
5059
4928
|
*/
|
|
5060
4929
|
findContextFile(dir, candidates = CONTEXT_FILE_CANDIDATES) {
|
|
5061
4930
|
for (const candidate of candidates) {
|
|
5062
|
-
const fullPath =
|
|
5063
|
-
if (
|
|
5064
|
-
const content =
|
|
4931
|
+
const fullPath = join4(dir, candidate);
|
|
4932
|
+
if (existsSync4(fullPath)) {
|
|
4933
|
+
const content = readFileSync3(fullPath, "utf-8").trim();
|
|
5065
4934
|
if (content) return { filePath: fullPath, content };
|
|
5066
4935
|
}
|
|
5067
4936
|
}
|
|
@@ -5089,10 +4958,10 @@ ${content}
|
|
|
5089
4958
|
const cwd = process.cwd();
|
|
5090
4959
|
const gitRoot = getGitRoot(cwd);
|
|
5091
4960
|
const projectRoot = gitRoot ?? cwd;
|
|
5092
|
-
const mcpPath =
|
|
5093
|
-
if (!
|
|
4961
|
+
const mcpPath = join4(projectRoot, MCP_PROJECT_CONFIG_NAME);
|
|
4962
|
+
if (!existsSync4(mcpPath)) return null;
|
|
5094
4963
|
try {
|
|
5095
|
-
const raw = JSON.parse(
|
|
4964
|
+
const raw = JSON.parse(readFileSync3(mcpPath, "utf-8"));
|
|
5096
4965
|
const servers = raw?.mcpServers;
|
|
5097
4966
|
if (!servers || typeof servers !== "object") {
|
|
5098
4967
|
process.stderr.write(
|
|
@@ -5138,8 +5007,8 @@ ${content}
|
|
|
5138
5007
|
);
|
|
5139
5008
|
return { layers: [], mergedContent: "" };
|
|
5140
5009
|
}
|
|
5141
|
-
if (
|
|
5142
|
-
const content =
|
|
5010
|
+
if (existsSync4(fullPath)) {
|
|
5011
|
+
const content = readFileSync3(fullPath, "utf-8").trim();
|
|
5143
5012
|
if (content) {
|
|
5144
5013
|
const layer = {
|
|
5145
5014
|
level: "project",
|
|
@@ -5196,9 +5065,9 @@ ${content}
|
|
|
5196
5065
|
* 超过 MEMORY_MAX_CHARS 时只取末尾最新部分。
|
|
5197
5066
|
*/
|
|
5198
5067
|
loadMemoryContent() {
|
|
5199
|
-
const memoryPath =
|
|
5200
|
-
if (!
|
|
5201
|
-
let content =
|
|
5068
|
+
const memoryPath = join4(this.config.getConfigDir(), MEMORY_FILE_NAME);
|
|
5069
|
+
if (!existsSync4(memoryPath)) return null;
|
|
5070
|
+
let content = readFileSync3(memoryPath, "utf-8").trim();
|
|
5202
5071
|
if (!content) return null;
|
|
5203
5072
|
if (content.length > MEMORY_MAX_CHARS) {
|
|
5204
5073
|
content = content.slice(-MEMORY_MAX_CHARS);
|
|
@@ -5586,14 +5455,14 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5586
5455
|
process.stdout.write(theme.dim(` \u{1F50C} Plugins loaded: ${pluginCount} tool(s) from plugins/
|
|
5587
5456
|
`));
|
|
5588
5457
|
}
|
|
5589
|
-
const skillsDir =
|
|
5458
|
+
const skillsDir = join4(this.config.getConfigDir(), SKILLS_DIR_NAME);
|
|
5590
5459
|
this.skillManager = new SkillManager(skillsDir, this.config.get("ui").skillSizeWarn);
|
|
5591
5460
|
const skillCount = this.skillManager.loadSkills();
|
|
5592
5461
|
if (skillCount > 0) {
|
|
5593
5462
|
process.stdout.write(theme.dim(` \u{1F3AF} Skills: ${skillCount} available (use /skill to manage)
|
|
5594
5463
|
`));
|
|
5595
5464
|
}
|
|
5596
|
-
const commandsDir =
|
|
5465
|
+
const commandsDir = join4(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
|
|
5597
5466
|
this.customCommandManager = new CustomCommandManager(commandsDir);
|
|
5598
5467
|
const customCmdCount = this.customCommandManager.loadCommands();
|
|
5599
5468
|
if (customCmdCount > 0) {
|
|
@@ -6228,14 +6097,14 @@ Session '${this.resumeSessionId}' not found.
|
|
|
6228
6097
|
const dir = normalized.includes("/") ? dirname3(normalized) : ".";
|
|
6229
6098
|
const prefix = normalized.includes("/") ? basename2(normalized) : normalized;
|
|
6230
6099
|
const absDir = resolve2(process.cwd(), dir);
|
|
6231
|
-
if (!
|
|
6100
|
+
if (!existsSync4(absDir)) return [];
|
|
6232
6101
|
const entries = readdirSync3(absDir);
|
|
6233
6102
|
const results = [];
|
|
6234
6103
|
for (const entry of entries) {
|
|
6235
6104
|
if (entry.startsWith(".")) continue;
|
|
6236
6105
|
if (!entry.toLowerCase().startsWith(prefix.toLowerCase())) continue;
|
|
6237
6106
|
try {
|
|
6238
|
-
const fullPath =
|
|
6107
|
+
const fullPath = join4(absDir, entry);
|
|
6239
6108
|
const stat = statSync3(fullPath);
|
|
6240
6109
|
const rel = dir === "." ? entry : `${dir}/${entry}`;
|
|
6241
6110
|
results.push(stat.isDirectory() ? `${rel}/` : rel);
|
|
@@ -6881,7 +6750,7 @@ This fresh stream has NO tools. Produce ONLY the document body: start with a mar
|
|
|
6881
6750
|
const cleaned = stripPseudoToolCalls(genContent);
|
|
6882
6751
|
if (looksLikeDocumentBody(cleaned)) {
|
|
6883
6752
|
try {
|
|
6884
|
-
|
|
6753
|
+
writeFileSync2(saveToFile, cleaned, "utf-8");
|
|
6885
6754
|
process.stdout.write(theme.warning(
|
|
6886
6755
|
`
|
|
6887
6756
|
\u26A0 Salvaged save: stripped pseudo-tool-call markup (matched: ${pseudoMatch})
|
|
@@ -7491,7 +7360,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
7491
7360
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
7492
7361
|
process.exit(1);
|
|
7493
7362
|
}
|
|
7494
|
-
const { startWebServer } = await import("./server-
|
|
7363
|
+
const { startWebServer } = await import("./server-D2NQLJBH.js");
|
|
7495
7364
|
await startWebServer({ port, host: options.host });
|
|
7496
7365
|
});
|
|
7497
7366
|
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) => {
|
|
@@ -7657,13 +7526,17 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
7657
7526
|
${total} session${total !== 1 ? "s" : ""} total`);
|
|
7658
7527
|
console.log(footer + "\n");
|
|
7659
7528
|
});
|
|
7529
|
+
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) => {
|
|
7530
|
+
const { runUsageCli } = await import("./usage-4724JLXN.js");
|
|
7531
|
+
await runUsageCli(options);
|
|
7532
|
+
});
|
|
7660
7533
|
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) => {
|
|
7661
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
7534
|
+
const { runDoctorCli } = await import("./doctor-cli-6OZTPWTL.js");
|
|
7662
7535
|
await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
|
|
7663
7536
|
});
|
|
7664
7537
|
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) => {
|
|
7665
7538
|
try {
|
|
7666
|
-
const batch = await import("./batch-
|
|
7539
|
+
const batch = await import("./batch-ROTBHZ56.js");
|
|
7667
7540
|
switch (action) {
|
|
7668
7541
|
case "submit":
|
|
7669
7542
|
if (!arg) {
|
|
@@ -7706,7 +7579,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
7706
7579
|
}
|
|
7707
7580
|
});
|
|
7708
7581
|
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) => {
|
|
7709
|
-
const { startMcpServer } = await import("./server-
|
|
7582
|
+
const { startMcpServer } = await import("./server-KUJV27ZT.js");
|
|
7710
7583
|
await startMcpServer({
|
|
7711
7584
|
allowDestructive: !!options.allowDestructive,
|
|
7712
7585
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7715,7 +7588,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
|
|
|
7715
7588
|
});
|
|
7716
7589
|
});
|
|
7717
7590
|
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) => {
|
|
7718
|
-
const { runCi } = await import("./ci-
|
|
7591
|
+
const { runCi } = await import("./ci-Y5JKHJPG.js");
|
|
7719
7592
|
const result = await runCi({
|
|
7720
7593
|
pr: options.pr,
|
|
7721
7594
|
base: options.base,
|
|
@@ -7761,6 +7634,7 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
|
|
|
7761
7634
|
` ${G}aicli config${R} Setup wizard (API keys, preferences)`,
|
|
7762
7635
|
` ${G}aicli providers${R} List all providers and status`,
|
|
7763
7636
|
` ${G}aicli sessions${R} List recent conversation sessions`,
|
|
7637
|
+
` ${G}aicli usage${R} Token + cost usage by provider/model (--days/--month/--json)`,
|
|
7764
7638
|
` ${G}aicli user <action>${R} User management (list/create/delete)`,
|
|
7765
7639
|
` ${G}aicli batch <action>${R} Anthropic Batches API (50% off, 24h): submit/list/status/results/cancel`,
|
|
7766
7640
|
` ${G}aicli mcp-serve${R} MCP server over STDIO (expose tools to Claude Desktop / Cursor)`,
|
|
@@ -7860,7 +7734,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7860
7734
|
}),
|
|
7861
7735
|
config.get("customProviders")
|
|
7862
7736
|
);
|
|
7863
|
-
const { startHub } = await import("./hub-
|
|
7737
|
+
const { startHub } = await import("./hub-UMVOJF26.js");
|
|
7864
7738
|
await startHub(
|
|
7865
7739
|
{
|
|
7866
7740
|
topic: topic ?? "",
|
|
@@ -16,12 +16,10 @@ import {
|
|
|
16
16
|
McpManager,
|
|
17
17
|
SkillManager,
|
|
18
18
|
autoTrimSessionIfNeeded,
|
|
19
|
-
computeCost,
|
|
20
|
-
formatCost,
|
|
21
19
|
loadDevState,
|
|
22
20
|
persistToolRound,
|
|
23
21
|
setupProxy
|
|
24
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-QLHGIWTT.js";
|
|
25
23
|
import {
|
|
26
24
|
ToolExecutor,
|
|
27
25
|
ToolRegistry,
|
|
@@ -39,14 +37,18 @@ import {
|
|
|
39
37
|
spawnAgentContext,
|
|
40
38
|
truncateOutput,
|
|
41
39
|
undoStack
|
|
42
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-4JWMT7XQ.js";
|
|
43
41
|
import "./chunk-HDSKW7Q3.js";
|
|
44
42
|
import "./chunk-ZWVIDFGY.js";
|
|
45
|
-
import "./chunk-
|
|
43
|
+
import "./chunk-NVCB6SFZ.js";
|
|
46
44
|
import {
|
|
47
45
|
SessionManager,
|
|
48
46
|
getContentText
|
|
49
47
|
} from "./chunk-RIVZNS3K.js";
|
|
48
|
+
import {
|
|
49
|
+
computeCost,
|
|
50
|
+
formatCost
|
|
51
|
+
} from "./chunk-BLRPRWZX.js";
|
|
50
52
|
import {
|
|
51
53
|
BudgetWarner,
|
|
52
54
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
@@ -74,13 +76,13 @@ import {
|
|
|
74
76
|
} from "./chunk-5LK7H45B.js";
|
|
75
77
|
import {
|
|
76
78
|
runTool
|
|
77
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-PS6S4IIW.js";
|
|
78
80
|
import {
|
|
79
81
|
getDangerLevel
|
|
80
82
|
} from "./chunk-HIU2SH4V.js";
|
|
81
83
|
import {
|
|
82
84
|
ConfigManager
|
|
83
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-WLMBMRIA.js";
|
|
84
86
|
import "./chunk-TZQHYZKT.js";
|
|
85
87
|
import {
|
|
86
88
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -100,7 +102,7 @@ import {
|
|
|
100
102
|
SKILLS_DIR_NAME,
|
|
101
103
|
VERSION,
|
|
102
104
|
buildUserIdentityPrompt
|
|
103
|
-
} from "./chunk-
|
|
105
|
+
} from "./chunk-2DVGTYZG.js";
|
|
104
106
|
import {
|
|
105
107
|
formatGitContextForPrompt,
|
|
106
108
|
getGitContext,
|
|
@@ -2487,7 +2489,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2487
2489
|
case "test": {
|
|
2488
2490
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2489
2491
|
try {
|
|
2490
|
-
const { executeTests } = await import("./run-tests-
|
|
2492
|
+
const { executeTests } = await import("./run-tests-JHICSWKH.js");
|
|
2491
2493
|
const argStr = args.join(" ").trim();
|
|
2492
2494
|
let testArgs = {};
|
|
2493
2495
|
if (argStr) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ToolRegistry
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4JWMT7XQ.js";
|
|
5
5
|
import "./chunk-HDSKW7Q3.js";
|
|
6
6
|
import "./chunk-ZWVIDFGY.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-NVCB6SFZ.js";
|
|
8
8
|
import {
|
|
9
9
|
runTool
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PS6S4IIW.js";
|
|
11
11
|
import {
|
|
12
12
|
getDangerLevel,
|
|
13
13
|
schemaToJsonSchema
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import "./chunk-TZQHYZKT.js";
|
|
16
16
|
import {
|
|
17
17
|
VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-2DVGTYZG.js";
|
|
19
19
|
import "./chunk-4BKXL7SM.js";
|
|
20
20
|
import "./chunk-MM3F43H6.js";
|
|
21
21
|
import "./chunk-KHYD3WXE.js";
|
|
@@ -3,20 +3,20 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
googleSearchContext,
|
|
5
5
|
truncateOutput
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4JWMT7XQ.js";
|
|
7
7
|
import "./chunk-HDSKW7Q3.js";
|
|
8
8
|
import "./chunk-ZWVIDFGY.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-NVCB6SFZ.js";
|
|
10
10
|
import {
|
|
11
11
|
runTool
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-PS6S4IIW.js";
|
|
13
13
|
import {
|
|
14
14
|
getDangerLevel
|
|
15
15
|
} from "./chunk-HIU2SH4V.js";
|
|
16
16
|
import "./chunk-TZQHYZKT.js";
|
|
17
17
|
import {
|
|
18
18
|
SUBAGENT_ALLOWED_TOOLS
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2DVGTYZG.js";
|
|
20
20
|
import "./chunk-4BKXL7SM.js";
|
|
21
21
|
import "./chunk-MM3F43H6.js";
|
|
22
22
|
import "./chunk-KHYD3WXE.js";
|