jinzd-ai-cli 0.4.268 → 0.4.269
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-HUOYPVJQ.js} +2 -2
- package/dist/{chunk-UT2WAJJG.js → chunk-3TOMHXDW.js} +1 -1
- package/dist/{chunk-EPVJS4F6.js → chunk-4HTJMLFY.js} +1 -1
- package/dist/{chunk-VGVKJTHF.js → chunk-5IUFUCIT.js} +1 -1
- package/dist/{chunk-2FQGMR34.js → chunk-5PRWBJCI.js} +1 -1
- package/dist/{chunk-YLSM7RF6.js → chunk-6PROC2JO.js} +3 -3
- package/dist/{chunk-7US7K3CD.js → chunk-AAERHPBN.js} +1 -1
- package/dist/{chunk-74BK22BM.js → chunk-DJNGUPM3.js} +4 -4
- package/dist/{chunk-RRQZRSXW.js → chunk-KIHNZBEA.js} +1 -1
- package/dist/{chunk-XDITAGE5.js → chunk-NVN3FHXI.js} +1 -1
- package/dist/{chunk-WNG3YVZX.js → chunk-QPPUYCRF.js} +1 -1
- package/dist/{chunk-VNCBY4KY.js → chunk-S3F5LOV3.js} +162 -2
- package/dist/{chunk-WWLXW4SY.js → chunk-V6KQ67VF.js} +1 -1
- package/dist/{chunk-Z7CZ72RP.js → chunk-XJAGGJVU.js} +3 -3
- package/dist/{ci-3RWVJSZ3.js → ci-4QS2J7BG.js} +4 -4
- package/dist/{ci-format-M6HVCXCG.js → ci-format-6L6M67WC.js} +2 -2
- package/dist/{constants-G6VN7SJL.js → constants-IO5VJLEE.js} +1 -1
- package/dist/{doctor-cli-Y3SVVJBO.js → doctor-cli-ZU4E2DDL.js} +4 -4
- package/dist/electron-server.js +245 -48
- package/dist/{hub-5T5HKOAR.js → hub-AMDWXSKZ.js} +1 -1
- package/dist/index.js +64 -153
- package/dist/{persistent-memory-YBWIZWQP.js → persistent-memory-52SE5K44.js} +2 -2
- package/dist/{persistent-memory-XVSSR277.js → persistent-memory-H4DNDIOQ.js} +2 -2
- package/dist/{pr-NF5IWLH3.js → pr-Z4O5H6I3.js} +4 -4
- package/dist/{run-tests-33X3D7PV.js → run-tests-FZSYHWYX.js} +2 -2
- package/dist/{run-tests-Y44SCLIO.js → run-tests-PYKKYMPA.js} +2 -2
- package/dist/{server-NJ3ZNPQW.js → server-WTJSM2MT.js} +79 -31
- package/dist/{server-3LERX42X.js → server-ZSTVYSYC.js} +5 -5
- package/dist/{task-orchestrator-JN2WFZSF.js → task-orchestrator-PNLI3V36.js} +5 -5
- package/dist/{usage-IFTNXTWC.js → usage-GVFUVYUG.js} +2 -2
- package/package.json +1 -1
package/dist/electron-server.js
CHANGED
|
@@ -26,7 +26,9 @@ import {
|
|
|
26
26
|
getGitContext,
|
|
27
27
|
getGitRoot,
|
|
28
28
|
isMemoryExpired,
|
|
29
|
+
isMemoryStale,
|
|
29
30
|
listMemoryEntries,
|
|
31
|
+
listOrphanedProjectMemories,
|
|
30
32
|
loadMemoryEntries,
|
|
31
33
|
memoryStorePath,
|
|
32
34
|
parseWritableScope,
|
|
@@ -34,14 +36,14 @@ import {
|
|
|
34
36
|
touchMemoryReferences,
|
|
35
37
|
updateMemoryApproval,
|
|
36
38
|
updateMemoryEntry
|
|
37
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-KIHNZBEA.js";
|
|
38
40
|
import {
|
|
39
41
|
redactJson,
|
|
40
42
|
scanString
|
|
41
43
|
} from "./chunk-YVTASHS5.js";
|
|
42
44
|
import {
|
|
43
45
|
runTestsTool
|
|
44
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-NVN3FHXI.js";
|
|
45
47
|
import {
|
|
46
48
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
47
49
|
APP_NAME,
|
|
@@ -74,7 +76,7 @@ import {
|
|
|
74
76
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
75
77
|
VERSION,
|
|
76
78
|
buildUserIdentityPrompt
|
|
77
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-4HTJMLFY.js";
|
|
78
80
|
import {
|
|
79
81
|
hasSemanticIndex,
|
|
80
82
|
semanticSearch
|
|
@@ -5258,9 +5260,9 @@ var SessionManager = class {
|
|
|
5258
5260
|
try {
|
|
5259
5261
|
const data = JSON.parse(readFileSync4(filePath, "utf-8"));
|
|
5260
5262
|
const messages = data.messages ?? [];
|
|
5261
|
-
const
|
|
5263
|
+
const matches2 = [];
|
|
5262
5264
|
for (const msg of messages) {
|
|
5263
|
-
if (
|
|
5265
|
+
if (matches2.length >= 3) break;
|
|
5264
5266
|
let text = "";
|
|
5265
5267
|
if (typeof msg.content === "string") {
|
|
5266
5268
|
text = msg.content;
|
|
@@ -5273,10 +5275,10 @@ var SessionManager = class {
|
|
|
5273
5275
|
const start = Math.max(0, idx - 30);
|
|
5274
5276
|
const end = Math.min(text.length, idx + query.length + 60);
|
|
5275
5277
|
const snippet = (start > 0 ? "\u2026" : "") + text.slice(start, end).replace(/\n/g, " ") + (end < text.length ? "\u2026" : "");
|
|
5276
|
-
|
|
5278
|
+
matches2.push({ role: msg.role, snippet });
|
|
5277
5279
|
}
|
|
5278
5280
|
}
|
|
5279
|
-
if (
|
|
5281
|
+
if (matches2.length > 0) {
|
|
5280
5282
|
results.push({
|
|
5281
5283
|
sessionMeta: {
|
|
5282
5284
|
id: data.id,
|
|
@@ -5287,7 +5289,7 @@ var SessionManager = class {
|
|
|
5287
5289
|
updated: safeDate(data.updated),
|
|
5288
5290
|
title: data.title
|
|
5289
5291
|
},
|
|
5290
|
-
matches
|
|
5292
|
+
matches: matches2
|
|
5291
5293
|
});
|
|
5292
5294
|
}
|
|
5293
5295
|
} catch (err) {
|
|
@@ -9395,20 +9397,20 @@ Results sorted by most recent modification time. Automatically skips node_module
|
|
|
9395
9397
|
if (!pattern) throw new ToolError("glob_files", "pattern is required");
|
|
9396
9398
|
if (!existsSync16(rootPath)) throw new ToolError("glob_files", `Path not found: ${rootPath}`);
|
|
9397
9399
|
const regex = globToRegex(pattern);
|
|
9398
|
-
const
|
|
9399
|
-
collectMatchingFiles(rootPath, rootPath, regex,
|
|
9400
|
-
if (
|
|
9400
|
+
const matches2 = [];
|
|
9401
|
+
collectMatchingFiles(rootPath, rootPath, regex, matches2, maxResults);
|
|
9402
|
+
if (matches2.length === 0) {
|
|
9401
9403
|
return `No files matched pattern: ${pattern}
|
|
9402
9404
|
Searched in: ${rootPath}`;
|
|
9403
9405
|
}
|
|
9404
|
-
|
|
9406
|
+
matches2.sort((a, b) => b.mtime - a.mtime);
|
|
9405
9407
|
const lines = [
|
|
9406
|
-
`Found ${
|
|
9408
|
+
`Found ${matches2.length} file(s) matching: ${pattern}`,
|
|
9407
9409
|
`Searched in: ${rootPath}`,
|
|
9408
9410
|
"",
|
|
9409
|
-
...
|
|
9411
|
+
...matches2.map((m) => m.relPath)
|
|
9410
9412
|
];
|
|
9411
|
-
if (
|
|
9413
|
+
if (matches2.length >= maxResults) {
|
|
9412
9414
|
lines.push("");
|
|
9413
9415
|
lines.push(`(Results truncated at ${maxResults}. Use max_results or narrow your pattern.)`);
|
|
9414
9416
|
}
|
|
@@ -10927,10 +10929,10 @@ function trustPlugin(configDir, name) {
|
|
|
10927
10929
|
}
|
|
10928
10930
|
function getInstalledPlugin(configDir, name) {
|
|
10929
10931
|
const plugins = listInstalledPlugins(configDir);
|
|
10930
|
-
const
|
|
10931
|
-
if (
|
|
10932
|
-
if (
|
|
10933
|
-
return
|
|
10932
|
+
const matches2 = plugins.filter((p) => p.name === name || p.name.startsWith(name));
|
|
10933
|
+
if (matches2.length === 0) throw new Error(`plugin not found: ${name}`);
|
|
10934
|
+
if (matches2.length > 1) throw new Error(`plugin name is ambiguous: ${name}`);
|
|
10935
|
+
return matches2[0];
|
|
10934
10936
|
}
|
|
10935
10937
|
function listInstalledPlugins(configDir) {
|
|
10936
10938
|
const root = pluginRoot(configDir);
|
|
@@ -11451,8 +11453,8 @@ function summarizeContent(content) {
|
|
|
11451
11453
|
function extractEvidence(content, toolNames) {
|
|
11452
11454
|
const evidence = /* @__PURE__ */ new Set();
|
|
11453
11455
|
if (toolNames.length > 0) evidence.add(`Tools: ${toolNames.join(", ")}`);
|
|
11454
|
-
const
|
|
11455
|
-
for (const match of
|
|
11456
|
+
const matches2 = content.match(/(?:[\w.-]+[\\/])+[\w.-]+\.(?:ts|tsx|js|jsx|json|md|css|html|py|go|rs|yml|yaml)/g) ?? [];
|
|
11457
|
+
for (const match of matches2.slice(0, 8)) evidence.add(match);
|
|
11456
11458
|
return [...evidence].slice(0, 10);
|
|
11457
11459
|
}
|
|
11458
11460
|
function formatAgentResult(input) {
|
|
@@ -14194,6 +14196,80 @@ function evaluateContextPressure(input) {
|
|
|
14194
14196
|
}
|
|
14195
14197
|
var AUTO_COMPACT_INSTRUCTION = "Preserve key context, compress old content, ensure seamless continuation";
|
|
14196
14198
|
|
|
14199
|
+
// src/core/model-router.ts
|
|
14200
|
+
var TAG_REGEX = /(?:^|\s)#([a-zA-Z][\w-]{0,31})\b/g;
|
|
14201
|
+
function extractTags(message) {
|
|
14202
|
+
const tags = /* @__PURE__ */ new Set();
|
|
14203
|
+
let m;
|
|
14204
|
+
TAG_REGEX.lastIndex = 0;
|
|
14205
|
+
while ((m = TAG_REGEX.exec(message)) !== null) {
|
|
14206
|
+
tags.add(m[1].toLowerCase());
|
|
14207
|
+
}
|
|
14208
|
+
return tags;
|
|
14209
|
+
}
|
|
14210
|
+
function matches(message, matcher) {
|
|
14211
|
+
const trimmed = message.trim();
|
|
14212
|
+
const lower = trimmed.toLowerCase();
|
|
14213
|
+
if (matcher.tag) {
|
|
14214
|
+
const tags = extractTags(trimmed);
|
|
14215
|
+
if (!tags.has(matcher.tag.toLowerCase())) return false;
|
|
14216
|
+
}
|
|
14217
|
+
if (matcher.contains && matcher.contains.length > 0) {
|
|
14218
|
+
const hit = matcher.contains.some((kw) => lower.includes(kw.toLowerCase()));
|
|
14219
|
+
if (!hit) return false;
|
|
14220
|
+
}
|
|
14221
|
+
if (typeof matcher.maxLength === "number") {
|
|
14222
|
+
if (trimmed.length > matcher.maxLength) return false;
|
|
14223
|
+
}
|
|
14224
|
+
if (typeof matcher.minLength === "number") {
|
|
14225
|
+
if (trimmed.length < matcher.minLength) return false;
|
|
14226
|
+
}
|
|
14227
|
+
const hasAnyCondition = !!matcher.tag || matcher.contains && matcher.contains.length > 0 || typeof matcher.maxLength === "number" || typeof matcher.minLength === "number";
|
|
14228
|
+
return !!hasAnyCondition;
|
|
14229
|
+
}
|
|
14230
|
+
function pickModel(message, currentModel, config, availableModels = []) {
|
|
14231
|
+
if (!config.enabled || config.rules.length === 0) {
|
|
14232
|
+
return { model: currentModel, reason: "routing disabled", overridden: false };
|
|
14233
|
+
}
|
|
14234
|
+
const isAvailable = (m) => availableModels.length === 0 || availableModels.includes(m);
|
|
14235
|
+
for (let i = 0; i < config.rules.length; i++) {
|
|
14236
|
+
const rule = config.rules[i];
|
|
14237
|
+
if (!matches(message, rule.match)) continue;
|
|
14238
|
+
if (!isAvailable(rule.model)) continue;
|
|
14239
|
+
if (rule.model === currentModel) {
|
|
14240
|
+
return {
|
|
14241
|
+
model: currentModel,
|
|
14242
|
+
reason: `rule "${rule.name ?? `#${i}`}" matched (same as current)`,
|
|
14243
|
+
overridden: false,
|
|
14244
|
+
ruleIdx: i
|
|
14245
|
+
};
|
|
14246
|
+
}
|
|
14247
|
+
return {
|
|
14248
|
+
model: rule.model,
|
|
14249
|
+
reason: `rule "${rule.name ?? `#${i}`}" matched`,
|
|
14250
|
+
overridden: true,
|
|
14251
|
+
ruleIdx: i
|
|
14252
|
+
};
|
|
14253
|
+
}
|
|
14254
|
+
if (config.fallback && config.fallback !== currentModel && isAvailable(config.fallback)) {
|
|
14255
|
+
return {
|
|
14256
|
+
model: config.fallback,
|
|
14257
|
+
reason: "fallback",
|
|
14258
|
+
overridden: true
|
|
14259
|
+
};
|
|
14260
|
+
}
|
|
14261
|
+
return { model: currentModel, reason: "no rule matched", overridden: false };
|
|
14262
|
+
}
|
|
14263
|
+
function stripRoutingTags(message) {
|
|
14264
|
+
return message.replace(/(?:^|\s)#(fast|deep|default)\b/gi, " ").replace(/\s{2,}/g, " ").trim();
|
|
14265
|
+
}
|
|
14266
|
+
function decideModel(input) {
|
|
14267
|
+
if (!input.routingConfig || !input.routingConfig.enabled) {
|
|
14268
|
+
return { model: input.currentModel, reason: "routing disabled", overridden: false };
|
|
14269
|
+
}
|
|
14270
|
+
return pickModel(input.userInput, input.currentModel, input.routingConfig, input.availableModels);
|
|
14271
|
+
}
|
|
14272
|
+
|
|
14197
14273
|
// src/core/context-files.ts
|
|
14198
14274
|
import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
|
|
14199
14275
|
import { join as join19, relative as relative4, resolve as resolve8 } from "path";
|
|
@@ -14544,6 +14620,84 @@ Output the Markdown content directly, do not wrap the entire file in a code bloc
|
|
|
14544
14620
|
return parts.join("\n");
|
|
14545
14621
|
}
|
|
14546
14622
|
|
|
14623
|
+
// src/core/memory-filters.ts
|
|
14624
|
+
function parseFlags(items) {
|
|
14625
|
+
const flags = {};
|
|
14626
|
+
const text = [];
|
|
14627
|
+
for (let i = 0; i < items.length; i++) {
|
|
14628
|
+
const item = items[i];
|
|
14629
|
+
if (item.startsWith("--")) {
|
|
14630
|
+
const key = item.slice(2);
|
|
14631
|
+
const next = items[i + 1];
|
|
14632
|
+
if (next && !next.startsWith("--")) {
|
|
14633
|
+
flags[key] = next;
|
|
14634
|
+
i++;
|
|
14635
|
+
} else {
|
|
14636
|
+
flags[key] = true;
|
|
14637
|
+
}
|
|
14638
|
+
} else {
|
|
14639
|
+
text.push(item);
|
|
14640
|
+
}
|
|
14641
|
+
}
|
|
14642
|
+
return { flags, text: text.join(" ").trim() };
|
|
14643
|
+
}
|
|
14644
|
+
var SCOPES = /* @__PURE__ */ new Set(["personal", "project", "session", "team"]);
|
|
14645
|
+
var BOOLEAN_FLAGS = ["pending", "orphaned"];
|
|
14646
|
+
function parseMemoryShowFilters(args) {
|
|
14647
|
+
const { flags, text } = parseFlags(args);
|
|
14648
|
+
const strayTerms = [];
|
|
14649
|
+
for (const key of BOOLEAN_FLAGS) {
|
|
14650
|
+
const v = flags[key];
|
|
14651
|
+
if (typeof v === "string") {
|
|
14652
|
+
strayTerms.push(v);
|
|
14653
|
+
flags[key] = true;
|
|
14654
|
+
}
|
|
14655
|
+
}
|
|
14656
|
+
const scopeRaw = flags["scope"];
|
|
14657
|
+
const freeText = [text, ...strayTerms].filter(Boolean).join(" ").trim();
|
|
14658
|
+
const searchRaw = typeof flags["search"] === "string" ? flags["search"] : freeText || void 0;
|
|
14659
|
+
const staleRaw = flags["stale"];
|
|
14660
|
+
let staleDays;
|
|
14661
|
+
let invalidStale = false;
|
|
14662
|
+
if (staleRaw !== void 0) {
|
|
14663
|
+
const n = typeof staleRaw === "string" ? Number(staleRaw) : NaN;
|
|
14664
|
+
if (!Number.isFinite(n) || n <= 0) invalidStale = true;
|
|
14665
|
+
else staleDays = n;
|
|
14666
|
+
}
|
|
14667
|
+
return {
|
|
14668
|
+
pending: flags["pending"] === true,
|
|
14669
|
+
orphaned: flags["orphaned"] === true,
|
|
14670
|
+
scope: typeof scopeRaw === "string" && SCOPES.has(scopeRaw) ? scopeRaw : void 0,
|
|
14671
|
+
search: searchRaw?.toLowerCase(),
|
|
14672
|
+
staleDays,
|
|
14673
|
+
invalidStale
|
|
14674
|
+
};
|
|
14675
|
+
}
|
|
14676
|
+
function filterMemoryEntries(entries, filters) {
|
|
14677
|
+
let out = entries;
|
|
14678
|
+
const applied = [];
|
|
14679
|
+
if (filters.orphaned) applied.push("orphaned");
|
|
14680
|
+
if (filters.pending) {
|
|
14681
|
+
out = out.filter((m) => !m.approved && !isMemoryExpired(m));
|
|
14682
|
+
applied.push("pending");
|
|
14683
|
+
}
|
|
14684
|
+
if (filters.scope) {
|
|
14685
|
+
out = out.filter((m) => m.scope === filters.scope);
|
|
14686
|
+
applied.push(`scope:${filters.scope}`);
|
|
14687
|
+
}
|
|
14688
|
+
if (filters.search) {
|
|
14689
|
+
const q = filters.search;
|
|
14690
|
+
out = out.filter((m) => m.content.toLowerCase().includes(q) || m.id.startsWith(q));
|
|
14691
|
+
applied.push(`search:"${q}"`);
|
|
14692
|
+
}
|
|
14693
|
+
if (filters.staleDays !== void 0) {
|
|
14694
|
+
const days = filters.staleDays;
|
|
14695
|
+
out = out.filter((m) => isMemoryStale(m, days));
|
|
14696
|
+
applied.push(`stale>${days}d`);
|
|
14697
|
+
}
|
|
14698
|
+
return { entries: out, applied };
|
|
14699
|
+
}
|
|
14700
|
+
|
|
14547
14701
|
// src/hub/convergence.ts
|
|
14548
14702
|
function convergenceThreshold(total) {
|
|
14549
14703
|
if (total <= 0) return Infinity;
|
|
@@ -15863,7 +16017,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
15863
16017
|
Cost: ${formatCost(cost)}` : "";
|
|
15864
16018
|
let memoryLine = "";
|
|
15865
16019
|
try {
|
|
15866
|
-
const { countPendingMemories } = await import("./persistent-memory-
|
|
16020
|
+
const { countPendingMemories } = await import("./persistent-memory-52SE5K44.js");
|
|
15867
16021
|
const pending = countPendingMemories(ctx.config.getConfigDir());
|
|
15868
16022
|
if (pending > 0) memoryLine = `
|
|
15869
16023
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -15967,14 +16121,14 @@ async function handleSession(args, ctx) {
|
|
|
15967
16121
|
return;
|
|
15968
16122
|
}
|
|
15969
16123
|
const list2 = ctx.sessions.listSessions();
|
|
15970
|
-
const
|
|
15971
|
-
if (
|
|
16124
|
+
const matches2 = list2.filter((s) => s.messageCount === filterMessages);
|
|
16125
|
+
if (matches2.length === 0) {
|
|
15972
16126
|
ctx.send({ type: "info", message: `No sessions with ${filterMessages} message(s) found.` });
|
|
15973
16127
|
return;
|
|
15974
16128
|
}
|
|
15975
16129
|
let deleted = 0;
|
|
15976
16130
|
let failed = 0;
|
|
15977
|
-
for (const s of
|
|
16131
|
+
for (const s of matches2) {
|
|
15978
16132
|
if (ctx.sessions.deleteSession(s.id)) {
|
|
15979
16133
|
deleted++;
|
|
15980
16134
|
} else {
|
|
@@ -16676,7 +16830,7 @@ async function handleTest(args, ctx) {
|
|
|
16676
16830
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
16677
16831
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
16678
16832
|
}
|
|
16679
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
16833
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-PYKKYMPA.js")).executeTests;
|
|
16680
16834
|
const report = await runTests(testArgs);
|
|
16681
16835
|
ctx.send({ type: "info", message: report });
|
|
16682
16836
|
} catch (err) {
|
|
@@ -16934,7 +17088,7 @@ async function handleMemory(args, ctx) {
|
|
|
16934
17088
|
ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
|
|
16935
17089
|
} else if (sub === "export") {
|
|
16936
17090
|
if (args[1] === "md") {
|
|
16937
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
17091
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-52SE5K44.js");
|
|
16938
17092
|
ctx.send({
|
|
16939
17093
|
type: "export_data",
|
|
16940
17094
|
format: "md",
|
|
@@ -16954,7 +17108,8 @@ async function handleMemory(args, ctx) {
|
|
|
16954
17108
|
});
|
|
16955
17109
|
}
|
|
16956
17110
|
} else {
|
|
16957
|
-
|
|
17111
|
+
const isShow = sub === "show" || sub === "view" || sub === "list";
|
|
17112
|
+
ctx.memoryShow(isShow ? args.slice(1) : args);
|
|
16958
17113
|
}
|
|
16959
17114
|
}
|
|
16960
17115
|
async function handleAddDir(args, ctx) {
|
|
@@ -17382,11 +17537,11 @@ async function handleSearch(args, ctx) {
|
|
|
17382
17537
|
}
|
|
17383
17538
|
const lines = [`\u{1F50D} Found ${results.length} session(s) containing "${query}"`, ""];
|
|
17384
17539
|
for (const r of results) {
|
|
17385
|
-
const { sessionMeta, matches } = r;
|
|
17540
|
+
const { sessionMeta, matches: matches2 } = r;
|
|
17386
17541
|
const dateStr = sessionMeta.updated instanceof Date ? sessionMeta.updated.toLocaleDateString() : String(sessionMeta.updated);
|
|
17387
17542
|
lines.push(`**${sessionMeta.id.slice(0, 8)}** [${dateStr}] ${sessionMeta.provider} / ${sessionMeta.model}`);
|
|
17388
17543
|
if (sessionMeta.title) lines.push(` ${sessionMeta.title}`);
|
|
17389
|
-
for (const m of
|
|
17544
|
+
for (const m of matches2) {
|
|
17390
17545
|
const icon = m.role === "user" ? "\u{1F464}" : "\u{1F916}";
|
|
17391
17546
|
lines.push(` ${icon} ${m.snippet}`);
|
|
17392
17547
|
}
|
|
@@ -17517,17 +17672,18 @@ var SessionHandler = class {
|
|
|
17517
17672
|
sessionAccruedCostUsd = 0;
|
|
17518
17673
|
sessionCostIncomplete = false;
|
|
17519
17674
|
/** Accumulate a TokenUsage (with optional cache fields) into sessionTokenUsage. */
|
|
17520
|
-
addWebSessionUsage(u) {
|
|
17675
|
+
addWebSessionUsage(u, modelOverride) {
|
|
17676
|
+
const usageModel = modelOverride ?? this.currentModel;
|
|
17521
17677
|
this.sessionTokenUsage.inputTokens += u.inputTokens;
|
|
17522
17678
|
this.sessionTokenUsage.outputTokens += u.outputTokens;
|
|
17523
17679
|
this.sessionTokenUsage.cacheCreationTokens += u.cacheCreationTokens ?? 0;
|
|
17524
17680
|
this.sessionTokenUsage.cacheReadTokens += u.cacheReadTokens ?? 0;
|
|
17525
|
-
const priced = this.costTracker.addCost(this.currentProvider,
|
|
17681
|
+
const priced = this.costTracker.addCost(this.currentProvider, usageModel, u);
|
|
17526
17682
|
if (priced === null) this.sessionCostIncomplete = true;
|
|
17527
17683
|
else this.sessionAccruedCostUsd += priced;
|
|
17528
17684
|
const totalTokens = u.inputTokens + u.outputTokens + (u.cacheCreationTokens ?? 0) + (u.cacheReadTokens ?? 0);
|
|
17529
|
-
if (totalTokens > 0 && !getPricing(this.currentProvider,
|
|
17530
|
-
const key = `${this.currentProvider}/${
|
|
17685
|
+
if (totalTokens > 0 && !getPricing(this.currentProvider, usageModel)) {
|
|
17686
|
+
const key = `${this.currentProvider}/${usageModel}`;
|
|
17531
17687
|
if (!this.unknownPricingWarnings.has(key)) {
|
|
17532
17688
|
this.unknownPricingWarnings.add(key);
|
|
17533
17689
|
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.` });
|
|
@@ -17975,6 +18131,16 @@ var SessionHandler = class {
|
|
|
17975
18131
|
} else {
|
|
17976
18132
|
msgContent = content;
|
|
17977
18133
|
}
|
|
18134
|
+
const routingDecision = this.computeRoutingDecision(typeof msgContent === "string" ? msgContent : content);
|
|
18135
|
+
if (typeof msgContent === "string") {
|
|
18136
|
+
msgContent = stripRoutingTags(msgContent);
|
|
18137
|
+
} else if (msgContent.length > 0 && msgContent[msgContent.length - 1]?.type === "text") {
|
|
18138
|
+
const last = msgContent[msgContent.length - 1];
|
|
18139
|
+
msgContent = [...msgContent.slice(0, -1), { type: "text", text: stripRoutingTags(last.text) }];
|
|
18140
|
+
}
|
|
18141
|
+
if (routingDecision.overridden) {
|
|
18142
|
+
this.send({ type: "info", message: `\u2192 Routed to ${routingDecision.model} (${routingDecision.reason})` });
|
|
18143
|
+
}
|
|
17978
18144
|
const userMessage = { role: "user", content: msgContent, timestamp: /* @__PURE__ */ new Date() };
|
|
17979
18145
|
session.addMessage(userMessage);
|
|
17980
18146
|
const provider = this.providers.get(this.currentProvider);
|
|
@@ -17986,11 +18152,13 @@ var SessionHandler = class {
|
|
|
17986
18152
|
const hasToolSupport = typeof provider.chatWithTools === "function";
|
|
17987
18153
|
const { toolDefs, mcpBudgetNote } = hasToolSupport ? this.getFilteredToolDefs() : { toolDefs: [], mcpBudgetNote: null };
|
|
17988
18154
|
if (hasToolSupport && toolDefs.length > 0) {
|
|
17989
|
-
await this.handleChatWithTools(provider, session.messages, toolDefs, mcpBudgetNote);
|
|
18155
|
+
await this.handleChatWithTools(provider, session.messages, toolDefs, mcpBudgetNote, routingDecision.model);
|
|
17990
18156
|
} else {
|
|
17991
|
-
await this.handleChatSimple(provider, session.messages);
|
|
18157
|
+
await this.handleChatSimple(provider, session.messages, routingDecision.model);
|
|
17992
18158
|
}
|
|
17993
18159
|
await this.checkContextPressure();
|
|
18160
|
+
const budgetWarning = this.costTracker.checkBudget(this.config.get("monthlyBudget"));
|
|
18161
|
+
if (budgetWarning) this.send({ type: "info", message: `\u26A0 ${budgetWarning}` });
|
|
17994
18162
|
} catch (err) {
|
|
17995
18163
|
const parts = [];
|
|
17996
18164
|
let current = err;
|
|
@@ -18009,8 +18177,9 @@ var SessionHandler = class {
|
|
|
18009
18177
|
this.sendSessionList();
|
|
18010
18178
|
}
|
|
18011
18179
|
}
|
|
18012
|
-
async handleChatSimple(provider, messages) {
|
|
18180
|
+
async handleChatSimple(provider, messages, modelOverride) {
|
|
18013
18181
|
const session = this.sessions.current;
|
|
18182
|
+
const effectiveModel = modelOverride ?? this.currentModel;
|
|
18014
18183
|
const modelParams = this.getModelParams();
|
|
18015
18184
|
const ac = new AbortController();
|
|
18016
18185
|
this.abortController = ac;
|
|
@@ -18018,7 +18187,7 @@ var SessionHandler = class {
|
|
|
18018
18187
|
const { stable: simplStable, volatile: simplVolatile } = this.buildSystemPrompt();
|
|
18019
18188
|
const stream = provider.chatStream({
|
|
18020
18189
|
messages,
|
|
18021
|
-
model:
|
|
18190
|
+
model: effectiveModel,
|
|
18022
18191
|
systemPrompt: simplStable,
|
|
18023
18192
|
systemPromptVolatile: simplVolatile,
|
|
18024
18193
|
stream: true,
|
|
@@ -18037,7 +18206,7 @@ var SessionHandler = class {
|
|
|
18037
18206
|
if (chunk.done) {
|
|
18038
18207
|
this.send({ type: "response_done", content: fullContent, usage: chunk.usage });
|
|
18039
18208
|
if (chunk.usage) {
|
|
18040
|
-
this.addWebSessionUsage(chunk.usage);
|
|
18209
|
+
this.addWebSessionUsage(chunk.usage, effectiveModel);
|
|
18041
18210
|
session.addTokenUsage(chunk.usage);
|
|
18042
18211
|
}
|
|
18043
18212
|
if (chunk.reasoningContent) simpleReasoning = chunk.reasoningContent;
|
|
@@ -18062,8 +18231,9 @@ var SessionHandler = class {
|
|
|
18062
18231
|
this.abortController = null;
|
|
18063
18232
|
}
|
|
18064
18233
|
}
|
|
18065
|
-
async handleChatWithTools(provider, messages, toolDefs, mcpBudgetNote) {
|
|
18234
|
+
async handleChatWithTools(provider, messages, toolDefs, mcpBudgetNote, modelOverride) {
|
|
18066
18235
|
const session = this.sessions.current;
|
|
18236
|
+
const effectiveModel = modelOverride ?? this.currentModel;
|
|
18067
18237
|
const apiMessages = [...messages];
|
|
18068
18238
|
const maxToolRounds = this.config.get("maxToolRounds") ?? DEFAULT_MAX_TOOL_ROUNDS;
|
|
18069
18239
|
const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
|
|
@@ -18093,7 +18263,7 @@ ${mcpBudgetNote}` : "");
|
|
|
18093
18263
|
callModel: async (_round, extraMessages) => {
|
|
18094
18264
|
const chatRequest = {
|
|
18095
18265
|
messages: apiMessages,
|
|
18096
|
-
model:
|
|
18266
|
+
model: effectiveModel,
|
|
18097
18267
|
systemPrompt,
|
|
18098
18268
|
systemPromptVolatile,
|
|
18099
18269
|
stream: false,
|
|
@@ -18138,7 +18308,7 @@ Details: ${errMsg.split("\n")[0]}
|
|
|
18138
18308
|
const summaryResult = await provider.chatWithTools(
|
|
18139
18309
|
{
|
|
18140
18310
|
messages: apiMessages,
|
|
18141
|
-
model:
|
|
18311
|
+
model: effectiveModel,
|
|
18142
18312
|
systemPrompt,
|
|
18143
18313
|
systemPromptVolatile,
|
|
18144
18314
|
stream: false,
|
|
@@ -18154,7 +18324,7 @@ Details: ${errMsg.split("\n")[0]}
|
|
|
18154
18324
|
executeTools: async (toolCalls) => {
|
|
18155
18325
|
googleSearchContext.configManager = this.config;
|
|
18156
18326
|
spawnAgentContext.provider = provider;
|
|
18157
|
-
spawnAgentContext.model =
|
|
18327
|
+
spawnAgentContext.model = effectiveModel;
|
|
18158
18328
|
spawnAgentContext.systemPrompt = systemPromptVolatile ? `${systemPrompt}
|
|
18159
18329
|
|
|
18160
18330
|
---
|
|
@@ -18528,6 +18698,24 @@ ${summaryContent}`,
|
|
|
18528
18698
|
* 到达上下文压力阈值时自动压缩(与 REPL 同一判据,见 core/context-pressure.ts)。
|
|
18529
18699
|
* 上下文窗口未知时不动——不基于猜测改用户的对话历史。
|
|
18530
18700
|
*/
|
|
18701
|
+
/**
|
|
18702
|
+
* 智能模型路由决策(审计附录 D-5)。候选限定在当前 provider 注册的模型内——
|
|
18703
|
+
* 跨 provider 换模型会破坏 API key 与对话连续性。
|
|
18704
|
+
*/
|
|
18705
|
+
computeRoutingDecision(userInput) {
|
|
18706
|
+
let availableModels = [];
|
|
18707
|
+
try {
|
|
18708
|
+
availableModels = this.providers.get(this.currentProvider).info.models.map((m) => m.id);
|
|
18709
|
+
} catch {
|
|
18710
|
+
availableModels = [];
|
|
18711
|
+
}
|
|
18712
|
+
return decideModel({
|
|
18713
|
+
userInput,
|
|
18714
|
+
currentModel: this.currentModel,
|
|
18715
|
+
routingConfig: this.config.get("routing"),
|
|
18716
|
+
availableModels
|
|
18717
|
+
});
|
|
18718
|
+
}
|
|
18531
18719
|
async checkContextPressure() {
|
|
18532
18720
|
const contextWindow = this.getContextWindowSize();
|
|
18533
18721
|
const session = this.sessions.current;
|
|
@@ -18690,18 +18878,27 @@ ${summaryContent}`,
|
|
|
18690
18878
|
});
|
|
18691
18879
|
}
|
|
18692
18880
|
}
|
|
18693
|
-
memoryShow() {
|
|
18881
|
+
memoryShow(args = []) {
|
|
18694
18882
|
const configDir = this.config.getConfigDir();
|
|
18695
|
-
const
|
|
18696
|
-
|
|
18883
|
+
const filters = parseMemoryShowFilters(args);
|
|
18884
|
+
if (filters.invalidStale) {
|
|
18885
|
+
this.send({ type: "error", message: "Usage: /memory show --stale <days> (positive number)" });
|
|
18886
|
+
return;
|
|
18887
|
+
}
|
|
18888
|
+
const source = filters.orphaned ? listOrphanedProjectMemories(configDir) : listMemoryEntries(configDir, { includeExpired: true, includeRejected: true });
|
|
18889
|
+
const { entries, applied } = filterMemoryEntries(source, filters);
|
|
18890
|
+
const filterNote = applied.length > 0 ? ` (filtered: ${applied.join(", ")})` : "";
|
|
18891
|
+
const content = entries.length === 0 ? applied.length > 0 ? `(no entries match [${applied.join(", ")}])` : "(empty \u2014 no persistent memory entries yet)" : `Governed persistent memory${filterNote}
|
|
18892
|
+
|
|
18893
|
+
` + entries.map((entry) => {
|
|
18697
18894
|
const status = isMemoryExpired(entry) ? "expired" : entry.approved ? "approved" : "pending";
|
|
18698
|
-
const
|
|
18895
|
+
const source2 = [
|
|
18699
18896
|
entry.source ?? "unknown",
|
|
18700
18897
|
entry.sourceSession ? `session ${entry.sourceSession.slice(0, 8)}` : "",
|
|
18701
18898
|
entry.sourceProject ? `project ${entry.sourceProject}` : ""
|
|
18702
18899
|
].filter(Boolean).join(" \xB7 ");
|
|
18703
18900
|
return `## ${entry.id.slice(0, 8)} \xB7 ${status} \xB7 scope:${entry.scope} \xB7 sensitivity:${entry.sensitivity}
|
|
18704
|
-
Source: ${
|
|
18901
|
+
Source: ${source2}
|
|
18705
18902
|
${entry.content}`;
|
|
18706
18903
|
}).join("\n\n");
|
|
18707
18904
|
this.send({
|
|
@@ -158,7 +158,7 @@ ${content}`);
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
161
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
161
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-PNLI3V36.js");
|
|
162
162
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
163
163
|
let interrupted = false;
|
|
164
164
|
const onSigint = () => {
|