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.
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-3GZ7RYAP.js";
4
+ } from "./chunk-WLMBMRIA.js";
5
5
  import "./chunk-TZQHYZKT.js";
6
- import "./chunk-A56C3L4P.js";
6
+ import "./chunk-2DVGTYZG.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
 
9
9
  // src/cli/batch.ts
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.183";
4
+ var VERSION = "0.4.184";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -5,10 +5,10 @@ import {
5
5
  } from "./chunk-HDSKW7Q3.js";
6
6
  import {
7
7
  runTestsTool
8
- } from "./chunk-2AZX76LV.js";
8
+ } from "./chunk-NVCB6SFZ.js";
9
9
  import {
10
10
  runTool
11
- } from "./chunk-ETGCCZBT.js";
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-A56C3L4P.js";
28
+ } from "./chunk-2DVGTYZG.js";
29
29
  import {
30
30
  fileCheckpoints
31
31
  } from "./chunk-4BKXL7SM.js";
@@ -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
+ };
@@ -6,7 +6,7 @@ import { platform } from "os";
6
6
  import chalk from "chalk";
7
7
 
8
8
  // src/core/constants.ts
9
- var VERSION = "0.4.183";
9
+ var VERSION = "0.4.184";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-A56C3L4P.js";
4
+ } from "./chunk-2DVGTYZG.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CONFIG_DIR_NAME
4
- } from "./chunk-A56C3L4P.js";
4
+ } from "./chunk-2DVGTYZG.js";
5
5
 
6
6
  // src/diagnostics/tool-stats.ts
7
7
  import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-G44XZPNZ.js";
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-A56C3L4P.js";
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,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  VERSION
5
- } from "./chunk-A56C3L4P.js";
5
+ } from "./chunk-2DVGTYZG.js";
6
6
 
7
7
  // src/diagnostics/crash-log.ts
8
8
  import {
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-A56C3L4P.js";
11
+ } from "./chunk-2DVGTYZG.js";
12
12
 
13
13
  // src/config/config-manager.ts
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -10,11 +10,11 @@ import {
10
10
  import "./chunk-HIU2SH4V.js";
11
11
  import {
12
12
  ConfigManager
13
- } from "./chunk-3GZ7RYAP.js";
13
+ } from "./chunk-WLMBMRIA.js";
14
14
  import "./chunk-TZQHYZKT.js";
15
15
  import {
16
16
  VERSION
17
- } from "./chunk-A56C3L4P.js";
17
+ } from "./chunk-2DVGTYZG.js";
18
18
  import "./chunk-PDX44BCA.js";
19
19
 
20
20
  // src/cli/ci.ts
@@ -36,7 +36,7 @@ import {
36
36
  TEST_TIMEOUT,
37
37
  VERSION,
38
38
  buildUserIdentityPrompt
39
- } from "./chunk-A56C3L4P.js";
39
+ } from "./chunk-2DVGTYZG.js";
40
40
  import "./chunk-PDX44BCA.js";
41
41
  export {
42
42
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getConfigDirUsage,
4
4
  listRecentCrashes
5
- } from "./chunk-M5JHEB35.js";
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-ETGCCZBT.js";
14
+ } from "./chunk-PS6S4IIW.js";
15
15
  import "./chunk-HIU2SH4V.js";
16
16
  import {
17
17
  ConfigManager
18
- } from "./chunk-3GZ7RYAP.js";
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-A56C3L4P.js";
24
+ } from "./chunk-2DVGTYZG.js";
25
25
  import "./chunk-PDX44BCA.js";
26
26
 
27
27
  // src/diagnostics/doctor-cli.ts
@@ -36,7 +36,7 @@ import {
36
36
  VERSION,
37
37
  buildUserIdentityPrompt,
38
38
  runTestsTool
39
- } from "./chunk-JWT54N7I.js";
39
+ } from "./chunk-HNSN575P.js";
40
40
  import {
41
41
  hasSemanticIndex,
42
42
  semanticSearch
@@ -11003,6 +11003,8 @@ function loadMemoryContent(configDir) {
11003
11003
  // src/core/pricing.ts
11004
11004
  var PRICING_TABLE = {
11005
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 },
11006
11008
  "claude-opus-4-6": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
11007
11009
  "claude-opus-4-5": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
11008
11010
  "claude-sonnet-4-6": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
@@ -13850,7 +13852,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
13850
13852
  case "test": {
13851
13853
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
13852
13854
  try {
13853
- const { executeTests } = await import("./run-tests-UM2YUDTP.js");
13855
+ const { executeTests } = await import("./run-tests-L6773UMG.js");
13854
13856
  const argStr = args.join(" ").trim();
13855
13857
  let testArgs = {};
13856
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-2S5WM7GH.js");
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 = () => {