jinzd-ai-cli 0.4.182 → 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-ZBKVDSMZ.js → batch-ROTBHZ56.js} +2 -2
- package/dist/{chunk-ISO5KVEJ.js → chunk-2DVGTYZG.js} +1 -1
- package/dist/{chunk-XI7EUUL7.js → chunk-4JWMT7XQ.js} +9 -3
- package/dist/chunk-7D67AR56.js +228 -0
- package/dist/chunk-BLRPRWZX.js +102 -0
- package/dist/{chunk-RUUJHLEV.js → chunk-HNSN575P.js} +1 -1
- package/dist/{chunk-QUYLXQRU.js → chunk-NVCB6SFZ.js} +1 -1
- package/dist/{chunk-LWZ6P73G.js → chunk-PS6S4IIW.js} +1 -1
- package/dist/{chunk-C6UJBTZO.js → chunk-QLHGIWTT.js} +2 -98
- package/dist/{chunk-4NPR3MFZ.js → chunk-WGJ7LE6T.js} +1 -1
- package/dist/{chunk-YDIR3MXD.js → chunk-WLMBMRIA.js} +1 -1
- package/dist/{ci-6WGF6ID6.js → ci-Y5JKHJPG.js} +2 -2
- package/dist/{constants-JI7VPTMJ.js → constants-UGNL2FJR.js} +1 -1
- package/dist/{doctor-cli-KSB3MLFV.js → doctor-cli-6OZTPWTL.js} +4 -4
- package/dist/electron-server.js +10 -2
- package/dist/{hub-DGEYFJPP.js → hub-UMVOJF26.js} +1 -1
- package/dist/index.js +156 -324
- package/dist/{run-tests-GFOHEIWM.js → run-tests-JHICSWKH.js} +2 -2
- package/dist/{run-tests-ZP5TPFTK.js → run-tests-L6773UMG.js} +1 -1
- package/dist/{server-2CBNRT2W.js → server-D2NQLJBH.js} +11 -9
- package/dist/{server-TXA5VTOS.js → server-KUJV27ZT.js} +4 -4
- package/dist/{task-orchestrator-4T457G22.js → task-orchestrator-DTX44RG2.js} +4 -4
- package/dist/usage-4724JLXN.js +80 -0
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WLMBMRIA.js";
|
|
5
5
|
import "./chunk-TZQHYZKT.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-2DVGTYZG.js";
|
|
7
7
|
import "./chunk-PDX44BCA.js";
|
|
8
8
|
|
|
9
9
|
// src/cli/batch.ts
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
} from "./chunk-HDSKW7Q3.js";
|
|
6
6
|
import {
|
|
7
7
|
runTestsTool
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NVCB6SFZ.js";
|
|
9
9
|
import {
|
|
10
10
|
runTool
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PS6S4IIW.js";
|
|
12
12
|
import {
|
|
13
13
|
getDangerLevel,
|
|
14
14
|
isFileWriteTool
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
SUBAGENT_ALLOWED_TOOLS,
|
|
26
26
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
27
27
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-2DVGTYZG.js";
|
|
29
29
|
import {
|
|
30
30
|
fileCheckpoints
|
|
31
31
|
} from "./chunk-4BKXL7SM.js";
|
|
@@ -5545,6 +5545,12 @@ var ToolRegistry = class {
|
|
|
5545
5545
|
listPluginTools() {
|
|
5546
5546
|
return [...this.tools.values()].filter((t) => this.pluginToolNames.has(t.definition.name));
|
|
5547
5547
|
}
|
|
5548
|
+
/** Returns only built-in tools (excludes plugin + MCP tools). */
|
|
5549
|
+
listBuiltinTools() {
|
|
5550
|
+
return [...this.tools.values()].filter(
|
|
5551
|
+
(t) => !this.pluginToolNames.has(t.definition.name) && !this.mcpToolNames.has(t.definition.name)
|
|
5552
|
+
);
|
|
5553
|
+
}
|
|
5548
5554
|
/** 注册一个 MCP 工具(名称以 mcp__ 开头) */
|
|
5549
5555
|
registerMcpTool(tool) {
|
|
5550
5556
|
this.tools.set(tool.definition.name, tool);
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
computeCost,
|
|
4
|
+
formatCost
|
|
5
|
+
} from "./chunk-BLRPRWZX.js";
|
|
6
|
+
|
|
7
|
+
// src/core/cost-tracker.ts
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, renameSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
var CostTracker = class {
|
|
11
|
+
filePath;
|
|
12
|
+
records = [];
|
|
13
|
+
dirty = false;
|
|
14
|
+
constructor(configDir) {
|
|
15
|
+
this.filePath = join(configDir, "cost-history.json");
|
|
16
|
+
this.load();
|
|
17
|
+
}
|
|
18
|
+
load() {
|
|
19
|
+
try {
|
|
20
|
+
if (existsSync(this.filePath)) {
|
|
21
|
+
const data = JSON.parse(readFileSync(this.filePath, "utf-8"));
|
|
22
|
+
if (data.version === 1 && Array.isArray(data.records)) {
|
|
23
|
+
this.records = [...data.records].sort((a, b) => a.date.localeCompare(b.date));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
this.records = [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Save to disk (atomic write).
|
|
32
|
+
*
|
|
33
|
+
* H2: Snapshot records before writing and only clear the dirty flag after
|
|
34
|
+
* the write succeeds. If writeFileSync/renameSync throws, dirty remains
|
|
35
|
+
* true so the next save() retries — prevents silent data loss on transient
|
|
36
|
+
* disk errors. writeFileSync is sync in Node.js so there's no interleaving
|
|
37
|
+
* risk within a single save() call; the snapshot mainly protects against
|
|
38
|
+
* future refactors to async I/O.
|
|
39
|
+
*/
|
|
40
|
+
save() {
|
|
41
|
+
if (!this.dirty) return;
|
|
42
|
+
const snapshot = {
|
|
43
|
+
version: 1,
|
|
44
|
+
records: [...this.records]
|
|
45
|
+
// shallow copy — records are plain data
|
|
46
|
+
};
|
|
47
|
+
try {
|
|
48
|
+
const tmp = this.filePath + ".tmp";
|
|
49
|
+
writeFileSync(tmp, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
50
|
+
renameSync(tmp, this.filePath);
|
|
51
|
+
this.dirty = false;
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error("[cost-tracker] Failed to persist cost history:", err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Record cost from a completed session/interaction.
|
|
58
|
+
*/
|
|
59
|
+
addCost(provider, model, usage) {
|
|
60
|
+
const cost = computeCost(provider, model, usage) ?? 0;
|
|
61
|
+
const inTok = usage.inputTokens || 0;
|
|
62
|
+
const outTok = usage.outputTokens || 0;
|
|
63
|
+
if (cost === 0 && inTok === 0 && outTok === 0) return;
|
|
64
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
65
|
+
let record = this.records.find((r) => r.date === today);
|
|
66
|
+
if (!record) {
|
|
67
|
+
record = { date: today, cost: 0, sessions: 0, inputTokens: 0, outputTokens: 0 };
|
|
68
|
+
this.records.push(record);
|
|
69
|
+
}
|
|
70
|
+
record.cost += cost;
|
|
71
|
+
record.sessions += 1;
|
|
72
|
+
record.inputTokens += inTok;
|
|
73
|
+
record.outputTokens += outTok;
|
|
74
|
+
const key = `${provider}/${model}`;
|
|
75
|
+
record.byModel ??= {};
|
|
76
|
+
const m = record.byModel[key] ??= { cost: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, calls: 0 };
|
|
77
|
+
m.cost += cost;
|
|
78
|
+
m.inputTokens += inTok;
|
|
79
|
+
m.outputTokens += outTok;
|
|
80
|
+
m.cacheReadTokens += usage.cacheReadTokens ?? 0;
|
|
81
|
+
m.calls += 1;
|
|
82
|
+
this.dirty = true;
|
|
83
|
+
if (this.records.length > 90) {
|
|
84
|
+
this.records = this.records.slice(-90);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Get total cost for a given month ("2026-04"). */
|
|
88
|
+
getMonthlyCost(yearMonth) {
|
|
89
|
+
const prefix = yearMonth ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
90
|
+
return this.records.filter((r) => r.date.startsWith(prefix)).reduce((sum, r) => sum + r.cost, 0);
|
|
91
|
+
}
|
|
92
|
+
/** Get today's cost. */
|
|
93
|
+
getTodayCost() {
|
|
94
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
95
|
+
return this.records.find((r) => r.date === today)?.cost ?? 0;
|
|
96
|
+
}
|
|
97
|
+
/** Get total cost for last N days. */
|
|
98
|
+
getRecentCost(days) {
|
|
99
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
100
|
+
cutoff.setDate(cutoff.getDate() - days);
|
|
101
|
+
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
102
|
+
return this.records.filter((r) => r.date >= cutoffStr).reduce((sum, r) => sum + r.cost, 0);
|
|
103
|
+
}
|
|
104
|
+
/** Get all records for display. */
|
|
105
|
+
getRecords() {
|
|
106
|
+
return [...this.records];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Aggregate usage across a date window, grouped by provider/model (v0.4.184+).
|
|
110
|
+
*
|
|
111
|
+
* Window selection (precedence): `month` ("2026-06") > `sinceDays` (N days back,
|
|
112
|
+
* inclusive of today) > all tracked history. Legacy records without a byModel
|
|
113
|
+
* breakdown fold into a single "(unattributed)" row so totals still reconcile
|
|
114
|
+
* with `getMonthlyCost()` etc.
|
|
115
|
+
*
|
|
116
|
+
* @returns rows sorted by cost desc then total tokens desc, plus grand totals
|
|
117
|
+
* and the actual covered date range.
|
|
118
|
+
*/
|
|
119
|
+
getUsageBreakdown(opts) {
|
|
120
|
+
let filtered;
|
|
121
|
+
if (opts?.month) {
|
|
122
|
+
filtered = this.records.filter((r) => r.date.startsWith(opts.month));
|
|
123
|
+
} else if (opts?.sinceDays && opts.sinceDays > 0) {
|
|
124
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
125
|
+
cutoff.setDate(cutoff.getDate() - (opts.sinceDays - 1));
|
|
126
|
+
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
127
|
+
filtered = this.records.filter((r) => r.date >= cutoffStr);
|
|
128
|
+
} else {
|
|
129
|
+
filtered = [...this.records];
|
|
130
|
+
}
|
|
131
|
+
const acc = /* @__PURE__ */ new Map();
|
|
132
|
+
const bump = (key, provider, model, v) => {
|
|
133
|
+
const row = acc.get(key) ?? { key, provider, model, cost: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, calls: 0 };
|
|
134
|
+
row.cost += v.cost;
|
|
135
|
+
row.inputTokens += v.inputTokens;
|
|
136
|
+
row.outputTokens += v.outputTokens;
|
|
137
|
+
row.cacheReadTokens += v.cacheReadTokens;
|
|
138
|
+
row.calls += v.calls;
|
|
139
|
+
acc.set(key, row);
|
|
140
|
+
};
|
|
141
|
+
for (const rec of filtered) {
|
|
142
|
+
if (rec.byModel && Object.keys(rec.byModel).length > 0) {
|
|
143
|
+
for (const [key, m] of Object.entries(rec.byModel)) {
|
|
144
|
+
const slash = key.indexOf("/");
|
|
145
|
+
const provider = slash >= 0 ? key.slice(0, slash) : key;
|
|
146
|
+
const model = slash >= 0 ? key.slice(slash + 1) : "";
|
|
147
|
+
bump(key, provider, model, m);
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
bump("(unattributed)", "(unattributed)", "", {
|
|
151
|
+
cost: rec.cost,
|
|
152
|
+
inputTokens: rec.inputTokens,
|
|
153
|
+
outputTokens: rec.outputTokens,
|
|
154
|
+
cacheReadTokens: 0,
|
|
155
|
+
calls: rec.sessions
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const rows = [...acc.values()].sort(
|
|
160
|
+
(a, b) => b.cost - a.cost || b.inputTokens + b.outputTokens - (a.inputTokens + a.outputTokens)
|
|
161
|
+
);
|
|
162
|
+
const totals = rows.reduce(
|
|
163
|
+
(t, r) => {
|
|
164
|
+
t.cost += r.cost;
|
|
165
|
+
t.inputTokens += r.inputTokens;
|
|
166
|
+
t.outputTokens += r.outputTokens;
|
|
167
|
+
t.cacheReadTokens += r.cacheReadTokens;
|
|
168
|
+
t.calls += r.calls;
|
|
169
|
+
return t;
|
|
170
|
+
},
|
|
171
|
+
{ cost: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, calls: 0 }
|
|
172
|
+
);
|
|
173
|
+
return {
|
|
174
|
+
rows,
|
|
175
|
+
totals,
|
|
176
|
+
fromDate: filtered.length > 0 ? filtered[0].date : null,
|
|
177
|
+
toDate: filtered.length > 0 ? filtered[filtered.length - 1].date : null,
|
|
178
|
+
dayCount: filtered.length
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Check if monthly cost exceeds budget, return warning message or null.
|
|
183
|
+
*/
|
|
184
|
+
checkBudget(monthlyBudget) {
|
|
185
|
+
if (!monthlyBudget || monthlyBudget <= 0) return null;
|
|
186
|
+
const monthlyCost = this.getMonthlyCost();
|
|
187
|
+
const ratio = monthlyCost / monthlyBudget;
|
|
188
|
+
if (ratio >= 1) {
|
|
189
|
+
return `\u{1F6A8} Monthly budget exceeded: ${formatCost(monthlyCost)} / ${formatCost(monthlyBudget)} (${Math.round(ratio * 100)}%)`;
|
|
190
|
+
}
|
|
191
|
+
if (ratio >= 0.8) {
|
|
192
|
+
return `\u26A0 Monthly budget warning: ${formatCost(monthlyCost)} / ${formatCost(monthlyBudget)} (${Math.round(ratio * 100)}%)`;
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Format a cost summary for display.
|
|
198
|
+
*/
|
|
199
|
+
formatSummary(monthlyBudget) {
|
|
200
|
+
const today = this.getTodayCost();
|
|
201
|
+
const monthly = this.getMonthlyCost();
|
|
202
|
+
const yearMonth = (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
203
|
+
const lines = [
|
|
204
|
+
`Today: ${formatCost(today)}`,
|
|
205
|
+
`This month: ${formatCost(monthly)} (${yearMonth})`
|
|
206
|
+
];
|
|
207
|
+
if (monthlyBudget && monthlyBudget > 0) {
|
|
208
|
+
const ratio = monthly / monthlyBudget;
|
|
209
|
+
const bar = "\u2588".repeat(Math.min(20, Math.round(ratio * 20))) + "\u2591".repeat(Math.max(0, 20 - Math.round(ratio * 20)));
|
|
210
|
+
lines.push(`Budget: ${formatCost(monthlyBudget)} [${bar}] ${Math.round(ratio * 100)}%`);
|
|
211
|
+
}
|
|
212
|
+
const last7 = [];
|
|
213
|
+
for (let i = 6; i >= 0; i--) {
|
|
214
|
+
const d = /* @__PURE__ */ new Date();
|
|
215
|
+
d.setDate(d.getDate() - i);
|
|
216
|
+
const dateStr = d.toISOString().slice(0, 10);
|
|
217
|
+
const record = this.records.find((r) => r.date === dateStr);
|
|
218
|
+
const dayLabel = dateStr.slice(5);
|
|
219
|
+
last7.push(`${dayLabel}: ${record ? formatCost(record.cost) : "$0.00"}`);
|
|
220
|
+
}
|
|
221
|
+
lines.push(`Last 7 days: ${last7.join(" ")}`);
|
|
222
|
+
return lines.join("\n");
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export {
|
|
227
|
+
CostTracker
|
|
228
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/core/pricing.ts
|
|
4
|
+
var PRICING_TABLE = {
|
|
5
|
+
// ── Anthropic Claude ──────────────────────────────────────────
|
|
6
|
+
"claude-opus-4-8": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
7
|
+
"claude-opus-4-7": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
8
|
+
"claude-opus-4-6": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
9
|
+
"claude-opus-4-5": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
10
|
+
"claude-sonnet-4-6": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
11
|
+
"claude-sonnet-4-5-20250929": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
12
|
+
"claude-haiku-4-5-20251001": { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 },
|
|
13
|
+
"claude-haiku-4-5": { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 },
|
|
14
|
+
// Legacy Claude 3.x families (prefix fallback handles minor date suffixes)
|
|
15
|
+
"claude-3-5-sonnet": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
16
|
+
"claude-3-5-haiku": { input: 0.8, output: 4, cacheWrite: 1, cacheRead: 0.08 },
|
|
17
|
+
"claude-3-opus": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
18
|
+
// ── OpenAI ────────────────────────────────────────────────────
|
|
19
|
+
"gpt-4o": { input: 2.5, output: 10, cacheRead: 1.25 },
|
|
20
|
+
"gpt-4o-mini": { input: 0.15, output: 0.6, cacheRead: 0.075 },
|
|
21
|
+
"gpt-4-turbo": { input: 10, output: 30 },
|
|
22
|
+
"gpt-4": { input: 30, output: 60 },
|
|
23
|
+
"gpt-4.1": { input: 2, output: 8, cacheRead: 0.5 },
|
|
24
|
+
"gpt-4.1-mini": { input: 0.4, output: 1.6, cacheRead: 0.1 },
|
|
25
|
+
"gpt-4.1-nano": { input: 0.1, output: 0.4, cacheRead: 0.025 },
|
|
26
|
+
"o1": { input: 15, output: 60, cacheRead: 7.5 },
|
|
27
|
+
"o1-mini": { input: 3, output: 12, cacheRead: 1.5 },
|
|
28
|
+
"o3": { input: 10, output: 40, cacheRead: 2.5 },
|
|
29
|
+
"o3-mini": { input: 1.1, output: 4.4, cacheRead: 0.55 },
|
|
30
|
+
// ── Google Gemini ─────────────────────────────────────────────
|
|
31
|
+
"gemini-2.5-pro": { input: 1.25, output: 10 },
|
|
32
|
+
"gemini-2.5-flash": { input: 0.3, output: 2.5 },
|
|
33
|
+
"gemini-2.0-flash": { input: 0.1, output: 0.4 },
|
|
34
|
+
"gemini-1.5-pro": { input: 1.25, output: 5 },
|
|
35
|
+
"gemini-1.5-flash": { input: 0.075, output: 0.3 },
|
|
36
|
+
// ── DeepSeek ──────────────────────────────────────────────────
|
|
37
|
+
// V4 family (2026-04-23+):1M context, Thinking / Non-Thinking dual-mode, 384K max output
|
|
38
|
+
"deepseek-v4-pro": { input: 1.74, output: 3.48, cacheRead: 0.145 },
|
|
39
|
+
"deepseek-v4-flash": { input: 0.14, output: 0.28, cacheRead: 0.028 },
|
|
40
|
+
// Legacy aliases:retires 2026-07-24 UTC 15:59,官方 route 到 V4 Flash
|
|
41
|
+
"deepseek-chat": { input: 0.14, output: 0.28, cacheRead: 0.028 },
|
|
42
|
+
"deepseek-reasoner": { input: 0.14, output: 0.28, cacheRead: 0.028 },
|
|
43
|
+
"deepseek-v3": { input: 0.27, output: 1.1, cacheRead: 0.07 },
|
|
44
|
+
// ── Moonshot Kimi ─────────────────────────────────────────────
|
|
45
|
+
"moonshot-v1-8k": { input: 0.17, output: 0.17 },
|
|
46
|
+
"moonshot-v1-32k": { input: 0.33, output: 0.33 },
|
|
47
|
+
"moonshot-v1-128k": { input: 0.83, output: 0.83 },
|
|
48
|
+
"kimi-k2": { input: 0.6, output: 2.5 },
|
|
49
|
+
"kimi-latest": { input: 0.6, output: 2.5 },
|
|
50
|
+
// ── Zhipu GLM ─────────────────────────────────────────────────
|
|
51
|
+
"glm-4-plus": { input: 0.7, output: 0.7 },
|
|
52
|
+
"glm-4": { input: 0.14, output: 0.14 },
|
|
53
|
+
"glm-4-flash": { input: 0, output: 0 },
|
|
54
|
+
"glm-4.5": { input: 0.29, output: 1.14 },
|
|
55
|
+
"glm-4.6": { input: 0.6, output: 2.2 },
|
|
56
|
+
"glm-4.6v": { input: 0.6, output: 2.2 },
|
|
57
|
+
"glm-5": { input: 0.85, output: 2.85 },
|
|
58
|
+
"glm-5.1": { input: 0.95, output: 3.15 },
|
|
59
|
+
"glm-5.1-reasoning": { input: 1.4, output: 4.4 },
|
|
60
|
+
"glm-5.1-air": { input: 0.4, output: 1.2 },
|
|
61
|
+
"glm-z1": { input: 0.5, output: 1.5 },
|
|
62
|
+
"glm-z1-air": { input: 0.2, output: 0.6 },
|
|
63
|
+
"glm-z1-flash": { input: 0, output: 0 }
|
|
64
|
+
// ── OpenRouter (pass-through — actual cost depends on underlying model) ──
|
|
65
|
+
// Left empty; callers should resolve via underlying model ID.
|
|
66
|
+
// ── Ollama (local, zero cost) ─────────────────────────────────
|
|
67
|
+
// Handled via provider check below.
|
|
68
|
+
};
|
|
69
|
+
var FREE_PROVIDERS = /* @__PURE__ */ new Set(["ollama"]);
|
|
70
|
+
function getPricing(provider, model) {
|
|
71
|
+
if (FREE_PROVIDERS.has(provider.toLowerCase())) {
|
|
72
|
+
return { input: 0, output: 0 };
|
|
73
|
+
}
|
|
74
|
+
const key = model.toLowerCase();
|
|
75
|
+
if (PRICING_TABLE[key]) return PRICING_TABLE[key];
|
|
76
|
+
const keys = Object.keys(PRICING_TABLE).sort((a, b) => b.length - a.length);
|
|
77
|
+
for (const k of keys) {
|
|
78
|
+
if (key.startsWith(k)) return PRICING_TABLE[k];
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function computeCost(provider, model, usage) {
|
|
83
|
+
const p = getPricing(provider, model);
|
|
84
|
+
if (!p) return null;
|
|
85
|
+
const input = usage.inputTokens * p.input;
|
|
86
|
+
const output = usage.outputTokens * p.output;
|
|
87
|
+
const cacheWrite = (usage.cacheCreationTokens ?? 0) * (p.cacheWrite ?? p.input);
|
|
88
|
+
const cacheRead = (usage.cacheReadTokens ?? 0) * (p.cacheRead ?? p.input);
|
|
89
|
+
return (input + output + cacheWrite + cacheRead) / 1e6;
|
|
90
|
+
}
|
|
91
|
+
function formatCost(amount) {
|
|
92
|
+
if (amount === 0) return "$0.0000";
|
|
93
|
+
if (amount < 0.01) return `$${amount.toFixed(4)}`;
|
|
94
|
+
if (amount < 1) return `$${amount.toFixed(3)}`;
|
|
95
|
+
return `$${amount.toFixed(2)}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export {
|
|
99
|
+
getPricing,
|
|
100
|
+
computeCost,
|
|
101
|
+
formatCost
|
|
102
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
truncateForPersist
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4JWMT7XQ.js";
|
|
5
5
|
import {
|
|
6
6
|
APP_NAME,
|
|
7
7
|
CONFIG_DIR_NAME,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
MCP_PROTOCOL_VERSION,
|
|
12
12
|
MCP_TOOL_PREFIX,
|
|
13
13
|
VERSION
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2DVGTYZG.js";
|
|
15
15
|
|
|
16
16
|
// src/mcp/client.ts
|
|
17
17
|
import { spawn } from "child_process";
|
|
@@ -696,99 +696,6 @@ async function setupProxy(configProxy) {
|
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
698
|
|
|
699
|
-
// src/core/pricing.ts
|
|
700
|
-
var PRICING_TABLE = {
|
|
701
|
-
// ── Anthropic Claude ──────────────────────────────────────────
|
|
702
|
-
"claude-opus-4-6": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
703
|
-
"claude-opus-4-5": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
704
|
-
"claude-sonnet-4-6": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
705
|
-
"claude-sonnet-4-5-20250929": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
706
|
-
"claude-haiku-4-5-20251001": { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 },
|
|
707
|
-
"claude-haiku-4-5": { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 },
|
|
708
|
-
// Legacy Claude 3.x families (prefix fallback handles minor date suffixes)
|
|
709
|
-
"claude-3-5-sonnet": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
710
|
-
"claude-3-5-haiku": { input: 0.8, output: 4, cacheWrite: 1, cacheRead: 0.08 },
|
|
711
|
-
"claude-3-opus": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
712
|
-
// ── OpenAI ────────────────────────────────────────────────────
|
|
713
|
-
"gpt-4o": { input: 2.5, output: 10, cacheRead: 1.25 },
|
|
714
|
-
"gpt-4o-mini": { input: 0.15, output: 0.6, cacheRead: 0.075 },
|
|
715
|
-
"gpt-4-turbo": { input: 10, output: 30 },
|
|
716
|
-
"gpt-4": { input: 30, output: 60 },
|
|
717
|
-
"gpt-4.1": { input: 2, output: 8, cacheRead: 0.5 },
|
|
718
|
-
"gpt-4.1-mini": { input: 0.4, output: 1.6, cacheRead: 0.1 },
|
|
719
|
-
"gpt-4.1-nano": { input: 0.1, output: 0.4, cacheRead: 0.025 },
|
|
720
|
-
"o1": { input: 15, output: 60, cacheRead: 7.5 },
|
|
721
|
-
"o1-mini": { input: 3, output: 12, cacheRead: 1.5 },
|
|
722
|
-
"o3": { input: 10, output: 40, cacheRead: 2.5 },
|
|
723
|
-
"o3-mini": { input: 1.1, output: 4.4, cacheRead: 0.55 },
|
|
724
|
-
// ── Google Gemini ─────────────────────────────────────────────
|
|
725
|
-
"gemini-2.5-pro": { input: 1.25, output: 10 },
|
|
726
|
-
"gemini-2.5-flash": { input: 0.3, output: 2.5 },
|
|
727
|
-
"gemini-2.0-flash": { input: 0.1, output: 0.4 },
|
|
728
|
-
"gemini-1.5-pro": { input: 1.25, output: 5 },
|
|
729
|
-
"gemini-1.5-flash": { input: 0.075, output: 0.3 },
|
|
730
|
-
// ── DeepSeek ──────────────────────────────────────────────────
|
|
731
|
-
// V4 family (2026-04-23+):1M context, Thinking / Non-Thinking dual-mode, 384K max output
|
|
732
|
-
"deepseek-v4-pro": { input: 1.74, output: 3.48, cacheRead: 0.145 },
|
|
733
|
-
"deepseek-v4-flash": { input: 0.14, output: 0.28, cacheRead: 0.028 },
|
|
734
|
-
// Legacy aliases:retires 2026-07-24 UTC 15:59,官方 route 到 V4 Flash
|
|
735
|
-
"deepseek-chat": { input: 0.14, output: 0.28, cacheRead: 0.028 },
|
|
736
|
-
"deepseek-reasoner": { input: 0.14, output: 0.28, cacheRead: 0.028 },
|
|
737
|
-
"deepseek-v3": { input: 0.27, output: 1.1, cacheRead: 0.07 },
|
|
738
|
-
// ── Moonshot Kimi ─────────────────────────────────────────────
|
|
739
|
-
"moonshot-v1-8k": { input: 0.17, output: 0.17 },
|
|
740
|
-
"moonshot-v1-32k": { input: 0.33, output: 0.33 },
|
|
741
|
-
"moonshot-v1-128k": { input: 0.83, output: 0.83 },
|
|
742
|
-
"kimi-k2": { input: 0.6, output: 2.5 },
|
|
743
|
-
"kimi-latest": { input: 0.6, output: 2.5 },
|
|
744
|
-
// ── Zhipu GLM ─────────────────────────────────────────────────
|
|
745
|
-
"glm-4-plus": { input: 0.7, output: 0.7 },
|
|
746
|
-
"glm-4": { input: 0.14, output: 0.14 },
|
|
747
|
-
"glm-4-flash": { input: 0, output: 0 },
|
|
748
|
-
"glm-4.5": { input: 0.29, output: 1.14 },
|
|
749
|
-
"glm-4.6": { input: 0.6, output: 2.2 },
|
|
750
|
-
"glm-4.6v": { input: 0.6, output: 2.2 },
|
|
751
|
-
"glm-5": { input: 0.85, output: 2.85 },
|
|
752
|
-
"glm-5.1": { input: 0.95, output: 3.15 },
|
|
753
|
-
"glm-5.1-reasoning": { input: 1.4, output: 4.4 },
|
|
754
|
-
"glm-5.1-air": { input: 0.4, output: 1.2 },
|
|
755
|
-
"glm-z1": { input: 0.5, output: 1.5 },
|
|
756
|
-
"glm-z1-air": { input: 0.2, output: 0.6 },
|
|
757
|
-
"glm-z1-flash": { input: 0, output: 0 }
|
|
758
|
-
// ── OpenRouter (pass-through — actual cost depends on underlying model) ──
|
|
759
|
-
// Left empty; callers should resolve via underlying model ID.
|
|
760
|
-
// ── Ollama (local, zero cost) ─────────────────────────────────
|
|
761
|
-
// Handled via provider check below.
|
|
762
|
-
};
|
|
763
|
-
var FREE_PROVIDERS = /* @__PURE__ */ new Set(["ollama"]);
|
|
764
|
-
function getPricing(provider, model) {
|
|
765
|
-
if (FREE_PROVIDERS.has(provider.toLowerCase())) {
|
|
766
|
-
return { input: 0, output: 0 };
|
|
767
|
-
}
|
|
768
|
-
const key = model.toLowerCase();
|
|
769
|
-
if (PRICING_TABLE[key]) return PRICING_TABLE[key];
|
|
770
|
-
const keys = Object.keys(PRICING_TABLE).sort((a, b) => b.length - a.length);
|
|
771
|
-
for (const k of keys) {
|
|
772
|
-
if (key.startsWith(k)) return PRICING_TABLE[k];
|
|
773
|
-
}
|
|
774
|
-
return null;
|
|
775
|
-
}
|
|
776
|
-
function computeCost(provider, model, usage) {
|
|
777
|
-
const p = getPricing(provider, model);
|
|
778
|
-
if (!p) return null;
|
|
779
|
-
const input = usage.inputTokens * p.input;
|
|
780
|
-
const output = usage.outputTokens * p.output;
|
|
781
|
-
const cacheWrite = (usage.cacheCreationTokens ?? 0) * (p.cacheWrite ?? p.input);
|
|
782
|
-
const cacheRead = (usage.cacheReadTokens ?? 0) * (p.cacheRead ?? p.input);
|
|
783
|
-
return (input + output + cacheWrite + cacheRead) / 1e6;
|
|
784
|
-
}
|
|
785
|
-
function formatCost(amount) {
|
|
786
|
-
if (amount === 0) return "$0.0000";
|
|
787
|
-
if (amount < 0.01) return `$${amount.toFixed(4)}`;
|
|
788
|
-
if (amount < 1) return `$${amount.toFixed(3)}`;
|
|
789
|
-
return `$${amount.toFixed(2)}`;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
699
|
// src/session/tool-history.ts
|
|
793
700
|
var SESSION_SIZE_LIMIT = 2 * 1024 * 1024;
|
|
794
701
|
function persistToolRound(session, toolCalls, toolResults, opts) {
|
|
@@ -967,9 +874,6 @@ function clearDevState() {
|
|
|
967
874
|
}
|
|
968
875
|
|
|
969
876
|
export {
|
|
970
|
-
getPricing,
|
|
971
|
-
computeCost,
|
|
972
|
-
formatCost,
|
|
973
877
|
parseSimpleYaml,
|
|
974
878
|
persistToolRound,
|
|
975
879
|
autoTrimSessionIfNeeded,
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
import "./chunk-HIU2SH4V.js";
|
|
11
11
|
import {
|
|
12
12
|
ConfigManager
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WLMBMRIA.js";
|
|
14
14
|
import "./chunk-TZQHYZKT.js";
|
|
15
15
|
import {
|
|
16
16
|
VERSION
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-2DVGTYZG.js";
|
|
18
18
|
import "./chunk-PDX44BCA.js";
|
|
19
19
|
|
|
20
20
|
// src/cli/ci.ts
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getConfigDirUsage,
|
|
4
4
|
listRecentCrashes
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WGJ7LE6T.js";
|
|
6
6
|
import {
|
|
7
7
|
ProviderRegistry
|
|
8
8
|
} from "./chunk-5LK7H45B.js";
|
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
getTopFailingTools,
|
|
12
12
|
getTopUsedTools,
|
|
13
13
|
resetStats
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-PS6S4IIW.js";
|
|
15
15
|
import "./chunk-HIU2SH4V.js";
|
|
16
16
|
import {
|
|
17
17
|
ConfigManager
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WLMBMRIA.js";
|
|
19
19
|
import "./chunk-TZQHYZKT.js";
|
|
20
20
|
import {
|
|
21
21
|
DEV_STATE_FILE_NAME,
|
|
22
22
|
MEMORY_FILE_NAME,
|
|
23
23
|
VERSION
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2DVGTYZG.js";
|
|
25
25
|
import "./chunk-PDX44BCA.js";
|
|
26
26
|
|
|
27
27
|
// src/diagnostics/doctor-cli.ts
|
package/dist/electron-server.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
VERSION,
|
|
37
37
|
buildUserIdentityPrompt,
|
|
38
38
|
runTestsTool
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-HNSN575P.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -9819,6 +9819,12 @@ var ToolRegistry = class {
|
|
|
9819
9819
|
listPluginTools() {
|
|
9820
9820
|
return [...this.tools.values()].filter((t) => this.pluginToolNames.has(t.definition.name));
|
|
9821
9821
|
}
|
|
9822
|
+
/** Returns only built-in tools (excludes plugin + MCP tools). */
|
|
9823
|
+
listBuiltinTools() {
|
|
9824
|
+
return [...this.tools.values()].filter(
|
|
9825
|
+
(t) => !this.pluginToolNames.has(t.definition.name) && !this.mcpToolNames.has(t.definition.name)
|
|
9826
|
+
);
|
|
9827
|
+
}
|
|
9822
9828
|
/** 注册一个 MCP 工具(名称以 mcp__ 开头) */
|
|
9823
9829
|
registerMcpTool(tool) {
|
|
9824
9830
|
this.tools.set(tool.definition.name, tool);
|
|
@@ -10997,6 +11003,8 @@ function loadMemoryContent(configDir) {
|
|
|
10997
11003
|
// src/core/pricing.ts
|
|
10998
11004
|
var PRICING_TABLE = {
|
|
10999
11005
|
// ── Anthropic Claude ──────────────────────────────────────────
|
|
11006
|
+
"claude-opus-4-8": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
11007
|
+
"claude-opus-4-7": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
11000
11008
|
"claude-opus-4-6": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
11001
11009
|
"claude-opus-4-5": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
11002
11010
|
"claude-sonnet-4-6": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
@@ -13844,7 +13852,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
13844
13852
|
case "test": {
|
|
13845
13853
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
13846
13854
|
try {
|
|
13847
|
-
const { executeTests } = await import("./run-tests-
|
|
13855
|
+
const { executeTests } = await import("./run-tests-L6773UMG.js");
|
|
13848
13856
|
const argStr = args.join(" ").trim();
|
|
13849
13857
|
let testArgs = {};
|
|
13850
13858
|
if (argStr) {
|
|
@@ -155,7 +155,7 @@ ${content}`);
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
158
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
158
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-DTX44RG2.js");
|
|
159
159
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
160
160
|
let interrupted = false;
|
|
161
161
|
const onSigint = () => {
|