jinzd-ai-cli 0.4.268 → 0.4.270
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-2N2YMRX2.js → batch-IMLMUXJL.js} +2 -2
- package/dist/{chunk-UT2WAJJG.js → chunk-75SPJKDY.js} +1 -1
- package/dist/{chunk-RRQZRSXW.js → chunk-BOMB6XCF.js} +1 -1
- package/dist/{chunk-74BK22BM.js → chunk-DIJIYWQE.js} +4 -4
- package/dist/{chunk-VGVKJTHF.js → chunk-F26YTEMB.js} +9 -1
- package/dist/{chunk-Z7CZ72RP.js → chunk-FXCDD7JS.js} +3 -3
- package/dist/{chunk-YLSM7RF6.js → chunk-HOT76ATM.js} +3 -3
- package/dist/{chunk-EPVJS4F6.js → chunk-JJVVCWO4.js} +1 -1
- package/dist/{chunk-R7GERZDA.js → chunk-JT6UN5C6.js} +26 -5
- package/dist/{chunk-2FQGMR34.js → chunk-M3GDYEUH.js} +1 -1
- package/dist/{chunk-7US7K3CD.js → chunk-PLFXDRNX.js} +1 -1
- package/dist/{chunk-WWLXW4SY.js → chunk-TG4PF7FZ.js} +1 -1
- package/dist/{chunk-XDITAGE5.js → chunk-UDUE4DAE.js} +1 -1
- package/dist/{chunk-VNCBY4KY.js → chunk-X3JPBJ6C.js} +163 -3
- package/dist/{chunk-WNG3YVZX.js → chunk-YHLTSZVH.js} +1 -1
- package/dist/{ci-3RWVJSZ3.js → ci-HQVXWJ53.js} +4 -4
- package/dist/{ci-format-M6HVCXCG.js → ci-format-762IL4OM.js} +2 -2
- package/dist/{constants-G6VN7SJL.js → constants-4TPE3JSV.js} +1 -1
- package/dist/{doctor-cli-Y3SVVJBO.js → doctor-cli-3ES6NFVL.js} +4 -4
- package/dist/electron-server.js +300 -55
- package/dist/{hub-5T5HKOAR.js → hub-QXRWPBJP.js} +1 -1
- package/dist/index.js +68 -155
- package/dist/{persistent-memory-XVSSR277.js → persistent-memory-F4JPWYZJ.js} +2 -2
- package/dist/{persistent-memory-YBWIZWQP.js → persistent-memory-URIJJJ3N.js} +2 -2
- package/dist/{pr-NF5IWLH3.js → pr-HVVHZOJ2.js} +4 -4
- package/dist/{run-tests-Y44SCLIO.js → run-tests-UZG6SVJ5.js} +2 -2
- package/dist/{run-tests-33X3D7PV.js → run-tests-WM7TMO2N.js} +2 -2
- package/dist/{server-3LERX42X.js → server-E5OBXT33.js} +5 -5
- package/dist/{server-NJ3ZNPQW.js → server-HPRLFLOI.js} +112 -35
- package/dist/{task-orchestrator-JN2WFZSF.js → task-orchestrator-HJUUL55Y.js} +5 -5
- package/dist/{usage-IFTNXTWC.js → usage-L3DUPHD6.js} +11 -4
- package/dist/web/client/actions.js.br +0 -0
- package/dist/web/client/actions.js.gz +0 -0
- package/dist/web/client/api.js.br +0 -0
- package/dist/web/client/api.js.gz +0 -0
- package/dist/web/client/app.js +3 -6
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/dist/web/client/dom.js.br +0 -0
- package/dist/web/client/dom.js.gz +0 -0
- package/dist/web/client/icon.svg.br +0 -0
- package/dist/web/client/icon.svg.gz +0 -0
- package/dist/web/client/index.html.br +0 -0
- package/dist/web/client/index.html.gz +0 -0
- package/dist/web/client/sidebar-tabs.js.br +0 -0
- package/dist/web/client/sidebar-tabs.js.gz +0 -0
- package/dist/web/client/state.js.br +0 -0
- package/dist/web/client/state.js.gz +0 -0
- package/dist/web/client/style.css.br +0 -0
- package/dist/web/client/style.css.gz +0 -0
- package/dist/web/client/sw.js.br +0 -0
- package/dist/web/client/sw.js.gz +0 -0
- package/dist/web/client/templates.js.br +0 -0
- package/dist/web/client/templates.js.gz +0 -0
- package/dist/web/client/util.js +22 -0
- package/dist/web/client/util.js.br +0 -0
- package/dist/web/client/util.js.gz +0 -0
- package/dist/web/client/vendor/daisyui-full.min.css.br +0 -0
- package/dist/web/client/vendor/daisyui-full.min.css.gz +0 -0
- package/dist/web/client/vendor/github-dark.min.css.br +0 -0
- package/dist/web/client/vendor/github-dark.min.css.gz +0 -0
- package/dist/web/client/vendor/github.min.css.br +0 -0
- package/dist/web/client/vendor/github.min.css.gz +0 -0
- package/dist/web/client/vendor/highlight.min.js.br +0 -0
- package/dist/web/client/vendor/highlight.min.js.gz +0 -0
- package/dist/web/client/vendor/marked.min.js.br +0 -0
- package/dist/web/client/vendor/marked.min.js.gz +0 -0
- package/dist/web/client/vendor/tailwind.js.br +0 -0
- package/dist/web/client/vendor/tailwind.js.gz +0 -0
- package/package.json +1 -1
|
@@ -22,21 +22,28 @@ import {
|
|
|
22
22
|
buildInitPrompt,
|
|
23
23
|
buildSessionCostReport,
|
|
24
24
|
costSourceNote,
|
|
25
|
+
decideModel,
|
|
25
26
|
estimateConversationTokens,
|
|
26
27
|
evaluateContextPressure,
|
|
28
|
+
filterMemoryEntries,
|
|
27
29
|
loadDevState,
|
|
30
|
+
parseMemoryShowFilters,
|
|
28
31
|
persistToolRound,
|
|
29
32
|
readGitDiff,
|
|
30
33
|
scanDirTree,
|
|
31
34
|
scanProject,
|
|
32
|
-
setupProxy
|
|
33
|
-
|
|
35
|
+
setupProxy,
|
|
36
|
+
stripRoutingTags
|
|
37
|
+
} from "./chunk-X3JPBJ6C.js";
|
|
34
38
|
import {
|
|
39
|
+
CNY_PER_USD,
|
|
35
40
|
CostTracker,
|
|
36
41
|
computeCost,
|
|
37
42
|
formatCost,
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
getCostCurrency,
|
|
44
|
+
getPricing,
|
|
45
|
+
setCostCurrency
|
|
46
|
+
} from "./chunk-JT6UN5C6.js";
|
|
40
47
|
import {
|
|
41
48
|
buildReviewPrompt,
|
|
42
49
|
buildSecurityReviewPrompt
|
|
@@ -75,7 +82,7 @@ import {
|
|
|
75
82
|
spawnAgentContext,
|
|
76
83
|
truncateOutput,
|
|
77
84
|
undoStack
|
|
78
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-DIJIYWQE.js";
|
|
79
86
|
import {
|
|
80
87
|
addMemoryEntry,
|
|
81
88
|
clearMemoryEntries,
|
|
@@ -85,11 +92,12 @@ import {
|
|
|
85
92
|
formatMemoryForPrompt,
|
|
86
93
|
isMemoryExpired,
|
|
87
94
|
listMemoryEntries,
|
|
95
|
+
listOrphanedProjectMemories,
|
|
88
96
|
memoryStorePath,
|
|
89
97
|
parseWritableScope,
|
|
90
98
|
updateMemoryApproval,
|
|
91
99
|
updateMemoryEntry
|
|
92
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-YHLTSZVH.js";
|
|
93
101
|
import "./chunk-GLSR2NR3.js";
|
|
94
102
|
import "./chunk-UUSRWSSX.js";
|
|
95
103
|
import "./chunk-CKH4KQ4E.js";
|
|
@@ -103,13 +111,13 @@ import {
|
|
|
103
111
|
buildDoctorReport,
|
|
104
112
|
formatDoctorReport,
|
|
105
113
|
loadContextFiles
|
|
106
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-HOT76ATM.js";
|
|
107
115
|
import {
|
|
108
116
|
ProviderRegistry
|
|
109
117
|
} from "./chunk-AUEX6RNY.js";
|
|
110
118
|
import {
|
|
111
119
|
ConfigManager
|
|
112
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-F26YTEMB.js";
|
|
113
121
|
import {
|
|
114
122
|
describePlugin,
|
|
115
123
|
getActivePluginAssets,
|
|
@@ -124,7 +132,7 @@ import {
|
|
|
124
132
|
runTool,
|
|
125
133
|
setPluginEnabled,
|
|
126
134
|
trustPlugin
|
|
127
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-M3GDYEUH.js";
|
|
128
136
|
import {
|
|
129
137
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
130
138
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -149,7 +157,7 @@ import {
|
|
|
149
157
|
getGitRoot
|
|
150
158
|
} from "./chunk-HOSJZMQS.js";
|
|
151
159
|
import "./chunk-4BKXL7SM.js";
|
|
152
|
-
import "./chunk-
|
|
160
|
+
import "./chunk-TG4PF7FZ.js";
|
|
153
161
|
import {
|
|
154
162
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
155
163
|
AUTHOR,
|
|
@@ -165,7 +173,7 @@ import {
|
|
|
165
173
|
SKILLS_DIR_NAME,
|
|
166
174
|
VERSION,
|
|
167
175
|
buildUserIdentityPrompt
|
|
168
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-75SPJKDY.js";
|
|
169
177
|
import "./chunk-6RPGQ5CG.js";
|
|
170
178
|
import "./chunk-KHYD3WXE.js";
|
|
171
179
|
import "./chunk-NYNSYLFY.js";
|
|
@@ -180,8 +188,8 @@ import {
|
|
|
180
188
|
import express from "express";
|
|
181
189
|
import { createServer } from "http";
|
|
182
190
|
import { WebSocketServer } from "ws";
|
|
183
|
-
import { join as join2, dirname as dirname3, resolve as resolve2, relative, sep } from "path";
|
|
184
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2, realpathSync } from "fs";
|
|
191
|
+
import { join as join2, dirname as dirname3, resolve as resolve2, relative, sep, extname, resolve as resolvePath } from "path";
|
|
192
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2, realpathSync, createReadStream } from "fs";
|
|
185
193
|
import { networkInterfaces } from "os";
|
|
186
194
|
|
|
187
195
|
// src/web/tool-executor-web.ts
|
|
@@ -845,7 +853,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
845
853
|
Cost: ${formatCost(cost)}` : "";
|
|
846
854
|
let memoryLine = "";
|
|
847
855
|
try {
|
|
848
|
-
const { countPendingMemories } = await import("./persistent-memory-
|
|
856
|
+
const { countPendingMemories } = await import("./persistent-memory-F4JPWYZJ.js");
|
|
849
857
|
const pending = countPendingMemories(ctx.config.getConfigDir());
|
|
850
858
|
if (pending > 0) memoryLine = `
|
|
851
859
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -1658,7 +1666,7 @@ async function handleTest(args, ctx) {
|
|
|
1658
1666
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
1659
1667
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
1660
1668
|
}
|
|
1661
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
1669
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-WM7TMO2N.js")).executeTests;
|
|
1662
1670
|
const report = await runTests(testArgs);
|
|
1663
1671
|
ctx.send({ type: "info", message: report });
|
|
1664
1672
|
} catch (err) {
|
|
@@ -1916,7 +1924,7 @@ async function handleMemory(args, ctx) {
|
|
|
1916
1924
|
ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
|
|
1917
1925
|
} else if (sub === "export") {
|
|
1918
1926
|
if (args[1] === "md") {
|
|
1919
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
1927
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-F4JPWYZJ.js");
|
|
1920
1928
|
ctx.send({
|
|
1921
1929
|
type: "export_data",
|
|
1922
1930
|
format: "md",
|
|
@@ -1936,7 +1944,8 @@ async function handleMemory(args, ctx) {
|
|
|
1936
1944
|
});
|
|
1937
1945
|
}
|
|
1938
1946
|
} else {
|
|
1939
|
-
|
|
1947
|
+
const isShow = sub === "show" || sub === "view" || sub === "list";
|
|
1948
|
+
ctx.memoryShow(isShow ? args.slice(1) : args);
|
|
1940
1949
|
}
|
|
1941
1950
|
}
|
|
1942
1951
|
async function handleAddDir(args, ctx) {
|
|
@@ -2386,17 +2395,18 @@ var SessionHandler = class {
|
|
|
2386
2395
|
sessionAccruedCostUsd = 0;
|
|
2387
2396
|
sessionCostIncomplete = false;
|
|
2388
2397
|
/** Accumulate a TokenUsage (with optional cache fields) into sessionTokenUsage. */
|
|
2389
|
-
addWebSessionUsage(u) {
|
|
2398
|
+
addWebSessionUsage(u, modelOverride) {
|
|
2399
|
+
const usageModel = modelOverride ?? this.currentModel;
|
|
2390
2400
|
this.sessionTokenUsage.inputTokens += u.inputTokens;
|
|
2391
2401
|
this.sessionTokenUsage.outputTokens += u.outputTokens;
|
|
2392
2402
|
this.sessionTokenUsage.cacheCreationTokens += u.cacheCreationTokens ?? 0;
|
|
2393
2403
|
this.sessionTokenUsage.cacheReadTokens += u.cacheReadTokens ?? 0;
|
|
2394
|
-
const priced = this.costTracker.addCost(this.currentProvider,
|
|
2404
|
+
const priced = this.costTracker.addCost(this.currentProvider, usageModel, u);
|
|
2395
2405
|
if (priced === null) this.sessionCostIncomplete = true;
|
|
2396
2406
|
else this.sessionAccruedCostUsd += priced;
|
|
2397
2407
|
const totalTokens = u.inputTokens + u.outputTokens + (u.cacheCreationTokens ?? 0) + (u.cacheReadTokens ?? 0);
|
|
2398
|
-
if (totalTokens > 0 && !getPricing(this.currentProvider,
|
|
2399
|
-
const key = `${this.currentProvider}/${
|
|
2408
|
+
if (totalTokens > 0 && !getPricing(this.currentProvider, usageModel)) {
|
|
2409
|
+
const key = `${this.currentProvider}/${usageModel}`;
|
|
2400
2410
|
if (!this.unknownPricingWarnings.has(key)) {
|
|
2401
2411
|
this.unknownPricingWarnings.add(key);
|
|
2402
2412
|
this.send({ type: "info", message: `Cost notice: pricing is unknown for ${key}. Tokens are tracked, but cost is excluded from totals. Run /cost or aicli usage to review.` });
|
|
@@ -2532,6 +2542,8 @@ var SessionHandler = class {
|
|
|
2532
2542
|
permissionProfile: this.config.get("defaultPermissionProfile") ?? "legacy",
|
|
2533
2543
|
tokenUsage: { ...this.sessionTokenUsage },
|
|
2534
2544
|
costUsd,
|
|
2545
|
+
costCurrency: getCostCurrency(),
|
|
2546
|
+
costCnyPerUsd: CNY_PER_USD,
|
|
2535
2547
|
costPricingUnknown,
|
|
2536
2548
|
providers: providerList,
|
|
2537
2549
|
branches,
|
|
@@ -2844,6 +2856,16 @@ var SessionHandler = class {
|
|
|
2844
2856
|
} else {
|
|
2845
2857
|
msgContent = content;
|
|
2846
2858
|
}
|
|
2859
|
+
const routingDecision = this.computeRoutingDecision(typeof msgContent === "string" ? msgContent : content);
|
|
2860
|
+
if (typeof msgContent === "string") {
|
|
2861
|
+
msgContent = stripRoutingTags(msgContent);
|
|
2862
|
+
} else if (msgContent.length > 0 && msgContent[msgContent.length - 1]?.type === "text") {
|
|
2863
|
+
const last = msgContent[msgContent.length - 1];
|
|
2864
|
+
msgContent = [...msgContent.slice(0, -1), { type: "text", text: stripRoutingTags(last.text) }];
|
|
2865
|
+
}
|
|
2866
|
+
if (routingDecision.overridden) {
|
|
2867
|
+
this.send({ type: "info", message: `\u2192 Routed to ${routingDecision.model} (${routingDecision.reason})` });
|
|
2868
|
+
}
|
|
2847
2869
|
const userMessage = { role: "user", content: msgContent, timestamp: /* @__PURE__ */ new Date() };
|
|
2848
2870
|
session.addMessage(userMessage);
|
|
2849
2871
|
const provider = this.providers.get(this.currentProvider);
|
|
@@ -2855,11 +2877,13 @@ var SessionHandler = class {
|
|
|
2855
2877
|
const hasToolSupport = typeof provider.chatWithTools === "function";
|
|
2856
2878
|
const { toolDefs, mcpBudgetNote } = hasToolSupport ? this.getFilteredToolDefs() : { toolDefs: [], mcpBudgetNote: null };
|
|
2857
2879
|
if (hasToolSupport && toolDefs.length > 0) {
|
|
2858
|
-
await this.handleChatWithTools(provider, session.messages, toolDefs, mcpBudgetNote);
|
|
2880
|
+
await this.handleChatWithTools(provider, session.messages, toolDefs, mcpBudgetNote, routingDecision.model);
|
|
2859
2881
|
} else {
|
|
2860
|
-
await this.handleChatSimple(provider, session.messages);
|
|
2882
|
+
await this.handleChatSimple(provider, session.messages, routingDecision.model);
|
|
2861
2883
|
}
|
|
2862
2884
|
await this.checkContextPressure();
|
|
2885
|
+
const budgetWarning = this.costTracker.checkBudget(this.config.get("monthlyBudget"));
|
|
2886
|
+
if (budgetWarning) this.send({ type: "info", message: `\u26A0 ${budgetWarning}` });
|
|
2863
2887
|
} catch (err) {
|
|
2864
2888
|
const parts = [];
|
|
2865
2889
|
let current = err;
|
|
@@ -2878,8 +2902,9 @@ var SessionHandler = class {
|
|
|
2878
2902
|
this.sendSessionList();
|
|
2879
2903
|
}
|
|
2880
2904
|
}
|
|
2881
|
-
async handleChatSimple(provider, messages) {
|
|
2905
|
+
async handleChatSimple(provider, messages, modelOverride) {
|
|
2882
2906
|
const session = this.sessions.current;
|
|
2907
|
+
const effectiveModel = modelOverride ?? this.currentModel;
|
|
2883
2908
|
const modelParams = this.getModelParams();
|
|
2884
2909
|
const ac = new AbortController();
|
|
2885
2910
|
this.abortController = ac;
|
|
@@ -2887,7 +2912,7 @@ var SessionHandler = class {
|
|
|
2887
2912
|
const { stable: simplStable, volatile: simplVolatile } = this.buildSystemPrompt();
|
|
2888
2913
|
const stream = provider.chatStream({
|
|
2889
2914
|
messages,
|
|
2890
|
-
model:
|
|
2915
|
+
model: effectiveModel,
|
|
2891
2916
|
systemPrompt: simplStable,
|
|
2892
2917
|
systemPromptVolatile: simplVolatile,
|
|
2893
2918
|
stream: true,
|
|
@@ -2906,7 +2931,7 @@ var SessionHandler = class {
|
|
|
2906
2931
|
if (chunk.done) {
|
|
2907
2932
|
this.send({ type: "response_done", content: fullContent, usage: chunk.usage });
|
|
2908
2933
|
if (chunk.usage) {
|
|
2909
|
-
this.addWebSessionUsage(chunk.usage);
|
|
2934
|
+
this.addWebSessionUsage(chunk.usage, effectiveModel);
|
|
2910
2935
|
session.addTokenUsage(chunk.usage);
|
|
2911
2936
|
}
|
|
2912
2937
|
if (chunk.reasoningContent) simpleReasoning = chunk.reasoningContent;
|
|
@@ -2931,8 +2956,9 @@ var SessionHandler = class {
|
|
|
2931
2956
|
this.abortController = null;
|
|
2932
2957
|
}
|
|
2933
2958
|
}
|
|
2934
|
-
async handleChatWithTools(provider, messages, toolDefs, mcpBudgetNote) {
|
|
2959
|
+
async handleChatWithTools(provider, messages, toolDefs, mcpBudgetNote, modelOverride) {
|
|
2935
2960
|
const session = this.sessions.current;
|
|
2961
|
+
const effectiveModel = modelOverride ?? this.currentModel;
|
|
2936
2962
|
const apiMessages = [...messages];
|
|
2937
2963
|
const maxToolRounds = this.config.get("maxToolRounds") ?? DEFAULT_MAX_TOOL_ROUNDS;
|
|
2938
2964
|
const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
|
|
@@ -2962,7 +2988,7 @@ ${mcpBudgetNote}` : "");
|
|
|
2962
2988
|
callModel: async (_round, extraMessages) => {
|
|
2963
2989
|
const chatRequest = {
|
|
2964
2990
|
messages: apiMessages,
|
|
2965
|
-
model:
|
|
2991
|
+
model: effectiveModel,
|
|
2966
2992
|
systemPrompt,
|
|
2967
2993
|
systemPromptVolatile,
|
|
2968
2994
|
stream: false,
|
|
@@ -3007,7 +3033,7 @@ Details: ${errMsg.split("\n")[0]}
|
|
|
3007
3033
|
const summaryResult = await provider.chatWithTools(
|
|
3008
3034
|
{
|
|
3009
3035
|
messages: apiMessages,
|
|
3010
|
-
model:
|
|
3036
|
+
model: effectiveModel,
|
|
3011
3037
|
systemPrompt,
|
|
3012
3038
|
systemPromptVolatile,
|
|
3013
3039
|
stream: false,
|
|
@@ -3023,7 +3049,7 @@ Details: ${errMsg.split("\n")[0]}
|
|
|
3023
3049
|
executeTools: async (toolCalls) => {
|
|
3024
3050
|
googleSearchContext.configManager = this.config;
|
|
3025
3051
|
spawnAgentContext.provider = provider;
|
|
3026
|
-
spawnAgentContext.model =
|
|
3052
|
+
spawnAgentContext.model = effectiveModel;
|
|
3027
3053
|
spawnAgentContext.systemPrompt = systemPromptVolatile ? `${systemPrompt}
|
|
3028
3054
|
|
|
3029
3055
|
---
|
|
@@ -3397,6 +3423,24 @@ ${summaryContent}`,
|
|
|
3397
3423
|
* 到达上下文压力阈值时自动压缩(与 REPL 同一判据,见 core/context-pressure.ts)。
|
|
3398
3424
|
* 上下文窗口未知时不动——不基于猜测改用户的对话历史。
|
|
3399
3425
|
*/
|
|
3426
|
+
/**
|
|
3427
|
+
* 智能模型路由决策(审计附录 D-5)。候选限定在当前 provider 注册的模型内——
|
|
3428
|
+
* 跨 provider 换模型会破坏 API key 与对话连续性。
|
|
3429
|
+
*/
|
|
3430
|
+
computeRoutingDecision(userInput) {
|
|
3431
|
+
let availableModels = [];
|
|
3432
|
+
try {
|
|
3433
|
+
availableModels = this.providers.get(this.currentProvider).info.models.map((m) => m.id);
|
|
3434
|
+
} catch {
|
|
3435
|
+
availableModels = [];
|
|
3436
|
+
}
|
|
3437
|
+
return decideModel({
|
|
3438
|
+
userInput,
|
|
3439
|
+
currentModel: this.currentModel,
|
|
3440
|
+
routingConfig: this.config.get("routing"),
|
|
3441
|
+
availableModels
|
|
3442
|
+
});
|
|
3443
|
+
}
|
|
3400
3444
|
async checkContextPressure() {
|
|
3401
3445
|
const contextWindow = this.getContextWindowSize();
|
|
3402
3446
|
const session = this.sessions.current;
|
|
@@ -3559,18 +3603,27 @@ ${summaryContent}`,
|
|
|
3559
3603
|
});
|
|
3560
3604
|
}
|
|
3561
3605
|
}
|
|
3562
|
-
memoryShow() {
|
|
3606
|
+
memoryShow(args = []) {
|
|
3563
3607
|
const configDir = this.config.getConfigDir();
|
|
3564
|
-
const
|
|
3565
|
-
|
|
3608
|
+
const filters = parseMemoryShowFilters(args);
|
|
3609
|
+
if (filters.invalidStale) {
|
|
3610
|
+
this.send({ type: "error", message: "Usage: /memory show --stale <days> (positive number)" });
|
|
3611
|
+
return;
|
|
3612
|
+
}
|
|
3613
|
+
const source = filters.orphaned ? listOrphanedProjectMemories(configDir) : listMemoryEntries(configDir, { includeExpired: true, includeRejected: true });
|
|
3614
|
+
const { entries, applied } = filterMemoryEntries(source, filters);
|
|
3615
|
+
const filterNote = applied.length > 0 ? ` (filtered: ${applied.join(", ")})` : "";
|
|
3616
|
+
const content = entries.length === 0 ? applied.length > 0 ? `(no entries match [${applied.join(", ")}])` : "(empty \u2014 no persistent memory entries yet)" : `Governed persistent memory${filterNote}
|
|
3617
|
+
|
|
3618
|
+
` + entries.map((entry) => {
|
|
3566
3619
|
const status = isMemoryExpired(entry) ? "expired" : entry.approved ? "approved" : "pending";
|
|
3567
|
-
const
|
|
3620
|
+
const source2 = [
|
|
3568
3621
|
entry.source ?? "unknown",
|
|
3569
3622
|
entry.sourceSession ? `session ${entry.sourceSession.slice(0, 8)}` : "",
|
|
3570
3623
|
entry.sourceProject ? `project ${entry.sourceProject}` : ""
|
|
3571
3624
|
].filter(Boolean).join(" \xB7 ");
|
|
3572
3625
|
return `## ${entry.id.slice(0, 8)} \xB7 ${status} \xB7 scope:${entry.scope} \xB7 sensitivity:${entry.sensitivity}
|
|
3573
|
-
Source: ${
|
|
3626
|
+
Source: ${source2}
|
|
3574
3627
|
${entry.content}`;
|
|
3575
3628
|
}).join("\n\n");
|
|
3576
3629
|
this.send({
|
|
@@ -3973,6 +4026,7 @@ async function startWebServer(options = {}) {
|
|
|
3973
4026
|
console.log(` Skills: ${count} available`);
|
|
3974
4027
|
}
|
|
3975
4028
|
}
|
|
4029
|
+
setCostCurrency(config.get("ui").currency);
|
|
3976
4030
|
const shared = {
|
|
3977
4031
|
config,
|
|
3978
4032
|
costTracker: new CostTracker(config.getConfigDir()),
|
|
@@ -4052,6 +4106,29 @@ async function startWebServer(options = {}) {
|
|
|
4052
4106
|
clientDir = join2(process.cwd(), "src", "web", "client");
|
|
4053
4107
|
}
|
|
4054
4108
|
console.log(` Static files: ${clientDir}`);
|
|
4109
|
+
const PRECOMPRESSED_TYPES = {
|
|
4110
|
+
".js": "text/javascript; charset=utf-8",
|
|
4111
|
+
".css": "text/css; charset=utf-8",
|
|
4112
|
+
".html": "text/html; charset=utf-8",
|
|
4113
|
+
".json": "application/json; charset=utf-8",
|
|
4114
|
+
".svg": "image/svg+xml",
|
|
4115
|
+
".map": "application/json; charset=utf-8"
|
|
4116
|
+
};
|
|
4117
|
+
app.get(/.*/, (req, res, next) => {
|
|
4118
|
+
const ext = extname(req.path).toLowerCase();
|
|
4119
|
+
const contentType = PRECOMPRESSED_TYPES[ext];
|
|
4120
|
+
if (!contentType) return next();
|
|
4121
|
+
const accept = String(req.headers["accept-encoding"] ?? "");
|
|
4122
|
+
const encoding = /\bbr\b/.test(accept) ? "br" : /\bgzip\b/.test(accept) ? "gzip" : null;
|
|
4123
|
+
if (!encoding) return next();
|
|
4124
|
+
const target = resolvePath(clientDir, `.${req.path}`) + (encoding === "br" ? ".br" : ".gz");
|
|
4125
|
+
if (!target.startsWith(clientDir) || !existsSync3(target)) return next();
|
|
4126
|
+
res.setHeader("Content-Type", contentType);
|
|
4127
|
+
res.setHeader("Content-Encoding", encoding);
|
|
4128
|
+
res.setHeader("Vary", "Accept-Encoding");
|
|
4129
|
+
if (req.path.startsWith("/vendor/")) res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
4130
|
+
createReadStream(target).pipe(res);
|
|
4131
|
+
});
|
|
4055
4132
|
app.use("/vendor", express.static(join2(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
|
|
4056
4133
|
app.use(express.static(clientDir));
|
|
4057
4134
|
app.get("/api/status", (_req, res) => {
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
googleSearchContext,
|
|
5
5
|
truncateOutput
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-DIJIYWQE.js";
|
|
7
|
+
import "./chunk-YHLTSZVH.js";
|
|
8
8
|
import "./chunk-GLSR2NR3.js";
|
|
9
9
|
import "./chunk-UUSRWSSX.js";
|
|
10
10
|
import "./chunk-CKH4KQ4E.js";
|
|
@@ -12,7 +12,7 @@ import "./chunk-BXP6YZ2P.js";
|
|
|
12
12
|
import "./chunk-5C76XDDF.js";
|
|
13
13
|
import {
|
|
14
14
|
runTool
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-M3GDYEUH.js";
|
|
16
16
|
import {
|
|
17
17
|
getDangerLevel,
|
|
18
18
|
runLeanAgentLoop
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
import "./chunk-TU3L3PW7.js";
|
|
21
21
|
import "./chunk-HOSJZMQS.js";
|
|
22
22
|
import "./chunk-4BKXL7SM.js";
|
|
23
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-TG4PF7FZ.js";
|
|
24
24
|
import {
|
|
25
25
|
SUBAGENT_ALLOWED_TOOLS
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-75SPJKDY.js";
|
|
27
27
|
import "./chunk-6RPGQ5CG.js";
|
|
28
28
|
import "./chunk-KHYD3WXE.js";
|
|
29
29
|
import "./chunk-NYNSYLFY.js";
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CostTracker,
|
|
4
|
+
currencyNote,
|
|
4
5
|
formatCost,
|
|
5
|
-
getPricing
|
|
6
|
-
|
|
6
|
+
getPricing,
|
|
7
|
+
setCostCurrency
|
|
8
|
+
} from "./chunk-JT6UN5C6.js";
|
|
7
9
|
import {
|
|
8
10
|
ConfigManager
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-F26YTEMB.js";
|
|
10
12
|
import "./chunk-TU3L3PW7.js";
|
|
11
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-75SPJKDY.js";
|
|
12
14
|
import "./chunk-IW3Q7AE5.js";
|
|
13
15
|
|
|
14
16
|
// src/cli/usage.ts
|
|
@@ -23,6 +25,7 @@ function num(n) {
|
|
|
23
25
|
async function runUsageCli(options = {}) {
|
|
24
26
|
const chalk = (await import("chalk")).default;
|
|
25
27
|
const config = new ConfigManager();
|
|
28
|
+
setCostCurrency(config.get("ui").currency);
|
|
26
29
|
const tracker = new CostTracker(config.getConfigDir());
|
|
27
30
|
const sinceDays = options.days ? Math.max(1, parseInt(options.days, 10) || 0) : void 0;
|
|
28
31
|
const month = options.month?.trim();
|
|
@@ -80,6 +83,10 @@ async function runUsageCli(options = {}) {
|
|
|
80
83
|
if (unknownCount > 0) {
|
|
81
84
|
console.log(chalk.yellow(` \u2014 = no pricing data for ${unknownCount} model(s); their tokens are tracked but cost is excluded from the total.`));
|
|
82
85
|
}
|
|
86
|
+
const rateNote = currencyNote();
|
|
87
|
+
if (rateNote) {
|
|
88
|
+
console.log(chalk.dim(` ${rateNote}`));
|
|
89
|
+
}
|
|
83
90
|
console.log();
|
|
84
91
|
}
|
|
85
92
|
function label(r) {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/web/client/app.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* global lexical environment and are read/reassigned here as free variables.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { escapeHtml, formatToolArgs, formatDuration, sanitizeHtml } from './util.js';
|
|
10
|
+
import { escapeHtml, formatToolArgs, formatDuration, sanitizeHtml, formatCostDisplay } from './util.js';
|
|
11
11
|
import { fetchSessionReplay, fetchStatus, logoutAuth, registerFirstUser, submitAuth } from './api.js';
|
|
12
12
|
|
|
13
13
|
// ── State ──────────────────────────────────────────────────────────
|
|
@@ -523,8 +523,7 @@ function handleStatus(msg) {
|
|
|
523
523
|
let line = `📊 in: ${u.inputTokens.toLocaleString()} out: ${u.outputTokens.toLocaleString()}`;
|
|
524
524
|
if (cacheRead > 0) line += ` cache: ${cacheRead.toLocaleString()}`;
|
|
525
525
|
if (msg.costUsd != null) {
|
|
526
|
-
const
|
|
527
|
-
const costStr = cost === 0 ? '$0' : cost < 0.01 ? `$${cost.toFixed(4)}` : cost < 1 ? `$${cost.toFixed(3)}` : `$${cost.toFixed(2)}`;
|
|
526
|
+
const costStr = formatCostDisplay(msg.costUsd, msg.costCurrency, msg.costCnyPerUsd);
|
|
528
527
|
line += ` 💰 ${costStr}`;
|
|
529
528
|
}
|
|
530
529
|
else if (msg.costPricingUnknown) {
|
|
@@ -559,9 +558,7 @@ function renderDashboard() {
|
|
|
559
558
|
const pending = [...pendingApprovals.values()];
|
|
560
559
|
const tokens = s.tokenUsage || {};
|
|
561
560
|
const totalTokens = (tokens.inputTokens || 0) + (tokens.outputTokens || 0) + (tokens.cacheCreationTokens || 0) + (tokens.cacheReadTokens || 0);
|
|
562
|
-
const cost =
|
|
563
|
-
? (s.costUsd === 0 ? '$0' : s.costUsd < 0.01 ? `$${s.costUsd.toFixed(4)}` : s.costUsd < 1 ? `$${s.costUsd.toFixed(3)}` : `$${s.costUsd.toFixed(2)}`)
|
|
564
|
-
: 'unknown';
|
|
561
|
+
const cost = formatCostDisplay(s.costUsd, s.costCurrency, s.costCnyPerUsd);
|
|
565
562
|
const recentTests = lastToolResults.filter(r => r.toolName === 'run_tests').slice(-3).reverse();
|
|
566
563
|
const recentToolErrors = lastToolResults.filter(r => r.isError).slice(-3).reverse();
|
|
567
564
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/web/client/util.js
CHANGED
|
@@ -85,3 +85,25 @@ export function sanitizeHtml(html) {
|
|
|
85
85
|
|
|
86
86
|
return safe;
|
|
87
87
|
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 成本显示(2026-08-14 审计 P3-02)。
|
|
91
|
+
*
|
|
92
|
+
* 客户端此前有两处各自写死 `$` 的格式化(状态栏与 Dashboard),与服务端的
|
|
93
|
+
* `formatCost` 是第三、第四份实现。币种由 status 消息带下来,这里只负责排版;
|
|
94
|
+
* 人民币按服务端给的记账换算率折算——**不是实时汇率**,调用方需在附近标注。
|
|
95
|
+
*
|
|
96
|
+
* @param {number} usd 美元金额(存储与传输恒为美元)
|
|
97
|
+
* @param {'usd'|'cny'} [currency]
|
|
98
|
+
* @param {number} [cnyPerUsd] 记账换算率,缺省时退回美元显示
|
|
99
|
+
*/
|
|
100
|
+
export function formatCostDisplay(usd, currency, cnyPerUsd) {
|
|
101
|
+
if (typeof usd !== 'number' || !isFinite(usd)) return 'unknown';
|
|
102
|
+
const useCny = currency === 'cny' && typeof cnyPerUsd === 'number' && cnyPerUsd > 0;
|
|
103
|
+
const amount = useCny ? usd * cnyPerUsd : usd;
|
|
104
|
+
const sym = useCny ? '¥' : '$';
|
|
105
|
+
if (amount === 0) return `${sym}0`;
|
|
106
|
+
if (amount < 0.01) return `${sym}${amount.toFixed(4)}`;
|
|
107
|
+
if (amount < 1) return `${sym}${amount.toFixed(3)}`;
|
|
108
|
+
return `${sym}${amount.toFixed(2)}`;
|
|
109
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|