zelari-code 2.18.1 → 2.20.0
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/cli/budget/contextProjection.js +52 -0
- package/dist/cli/budget/contextProjection.js.map +1 -0
- package/dist/cli/budget/modelContextBuilder.js +9 -0
- package/dist/cli/budget/modelContextBuilder.js.map +1 -1
- package/dist/cli/budget/retrievalPolicy.js +82 -0
- package/dist/cli/budget/retrievalPolicy.js.map +1 -0
- package/dist/cli/commands/inspectSession.js +12 -2
- package/dist/cli/commands/inspectSession.js.map +1 -1
- package/dist/cli/harnessState.js +17 -5
- package/dist/cli/harnessState.js.map +1 -1
- package/dist/cli/headless/runOneTurn.js +7 -2
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/hooks/permissionPicker.js +9 -1
- package/dist/cli/hooks/permissionPicker.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +10 -2
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +1141 -902
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/memory/spineTelemetry.js +38 -5
- package/dist/cli/memory/spineTelemetry.js.map +1 -1
- package/dist/cli/provider/capabilities.js +3 -0
- package/dist/cli/provider/capabilities.js.map +1 -1
- package/dist/cli/provider/openai-compatible.js +27 -1
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/runHeadless.js +16 -4
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/safety/resourceClaims.js +33 -2
- package/dist/cli/safety/resourceClaims.js.map +1 -1
- package/dist/cli/safety/toolPermissions.js +11 -4
- package/dist/cli/safety/toolPermissions.js.map +1 -1
- package/dist/cli/slashHandlers/krakenGraph.js +4 -1
- package/dist/cli/slashHandlers/krakenGraph.js.map +1 -1
- package/dist/cli/toolRegistry.js +16 -2
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/skillTool.js +20 -6
- package/dist/cli/tools/skillTool.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -29977,8 +29977,9 @@ var init_service = __esm({
|
|
|
29977
29977
|
const text = (raw.query ?? raw.text ?? "").slice(0, 64e3);
|
|
29978
29978
|
const limit = Math.max(1, Math.min(raw.limit ?? 8, 100));
|
|
29979
29979
|
this.emit({ type: "memory_recall_start" });
|
|
29980
|
+
const { weights, ...recallQuery } = raw;
|
|
29980
29981
|
const candidates = await this.backend.search({
|
|
29981
|
-
...
|
|
29982
|
+
...recallQuery,
|
|
29982
29983
|
text,
|
|
29983
29984
|
projectId: this.projectId,
|
|
29984
29985
|
statuses: raw.statuses ?? (raw.includeHistorical ? void 0 : ["active"]),
|
|
@@ -30025,7 +30026,7 @@ var init_service = __esm({
|
|
|
30025
30026
|
}
|
|
30026
30027
|
}
|
|
30027
30028
|
}
|
|
30028
|
-
const ranked = diverse(rankMemoryCandidates([...byId.values()], text), limit);
|
|
30029
|
+
const ranked = diverse(rankMemoryCandidates([...byId.values()], text, weights ? { weights } : {}), limit);
|
|
30029
30030
|
this.emit({
|
|
30030
30031
|
type: "memory_recall_end",
|
|
30031
30032
|
durationMs: Date.now() - started,
|
|
@@ -40721,25 +40722,883 @@ var init_skillsMd = __esm({
|
|
|
40721
40722
|
}
|
|
40722
40723
|
});
|
|
40723
40724
|
|
|
40725
|
+
// src/cli/budget/historySummary.ts
|
|
40726
|
+
function extractiveHistorySummary(dropped, opts) {
|
|
40727
|
+
const maxChars = opts?.maxChars ?? MAX_SUMMARY_CHARS;
|
|
40728
|
+
if (dropped.length === 0) return "No prior turns.";
|
|
40729
|
+
const userGoals = [];
|
|
40730
|
+
const assistantNotes = [];
|
|
40731
|
+
const userConstraints = [];
|
|
40732
|
+
const unresolved = [];
|
|
40733
|
+
const verification = [];
|
|
40734
|
+
const decisions = [];
|
|
40735
|
+
const tools = /* @__PURE__ */ new Map();
|
|
40736
|
+
const files = /* @__PURE__ */ new Set();
|
|
40737
|
+
let toolResults = 0;
|
|
40738
|
+
for (const m of dropped) {
|
|
40739
|
+
if (m.role === "user" && m.content.trim()) {
|
|
40740
|
+
const goal = oneLine(m.content, 220);
|
|
40741
|
+
userGoals.push(goal);
|
|
40742
|
+
if (/\b(must|never|required|only|do not|constraint|vincolo|deve|senza)\b/i.test(goal)) userConstraints.push(goal);
|
|
40743
|
+
} else if (m.role === "assistant") {
|
|
40744
|
+
if (m.content.trim()) {
|
|
40745
|
+
const note = oneLine(m.content, 220);
|
|
40746
|
+
assistantNotes.push(note);
|
|
40747
|
+
if (/\b(fail|failed|error|unresolved|remaining|todo|blocked|gap|errore|fallit|irrisolt|manca)\b/i.test(note)) unresolved.push(note);
|
|
40748
|
+
if (/\b(test|typecheck|build|verify|verification|passed|failed|green|red)\b/i.test(note)) verification.push(note);
|
|
40749
|
+
if (/\b(decid|decision|chosen|choose|scelt|adopt|implement)\b/i.test(note)) decisions.push(note);
|
|
40750
|
+
}
|
|
40751
|
+
if (m.toolCalls) {
|
|
40752
|
+
for (const tc of m.toolCalls) {
|
|
40753
|
+
tools.set(tc.name, (tools.get(tc.name) ?? 0) + 1);
|
|
40754
|
+
collectPaths3(tc.args, files);
|
|
40755
|
+
}
|
|
40756
|
+
}
|
|
40757
|
+
} else if (m.role === "tool") {
|
|
40758
|
+
toolResults += 1;
|
|
40759
|
+
collectPathsFromText(m.content, files);
|
|
40760
|
+
if (/\b(fail|failed|error|exception|blocked|errore|fallit)\b/i.test(m.content)) unresolved.push(oneLine(m.content, 220));
|
|
40761
|
+
if (/\b(test|typecheck|build|verify|passed|failed|success)\b/i.test(m.content)) verification.push(oneLine(m.content, 220));
|
|
40762
|
+
}
|
|
40763
|
+
}
|
|
40764
|
+
const parts = [
|
|
40765
|
+
"[history-summary] Earlier turns were compacted to stay within the context budget.",
|
|
40766
|
+
`Dropped ${dropped.length} message(s) (${userGoals.length} user, ${assistantNotes.length} assistant notes, ${toolResults} tool results).`
|
|
40767
|
+
];
|
|
40768
|
+
if (userGoals.length) {
|
|
40769
|
+
parts.push("## User goals / requests");
|
|
40770
|
+
for (const g of userGoals.slice(-6)) parts.push(`- ${g}`);
|
|
40771
|
+
}
|
|
40772
|
+
if (userConstraints.length) {
|
|
40773
|
+
parts.push("## User constraints (preserve exactly)");
|
|
40774
|
+
for (const item of [...new Set(userConstraints)].slice(-8)) parts.push(`- ${item}`);
|
|
40775
|
+
}
|
|
40776
|
+
if (unresolved.length) {
|
|
40777
|
+
parts.push("## Unresolved failures / pending repair");
|
|
40778
|
+
for (const item of [...new Set(unresolved)].slice(-8)) parts.push(`- ${item}`);
|
|
40779
|
+
}
|
|
40780
|
+
if (verification.length) {
|
|
40781
|
+
parts.push("## Latest verification state");
|
|
40782
|
+
for (const item of [...new Set(verification)].slice(-6)) parts.push(`- ${item}`);
|
|
40783
|
+
}
|
|
40784
|
+
if (decisions.length) {
|
|
40785
|
+
parts.push("## Recent active decisions");
|
|
40786
|
+
for (const item of [...new Set(decisions)].slice(-6)) parts.push(`- ${item}`);
|
|
40787
|
+
}
|
|
40788
|
+
if (assistantNotes.length) {
|
|
40789
|
+
parts.push("## Assistant conclusions (truncated)");
|
|
40790
|
+
for (const a of assistantNotes.slice(-5)) parts.push(`- ${a}`);
|
|
40791
|
+
}
|
|
40792
|
+
if (tools.size) {
|
|
40793
|
+
const ranked = [...tools.entries()].sort((a, b) => b[1] - a[1]).slice(0, 12).map(([n, c]) => `${n}\xD7${c}`);
|
|
40794
|
+
parts.push(`## Tools used: ${ranked.join(", ")}`);
|
|
40795
|
+
}
|
|
40796
|
+
if (files.size) {
|
|
40797
|
+
const list = [...files].slice(0, 24);
|
|
40798
|
+
parts.push(`## Paths mentioned: ${list.join(", ")}`);
|
|
40799
|
+
}
|
|
40800
|
+
parts.push(
|
|
40801
|
+
"Continue from the recent messages below; do not re-ask goals already answered above unless the user changes them."
|
|
40802
|
+
);
|
|
40803
|
+
let out = parts.join("\n");
|
|
40804
|
+
if (out.length > maxChars) {
|
|
40805
|
+
out = `${out.slice(0, maxChars - 1)}\u2026`;
|
|
40806
|
+
}
|
|
40807
|
+
return out;
|
|
40808
|
+
}
|
|
40809
|
+
function oneLine(s, max) {
|
|
40810
|
+
const t = s.replace(/\s+/g, " ").trim();
|
|
40811
|
+
if (t.length <= max) return t;
|
|
40812
|
+
return `${t.slice(0, max - 1)}\u2026`;
|
|
40813
|
+
}
|
|
40814
|
+
function collectPaths3(args, out) {
|
|
40815
|
+
if (!args || typeof args !== "object") return;
|
|
40816
|
+
const obj = args;
|
|
40817
|
+
for (const key of ["path", "file", "filepath", "filePath", "target", "cwd"]) {
|
|
40818
|
+
const v = obj[key];
|
|
40819
|
+
if (typeof v === "string" && v.length > 1 && v.length < 260) {
|
|
40820
|
+
out.add(v.replace(/\\/g, "/"));
|
|
40821
|
+
}
|
|
40822
|
+
}
|
|
40823
|
+
if (typeof obj.file_path === "string") out.add(String(obj.file_path));
|
|
40824
|
+
}
|
|
40825
|
+
function collectPathsFromText(text, out) {
|
|
40826
|
+
const re = /(?:^|[\s"'`])((?:[\w.-]+\/)+[\w.-]+\.\w{1,8})/g;
|
|
40827
|
+
let m;
|
|
40828
|
+
let n = 0;
|
|
40829
|
+
while ((m = re.exec(text)) !== null && n < 8) {
|
|
40830
|
+
out.add(m[1]);
|
|
40831
|
+
n += 1;
|
|
40832
|
+
}
|
|
40833
|
+
}
|
|
40834
|
+
var MAX_SUMMARY_CHARS;
|
|
40835
|
+
var init_historySummary = __esm({
|
|
40836
|
+
"src/cli/budget/historySummary.ts"() {
|
|
40837
|
+
"use strict";
|
|
40838
|
+
MAX_SUMMARY_CHARS = 3500;
|
|
40839
|
+
}
|
|
40840
|
+
});
|
|
40841
|
+
|
|
40842
|
+
// src/cli/budget/llmCompact.ts
|
|
40843
|
+
function isLlmCompactEnabled() {
|
|
40844
|
+
const v = process.env.ZELARI_LLM_COMPACT?.trim().toLowerCase();
|
|
40845
|
+
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
40846
|
+
return true;
|
|
40847
|
+
}
|
|
40848
|
+
function compactModelOverride() {
|
|
40849
|
+
const v = process.env.ZELARI_COMPACT_MODEL?.trim();
|
|
40850
|
+
return v ? v : void 0;
|
|
40851
|
+
}
|
|
40852
|
+
async function llmSummarizeHistoryReplay(input) {
|
|
40853
|
+
const override = input.overrideModel ?? compactModelOverride();
|
|
40854
|
+
const model = override ?? input.model;
|
|
40855
|
+
const cacheReuseExpected = !override;
|
|
40856
|
+
if (!isLlmCompactEnabled()) return { summary: null, model, cacheReuseExpected };
|
|
40857
|
+
if (input.droppedMessages.length === 0) {
|
|
40858
|
+
return { summary: null, model, cacheReuseExpected };
|
|
40859
|
+
}
|
|
40860
|
+
const messages = [
|
|
40861
|
+
...input.systemMessages,
|
|
40862
|
+
...input.droppedMessages,
|
|
40863
|
+
{
|
|
40864
|
+
role: "user",
|
|
40865
|
+
content: COMPACTION_INSTRUCTION
|
|
40866
|
+
}
|
|
40867
|
+
];
|
|
40868
|
+
const controller = new AbortController();
|
|
40869
|
+
const timeout = setTimeout(() => controller.abort(), REPLAY_TIMEOUT_MS);
|
|
40870
|
+
const onOuterAbort = () => controller.abort();
|
|
40871
|
+
input.signal?.addEventListener("abort", onOuterAbort, { once: true });
|
|
40872
|
+
try {
|
|
40873
|
+
let text = "";
|
|
40874
|
+
let emittedToolCall = false;
|
|
40875
|
+
for await (const delta of input.providerStream({
|
|
40876
|
+
provider: input.provider,
|
|
40877
|
+
model,
|
|
40878
|
+
messages,
|
|
40879
|
+
// Tools stay advertised: dropping them would change the prefix token
|
|
40880
|
+
// sequence and destroy cache reuse (explicit DSH decision). They are
|
|
40881
|
+
// sorted canonically (same discipline as the live routed request and
|
|
40882
|
+
// the snapshot fingerprints) so the replay prefix is byte-identical.
|
|
40883
|
+
tools: [...input.tools].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0),
|
|
40884
|
+
signal: controller.signal,
|
|
40885
|
+
generation: {
|
|
40886
|
+
purpose: "compaction",
|
|
40887
|
+
temperature: 0.1,
|
|
40888
|
+
maxTokens: 900
|
|
40889
|
+
}
|
|
40890
|
+
})) {
|
|
40891
|
+
if (delta.kind === "text") text += delta.delta;
|
|
40892
|
+
if (delta.kind === "tool_call") emittedToolCall = true;
|
|
40893
|
+
}
|
|
40894
|
+
if (emittedToolCall) return { summary: null, model, cacheReuseExpected };
|
|
40895
|
+
if (!text.trim()) return { summary: null, model, cacheReuseExpected };
|
|
40896
|
+
return { summary: text.trim(), model, cacheReuseExpected };
|
|
40897
|
+
} catch {
|
|
40898
|
+
return { summary: null, model, cacheReuseExpected };
|
|
40899
|
+
} finally {
|
|
40900
|
+
clearTimeout(timeout);
|
|
40901
|
+
input.signal?.removeEventListener("abort", onOuterAbort);
|
|
40902
|
+
}
|
|
40903
|
+
}
|
|
40904
|
+
var COMPACTION_INSTRUCTION, REPLAY_TIMEOUT_MS;
|
|
40905
|
+
var init_llmCompact = __esm({
|
|
40906
|
+
"src/cli/budget/llmCompact.ts"() {
|
|
40907
|
+
"use strict";
|
|
40908
|
+
COMPACTION_INSTRUCTION = `
|
|
40909
|
+
You are now acting as a compaction engine for this coding-agent session.
|
|
40910
|
+
|
|
40911
|
+
Condense the conversation ABOVE into a compact checkpoint sufficient to continue the task.
|
|
40912
|
+
|
|
40913
|
+
Preserve:
|
|
40914
|
+
- user's goal and evolving intent
|
|
40915
|
+
- decisions already made
|
|
40916
|
+
- exact file paths and identifiers
|
|
40917
|
+
- code changes already completed
|
|
40918
|
+
- commands/errors that still matter
|
|
40919
|
+
- constraints
|
|
40920
|
+
- unfinished work
|
|
40921
|
+
- the single most likely next action
|
|
40922
|
+
|
|
40923
|
+
Do not call tools.
|
|
40924
|
+
Do not mention this summarization request.
|
|
40925
|
+
Output only the checkpoint.
|
|
40926
|
+
Be concise.
|
|
40927
|
+
`.trim();
|
|
40928
|
+
REPLAY_TIMEOUT_MS = 6e4;
|
|
40929
|
+
}
|
|
40930
|
+
});
|
|
40931
|
+
|
|
40932
|
+
// src/cli/hooks/historyCompaction.ts
|
|
40933
|
+
function compactedRangeFromDropped(dropped) {
|
|
40934
|
+
if (dropped.length === 0) return void 0;
|
|
40935
|
+
const seqs = [];
|
|
40936
|
+
const sources = [];
|
|
40937
|
+
for (const m of dropped) {
|
|
40938
|
+
const hasCompactRange = typeof m.compactedFromSeq === "number" && Number.isInteger(m.compactedFromSeq) && m.compactedFromSeq > 0 && typeof m.compactedToSeq === "number" && Number.isInteger(m.compactedToSeq) && m.compactedToSeq >= m.compactedFromSeq;
|
|
40939
|
+
if (hasCompactRange) {
|
|
40940
|
+
seqs.push(m.compactedFromSeq, m.compactedToSeq);
|
|
40941
|
+
sources.push(...m.sourceEventSeqs ?? []);
|
|
40942
|
+
if (typeof m.seq === "number" && Number.isInteger(m.seq) && m.seq > 0) {
|
|
40943
|
+
seqs.push(m.seq);
|
|
40944
|
+
sources.push(m.seq);
|
|
40945
|
+
}
|
|
40946
|
+
continue;
|
|
40947
|
+
}
|
|
40948
|
+
if (typeof m.seq !== "number" || !Number.isInteger(m.seq) || m.seq < 1) return void 0;
|
|
40949
|
+
seqs.push(m.seq);
|
|
40950
|
+
sources.push(m.seq);
|
|
40951
|
+
}
|
|
40952
|
+
return {
|
|
40953
|
+
fromSeq: Math.min(...seqs),
|
|
40954
|
+
toSeq: Math.max(...seqs),
|
|
40955
|
+
sourceEventSeqs: [...new Set(sources)]
|
|
40956
|
+
};
|
|
40957
|
+
}
|
|
40958
|
+
function withDroppedRange(result, dropped, strategy) {
|
|
40959
|
+
const range = compactedRangeFromDropped(dropped);
|
|
40960
|
+
if (!range) return { ...result, strategy };
|
|
40961
|
+
return { ...result, ...range, strategy };
|
|
40962
|
+
}
|
|
40963
|
+
function resolveMaxMessages(opts) {
|
|
40964
|
+
const envTurns = envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 });
|
|
40965
|
+
let turns = opts?.maxMessages ? Math.ceil(opts.maxMessages / 4) : envTurns;
|
|
40966
|
+
if (opts?.durableStatePresent && !opts?.maxMessages && process.env.ZELARI_HISTORY_TURNS === void 0) {
|
|
40967
|
+
turns = Math.min(turns, 3);
|
|
40968
|
+
}
|
|
40969
|
+
if (turns <= 0) return 0;
|
|
40970
|
+
if (opts?.force && opts?.maxMessages) return Math.max(1, opts.maxMessages);
|
|
40971
|
+
return turns * 4;
|
|
40972
|
+
}
|
|
40973
|
+
function findValidCutIndex(messages, naiveCut) {
|
|
40974
|
+
let cut = naiveCut;
|
|
40975
|
+
while (cut < messages.length) {
|
|
40976
|
+
const kept = messages.slice(cut);
|
|
40977
|
+
const declared = /* @__PURE__ */ new Set();
|
|
40978
|
+
for (const m of kept) {
|
|
40979
|
+
if (m.role === "assistant" && m.toolCalls) {
|
|
40980
|
+
for (const tc of m.toolCalls) declared.add(tc.id);
|
|
40981
|
+
}
|
|
40982
|
+
}
|
|
40983
|
+
let moved = false;
|
|
40984
|
+
for (let k = 0; k < kept.length; k++) {
|
|
40985
|
+
const m = kept[k];
|
|
40986
|
+
if (m.role === "tool" && m.toolCallId && !declared.has(m.toolCallId)) {
|
|
40987
|
+
for (let j = cut - 1; j >= 0; j--) {
|
|
40988
|
+
const prev2 = messages[j];
|
|
40989
|
+
if (prev2.role === "assistant" && prev2.toolCalls && prev2.toolCalls.some((tc) => tc.id === m.toolCallId)) {
|
|
40990
|
+
cut = j;
|
|
40991
|
+
moved = true;
|
|
40992
|
+
break;
|
|
40993
|
+
}
|
|
40994
|
+
}
|
|
40995
|
+
break;
|
|
40996
|
+
}
|
|
40997
|
+
}
|
|
40998
|
+
if (!moved) break;
|
|
40999
|
+
}
|
|
41000
|
+
return cut;
|
|
41001
|
+
}
|
|
41002
|
+
function resolvePruneLimits(opts) {
|
|
41003
|
+
const maxChars = opts?.maxChars ?? envNumber(process.env.ZELARI_TOOL_RESULT_MAX_CHARS, { default: 8e3, min: 256 });
|
|
41004
|
+
const rawTail = opts?.tailChars ?? envNumber(process.env.ZELARI_TOOL_RESULT_TAIL_CHARS, { default: 1e3, min: 0 });
|
|
41005
|
+
const tailChars = Math.min(rawTail, maxChars);
|
|
41006
|
+
return { maxChars, tailChars };
|
|
41007
|
+
}
|
|
41008
|
+
function pruneToolResultsDetailed(messages, opts) {
|
|
41009
|
+
const { maxChars, tailChars } = resolvePruneLimits(opts);
|
|
41010
|
+
const headChars = maxChars - tailChars;
|
|
41011
|
+
const stats = { pruned: 0, charsOmitted: 0 };
|
|
41012
|
+
let changed = false;
|
|
41013
|
+
const out = messages.map((m) => {
|
|
41014
|
+
if (m.role !== "tool") return m;
|
|
41015
|
+
const body = m.content ?? "";
|
|
41016
|
+
if (body.length <= maxChars) return m;
|
|
41017
|
+
const head = headChars > 0 ? body.slice(0, headChars) : "";
|
|
41018
|
+
const tail2 = tailChars > 0 ? body.slice(-tailChars) : "";
|
|
41019
|
+
const omitted = body.length - head.length - tail2.length;
|
|
41020
|
+
changed = true;
|
|
41021
|
+
stats.pruned += 1;
|
|
41022
|
+
stats.charsOmitted += omitted;
|
|
41023
|
+
return {
|
|
41024
|
+
...m,
|
|
41025
|
+
content: [head, "\u2026[pruned " + omitted + " chars]\u2026", tail2].join(String.fromCharCode(10))
|
|
41026
|
+
};
|
|
41027
|
+
});
|
|
41028
|
+
return {
|
|
41029
|
+
messages: changed ? out : messages,
|
|
41030
|
+
stats
|
|
41031
|
+
};
|
|
41032
|
+
}
|
|
41033
|
+
function compactHistory(messages, opts) {
|
|
41034
|
+
return compactHistoryDetailed(messages, opts).messages;
|
|
41035
|
+
}
|
|
41036
|
+
function buildCheckpointMessage(summaryText, range) {
|
|
41037
|
+
return {
|
|
41038
|
+
role: "user",
|
|
41039
|
+
content: CHECKPOINT_WRAPPER_PREFIX + "\n\n<compacted-summary>\n" + summaryText + "\n</compacted-summary>",
|
|
41040
|
+
...range ? {
|
|
41041
|
+
compactedFromSeq: range.fromSeq,
|
|
41042
|
+
compactedToSeq: range.toSeq,
|
|
41043
|
+
sourceEventSeqs: [...range.sourceEventSeqs]
|
|
41044
|
+
} : {}
|
|
41045
|
+
};
|
|
41046
|
+
}
|
|
41047
|
+
function compactHistoryDetailed(messages, opts) {
|
|
41048
|
+
const maxMessages = resolveMaxMessages(opts);
|
|
41049
|
+
if (maxMessages === 0) {
|
|
41050
|
+
return withDroppedRange(
|
|
41051
|
+
{ messages: [], compacted: true, messagesRemoved: messages.length, summary: "" },
|
|
41052
|
+
messages,
|
|
41053
|
+
"extractive"
|
|
41054
|
+
);
|
|
41055
|
+
}
|
|
41056
|
+
if (messages.length <= maxMessages * 2 && !opts?.force) {
|
|
41057
|
+
return {
|
|
41058
|
+
messages,
|
|
41059
|
+
compacted: false,
|
|
41060
|
+
messagesRemoved: 0,
|
|
41061
|
+
summary: ""
|
|
41062
|
+
};
|
|
41063
|
+
}
|
|
41064
|
+
const naiveCut = Math.max(0, messages.length - maxMessages);
|
|
41065
|
+
const cut = findValidCutIndex(messages, naiveCut);
|
|
41066
|
+
if (cut === 0) {
|
|
41067
|
+
return {
|
|
41068
|
+
messages,
|
|
41069
|
+
compacted: false,
|
|
41070
|
+
messagesRemoved: 0,
|
|
41071
|
+
summary: ""
|
|
41072
|
+
};
|
|
41073
|
+
}
|
|
41074
|
+
const droppedMsgs = messages.slice(0, cut);
|
|
41075
|
+
const droppedRange = compactedRangeFromDropped(droppedMsgs);
|
|
41076
|
+
const pruned = pruneToolResultsDetailed(messages.slice(cut));
|
|
41077
|
+
const kept = pruned.messages;
|
|
41078
|
+
const summaryText = extractiveHistorySummary(droppedMsgs);
|
|
41079
|
+
const summary = buildCheckpointMessage(
|
|
41080
|
+
summaryText || `${COMPACT_MARKER} ${cut} earlier message(s) dropped.`,
|
|
41081
|
+
droppedRange
|
|
41082
|
+
);
|
|
41083
|
+
return withDroppedRange(
|
|
41084
|
+
{
|
|
41085
|
+
messages: [summary, ...kept],
|
|
41086
|
+
compacted: true,
|
|
41087
|
+
messagesRemoved: cut,
|
|
41088
|
+
summary: summary.content,
|
|
41089
|
+
prunedToolResults: pruned.stats.pruned
|
|
41090
|
+
},
|
|
41091
|
+
droppedMsgs,
|
|
41092
|
+
"extractive"
|
|
41093
|
+
);
|
|
41094
|
+
}
|
|
41095
|
+
async function compactHistoryAsync(messages, opts) {
|
|
41096
|
+
const base2 = compactHistoryDetailed(messages, opts);
|
|
41097
|
+
if (!base2.compacted || base2.messagesRemoved === 0) return base2;
|
|
41098
|
+
const cut = base2.messagesRemoved;
|
|
41099
|
+
const droppedMsgs = messages.slice(0, cut);
|
|
41100
|
+
const extractive = extractiveHistorySummary(droppedMsgs);
|
|
41101
|
+
let summaryText = extractive;
|
|
41102
|
+
let cacheReuseExpected;
|
|
41103
|
+
let replayExactPrefix;
|
|
41104
|
+
const canReplay = !!(opts?.providerStream && opts?.requestSnapshot);
|
|
41105
|
+
if (canReplay) {
|
|
41106
|
+
try {
|
|
41107
|
+
const replay = await llmSummarizeHistoryReplay({
|
|
41108
|
+
providerStream: opts.providerStream,
|
|
41109
|
+
provider: opts.requestSnapshot.provider,
|
|
41110
|
+
model: opts.requestSnapshot.model,
|
|
41111
|
+
systemMessages: opts.requestSnapshot.systemMessages,
|
|
41112
|
+
tools: opts.requestSnapshot.tools,
|
|
41113
|
+
droppedMessages: droppedMsgs,
|
|
41114
|
+
signal: opts?.signal
|
|
41115
|
+
});
|
|
41116
|
+
cacheReuseExpected = replay.cacheReuseExpected;
|
|
41117
|
+
if (replay.summary && replay.summary.trim().length > 40) {
|
|
41118
|
+
const sourceTokens = roughTokens(droppedMsgs);
|
|
41119
|
+
const summaryTok = Math.ceil(replay.summary.length / 4);
|
|
41120
|
+
if (summaryTok < sourceTokens) {
|
|
41121
|
+
summaryText = replay.summary.trim();
|
|
41122
|
+
}
|
|
41123
|
+
}
|
|
41124
|
+
} catch {
|
|
41125
|
+
}
|
|
41126
|
+
}
|
|
41127
|
+
const pruned = pruneToolResultsDetailed(messages.slice(cut));
|
|
41128
|
+
const kept = pruned.messages;
|
|
41129
|
+
const summary = buildCheckpointMessage(summaryText, compactedRangeFromDropped(droppedMsgs));
|
|
41130
|
+
const usedLlm = summaryText !== extractive && summaryText.trim().length > 40;
|
|
41131
|
+
return withDroppedRange(
|
|
41132
|
+
{
|
|
41133
|
+
messages: [summary, ...kept],
|
|
41134
|
+
compacted: true,
|
|
41135
|
+
messagesRemoved: cut,
|
|
41136
|
+
summary: summaryText,
|
|
41137
|
+
prunedToolResults: pruned.stats.pruned,
|
|
41138
|
+
cacheReuseExpected,
|
|
41139
|
+
replayExactPrefix
|
|
41140
|
+
},
|
|
41141
|
+
droppedMsgs,
|
|
41142
|
+
usedLlm ? "llm" : "extractive"
|
|
41143
|
+
);
|
|
41144
|
+
}
|
|
41145
|
+
function roughTokens(msgs) {
|
|
41146
|
+
let n = 0;
|
|
41147
|
+
for (const m of msgs) {
|
|
41148
|
+
n += Math.ceil((m.content ?? "").length / 4);
|
|
41149
|
+
if (m.toolCalls) {
|
|
41150
|
+
for (const tc of m.toolCalls) {
|
|
41151
|
+
n += Math.ceil(JSON.stringify(tc.args ?? {}).length / 4);
|
|
41152
|
+
}
|
|
41153
|
+
}
|
|
41154
|
+
}
|
|
41155
|
+
return Math.max(1, n);
|
|
41156
|
+
}
|
|
41157
|
+
var COMPACT_MARKER, CHECKPOINT_WRAPPER_PREFIX;
|
|
41158
|
+
var init_historyCompaction = __esm({
|
|
41159
|
+
"src/cli/hooks/historyCompaction.ts"() {
|
|
41160
|
+
"use strict";
|
|
41161
|
+
init_historySummary();
|
|
41162
|
+
init_llmCompact();
|
|
41163
|
+
init_envNumber();
|
|
41164
|
+
COMPACT_MARKER = "[history] Earlier turns were compacted to stay within the context budget.";
|
|
41165
|
+
CHECKPOINT_WRAPPER_PREFIX = "This is an automatically generated checkpoint of earlier conversation. Treat it as established context and continue directly.";
|
|
41166
|
+
}
|
|
41167
|
+
});
|
|
41168
|
+
|
|
41169
|
+
// src/cli/provider/capabilities.ts
|
|
41170
|
+
function frozenProfile(input) {
|
|
41171
|
+
if (input.reasoning.levels) Object.freeze(input.reasoning.levels);
|
|
41172
|
+
Object.freeze(input.reasoning);
|
|
41173
|
+
Object.freeze(input.promptCache);
|
|
41174
|
+
Object.freeze(input.toolCalling);
|
|
41175
|
+
Object.freeze(input.buildRecovery);
|
|
41176
|
+
Object.freeze(input.sampling);
|
|
41177
|
+
Object.freeze(input.compaction);
|
|
41178
|
+
return Object.freeze(input);
|
|
41179
|
+
}
|
|
41180
|
+
function resolveHarnessProfile(model, providerId) {
|
|
41181
|
+
const provider = providerId?.trim().toLowerCase();
|
|
41182
|
+
if (provider === "deepseek") return "deepseek-v4";
|
|
41183
|
+
if (provider === "grok") return "grok";
|
|
41184
|
+
if (provider === "minimax") return "minimax";
|
|
41185
|
+
if (provider === "glm") return "glm";
|
|
41186
|
+
if (model && DEEPSEEK_RE.test(model)) return "deepseek-v4";
|
|
41187
|
+
if (model && GROK_RE.test(model)) return "grok";
|
|
41188
|
+
if (model && MINIMAX_RE.test(model)) return "minimax";
|
|
41189
|
+
if (model && GLM_RE.test(model)) return "glm";
|
|
41190
|
+
return "default";
|
|
41191
|
+
}
|
|
41192
|
+
function capabilitiesFor(model, providerId) {
|
|
41193
|
+
switch (resolveHarnessProfile(model, providerId)) {
|
|
41194
|
+
case "deepseek-v4":
|
|
41195
|
+
return DEEPSEEK_V4_CAPS;
|
|
41196
|
+
case "grok":
|
|
41197
|
+
return GROK_CAPS;
|
|
41198
|
+
case "minimax":
|
|
41199
|
+
return model && MINIMAX_M3_RE.test(model) ? MINIMAX_M3_CAPS : MINIMAX_M2_CAPS;
|
|
41200
|
+
case "glm":
|
|
41201
|
+
return GLM_CAPS;
|
|
41202
|
+
default:
|
|
41203
|
+
return DEFAULT_CAPS;
|
|
41204
|
+
}
|
|
41205
|
+
}
|
|
41206
|
+
var SHARED_COMPACTION, DEFAULT_CAPS, DEEPSEEK_V4_CAPS, GROK_CAPS, MINIMAX_M3_CAPS, MINIMAX_M2_CAPS, GLM_CAPS, DEEPSEEK_RE, GROK_RE, MINIMAX_RE, MINIMAX_M3_RE, GLM_RE;
|
|
41207
|
+
var init_capabilities = __esm({
|
|
41208
|
+
"src/cli/provider/capabilities.ts"() {
|
|
41209
|
+
"use strict";
|
|
41210
|
+
SHARED_COMPACTION = { warnAt: 0.7, compactAt: 0.85, hardAt: 0.95 };
|
|
41211
|
+
DEFAULT_CAPS = frozenProfile({
|
|
41212
|
+
contextWindow: 4e5,
|
|
41213
|
+
reasoning: { supported: true, levels: ["low", "medium", "high"], replayReasoning: true },
|
|
41214
|
+
promptCache: { supported: true, pricedCacheRead: false },
|
|
41215
|
+
toolCalling: { parallel: true },
|
|
41216
|
+
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
41217
|
+
sampling: { temperature: 0.7 },
|
|
41218
|
+
compaction: { ...SHARED_COMPACTION },
|
|
41219
|
+
profile: "default"
|
|
41220
|
+
});
|
|
41221
|
+
DEEPSEEK_V4_CAPS = frozenProfile({
|
|
41222
|
+
contextWindow: 1e6,
|
|
41223
|
+
reasoning: { supported: true, levels: ["high", "max"], replayReasoning: true },
|
|
41224
|
+
promptCache: { supported: true, pricedCacheRead: true },
|
|
41225
|
+
toolCalling: { parallel: true },
|
|
41226
|
+
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
41227
|
+
sampling: { temperature: 0.7 },
|
|
41228
|
+
compaction: { ...SHARED_COMPACTION },
|
|
41229
|
+
profile: "deepseek-v4"
|
|
41230
|
+
});
|
|
41231
|
+
GROK_CAPS = frozenProfile({
|
|
41232
|
+
contextWindow: 5e5,
|
|
41233
|
+
// grok-4.x truncation fix: explicit conversation ceiling (see interface
|
|
41234
|
+
// doc). Override at runtime via ZELARI_MAX_OUTPUT_TOKENS.
|
|
41235
|
+
maxOutputTokens: 32768,
|
|
41236
|
+
reasoning: {
|
|
41237
|
+
supported: true,
|
|
41238
|
+
levels: ["low", "medium", "high", "xhigh"],
|
|
41239
|
+
replayReasoning: false
|
|
41240
|
+
},
|
|
41241
|
+
promptCache: {
|
|
41242
|
+
supported: true,
|
|
41243
|
+
pricedCacheRead: true,
|
|
41244
|
+
conversationAffinityHeader: "x-grok-conv-id"
|
|
41245
|
+
},
|
|
41246
|
+
toolCalling: { parallel: true },
|
|
41247
|
+
buildRecovery: { forceToolChoice: true, maxForcedTurns: 1 },
|
|
41248
|
+
sampling: { temperature: 0.7 },
|
|
41249
|
+
compaction: { ...SHARED_COMPACTION },
|
|
41250
|
+
profile: "grok"
|
|
41251
|
+
});
|
|
41252
|
+
MINIMAX_M3_CAPS = frozenProfile({
|
|
41253
|
+
contextWindow: 1e6,
|
|
41254
|
+
reasoning: { supported: true, replayReasoning: true },
|
|
41255
|
+
promptCache: { supported: false, pricedCacheRead: false },
|
|
41256
|
+
toolCalling: { parallel: true },
|
|
41257
|
+
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
41258
|
+
sampling: { temperature: 0.7 },
|
|
41259
|
+
compaction: { ...SHARED_COMPACTION },
|
|
41260
|
+
profile: "minimax"
|
|
41261
|
+
});
|
|
41262
|
+
MINIMAX_M2_CAPS = frozenProfile({
|
|
41263
|
+
contextWindow: 204800,
|
|
41264
|
+
reasoning: { supported: true, replayReasoning: true },
|
|
41265
|
+
promptCache: { supported: false, pricedCacheRead: false },
|
|
41266
|
+
toolCalling: { parallel: true },
|
|
41267
|
+
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
41268
|
+
sampling: { temperature: 0.7 },
|
|
41269
|
+
compaction: { ...SHARED_COMPACTION },
|
|
41270
|
+
profile: "minimax"
|
|
41271
|
+
});
|
|
41272
|
+
GLM_CAPS = frozenProfile({
|
|
41273
|
+
contextWindow: 2e5,
|
|
41274
|
+
reasoning: { supported: true, replayReasoning: true },
|
|
41275
|
+
promptCache: { supported: true, pricedCacheRead: false },
|
|
41276
|
+
toolCalling: { parallel: true },
|
|
41277
|
+
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
41278
|
+
sampling: { temperature: 0.7 },
|
|
41279
|
+
compaction: { ...SHARED_COMPACTION },
|
|
41280
|
+
profile: "glm"
|
|
41281
|
+
});
|
|
41282
|
+
DEEPSEEK_RE = /^deepseek-(?:v4(?:\.|-|$)|chat$|reasoner$)/i;
|
|
41283
|
+
GROK_RE = /^grok(?:\.|-|$)/i;
|
|
41284
|
+
MINIMAX_RE = /^minimax(?:\.|-|$)/i;
|
|
41285
|
+
MINIMAX_M3_RE = /^minimax-m3(?:\.|-|$)/i;
|
|
41286
|
+
GLM_RE = /^glm(?:\.|-|$)/i;
|
|
41287
|
+
}
|
|
41288
|
+
});
|
|
41289
|
+
|
|
41290
|
+
// src/cli/budget/tokenBudget.ts
|
|
41291
|
+
function mergeCompactRange(into, r) {
|
|
41292
|
+
if (r.fromSeq !== void 0 && r.toSeq !== void 0) {
|
|
41293
|
+
into.fromSeq = into.fromSeq === void 0 ? r.fromSeq : Math.min(into.fromSeq, r.fromSeq);
|
|
41294
|
+
into.toSeq = into.toSeq === void 0 ? r.toSeq : Math.max(into.toSeq, r.toSeq);
|
|
41295
|
+
if (r.sourceEventSeqs) into.sourceSeqs.push(...r.sourceEventSeqs);
|
|
41296
|
+
}
|
|
41297
|
+
if (r.strategy === "llm") into.strategy = "llm";
|
|
41298
|
+
else if (r.strategy && !into.strategy) into.strategy = r.strategy;
|
|
41299
|
+
}
|
|
41300
|
+
function estimateTokens2(text) {
|
|
41301
|
+
if (!text) return 0;
|
|
41302
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
41303
|
+
}
|
|
41304
|
+
function estimateHistoryTokens(messages) {
|
|
41305
|
+
let n = 0;
|
|
41306
|
+
for (const m of messages) {
|
|
41307
|
+
n += estimateTokens2(m.content);
|
|
41308
|
+
if (m.toolCalls) {
|
|
41309
|
+
for (const tc of m.toolCalls) {
|
|
41310
|
+
n += estimateTokens2(tc.name) + estimateTokens2(JSON.stringify(tc.args ?? {}));
|
|
41311
|
+
}
|
|
41312
|
+
}
|
|
41313
|
+
}
|
|
41314
|
+
return n;
|
|
41315
|
+
}
|
|
41316
|
+
function defaultContextLimitForModel(model, provider) {
|
|
41317
|
+
return capabilitiesFor(model, provider).contextWindow;
|
|
41318
|
+
}
|
|
41319
|
+
function resolveContextLimit(model, provider) {
|
|
41320
|
+
return envNumber(process.env.ZELARI_CONTEXT_LIMIT, {
|
|
41321
|
+
default: defaultContextLimitForModel(model, provider),
|
|
41322
|
+
min: 4e3,
|
|
41323
|
+
max: 2e6
|
|
41324
|
+
});
|
|
41325
|
+
}
|
|
41326
|
+
function phaseKnobs(phase2) {
|
|
41327
|
+
return {
|
|
41328
|
+
historyTurns: phase2 === "plan" ? envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 8, min: 0 }) : envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 }),
|
|
41329
|
+
maxToolLoopIterations: phase2 === "plan" ? envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, { default: 60, min: 1 }) : envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, {
|
|
41330
|
+
default: 120,
|
|
41331
|
+
min: 1
|
|
41332
|
+
})
|
|
41333
|
+
};
|
|
41334
|
+
}
|
|
41335
|
+
async function applyBudgetPolicyAsync(history2, phase2, opts) {
|
|
41336
|
+
const contextLimit = resolveContextLimit(opts?.model, opts?.provider);
|
|
41337
|
+
const compact3 = capabilitiesFor(opts?.model, opts?.provider).compaction;
|
|
41338
|
+
const sessionExtra = opts?.sessionTokens ?? 0;
|
|
41339
|
+
const warnings = [];
|
|
41340
|
+
let { historyTurns, maxToolLoopIterations } = phaseKnobs(phase2);
|
|
41341
|
+
const envelope = opts?.requestSnapshot ?? null;
|
|
41342
|
+
const surface = envelope?.snapshot ?? opts?.requestSurface ?? null;
|
|
41343
|
+
const replayBase = surface ? {
|
|
41344
|
+
provider: surface.provider,
|
|
41345
|
+
model: surface.model,
|
|
41346
|
+
systemMessages: surface.systemMessages,
|
|
41347
|
+
tools: surface.tools
|
|
41348
|
+
} : opts?.providerStream ? { provider: "local", model: opts?.model ?? "unknown", systemMessages: [], tools: [] } : null;
|
|
41349
|
+
const headerTokens = surface ? estimateSystemTokensLite(surface.systemMessages) + estimateToolSchemaTokensLite(surface.tools) : 0;
|
|
41350
|
+
const convTokensOf = (h) => estimateConversationTokensLite(h);
|
|
41351
|
+
let hist = history2;
|
|
41352
|
+
let estimated = surface ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
41353
|
+
let occupancy = Math.min(1, estimated / contextLimit);
|
|
41354
|
+
let compactSummary = "";
|
|
41355
|
+
let messagesRemoved = 0;
|
|
41356
|
+
let cacheReuseExpected;
|
|
41357
|
+
let prunedTotal = 0;
|
|
41358
|
+
const compactRange = { sourceSeqs: [] };
|
|
41359
|
+
if (occupancy >= compact3.warnAt && occupancy < compact3.compactAt) {
|
|
41360
|
+
warnings.push(
|
|
41361
|
+
`[budget] context ~${Math.round(occupancy * 100)}% full (${estimated}/${contextLimit} tok full-request est.) \u2014 consider /compact or shorter replies.`
|
|
41362
|
+
);
|
|
41363
|
+
}
|
|
41364
|
+
if (occupancy >= 0.8) {
|
|
41365
|
+
const pruned = pruneToolResultsDetailed(hist);
|
|
41366
|
+
if (pruned.stats.pruned > 0) {
|
|
41367
|
+
hist = pruned.messages;
|
|
41368
|
+
prunedTotal += pruned.stats.pruned;
|
|
41369
|
+
estimated = surface ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
41370
|
+
occupancy = Math.min(1, estimated / contextLimit);
|
|
41371
|
+
warnings.push(
|
|
41372
|
+
`[budget] pruned ${pruned.stats.pruned} oversized tool result(s) \u2192 ${Math.round(occupancy * 100)}% (${estimated} tok).`
|
|
41373
|
+
);
|
|
41374
|
+
}
|
|
41375
|
+
}
|
|
41376
|
+
const fold = (r, label, forcedTurns) => {
|
|
41377
|
+
hist = applySessionSurface(r.messages);
|
|
41378
|
+
if (r.compacted) {
|
|
41379
|
+
messagesRemoved += r.messagesRemoved;
|
|
41380
|
+
if (r.summary) compactSummary = r.summary;
|
|
41381
|
+
mergeCompactRange(compactRange, r);
|
|
41382
|
+
if (r.cacheReuseExpected !== void 0) {
|
|
41383
|
+
cacheReuseExpected = r.cacheReuseExpected;
|
|
41384
|
+
}
|
|
41385
|
+
}
|
|
41386
|
+
estimated = surface ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
41387
|
+
occupancy = Math.min(1, estimated / contextLimit);
|
|
41388
|
+
warnings.push(
|
|
41389
|
+
`[budget] ${label} \u2014 kept ~${forcedTurns} turns (${estimated} tok est.` + (r.messagesRemoved ? `, removed ${r.messagesRemoved} msgs` : "") + (r.cacheReuseExpected === false ? ", cache reuse NOT expected (model override)" : "") + ")."
|
|
41390
|
+
);
|
|
41391
|
+
};
|
|
41392
|
+
if (occupancy >= compact3.compactAt) {
|
|
41393
|
+
const forcedTurns = Math.max(1, Math.floor(historyTurns / 2));
|
|
41394
|
+
historyTurns = forcedTurns;
|
|
41395
|
+
maxToolLoopIterations = Math.min(
|
|
41396
|
+
maxToolLoopIterations,
|
|
41397
|
+
phase2 === "plan" ? 24 : 40
|
|
41398
|
+
);
|
|
41399
|
+
let r = await compactHistoryAsync(hist, {
|
|
41400
|
+
maxMessages: Math.max(2, forcedTurns * 4),
|
|
41401
|
+
force: true,
|
|
41402
|
+
signal: opts?.signal,
|
|
41403
|
+
...replayBase ? { requestSnapshot: replayBase, providerStream: opts?.providerStream } : {}
|
|
41404
|
+
});
|
|
41405
|
+
if (!r.compacted) {
|
|
41406
|
+
r = await compactHistoryAsync(hist, {
|
|
41407
|
+
maxMessages: 2,
|
|
41408
|
+
force: true,
|
|
41409
|
+
signal: opts?.signal,
|
|
41410
|
+
...replayBase ? { requestSnapshot: replayBase, providerStream: opts?.providerStream } : {}
|
|
41411
|
+
});
|
|
41412
|
+
}
|
|
41413
|
+
const label = r.cacheReuseExpected === false ? "llm-compact (model override)" : "auto-compact";
|
|
41414
|
+
fold(r, label, forcedTurns);
|
|
41415
|
+
}
|
|
41416
|
+
if (occupancy >= compact3.hardAt) {
|
|
41417
|
+
const hard = await compactHistoryAsync(hist, {
|
|
41418
|
+
maxMessages: 2,
|
|
41419
|
+
force: true,
|
|
41420
|
+
signal: opts?.signal
|
|
41421
|
+
});
|
|
41422
|
+
fold(hard, hard.summary.includes("\xB7 llm") ? "llm-compact" : "HARD trim", 2);
|
|
41423
|
+
historyTurns = 2;
|
|
41424
|
+
maxToolLoopIterations = Math.min(maxToolLoopIterations, 16);
|
|
41425
|
+
warnings.push(
|
|
41426
|
+
"[budget] HARD context pressure (\u226595%) \u2014 prefer /clear or a new session if quality drops."
|
|
41427
|
+
);
|
|
41428
|
+
}
|
|
41429
|
+
const cacheMetricsLine = envelope ? [
|
|
41430
|
+
"compaction meter:",
|
|
41431
|
+
`provider/model: ${envelope.snapshot.provider}/${envelope.snapshot.model}`,
|
|
41432
|
+
`headerFingerprint: ${envelope.snapshot.headerFingerprint.slice(0, 12)}`,
|
|
41433
|
+
`occupancy: ${Math.round(occupancy * 100)}% (${estimated}/${contextLimit})`,
|
|
41434
|
+
...envelope.usage?.cachedPromptTokens !== void 0 ? [`cachedPromptTokens: ${envelope.usage.cachedPromptTokens}`] : [],
|
|
41435
|
+
...cacheReuseExpected !== void 0 ? [`cacheReuseExpected: ${cacheReuseExpected}`] : []
|
|
41436
|
+
].join(" | ") : void 0;
|
|
41437
|
+
return {
|
|
41438
|
+
history: hist,
|
|
41439
|
+
warnings,
|
|
41440
|
+
maxToolLoopIterations,
|
|
41441
|
+
historyTurns,
|
|
41442
|
+
estimatedHistoryTokens: surface ? convTokensOf(hist) : estimated,
|
|
41443
|
+
contextLimit,
|
|
41444
|
+
occupancy,
|
|
41445
|
+
compactSummary: compactSummary || void 0,
|
|
41446
|
+
messagesRemoved: messagesRemoved || void 0,
|
|
41447
|
+
...compactRange.fromSeq !== void 0 && compactRange.toSeq !== void 0 ? {
|
|
41448
|
+
compactedFromSeq: compactRange.fromSeq,
|
|
41449
|
+
compactedToSeq: compactRange.toSeq,
|
|
41450
|
+
compactSourceSeqs: compactRange.sourceSeqs,
|
|
41451
|
+
compactStrategy: compactRange.strategy
|
|
41452
|
+
} : {},
|
|
41453
|
+
...surface ? { contextPressureTokens: estimated } : {},
|
|
41454
|
+
...cacheReuseExpected !== void 0 ? { cacheReuseExpected } : {},
|
|
41455
|
+
...cacheMetricsLine ? { cacheMetricsLine } : {}
|
|
41456
|
+
};
|
|
41457
|
+
}
|
|
41458
|
+
function estimateSystemTokensLite(systemMessages) {
|
|
41459
|
+
let n = 0;
|
|
41460
|
+
for (const m of systemMessages) n += 4 + Math.ceil((m.content ?? "").length / 4);
|
|
41461
|
+
return n;
|
|
41462
|
+
}
|
|
41463
|
+
function estimateToolSchemaTokensLite(tools) {
|
|
41464
|
+
let n = 0;
|
|
41465
|
+
for (const t of tools) {
|
|
41466
|
+
n += Math.ceil((t.name ?? "").length / 4);
|
|
41467
|
+
n += Math.ceil((t.description ?? "").length / 4);
|
|
41468
|
+
n += Math.ceil(JSON.stringify(t.parameters ?? {}).length / 4);
|
|
41469
|
+
}
|
|
41470
|
+
return n + tools.length * 4;
|
|
41471
|
+
}
|
|
41472
|
+
function estimateConversationTokensLite(messages) {
|
|
41473
|
+
let n = 0;
|
|
41474
|
+
for (const m of messages) {
|
|
41475
|
+
n += 4 + Math.ceil((m.content ?? "").length / 4);
|
|
41476
|
+
if (m.toolCalls) {
|
|
41477
|
+
for (const tc of m.toolCalls) {
|
|
41478
|
+
n += Math.ceil(tc.name.length / 4) + Math.ceil(tc.id.length / 4);
|
|
41479
|
+
n += Math.ceil(JSON.stringify(tc.args ?? {}).length / 4);
|
|
41480
|
+
}
|
|
41481
|
+
}
|
|
41482
|
+
if (m.reasoningContent) n += Math.ceil(m.reasoningContent.length / 4);
|
|
41483
|
+
if (m.toolCallId) n += Math.ceil(m.toolCallId.length / 4);
|
|
41484
|
+
}
|
|
41485
|
+
return n;
|
|
41486
|
+
}
|
|
41487
|
+
var RESERVED_OUTPUT_TOKENS;
|
|
41488
|
+
var init_tokenBudget = __esm({
|
|
41489
|
+
"src/cli/budget/tokenBudget.ts"() {
|
|
41490
|
+
"use strict";
|
|
41491
|
+
init_envNumber();
|
|
41492
|
+
init_historyCompaction();
|
|
41493
|
+
init_observationStore();
|
|
41494
|
+
init_capabilities();
|
|
41495
|
+
RESERVED_OUTPUT_TOKENS = 8192;
|
|
41496
|
+
}
|
|
41497
|
+
});
|
|
41498
|
+
|
|
41499
|
+
// src/cli/budget/retrievalPolicy.ts
|
|
41500
|
+
var retrievalPolicy_exports = {};
|
|
41501
|
+
__export(retrievalPolicy_exports, {
|
|
41502
|
+
BASELINE_RETRIEVAL_POLICY: () => BASELINE_RETRIEVAL_POLICY,
|
|
41503
|
+
RETRIEVAL_PRESSURE_THRESHOLDS: () => RETRIEVAL_PRESSURE_THRESHOLDS,
|
|
41504
|
+
estimateHistoryOccupancy: () => estimateHistoryOccupancy,
|
|
41505
|
+
filterSkillCatalogByBand: () => filterSkillCatalogByBand,
|
|
41506
|
+
resolveRetrievalPolicy: () => resolveRetrievalPolicy,
|
|
41507
|
+
retrievalBand: () => retrievalBand
|
|
41508
|
+
});
|
|
41509
|
+
function retrievalBand(occupancy) {
|
|
41510
|
+
const occ = Number.isFinite(occupancy) ? Math.max(0, Math.min(1, occupancy)) : 0;
|
|
41511
|
+
if (occ >= RETRIEVAL_PRESSURE_THRESHOLDS.high) return "high";
|
|
41512
|
+
if (occ >= RETRIEVAL_PRESSURE_THRESHOLDS.medium) return "medium";
|
|
41513
|
+
return "low";
|
|
41514
|
+
}
|
|
41515
|
+
function resolveRetrievalPolicy(occupancy) {
|
|
41516
|
+
const band = retrievalBand(occupancy);
|
|
41517
|
+
const packing = PRESSURE_PACKING[band];
|
|
41518
|
+
const weights = PRESSURE_WEIGHTS[band];
|
|
41519
|
+
return {
|
|
41520
|
+
band,
|
|
41521
|
+
...packing,
|
|
41522
|
+
...weights ? { weights } : {}
|
|
41523
|
+
};
|
|
41524
|
+
}
|
|
41525
|
+
function estimateHistoryOccupancy(history2, opts) {
|
|
41526
|
+
const limit = resolveContextLimit(opts?.model, opts?.provider);
|
|
41527
|
+
return Math.min(1, estimateHistoryTokens(history2) / limit);
|
|
41528
|
+
}
|
|
41529
|
+
function filterSkillCatalogByBand(skills, band) {
|
|
41530
|
+
if (band !== "high") return [...skills];
|
|
41531
|
+
return skills.filter((s) => s.estimatedCost !== "high");
|
|
41532
|
+
}
|
|
41533
|
+
var RETRIEVAL_PRESSURE_THRESHOLDS, BASELINE_RETRIEVAL_POLICY, PRESSURE_WEIGHTS, PRESSURE_PACKING;
|
|
41534
|
+
var init_retrievalPolicy = __esm({
|
|
41535
|
+
"src/cli/budget/retrievalPolicy.ts"() {
|
|
41536
|
+
"use strict";
|
|
41537
|
+
init_tokenBudget();
|
|
41538
|
+
RETRIEVAL_PRESSURE_THRESHOLDS = { medium: 0.5, high: 0.8 };
|
|
41539
|
+
BASELINE_RETRIEVAL_POLICY = {
|
|
41540
|
+
band: "low",
|
|
41541
|
+
maxChars: 2e3,
|
|
41542
|
+
maxMemories: 8
|
|
41543
|
+
};
|
|
41544
|
+
PRESSURE_WEIGHTS = {
|
|
41545
|
+
low: void 0,
|
|
41546
|
+
medium: {
|
|
41547
|
+
semanticRelevance: 0.35,
|
|
41548
|
+
lexicalRelevance: 0.2,
|
|
41549
|
+
importance: 0.15,
|
|
41550
|
+
confidence: 0.1,
|
|
41551
|
+
recency: 0.05,
|
|
41552
|
+
graphProximity: 0.1,
|
|
41553
|
+
verificationBonus: 0.05
|
|
41554
|
+
},
|
|
41555
|
+
high: {
|
|
41556
|
+
semanticRelevance: 0.4,
|
|
41557
|
+
lexicalRelevance: 0.25,
|
|
41558
|
+
importance: 0.15,
|
|
41559
|
+
confidence: 0.1,
|
|
41560
|
+
recency: 0,
|
|
41561
|
+
graphProximity: 0.05,
|
|
41562
|
+
verificationBonus: 0.05
|
|
41563
|
+
}
|
|
41564
|
+
};
|
|
41565
|
+
PRESSURE_PACKING = {
|
|
41566
|
+
low: { maxChars: 2e3, maxMemories: 8 },
|
|
41567
|
+
medium: { maxChars: 1200, maxMemories: 6 },
|
|
41568
|
+
high: { maxChars: 600, maxMemories: 4 }
|
|
41569
|
+
};
|
|
41570
|
+
}
|
|
41571
|
+
});
|
|
41572
|
+
|
|
40724
41573
|
// src/cli/tools/skillTool.ts
|
|
40725
|
-
function formatAvailableSkillsCatalog(cwd = process.cwd()) {
|
|
41574
|
+
function formatAvailableSkillsCatalog(cwd = process.cwd(), opts) {
|
|
40726
41575
|
try {
|
|
40727
41576
|
loadSkillMdSkills(cwd);
|
|
40728
41577
|
} catch {
|
|
40729
41578
|
}
|
|
40730
|
-
const
|
|
40731
|
-
|
|
41579
|
+
const band = opts?.pressureBand;
|
|
41580
|
+
const all = listCodingSkills();
|
|
41581
|
+
if (all.length === 0) {
|
|
40732
41582
|
return "No skills registered.";
|
|
40733
41583
|
}
|
|
40734
|
-
const
|
|
41584
|
+
const gated = band ? filterSkillCatalogByBand(all, band) : all;
|
|
41585
|
+
const hidden = all.length - gated.length;
|
|
41586
|
+
const lines = gated.slice(0, 80).map((s) => {
|
|
40735
41587
|
const desc = (s.description || s.id).replace(/\s+/g, " ").trim().slice(0, 160);
|
|
40736
41588
|
return `- ${s.id}: ${desc}`;
|
|
40737
41589
|
});
|
|
41590
|
+
if (hidden > 0) {
|
|
41591
|
+
lines.push(
|
|
41592
|
+
`(plus ${hidden} high-cost skill(s) hidden under context pressure \u2014 still loadable by name if truly needed)`
|
|
41593
|
+
);
|
|
41594
|
+
}
|
|
40738
41595
|
return lines.join("\n");
|
|
40739
41596
|
}
|
|
40740
41597
|
function createSkillTool(opts) {
|
|
40741
41598
|
const cwd = opts?.cwd ?? process.cwd();
|
|
40742
|
-
const catalog = formatAvailableSkillsCatalog(cwd
|
|
41599
|
+
const catalog = formatAvailableSkillsCatalog(cwd, {
|
|
41600
|
+
pressureBand: opts?.pressureBand
|
|
41601
|
+
});
|
|
40743
41602
|
return {
|
|
40744
41603
|
name: "skill",
|
|
40745
41604
|
description: "Load the full instructions for a named coding skill into this turn. Call when a skill matches the current task. Available skills:\n" + catalog,
|
|
@@ -40781,6 +41640,7 @@ var init_skillTool = __esm({
|
|
|
40781
41640
|
init_skills2();
|
|
40782
41641
|
init_toolTypes();
|
|
40783
41642
|
init_skillsMd();
|
|
41643
|
+
init_retrievalPolicy();
|
|
40784
41644
|
SkillArgsSchema = external_exports.object({
|
|
40785
41645
|
name: external_exports.string().min(1).describe("Skill id/name to load (from the available skills list).")
|
|
40786
41646
|
});
|
|
@@ -43862,124 +44722,6 @@ var init_semantic2 = __esm({
|
|
|
43862
44722
|
}
|
|
43863
44723
|
});
|
|
43864
44724
|
|
|
43865
|
-
// src/cli/provider/capabilities.ts
|
|
43866
|
-
function frozenProfile(input) {
|
|
43867
|
-
if (input.reasoning.levels) Object.freeze(input.reasoning.levels);
|
|
43868
|
-
Object.freeze(input.reasoning);
|
|
43869
|
-
Object.freeze(input.promptCache);
|
|
43870
|
-
Object.freeze(input.toolCalling);
|
|
43871
|
-
Object.freeze(input.buildRecovery);
|
|
43872
|
-
Object.freeze(input.sampling);
|
|
43873
|
-
Object.freeze(input.compaction);
|
|
43874
|
-
return Object.freeze(input);
|
|
43875
|
-
}
|
|
43876
|
-
function resolveHarnessProfile(model, providerId) {
|
|
43877
|
-
const provider = providerId?.trim().toLowerCase();
|
|
43878
|
-
if (provider === "deepseek") return "deepseek-v4";
|
|
43879
|
-
if (provider === "grok") return "grok";
|
|
43880
|
-
if (provider === "minimax") return "minimax";
|
|
43881
|
-
if (provider === "glm") return "glm";
|
|
43882
|
-
if (model && DEEPSEEK_RE.test(model)) return "deepseek-v4";
|
|
43883
|
-
if (model && GROK_RE.test(model)) return "grok";
|
|
43884
|
-
if (model && MINIMAX_RE.test(model)) return "minimax";
|
|
43885
|
-
if (model && GLM_RE.test(model)) return "glm";
|
|
43886
|
-
return "default";
|
|
43887
|
-
}
|
|
43888
|
-
function capabilitiesFor(model, providerId) {
|
|
43889
|
-
switch (resolveHarnessProfile(model, providerId)) {
|
|
43890
|
-
case "deepseek-v4":
|
|
43891
|
-
return DEEPSEEK_V4_CAPS;
|
|
43892
|
-
case "grok":
|
|
43893
|
-
return GROK_CAPS;
|
|
43894
|
-
case "minimax":
|
|
43895
|
-
return model && MINIMAX_M3_RE.test(model) ? MINIMAX_M3_CAPS : MINIMAX_M2_CAPS;
|
|
43896
|
-
case "glm":
|
|
43897
|
-
return GLM_CAPS;
|
|
43898
|
-
default:
|
|
43899
|
-
return DEFAULT_CAPS;
|
|
43900
|
-
}
|
|
43901
|
-
}
|
|
43902
|
-
var SHARED_COMPACTION, DEFAULT_CAPS, DEEPSEEK_V4_CAPS, GROK_CAPS, MINIMAX_M3_CAPS, MINIMAX_M2_CAPS, GLM_CAPS, DEEPSEEK_RE, GROK_RE, MINIMAX_RE, MINIMAX_M3_RE, GLM_RE;
|
|
43903
|
-
var init_capabilities = __esm({
|
|
43904
|
-
"src/cli/provider/capabilities.ts"() {
|
|
43905
|
-
"use strict";
|
|
43906
|
-
SHARED_COMPACTION = { warnAt: 0.7, compactAt: 0.85, hardAt: 0.95 };
|
|
43907
|
-
DEFAULT_CAPS = frozenProfile({
|
|
43908
|
-
contextWindow: 4e5,
|
|
43909
|
-
reasoning: { supported: true, levels: ["low", "medium", "high"], replayReasoning: true },
|
|
43910
|
-
promptCache: { supported: true, pricedCacheRead: false },
|
|
43911
|
-
toolCalling: { parallel: true },
|
|
43912
|
-
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
43913
|
-
sampling: { temperature: 0.7 },
|
|
43914
|
-
compaction: { ...SHARED_COMPACTION },
|
|
43915
|
-
profile: "default"
|
|
43916
|
-
});
|
|
43917
|
-
DEEPSEEK_V4_CAPS = frozenProfile({
|
|
43918
|
-
contextWindow: 1e6,
|
|
43919
|
-
reasoning: { supported: true, levels: ["high", "max"], replayReasoning: true },
|
|
43920
|
-
promptCache: { supported: true, pricedCacheRead: true },
|
|
43921
|
-
toolCalling: { parallel: true },
|
|
43922
|
-
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
43923
|
-
sampling: { temperature: 0.7 },
|
|
43924
|
-
compaction: { ...SHARED_COMPACTION },
|
|
43925
|
-
profile: "deepseek-v4"
|
|
43926
|
-
});
|
|
43927
|
-
GROK_CAPS = frozenProfile({
|
|
43928
|
-
contextWindow: 5e5,
|
|
43929
|
-
reasoning: {
|
|
43930
|
-
supported: true,
|
|
43931
|
-
levels: ["low", "medium", "high", "xhigh"],
|
|
43932
|
-
replayReasoning: false
|
|
43933
|
-
},
|
|
43934
|
-
promptCache: {
|
|
43935
|
-
supported: true,
|
|
43936
|
-
pricedCacheRead: true,
|
|
43937
|
-
conversationAffinityHeader: "x-grok-conv-id"
|
|
43938
|
-
},
|
|
43939
|
-
toolCalling: { parallel: true },
|
|
43940
|
-
buildRecovery: { forceToolChoice: true, maxForcedTurns: 1 },
|
|
43941
|
-
sampling: { temperature: 0.7 },
|
|
43942
|
-
compaction: { ...SHARED_COMPACTION },
|
|
43943
|
-
profile: "grok"
|
|
43944
|
-
});
|
|
43945
|
-
MINIMAX_M3_CAPS = frozenProfile({
|
|
43946
|
-
contextWindow: 1e6,
|
|
43947
|
-
reasoning: { supported: true, replayReasoning: true },
|
|
43948
|
-
promptCache: { supported: false, pricedCacheRead: false },
|
|
43949
|
-
toolCalling: { parallel: true },
|
|
43950
|
-
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
43951
|
-
sampling: { temperature: 0.7 },
|
|
43952
|
-
compaction: { ...SHARED_COMPACTION },
|
|
43953
|
-
profile: "minimax"
|
|
43954
|
-
});
|
|
43955
|
-
MINIMAX_M2_CAPS = frozenProfile({
|
|
43956
|
-
contextWindow: 204800,
|
|
43957
|
-
reasoning: { supported: true, replayReasoning: true },
|
|
43958
|
-
promptCache: { supported: false, pricedCacheRead: false },
|
|
43959
|
-
toolCalling: { parallel: true },
|
|
43960
|
-
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
43961
|
-
sampling: { temperature: 0.7 },
|
|
43962
|
-
compaction: { ...SHARED_COMPACTION },
|
|
43963
|
-
profile: "minimax"
|
|
43964
|
-
});
|
|
43965
|
-
GLM_CAPS = frozenProfile({
|
|
43966
|
-
contextWindow: 2e5,
|
|
43967
|
-
reasoning: { supported: true, replayReasoning: true },
|
|
43968
|
-
promptCache: { supported: true, pricedCacheRead: false },
|
|
43969
|
-
toolCalling: { parallel: true },
|
|
43970
|
-
buildRecovery: { forceToolChoice: false, maxForcedTurns: 0 },
|
|
43971
|
-
sampling: { temperature: 0.7 },
|
|
43972
|
-
compaction: { ...SHARED_COMPACTION },
|
|
43973
|
-
profile: "glm"
|
|
43974
|
-
});
|
|
43975
|
-
DEEPSEEK_RE = /^deepseek-(?:v4(?:\.|-|$)|chat$|reasoner$)/i;
|
|
43976
|
-
GROK_RE = /^grok(?:\.|-|$)/i;
|
|
43977
|
-
MINIMAX_RE = /^minimax(?:\.|-|$)/i;
|
|
43978
|
-
MINIMAX_M3_RE = /^minimax-m3(?:\.|-|$)/i;
|
|
43979
|
-
GLM_RE = /^glm(?:\.|-|$)/i;
|
|
43980
|
-
}
|
|
43981
|
-
});
|
|
43982
|
-
|
|
43983
44725
|
// src/cli/provider/openai-compatible.ts
|
|
43984
44726
|
var openai_compatible_exports = {};
|
|
43985
44727
|
__export(openai_compatible_exports, {
|
|
@@ -44163,6 +44905,12 @@ ${notes}
|
|
|
44163
44905
|
}
|
|
44164
44906
|
return { role: m.role, content: m.content };
|
|
44165
44907
|
}
|
|
44908
|
+
function positiveEnvInt(name) {
|
|
44909
|
+
const raw = process.env[name];
|
|
44910
|
+
if (!raw) return void 0;
|
|
44911
|
+
const n = Number.parseInt(raw, 10);
|
|
44912
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
44913
|
+
}
|
|
44166
44914
|
function openaiCompatibleProvider(config2) {
|
|
44167
44915
|
return async function* (params) {
|
|
44168
44916
|
const capabilities = capabilitiesFor(params.model, config2.providerId);
|
|
@@ -44195,6 +44943,8 @@ function openaiCompatibleProvider(config2) {
|
|
|
44195
44943
|
};
|
|
44196
44944
|
if (typeof generation?.maxTokens === "number" && generation.maxTokens > 0) {
|
|
44197
44945
|
body.max_tokens = generation.maxTokens;
|
|
44946
|
+
} else if (typeof capabilities.maxOutputTokens === "number" && capabilities.maxOutputTokens > 0) {
|
|
44947
|
+
body.max_tokens = positiveEnvInt("ZELARI_MAX_OUTPUT_TOKENS") ?? capabilities.maxOutputTokens;
|
|
44198
44948
|
}
|
|
44199
44949
|
const thinkingSpec = config2.thinking ?? "auto";
|
|
44200
44950
|
if (config2.providerId === "deepseek" && thinkingSpec === "auto") {
|
|
@@ -46386,8 +47136,8 @@ function defaultPermissionPolicy(overrides) {
|
|
|
46386
47136
|
return {
|
|
46387
47137
|
read: parseAction(process.env.ZELARI_PERMISSION_READ, "allow"),
|
|
46388
47138
|
write: parseAction(process.env.ZELARI_PERMISSION_WRITE, "allow"),
|
|
46389
|
-
execute: parseAction(process.env.ZELARI_PERMISSION_EXECUTE, "
|
|
46390
|
-
network: parseAction(process.env.ZELARI_PERMISSION_NETWORK, "
|
|
47139
|
+
execute: parseAction(process.env.ZELARI_PERMISSION_EXECUTE, "ask"),
|
|
47140
|
+
network: parseAction(process.env.ZELARI_PERMISSION_NETWORK, "ask"),
|
|
46391
47141
|
ui: "allow",
|
|
46392
47142
|
auto: isAutoPermissions(),
|
|
46393
47143
|
...overrides
|
|
@@ -47353,7 +48103,7 @@ function matchResourceClaimLayered(layers, precedence, claim, root) {
|
|
|
47353
48103
|
function resolveClaimsVerdict(layers, precedence, toolName, args, root) {
|
|
47354
48104
|
const claims = resourceClaimsFor(toolName, args);
|
|
47355
48105
|
const matchedRules = [];
|
|
47356
|
-
if (!layers || claims.length === 0) return { matchedRules };
|
|
48106
|
+
if (!layers || claims.length === 0) return { claims, matchedRules };
|
|
47357
48107
|
const effects = [];
|
|
47358
48108
|
for (const claim of claims) {
|
|
47359
48109
|
const hit = matchResourceClaimLayered(layers, precedence, claim, root);
|
|
@@ -47362,7 +48112,26 @@ function resolveClaimsVerdict(layers, precedence, toolName, args, root) {
|
|
|
47362
48112
|
matchedRules.push(hit);
|
|
47363
48113
|
}
|
|
47364
48114
|
}
|
|
47365
|
-
return effects.length > 0 ? { effect: intersectEffects(...effects), matchedRules } : { matchedRules };
|
|
48115
|
+
return effects.length > 0 ? { effect: intersectEffects(...effects), claims, matchedRules } : { claims, matchedRules };
|
|
48116
|
+
}
|
|
48117
|
+
function describeResourceClaim(claim) {
|
|
48118
|
+
const cap3 = (s) => s.length > 160 ? `${s.slice(0, 157)}\u2026` : s;
|
|
48119
|
+
switch (claim.kind) {
|
|
48120
|
+
case "path":
|
|
48121
|
+
return cap3(`path ${claim.operation}: ${claim.path}`);
|
|
48122
|
+
case "process":
|
|
48123
|
+
return cap3(`process: ${[claim.executable, ...claim.argv ?? []].join(" ")}`);
|
|
48124
|
+
case "network":
|
|
48125
|
+
return cap3(`network: ${claim.host}${claim.port !== void 0 ? `:${claim.port}` : ""}`);
|
|
48126
|
+
case "mcp":
|
|
48127
|
+
return cap3(`mcp: ${claim.server}/${claim.tool}`);
|
|
48128
|
+
case "ssh":
|
|
48129
|
+
return cap3(`ssh: ${claim.target}${claim.command ? ` (${claim.command})` : ""}`);
|
|
48130
|
+
case "ui":
|
|
48131
|
+
return cap3(`ui: ${claim.action}`);
|
|
48132
|
+
case "agent":
|
|
48133
|
+
return cap3(`agent: ${claim.role}`);
|
|
48134
|
+
}
|
|
47366
48135
|
}
|
|
47367
48136
|
var MAX_RAW_SHELL_STRIP_DEPTH, RAW_SHELL_WRAPPERS, RAW_SHELL_INTERPRETERS;
|
|
47368
48137
|
var init_resourceClaims = __esm({
|
|
@@ -47819,7 +48588,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
47819
48588
|
registry4.register(withPerm(askUserTool));
|
|
47820
48589
|
}
|
|
47821
48590
|
const enableSkill = options.enableSkill !== false && options.readOnly !== true && !gauntletParent && profile !== "explore" && profile !== "verify";
|
|
47822
|
-
const skillTool = enableSkill ? withPerm(createSkillTool({ cwd: root })) : null;
|
|
48591
|
+
const skillTool = enableSkill ? withPerm(createSkillTool({ cwd: root, pressureBand: options.pressureBand })) : null;
|
|
47823
48592
|
if (skillTool) {
|
|
47824
48593
|
registry4.register(skillTool);
|
|
47825
48594
|
}
|
|
@@ -48113,11 +48882,17 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
48113
48882
|
);
|
|
48114
48883
|
}
|
|
48115
48884
|
try {
|
|
48885
|
+
const expanded = claims?.claims ?? resourceClaimsFor(original.name, input ?? {});
|
|
48116
48886
|
const ok = await onAsk({
|
|
48117
48887
|
toolName: original.name,
|
|
48118
48888
|
reason: decision.reason,
|
|
48119
48889
|
categories: decision.categories,
|
|
48120
|
-
args: input
|
|
48890
|
+
args: input,
|
|
48891
|
+
policyNote: rulePrefix || void 0,
|
|
48892
|
+
claims: expanded.slice(0, 6).map((c) => ({
|
|
48893
|
+
kind: c.kind,
|
|
48894
|
+
summary: describeResourceClaim(c)
|
|
48895
|
+
}))
|
|
48121
48896
|
});
|
|
48122
48897
|
if (!ok) {
|
|
48123
48898
|
return typedErr(
|
|
@@ -50136,15 +50911,39 @@ function spineMemoryEventNote(handle, event) {
|
|
|
50136
50911
|
} catch {
|
|
50137
50912
|
}
|
|
50138
50913
|
}
|
|
50914
|
+
function bufferOf(holder) {
|
|
50915
|
+
let buf = buffers.get(holder);
|
|
50916
|
+
if (!buf) {
|
|
50917
|
+
buf = [];
|
|
50918
|
+
buffers.set(holder, buf);
|
|
50919
|
+
}
|
|
50920
|
+
return buf;
|
|
50921
|
+
}
|
|
50139
50922
|
function memorySinkFor(holder) {
|
|
50140
50923
|
return (event) => {
|
|
50141
50924
|
const handle = holder.current;
|
|
50142
|
-
if (handle)
|
|
50925
|
+
if (handle) {
|
|
50926
|
+
spineMemoryEventNote(handle, event);
|
|
50927
|
+
return;
|
|
50928
|
+
}
|
|
50929
|
+
const buf = bufferOf(holder);
|
|
50930
|
+
if (buf.length < PRE_BIND_BUFFER_CAP) buf.push(event);
|
|
50931
|
+
else holder.droppedEvents = (holder.droppedEvents ?? 0) + 1;
|
|
50143
50932
|
};
|
|
50144
50933
|
}
|
|
50934
|
+
function flushMemorySpineNotes(holder) {
|
|
50935
|
+
const handle = holder.current;
|
|
50936
|
+
const buf = buffers.get(holder);
|
|
50937
|
+
if (!handle || !buf?.length) return;
|
|
50938
|
+
const pending = buf.splice(0, buf.length);
|
|
50939
|
+
for (const event of pending) spineMemoryEventNote(handle, event);
|
|
50940
|
+
}
|
|
50941
|
+
var PRE_BIND_BUFFER_CAP, buffers;
|
|
50145
50942
|
var init_spineTelemetry = __esm({
|
|
50146
50943
|
"src/cli/memory/spineTelemetry.ts"() {
|
|
50147
50944
|
"use strict";
|
|
50945
|
+
PRE_BIND_BUFFER_CAP = 32;
|
|
50946
|
+
buffers = /* @__PURE__ */ new WeakMap();
|
|
50148
50947
|
}
|
|
50149
50948
|
});
|
|
50150
50949
|
|
|
@@ -50356,567 +51155,123 @@ var init_fileStateStore = __esm({
|
|
|
50356
51155
|
mode: input.mode,
|
|
50357
51156
|
label: input.label,
|
|
50358
51157
|
verification: input.verification,
|
|
50359
|
-
changedPaths: input.changedPaths ?? [],
|
|
50360
|
-
discoveryCount: input.discoveries?.length ?? 0
|
|
50361
|
-
};
|
|
50362
|
-
}
|
|
50363
|
-
async head() {
|
|
50364
|
-
return null;
|
|
50365
|
-
}
|
|
50366
|
-
async get() {
|
|
50367
|
-
return null;
|
|
50368
|
-
}
|
|
50369
|
-
async list() {
|
|
50370
|
-
return [];
|
|
50371
|
-
}
|
|
50372
|
-
async setHead(id3) {
|
|
50373
|
-
throw new Error(`NoopDurableStateStore.setHead: state disabled (id=${id3})`);
|
|
50374
|
-
}
|
|
50375
|
-
async loadDiscoveries() {
|
|
50376
|
-
return [];
|
|
50377
|
-
}
|
|
50378
|
-
async materializeContext() {
|
|
50379
|
-
return "";
|
|
50380
|
-
}
|
|
50381
|
-
async close() {
|
|
50382
|
-
}
|
|
50383
|
-
};
|
|
50384
|
-
}
|
|
50385
|
-
});
|
|
50386
|
-
|
|
50387
|
-
// src/cli/hooks/messageHelpers.ts
|
|
50388
|
-
function appendSystem(setMessages, content, ts = Date.now()) {
|
|
50389
|
-
setMessages((prev2) => [
|
|
50390
|
-
...prev2,
|
|
50391
|
-
{ id: crypto.randomUUID(), role: "system", content, ts }
|
|
50392
|
-
]);
|
|
50393
|
-
}
|
|
50394
|
-
function appendUser(setMessages, content, ts = Date.now()) {
|
|
50395
|
-
setMessages((prev2) => [
|
|
50396
|
-
...prev2,
|
|
50397
|
-
{ id: crypto.randomUUID(), role: "user", content, ts }
|
|
50398
|
-
]);
|
|
50399
|
-
}
|
|
50400
|
-
function appendOrExtendStreamingAssistant(setMessages, fullContent, ts, memberContext) {
|
|
50401
|
-
setMessages((prev2) => {
|
|
50402
|
-
const last = prev2[prev2.length - 1];
|
|
50403
|
-
if (last && last.role === "assistant" && last.id.startsWith("streaming-")) {
|
|
50404
|
-
return [...prev2.slice(0, -1), { ...last, content: fullContent }];
|
|
50405
|
-
}
|
|
50406
|
-
return [
|
|
50407
|
-
...prev2,
|
|
50408
|
-
{
|
|
50409
|
-
id: `streaming-${crypto.randomUUID()}`,
|
|
50410
|
-
role: "assistant",
|
|
50411
|
-
content: fullContent,
|
|
50412
|
-
ts,
|
|
50413
|
-
...memberContext?.memberId ? { memberId: memberContext.memberId } : {},
|
|
50414
|
-
...memberContext?.memberName ? { memberName: memberContext.memberName } : {}
|
|
50415
|
-
}
|
|
50416
|
-
];
|
|
50417
|
-
});
|
|
50418
|
-
}
|
|
50419
|
-
function appendToolStart(setMessages, toolName, toolCallId, args, ts) {
|
|
50420
|
-
const argsPreview = formatToolSummary(toolName, args);
|
|
50421
|
-
setMessages((prev2) => [
|
|
50422
|
-
...prev2,
|
|
50423
|
-
{
|
|
50424
|
-
id: crypto.randomUUID(),
|
|
50425
|
-
role: "tool",
|
|
50426
|
-
content: argsPreview,
|
|
50427
|
-
ts,
|
|
50428
|
-
toolName,
|
|
50429
|
-
toolCallId,
|
|
50430
|
-
toolOk: void 0,
|
|
50431
|
-
toolDurationMs: void 0
|
|
50432
|
-
}
|
|
50433
|
-
]);
|
|
50434
|
-
}
|
|
50435
|
-
function updateToolMessageEnd(setMessages, toolCallId, isError, durationMs, result) {
|
|
50436
|
-
setMessages((prev2) => {
|
|
50437
|
-
for (let i = prev2.length - 1; i >= 0; i--) {
|
|
50438
|
-
const m = prev2[i];
|
|
50439
|
-
if (m && m.role === "tool" && m.toolCallId === toolCallId && m.toolDurationMs === void 0) {
|
|
50440
|
-
const updated = [...prev2];
|
|
50441
|
-
updated[i] = {
|
|
50442
|
-
...m,
|
|
50443
|
-
toolOk: !isError,
|
|
50444
|
-
toolDurationMs: durationMs,
|
|
50445
|
-
...result !== void 0 ? {
|
|
50446
|
-
toolResult: toolResultForStorage(
|
|
50447
|
-
m.toolName ?? "",
|
|
50448
|
-
result,
|
|
50449
|
-
isError
|
|
50450
|
-
)
|
|
50451
|
-
} : {}
|
|
50452
|
-
};
|
|
50453
|
-
return updated;
|
|
50454
|
-
}
|
|
50455
|
-
}
|
|
50456
|
-
return prev2;
|
|
50457
|
-
});
|
|
50458
|
-
}
|
|
50459
|
-
function finalizeStreamingAssistant(setMessages) {
|
|
50460
|
-
setMessages((prev2) => {
|
|
50461
|
-
const last = prev2[prev2.length - 1];
|
|
50462
|
-
if (last && last.role === "assistant" && last.id.startsWith("streaming-")) {
|
|
50463
|
-
return [
|
|
50464
|
-
...prev2.slice(0, -1),
|
|
50465
|
-
{ ...last, id: last.id.slice("streaming-".length) }
|
|
50466
|
-
];
|
|
50467
|
-
}
|
|
50468
|
-
return prev2;
|
|
50469
|
-
});
|
|
50470
|
-
}
|
|
50471
|
-
var init_messageHelpers = __esm({
|
|
50472
|
-
"src/cli/hooks/messageHelpers.ts"() {
|
|
50473
|
-
"use strict";
|
|
50474
|
-
init_toolFormat();
|
|
50475
|
-
init_toolFormat();
|
|
50476
|
-
}
|
|
50477
|
-
});
|
|
50478
|
-
|
|
50479
|
-
// src/cli/budget/historySummary.ts
|
|
50480
|
-
function extractiveHistorySummary(dropped, opts) {
|
|
50481
|
-
const maxChars = opts?.maxChars ?? MAX_SUMMARY_CHARS;
|
|
50482
|
-
if (dropped.length === 0) return "No prior turns.";
|
|
50483
|
-
const userGoals = [];
|
|
50484
|
-
const assistantNotes = [];
|
|
50485
|
-
const userConstraints = [];
|
|
50486
|
-
const unresolved = [];
|
|
50487
|
-
const verification = [];
|
|
50488
|
-
const decisions = [];
|
|
50489
|
-
const tools = /* @__PURE__ */ new Map();
|
|
50490
|
-
const files = /* @__PURE__ */ new Set();
|
|
50491
|
-
let toolResults = 0;
|
|
50492
|
-
for (const m of dropped) {
|
|
50493
|
-
if (m.role === "user" && m.content.trim()) {
|
|
50494
|
-
const goal = oneLine(m.content, 220);
|
|
50495
|
-
userGoals.push(goal);
|
|
50496
|
-
if (/\b(must|never|required|only|do not|constraint|vincolo|deve|senza)\b/i.test(goal)) userConstraints.push(goal);
|
|
50497
|
-
} else if (m.role === "assistant") {
|
|
50498
|
-
if (m.content.trim()) {
|
|
50499
|
-
const note = oneLine(m.content, 220);
|
|
50500
|
-
assistantNotes.push(note);
|
|
50501
|
-
if (/\b(fail|failed|error|unresolved|remaining|todo|blocked|gap|errore|fallit|irrisolt|manca)\b/i.test(note)) unresolved.push(note);
|
|
50502
|
-
if (/\b(test|typecheck|build|verify|verification|passed|failed|green|red)\b/i.test(note)) verification.push(note);
|
|
50503
|
-
if (/\b(decid|decision|chosen|choose|scelt|adopt|implement)\b/i.test(note)) decisions.push(note);
|
|
50504
|
-
}
|
|
50505
|
-
if (m.toolCalls) {
|
|
50506
|
-
for (const tc of m.toolCalls) {
|
|
50507
|
-
tools.set(tc.name, (tools.get(tc.name) ?? 0) + 1);
|
|
50508
|
-
collectPaths3(tc.args, files);
|
|
50509
|
-
}
|
|
50510
|
-
}
|
|
50511
|
-
} else if (m.role === "tool") {
|
|
50512
|
-
toolResults += 1;
|
|
50513
|
-
collectPathsFromText(m.content, files);
|
|
50514
|
-
if (/\b(fail|failed|error|exception|blocked|errore|fallit)\b/i.test(m.content)) unresolved.push(oneLine(m.content, 220));
|
|
50515
|
-
if (/\b(test|typecheck|build|verify|passed|failed|success)\b/i.test(m.content)) verification.push(oneLine(m.content, 220));
|
|
50516
|
-
}
|
|
50517
|
-
}
|
|
50518
|
-
const parts = [
|
|
50519
|
-
"[history-summary] Earlier turns were compacted to stay within the context budget.",
|
|
50520
|
-
`Dropped ${dropped.length} message(s) (${userGoals.length} user, ${assistantNotes.length} assistant notes, ${toolResults} tool results).`
|
|
50521
|
-
];
|
|
50522
|
-
if (userGoals.length) {
|
|
50523
|
-
parts.push("## User goals / requests");
|
|
50524
|
-
for (const g of userGoals.slice(-6)) parts.push(`- ${g}`);
|
|
50525
|
-
}
|
|
50526
|
-
if (userConstraints.length) {
|
|
50527
|
-
parts.push("## User constraints (preserve exactly)");
|
|
50528
|
-
for (const item of [...new Set(userConstraints)].slice(-8)) parts.push(`- ${item}`);
|
|
50529
|
-
}
|
|
50530
|
-
if (unresolved.length) {
|
|
50531
|
-
parts.push("## Unresolved failures / pending repair");
|
|
50532
|
-
for (const item of [...new Set(unresolved)].slice(-8)) parts.push(`- ${item}`);
|
|
50533
|
-
}
|
|
50534
|
-
if (verification.length) {
|
|
50535
|
-
parts.push("## Latest verification state");
|
|
50536
|
-
for (const item of [...new Set(verification)].slice(-6)) parts.push(`- ${item}`);
|
|
50537
|
-
}
|
|
50538
|
-
if (decisions.length) {
|
|
50539
|
-
parts.push("## Recent active decisions");
|
|
50540
|
-
for (const item of [...new Set(decisions)].slice(-6)) parts.push(`- ${item}`);
|
|
50541
|
-
}
|
|
50542
|
-
if (assistantNotes.length) {
|
|
50543
|
-
parts.push("## Assistant conclusions (truncated)");
|
|
50544
|
-
for (const a of assistantNotes.slice(-5)) parts.push(`- ${a}`);
|
|
50545
|
-
}
|
|
50546
|
-
if (tools.size) {
|
|
50547
|
-
const ranked = [...tools.entries()].sort((a, b) => b[1] - a[1]).slice(0, 12).map(([n, c]) => `${n}\xD7${c}`);
|
|
50548
|
-
parts.push(`## Tools used: ${ranked.join(", ")}`);
|
|
50549
|
-
}
|
|
50550
|
-
if (files.size) {
|
|
50551
|
-
const list = [...files].slice(0, 24);
|
|
50552
|
-
parts.push(`## Paths mentioned: ${list.join(", ")}`);
|
|
50553
|
-
}
|
|
50554
|
-
parts.push(
|
|
50555
|
-
"Continue from the recent messages below; do not re-ask goals already answered above unless the user changes them."
|
|
50556
|
-
);
|
|
50557
|
-
let out = parts.join("\n");
|
|
50558
|
-
if (out.length > maxChars) {
|
|
50559
|
-
out = `${out.slice(0, maxChars - 1)}\u2026`;
|
|
50560
|
-
}
|
|
50561
|
-
return out;
|
|
50562
|
-
}
|
|
50563
|
-
function oneLine(s, max) {
|
|
50564
|
-
const t = s.replace(/\s+/g, " ").trim();
|
|
50565
|
-
if (t.length <= max) return t;
|
|
50566
|
-
return `${t.slice(0, max - 1)}\u2026`;
|
|
50567
|
-
}
|
|
50568
|
-
function collectPaths3(args, out) {
|
|
50569
|
-
if (!args || typeof args !== "object") return;
|
|
50570
|
-
const obj = args;
|
|
50571
|
-
for (const key of ["path", "file", "filepath", "filePath", "target", "cwd"]) {
|
|
50572
|
-
const v = obj[key];
|
|
50573
|
-
if (typeof v === "string" && v.length > 1 && v.length < 260) {
|
|
50574
|
-
out.add(v.replace(/\\/g, "/"));
|
|
50575
|
-
}
|
|
50576
|
-
}
|
|
50577
|
-
if (typeof obj.file_path === "string") out.add(String(obj.file_path));
|
|
50578
|
-
}
|
|
50579
|
-
function collectPathsFromText(text, out) {
|
|
50580
|
-
const re = /(?:^|[\s"'`])((?:[\w.-]+\/)+[\w.-]+\.\w{1,8})/g;
|
|
50581
|
-
let m;
|
|
50582
|
-
let n = 0;
|
|
50583
|
-
while ((m = re.exec(text)) !== null && n < 8) {
|
|
50584
|
-
out.add(m[1]);
|
|
50585
|
-
n += 1;
|
|
50586
|
-
}
|
|
50587
|
-
}
|
|
50588
|
-
var MAX_SUMMARY_CHARS;
|
|
50589
|
-
var init_historySummary = __esm({
|
|
50590
|
-
"src/cli/budget/historySummary.ts"() {
|
|
50591
|
-
"use strict";
|
|
50592
|
-
MAX_SUMMARY_CHARS = 3500;
|
|
50593
|
-
}
|
|
50594
|
-
});
|
|
50595
|
-
|
|
50596
|
-
// src/cli/budget/llmCompact.ts
|
|
50597
|
-
function isLlmCompactEnabled() {
|
|
50598
|
-
const v = process.env.ZELARI_LLM_COMPACT?.trim().toLowerCase();
|
|
50599
|
-
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
50600
|
-
return true;
|
|
50601
|
-
}
|
|
50602
|
-
function compactModelOverride() {
|
|
50603
|
-
const v = process.env.ZELARI_COMPACT_MODEL?.trim();
|
|
50604
|
-
return v ? v : void 0;
|
|
50605
|
-
}
|
|
50606
|
-
async function llmSummarizeHistoryReplay(input) {
|
|
50607
|
-
const override = input.overrideModel ?? compactModelOverride();
|
|
50608
|
-
const model = override ?? input.model;
|
|
50609
|
-
const cacheReuseExpected = !override;
|
|
50610
|
-
if (!isLlmCompactEnabled()) return { summary: null, model, cacheReuseExpected };
|
|
50611
|
-
if (input.droppedMessages.length === 0) {
|
|
50612
|
-
return { summary: null, model, cacheReuseExpected };
|
|
50613
|
-
}
|
|
50614
|
-
const messages = [
|
|
50615
|
-
...input.systemMessages,
|
|
50616
|
-
...input.droppedMessages,
|
|
50617
|
-
{
|
|
50618
|
-
role: "user",
|
|
50619
|
-
content: COMPACTION_INSTRUCTION
|
|
50620
|
-
}
|
|
50621
|
-
];
|
|
50622
|
-
const controller = new AbortController();
|
|
50623
|
-
const timeout = setTimeout(() => controller.abort(), REPLAY_TIMEOUT_MS);
|
|
50624
|
-
const onOuterAbort = () => controller.abort();
|
|
50625
|
-
input.signal?.addEventListener("abort", onOuterAbort, { once: true });
|
|
50626
|
-
try {
|
|
50627
|
-
let text = "";
|
|
50628
|
-
let emittedToolCall = false;
|
|
50629
|
-
for await (const delta of input.providerStream({
|
|
50630
|
-
provider: input.provider,
|
|
50631
|
-
model,
|
|
50632
|
-
messages,
|
|
50633
|
-
// Tools stay advertised: dropping them would change the prefix token
|
|
50634
|
-
// sequence and destroy cache reuse (explicit DSH decision). They are
|
|
50635
|
-
// sorted canonically (same discipline as the live routed request and
|
|
50636
|
-
// the snapshot fingerprints) so the replay prefix is byte-identical.
|
|
50637
|
-
tools: [...input.tools].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0),
|
|
50638
|
-
signal: controller.signal,
|
|
50639
|
-
generation: {
|
|
50640
|
-
purpose: "compaction",
|
|
50641
|
-
temperature: 0.1,
|
|
50642
|
-
maxTokens: 900
|
|
50643
|
-
}
|
|
50644
|
-
})) {
|
|
50645
|
-
if (delta.kind === "text") text += delta.delta;
|
|
50646
|
-
if (delta.kind === "tool_call") emittedToolCall = true;
|
|
50647
|
-
}
|
|
50648
|
-
if (emittedToolCall) return { summary: null, model, cacheReuseExpected };
|
|
50649
|
-
if (!text.trim()) return { summary: null, model, cacheReuseExpected };
|
|
50650
|
-
return { summary: text.trim(), model, cacheReuseExpected };
|
|
50651
|
-
} catch {
|
|
50652
|
-
return { summary: null, model, cacheReuseExpected };
|
|
50653
|
-
} finally {
|
|
50654
|
-
clearTimeout(timeout);
|
|
50655
|
-
input.signal?.removeEventListener("abort", onOuterAbort);
|
|
50656
|
-
}
|
|
50657
|
-
}
|
|
50658
|
-
var COMPACTION_INSTRUCTION, REPLAY_TIMEOUT_MS;
|
|
50659
|
-
var init_llmCompact = __esm({
|
|
50660
|
-
"src/cli/budget/llmCompact.ts"() {
|
|
50661
|
-
"use strict";
|
|
50662
|
-
COMPACTION_INSTRUCTION = `
|
|
50663
|
-
You are now acting as a compaction engine for this coding-agent session.
|
|
50664
|
-
|
|
50665
|
-
Condense the conversation ABOVE into a compact checkpoint sufficient to continue the task.
|
|
50666
|
-
|
|
50667
|
-
Preserve:
|
|
50668
|
-
- user's goal and evolving intent
|
|
50669
|
-
- decisions already made
|
|
50670
|
-
- exact file paths and identifiers
|
|
50671
|
-
- code changes already completed
|
|
50672
|
-
- commands/errors that still matter
|
|
50673
|
-
- constraints
|
|
50674
|
-
- unfinished work
|
|
50675
|
-
- the single most likely next action
|
|
50676
|
-
|
|
50677
|
-
Do not call tools.
|
|
50678
|
-
Do not mention this summarization request.
|
|
50679
|
-
Output only the checkpoint.
|
|
50680
|
-
Be concise.
|
|
50681
|
-
`.trim();
|
|
50682
|
-
REPLAY_TIMEOUT_MS = 6e4;
|
|
50683
|
-
}
|
|
50684
|
-
});
|
|
50685
|
-
|
|
50686
|
-
// src/cli/hooks/historyCompaction.ts
|
|
50687
|
-
function compactedRangeFromDropped(dropped) {
|
|
50688
|
-
if (dropped.length === 0) return void 0;
|
|
50689
|
-
const seqs = [];
|
|
50690
|
-
const sources = [];
|
|
50691
|
-
for (const m of dropped) {
|
|
50692
|
-
const hasCompactRange = typeof m.compactedFromSeq === "number" && Number.isInteger(m.compactedFromSeq) && m.compactedFromSeq > 0 && typeof m.compactedToSeq === "number" && Number.isInteger(m.compactedToSeq) && m.compactedToSeq >= m.compactedFromSeq;
|
|
50693
|
-
if (hasCompactRange) {
|
|
50694
|
-
seqs.push(m.compactedFromSeq, m.compactedToSeq);
|
|
50695
|
-
sources.push(...m.sourceEventSeqs ?? []);
|
|
50696
|
-
if (typeof m.seq === "number" && Number.isInteger(m.seq) && m.seq > 0) {
|
|
50697
|
-
seqs.push(m.seq);
|
|
50698
|
-
sources.push(m.seq);
|
|
50699
|
-
}
|
|
50700
|
-
continue;
|
|
50701
|
-
}
|
|
50702
|
-
if (typeof m.seq !== "number" || !Number.isInteger(m.seq) || m.seq < 1) return void 0;
|
|
50703
|
-
seqs.push(m.seq);
|
|
50704
|
-
sources.push(m.seq);
|
|
50705
|
-
}
|
|
50706
|
-
return {
|
|
50707
|
-
fromSeq: Math.min(...seqs),
|
|
50708
|
-
toSeq: Math.max(...seqs),
|
|
50709
|
-
sourceEventSeqs: [...new Set(sources)]
|
|
50710
|
-
};
|
|
50711
|
-
}
|
|
50712
|
-
function withDroppedRange(result, dropped, strategy) {
|
|
50713
|
-
const range = compactedRangeFromDropped(dropped);
|
|
50714
|
-
if (!range) return { ...result, strategy };
|
|
50715
|
-
return { ...result, ...range, strategy };
|
|
50716
|
-
}
|
|
50717
|
-
function resolveMaxMessages(opts) {
|
|
50718
|
-
const envTurns = envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 });
|
|
50719
|
-
let turns = opts?.maxMessages ? Math.ceil(opts.maxMessages / 4) : envTurns;
|
|
50720
|
-
if (opts?.durableStatePresent && !opts?.maxMessages && process.env.ZELARI_HISTORY_TURNS === void 0) {
|
|
50721
|
-
turns = Math.min(turns, 3);
|
|
50722
|
-
}
|
|
50723
|
-
if (turns <= 0) return 0;
|
|
50724
|
-
if (opts?.force && opts?.maxMessages) return Math.max(1, opts.maxMessages);
|
|
50725
|
-
return turns * 4;
|
|
50726
|
-
}
|
|
50727
|
-
function findValidCutIndex(messages, naiveCut) {
|
|
50728
|
-
let cut = naiveCut;
|
|
50729
|
-
while (cut < messages.length) {
|
|
50730
|
-
const kept = messages.slice(cut);
|
|
50731
|
-
const declared = /* @__PURE__ */ new Set();
|
|
50732
|
-
for (const m of kept) {
|
|
50733
|
-
if (m.role === "assistant" && m.toolCalls) {
|
|
50734
|
-
for (const tc of m.toolCalls) declared.add(tc.id);
|
|
51158
|
+
changedPaths: input.changedPaths ?? [],
|
|
51159
|
+
discoveryCount: input.discoveries?.length ?? 0
|
|
51160
|
+
};
|
|
50735
51161
|
}
|
|
50736
|
-
|
|
50737
|
-
|
|
50738
|
-
for (let k = 0; k < kept.length; k++) {
|
|
50739
|
-
const m = kept[k];
|
|
50740
|
-
if (m.role === "tool" && m.toolCallId && !declared.has(m.toolCallId)) {
|
|
50741
|
-
for (let j = cut - 1; j >= 0; j--) {
|
|
50742
|
-
const prev2 = messages[j];
|
|
50743
|
-
if (prev2.role === "assistant" && prev2.toolCalls && prev2.toolCalls.some((tc) => tc.id === m.toolCallId)) {
|
|
50744
|
-
cut = j;
|
|
50745
|
-
moved = true;
|
|
50746
|
-
break;
|
|
50747
|
-
}
|
|
50748
|
-
}
|
|
50749
|
-
break;
|
|
51162
|
+
async head() {
|
|
51163
|
+
return null;
|
|
50750
51164
|
}
|
|
50751
|
-
|
|
50752
|
-
|
|
51165
|
+
async get() {
|
|
51166
|
+
return null;
|
|
51167
|
+
}
|
|
51168
|
+
async list() {
|
|
51169
|
+
return [];
|
|
51170
|
+
}
|
|
51171
|
+
async setHead(id3) {
|
|
51172
|
+
throw new Error(`NoopDurableStateStore.setHead: state disabled (id=${id3})`);
|
|
51173
|
+
}
|
|
51174
|
+
async loadDiscoveries() {
|
|
51175
|
+
return [];
|
|
51176
|
+
}
|
|
51177
|
+
async materializeContext() {
|
|
51178
|
+
return "";
|
|
51179
|
+
}
|
|
51180
|
+
async close() {
|
|
51181
|
+
}
|
|
51182
|
+
};
|
|
50753
51183
|
}
|
|
50754
|
-
|
|
51184
|
+
});
|
|
51185
|
+
|
|
51186
|
+
// src/cli/hooks/messageHelpers.ts
|
|
51187
|
+
function appendSystem(setMessages, content, ts = Date.now()) {
|
|
51188
|
+
setMessages((prev2) => [
|
|
51189
|
+
...prev2,
|
|
51190
|
+
{ id: crypto.randomUUID(), role: "system", content, ts }
|
|
51191
|
+
]);
|
|
50755
51192
|
}
|
|
50756
|
-
function
|
|
50757
|
-
|
|
50758
|
-
|
|
50759
|
-
|
|
50760
|
-
|
|
51193
|
+
function appendUser(setMessages, content, ts = Date.now()) {
|
|
51194
|
+
setMessages((prev2) => [
|
|
51195
|
+
...prev2,
|
|
51196
|
+
{ id: crypto.randomUUID(), role: "user", content, ts }
|
|
51197
|
+
]);
|
|
50761
51198
|
}
|
|
50762
|
-
function
|
|
50763
|
-
|
|
50764
|
-
|
|
50765
|
-
|
|
50766
|
-
|
|
50767
|
-
|
|
50768
|
-
|
|
50769
|
-
|
|
50770
|
-
|
|
50771
|
-
|
|
50772
|
-
|
|
50773
|
-
|
|
50774
|
-
|
|
50775
|
-
|
|
50776
|
-
|
|
50777
|
-
|
|
50778
|
-
|
|
50779
|
-
content: [head, "\u2026[pruned " + omitted + " chars]\u2026", tail2].join(String.fromCharCode(10))
|
|
50780
|
-
};
|
|
51199
|
+
function appendOrExtendStreamingAssistant(setMessages, fullContent, ts, memberContext) {
|
|
51200
|
+
setMessages((prev2) => {
|
|
51201
|
+
const last = prev2[prev2.length - 1];
|
|
51202
|
+
if (last && last.role === "assistant" && last.id.startsWith("streaming-")) {
|
|
51203
|
+
return [...prev2.slice(0, -1), { ...last, content: fullContent }];
|
|
51204
|
+
}
|
|
51205
|
+
return [
|
|
51206
|
+
...prev2,
|
|
51207
|
+
{
|
|
51208
|
+
id: `streaming-${crypto.randomUUID()}`,
|
|
51209
|
+
role: "assistant",
|
|
51210
|
+
content: fullContent,
|
|
51211
|
+
ts,
|
|
51212
|
+
...memberContext?.memberId ? { memberId: memberContext.memberId } : {},
|
|
51213
|
+
...memberContext?.memberName ? { memberName: memberContext.memberName } : {}
|
|
51214
|
+
}
|
|
51215
|
+
];
|
|
50781
51216
|
});
|
|
50782
|
-
return {
|
|
50783
|
-
messages: changed ? out : messages,
|
|
50784
|
-
stats
|
|
50785
|
-
};
|
|
50786
|
-
}
|
|
50787
|
-
function compactHistory(messages, opts) {
|
|
50788
|
-
return compactHistoryDetailed(messages, opts).messages;
|
|
50789
|
-
}
|
|
50790
|
-
function buildCheckpointMessage(summaryText, range) {
|
|
50791
|
-
return {
|
|
50792
|
-
role: "user",
|
|
50793
|
-
content: CHECKPOINT_WRAPPER_PREFIX + "\n\n<compacted-summary>\n" + summaryText + "\n</compacted-summary>",
|
|
50794
|
-
...range ? {
|
|
50795
|
-
compactedFromSeq: range.fromSeq,
|
|
50796
|
-
compactedToSeq: range.toSeq,
|
|
50797
|
-
sourceEventSeqs: [...range.sourceEventSeqs]
|
|
50798
|
-
} : {}
|
|
50799
|
-
};
|
|
50800
51217
|
}
|
|
50801
|
-
function
|
|
50802
|
-
const
|
|
50803
|
-
|
|
50804
|
-
|
|
50805
|
-
{ messages: [], compacted: true, messagesRemoved: messages.length, summary: "" },
|
|
50806
|
-
messages,
|
|
50807
|
-
"extractive"
|
|
50808
|
-
);
|
|
50809
|
-
}
|
|
50810
|
-
if (messages.length <= maxMessages * 2 && !opts?.force) {
|
|
50811
|
-
return {
|
|
50812
|
-
messages,
|
|
50813
|
-
compacted: false,
|
|
50814
|
-
messagesRemoved: 0,
|
|
50815
|
-
summary: ""
|
|
50816
|
-
};
|
|
50817
|
-
}
|
|
50818
|
-
const naiveCut = Math.max(0, messages.length - maxMessages);
|
|
50819
|
-
const cut = findValidCutIndex(messages, naiveCut);
|
|
50820
|
-
if (cut === 0) {
|
|
50821
|
-
return {
|
|
50822
|
-
messages,
|
|
50823
|
-
compacted: false,
|
|
50824
|
-
messagesRemoved: 0,
|
|
50825
|
-
summary: ""
|
|
50826
|
-
};
|
|
50827
|
-
}
|
|
50828
|
-
const droppedMsgs = messages.slice(0, cut);
|
|
50829
|
-
const droppedRange = compactedRangeFromDropped(droppedMsgs);
|
|
50830
|
-
const pruned = pruneToolResultsDetailed(messages.slice(cut));
|
|
50831
|
-
const kept = pruned.messages;
|
|
50832
|
-
const summaryText = extractiveHistorySummary(droppedMsgs);
|
|
50833
|
-
const summary = buildCheckpointMessage(
|
|
50834
|
-
summaryText || `${COMPACT_MARKER} ${cut} earlier message(s) dropped.`,
|
|
50835
|
-
droppedRange
|
|
50836
|
-
);
|
|
50837
|
-
return withDroppedRange(
|
|
51218
|
+
function appendToolStart(setMessages, toolName, toolCallId, args, ts) {
|
|
51219
|
+
const argsPreview = formatToolSummary(toolName, args);
|
|
51220
|
+
setMessages((prev2) => [
|
|
51221
|
+
...prev2,
|
|
50838
51222
|
{
|
|
50839
|
-
|
|
50840
|
-
|
|
50841
|
-
|
|
50842
|
-
|
|
50843
|
-
|
|
50844
|
-
|
|
50845
|
-
|
|
50846
|
-
|
|
50847
|
-
|
|
51223
|
+
id: crypto.randomUUID(),
|
|
51224
|
+
role: "tool",
|
|
51225
|
+
content: argsPreview,
|
|
51226
|
+
ts,
|
|
51227
|
+
toolName,
|
|
51228
|
+
toolCallId,
|
|
51229
|
+
toolOk: void 0,
|
|
51230
|
+
toolDurationMs: void 0
|
|
51231
|
+
}
|
|
51232
|
+
]);
|
|
50848
51233
|
}
|
|
50849
|
-
|
|
50850
|
-
|
|
50851
|
-
|
|
50852
|
-
|
|
50853
|
-
|
|
50854
|
-
|
|
50855
|
-
|
|
50856
|
-
|
|
50857
|
-
|
|
50858
|
-
|
|
50859
|
-
|
|
50860
|
-
|
|
50861
|
-
|
|
50862
|
-
|
|
50863
|
-
|
|
50864
|
-
|
|
50865
|
-
|
|
50866
|
-
|
|
50867
|
-
|
|
50868
|
-
signal: opts?.signal
|
|
50869
|
-
});
|
|
50870
|
-
cacheReuseExpected = replay.cacheReuseExpected;
|
|
50871
|
-
if (replay.summary && replay.summary.trim().length > 40) {
|
|
50872
|
-
const sourceTokens = roughTokens(droppedMsgs);
|
|
50873
|
-
const summaryTok = Math.ceil(replay.summary.length / 4);
|
|
50874
|
-
if (summaryTok < sourceTokens) {
|
|
50875
|
-
summaryText = replay.summary.trim();
|
|
50876
|
-
}
|
|
51234
|
+
function updateToolMessageEnd(setMessages, toolCallId, isError, durationMs, result) {
|
|
51235
|
+
setMessages((prev2) => {
|
|
51236
|
+
for (let i = prev2.length - 1; i >= 0; i--) {
|
|
51237
|
+
const m = prev2[i];
|
|
51238
|
+
if (m && m.role === "tool" && m.toolCallId === toolCallId && m.toolDurationMs === void 0) {
|
|
51239
|
+
const updated = [...prev2];
|
|
51240
|
+
updated[i] = {
|
|
51241
|
+
...m,
|
|
51242
|
+
toolOk: !isError,
|
|
51243
|
+
toolDurationMs: durationMs,
|
|
51244
|
+
...result !== void 0 ? {
|
|
51245
|
+
toolResult: toolResultForStorage(
|
|
51246
|
+
m.toolName ?? "",
|
|
51247
|
+
result,
|
|
51248
|
+
isError
|
|
51249
|
+
)
|
|
51250
|
+
} : {}
|
|
51251
|
+
};
|
|
51252
|
+
return updated;
|
|
50877
51253
|
}
|
|
50878
|
-
} catch {
|
|
50879
51254
|
}
|
|
50880
|
-
|
|
50881
|
-
|
|
50882
|
-
const kept = pruned.messages;
|
|
50883
|
-
const summary = buildCheckpointMessage(summaryText, compactedRangeFromDropped(droppedMsgs));
|
|
50884
|
-
const usedLlm = summaryText !== extractive && summaryText.trim().length > 40;
|
|
50885
|
-
return withDroppedRange(
|
|
50886
|
-
{
|
|
50887
|
-
messages: [summary, ...kept],
|
|
50888
|
-
compacted: true,
|
|
50889
|
-
messagesRemoved: cut,
|
|
50890
|
-
summary: summaryText,
|
|
50891
|
-
prunedToolResults: pruned.stats.pruned,
|
|
50892
|
-
cacheReuseExpected,
|
|
50893
|
-
replayExactPrefix
|
|
50894
|
-
},
|
|
50895
|
-
droppedMsgs,
|
|
50896
|
-
usedLlm ? "llm" : "extractive"
|
|
50897
|
-
);
|
|
51255
|
+
return prev2;
|
|
51256
|
+
});
|
|
50898
51257
|
}
|
|
50899
|
-
function
|
|
50900
|
-
|
|
50901
|
-
|
|
50902
|
-
|
|
50903
|
-
|
|
50904
|
-
|
|
50905
|
-
|
|
50906
|
-
|
|
51258
|
+
function finalizeStreamingAssistant(setMessages) {
|
|
51259
|
+
setMessages((prev2) => {
|
|
51260
|
+
const last = prev2[prev2.length - 1];
|
|
51261
|
+
if (last && last.role === "assistant" && last.id.startsWith("streaming-")) {
|
|
51262
|
+
return [
|
|
51263
|
+
...prev2.slice(0, -1),
|
|
51264
|
+
{ ...last, id: last.id.slice("streaming-".length) }
|
|
51265
|
+
];
|
|
50907
51266
|
}
|
|
50908
|
-
|
|
50909
|
-
|
|
51267
|
+
return prev2;
|
|
51268
|
+
});
|
|
50910
51269
|
}
|
|
50911
|
-
var
|
|
50912
|
-
|
|
50913
|
-
"src/cli/hooks/historyCompaction.ts"() {
|
|
51270
|
+
var init_messageHelpers = __esm({
|
|
51271
|
+
"src/cli/hooks/messageHelpers.ts"() {
|
|
50914
51272
|
"use strict";
|
|
50915
|
-
|
|
50916
|
-
|
|
50917
|
-
init_envNumber();
|
|
50918
|
-
COMPACT_MARKER = "[history] Earlier turns were compacted to stay within the context budget.";
|
|
50919
|
-
CHECKPOINT_WRAPPER_PREFIX = "This is an automatically generated checkpoint of earlier conversation. Treat it as established context and continue directly.";
|
|
51273
|
+
init_toolFormat();
|
|
51274
|
+
init_toolFormat();
|
|
50920
51275
|
}
|
|
50921
51276
|
});
|
|
50922
51277
|
|
|
@@ -51229,215 +51584,6 @@ var init_phase = __esm({
|
|
|
51229
51584
|
}
|
|
51230
51585
|
});
|
|
51231
51586
|
|
|
51232
|
-
// src/cli/budget/tokenBudget.ts
|
|
51233
|
-
function mergeCompactRange(into, r) {
|
|
51234
|
-
if (r.fromSeq !== void 0 && r.toSeq !== void 0) {
|
|
51235
|
-
into.fromSeq = into.fromSeq === void 0 ? r.fromSeq : Math.min(into.fromSeq, r.fromSeq);
|
|
51236
|
-
into.toSeq = into.toSeq === void 0 ? r.toSeq : Math.max(into.toSeq, r.toSeq);
|
|
51237
|
-
if (r.sourceEventSeqs) into.sourceSeqs.push(...r.sourceEventSeqs);
|
|
51238
|
-
}
|
|
51239
|
-
if (r.strategy === "llm") into.strategy = "llm";
|
|
51240
|
-
else if (r.strategy && !into.strategy) into.strategy = r.strategy;
|
|
51241
|
-
}
|
|
51242
|
-
function estimateTokens2(text) {
|
|
51243
|
-
if (!text) return 0;
|
|
51244
|
-
return Math.max(1, Math.ceil(text.length / 4));
|
|
51245
|
-
}
|
|
51246
|
-
function estimateHistoryTokens(messages) {
|
|
51247
|
-
let n = 0;
|
|
51248
|
-
for (const m of messages) {
|
|
51249
|
-
n += estimateTokens2(m.content);
|
|
51250
|
-
if (m.toolCalls) {
|
|
51251
|
-
for (const tc of m.toolCalls) {
|
|
51252
|
-
n += estimateTokens2(tc.name) + estimateTokens2(JSON.stringify(tc.args ?? {}));
|
|
51253
|
-
}
|
|
51254
|
-
}
|
|
51255
|
-
}
|
|
51256
|
-
return n;
|
|
51257
|
-
}
|
|
51258
|
-
function defaultContextLimitForModel(model, provider) {
|
|
51259
|
-
return capabilitiesFor(model, provider).contextWindow;
|
|
51260
|
-
}
|
|
51261
|
-
function resolveContextLimit(model, provider) {
|
|
51262
|
-
return envNumber(process.env.ZELARI_CONTEXT_LIMIT, {
|
|
51263
|
-
default: defaultContextLimitForModel(model, provider),
|
|
51264
|
-
min: 4e3,
|
|
51265
|
-
max: 2e6
|
|
51266
|
-
});
|
|
51267
|
-
}
|
|
51268
|
-
function phaseKnobs(phase2) {
|
|
51269
|
-
return {
|
|
51270
|
-
historyTurns: phase2 === "plan" ? envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 8, min: 0 }) : envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 }),
|
|
51271
|
-
maxToolLoopIterations: phase2 === "plan" ? envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, { default: 60, min: 1 }) : envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, {
|
|
51272
|
-
default: 120,
|
|
51273
|
-
min: 1
|
|
51274
|
-
})
|
|
51275
|
-
};
|
|
51276
|
-
}
|
|
51277
|
-
async function applyBudgetPolicyAsync(history2, phase2, opts) {
|
|
51278
|
-
const contextLimit = resolveContextLimit(opts?.model, opts?.provider);
|
|
51279
|
-
const compact3 = capabilitiesFor(opts?.model, opts?.provider).compaction;
|
|
51280
|
-
const sessionExtra = opts?.sessionTokens ?? 0;
|
|
51281
|
-
const warnings = [];
|
|
51282
|
-
let { historyTurns, maxToolLoopIterations } = phaseKnobs(phase2);
|
|
51283
|
-
const envelope = opts?.requestSnapshot ?? null;
|
|
51284
|
-
const surface = envelope?.snapshot ?? opts?.requestSurface ?? null;
|
|
51285
|
-
const replayBase = surface ? {
|
|
51286
|
-
provider: surface.provider,
|
|
51287
|
-
model: surface.model,
|
|
51288
|
-
systemMessages: surface.systemMessages,
|
|
51289
|
-
tools: surface.tools
|
|
51290
|
-
} : opts?.providerStream ? { provider: "local", model: opts?.model ?? "unknown", systemMessages: [], tools: [] } : null;
|
|
51291
|
-
const headerTokens = surface ? estimateSystemTokensLite(surface.systemMessages) + estimateToolSchemaTokensLite(surface.tools) : 0;
|
|
51292
|
-
const convTokensOf = (h) => estimateConversationTokensLite(h);
|
|
51293
|
-
let hist = history2;
|
|
51294
|
-
let estimated = surface ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
51295
|
-
let occupancy = Math.min(1, estimated / contextLimit);
|
|
51296
|
-
let compactSummary = "";
|
|
51297
|
-
let messagesRemoved = 0;
|
|
51298
|
-
let cacheReuseExpected;
|
|
51299
|
-
let prunedTotal = 0;
|
|
51300
|
-
const compactRange = { sourceSeqs: [] };
|
|
51301
|
-
if (occupancy >= compact3.warnAt && occupancy < compact3.compactAt) {
|
|
51302
|
-
warnings.push(
|
|
51303
|
-
`[budget] context ~${Math.round(occupancy * 100)}% full (${estimated}/${contextLimit} tok full-request est.) \u2014 consider /compact or shorter replies.`
|
|
51304
|
-
);
|
|
51305
|
-
}
|
|
51306
|
-
if (occupancy >= 0.8) {
|
|
51307
|
-
const pruned = pruneToolResultsDetailed(hist);
|
|
51308
|
-
if (pruned.stats.pruned > 0) {
|
|
51309
|
-
hist = pruned.messages;
|
|
51310
|
-
prunedTotal += pruned.stats.pruned;
|
|
51311
|
-
estimated = surface ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
51312
|
-
occupancy = Math.min(1, estimated / contextLimit);
|
|
51313
|
-
warnings.push(
|
|
51314
|
-
`[budget] pruned ${pruned.stats.pruned} oversized tool result(s) \u2192 ${Math.round(occupancy * 100)}% (${estimated} tok).`
|
|
51315
|
-
);
|
|
51316
|
-
}
|
|
51317
|
-
}
|
|
51318
|
-
const fold = (r, label, forcedTurns) => {
|
|
51319
|
-
hist = applySessionSurface(r.messages);
|
|
51320
|
-
if (r.compacted) {
|
|
51321
|
-
messagesRemoved += r.messagesRemoved;
|
|
51322
|
-
if (r.summary) compactSummary = r.summary;
|
|
51323
|
-
mergeCompactRange(compactRange, r);
|
|
51324
|
-
if (r.cacheReuseExpected !== void 0) {
|
|
51325
|
-
cacheReuseExpected = r.cacheReuseExpected;
|
|
51326
|
-
}
|
|
51327
|
-
}
|
|
51328
|
-
estimated = surface ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
51329
|
-
occupancy = Math.min(1, estimated / contextLimit);
|
|
51330
|
-
warnings.push(
|
|
51331
|
-
`[budget] ${label} \u2014 kept ~${forcedTurns} turns (${estimated} tok est.` + (r.messagesRemoved ? `, removed ${r.messagesRemoved} msgs` : "") + (r.cacheReuseExpected === false ? ", cache reuse NOT expected (model override)" : "") + ")."
|
|
51332
|
-
);
|
|
51333
|
-
};
|
|
51334
|
-
if (occupancy >= compact3.compactAt) {
|
|
51335
|
-
const forcedTurns = Math.max(1, Math.floor(historyTurns / 2));
|
|
51336
|
-
historyTurns = forcedTurns;
|
|
51337
|
-
maxToolLoopIterations = Math.min(
|
|
51338
|
-
maxToolLoopIterations,
|
|
51339
|
-
phase2 === "plan" ? 24 : 40
|
|
51340
|
-
);
|
|
51341
|
-
let r = await compactHistoryAsync(hist, {
|
|
51342
|
-
maxMessages: Math.max(2, forcedTurns * 4),
|
|
51343
|
-
force: true,
|
|
51344
|
-
signal: opts?.signal,
|
|
51345
|
-
...replayBase ? { requestSnapshot: replayBase, providerStream: opts?.providerStream } : {}
|
|
51346
|
-
});
|
|
51347
|
-
if (!r.compacted) {
|
|
51348
|
-
r = await compactHistoryAsync(hist, {
|
|
51349
|
-
maxMessages: 2,
|
|
51350
|
-
force: true,
|
|
51351
|
-
signal: opts?.signal,
|
|
51352
|
-
...replayBase ? { requestSnapshot: replayBase, providerStream: opts?.providerStream } : {}
|
|
51353
|
-
});
|
|
51354
|
-
}
|
|
51355
|
-
const label = r.cacheReuseExpected === false ? "llm-compact (model override)" : "auto-compact";
|
|
51356
|
-
fold(r, label, forcedTurns);
|
|
51357
|
-
}
|
|
51358
|
-
if (occupancy >= compact3.hardAt) {
|
|
51359
|
-
const hard = await compactHistoryAsync(hist, {
|
|
51360
|
-
maxMessages: 2,
|
|
51361
|
-
force: true,
|
|
51362
|
-
signal: opts?.signal
|
|
51363
|
-
});
|
|
51364
|
-
fold(hard, hard.summary.includes("\xB7 llm") ? "llm-compact" : "HARD trim", 2);
|
|
51365
|
-
historyTurns = 2;
|
|
51366
|
-
maxToolLoopIterations = Math.min(maxToolLoopIterations, 16);
|
|
51367
|
-
warnings.push(
|
|
51368
|
-
"[budget] HARD context pressure (\u226595%) \u2014 prefer /clear or a new session if quality drops."
|
|
51369
|
-
);
|
|
51370
|
-
}
|
|
51371
|
-
const cacheMetricsLine = envelope ? [
|
|
51372
|
-
"compaction meter:",
|
|
51373
|
-
`provider/model: ${envelope.snapshot.provider}/${envelope.snapshot.model}`,
|
|
51374
|
-
`headerFingerprint: ${envelope.snapshot.headerFingerprint.slice(0, 12)}`,
|
|
51375
|
-
`occupancy: ${Math.round(occupancy * 100)}% (${estimated}/${contextLimit})`,
|
|
51376
|
-
...envelope.usage?.cachedPromptTokens !== void 0 ? [`cachedPromptTokens: ${envelope.usage.cachedPromptTokens}`] : [],
|
|
51377
|
-
...cacheReuseExpected !== void 0 ? [`cacheReuseExpected: ${cacheReuseExpected}`] : []
|
|
51378
|
-
].join(" | ") : void 0;
|
|
51379
|
-
return {
|
|
51380
|
-
history: hist,
|
|
51381
|
-
warnings,
|
|
51382
|
-
maxToolLoopIterations,
|
|
51383
|
-
historyTurns,
|
|
51384
|
-
estimatedHistoryTokens: surface ? convTokensOf(hist) : estimated,
|
|
51385
|
-
contextLimit,
|
|
51386
|
-
occupancy,
|
|
51387
|
-
compactSummary: compactSummary || void 0,
|
|
51388
|
-
messagesRemoved: messagesRemoved || void 0,
|
|
51389
|
-
...compactRange.fromSeq !== void 0 && compactRange.toSeq !== void 0 ? {
|
|
51390
|
-
compactedFromSeq: compactRange.fromSeq,
|
|
51391
|
-
compactedToSeq: compactRange.toSeq,
|
|
51392
|
-
compactSourceSeqs: compactRange.sourceSeqs,
|
|
51393
|
-
compactStrategy: compactRange.strategy
|
|
51394
|
-
} : {},
|
|
51395
|
-
...surface ? { contextPressureTokens: estimated } : {},
|
|
51396
|
-
...cacheReuseExpected !== void 0 ? { cacheReuseExpected } : {},
|
|
51397
|
-
...cacheMetricsLine ? { cacheMetricsLine } : {}
|
|
51398
|
-
};
|
|
51399
|
-
}
|
|
51400
|
-
function estimateSystemTokensLite(systemMessages) {
|
|
51401
|
-
let n = 0;
|
|
51402
|
-
for (const m of systemMessages) n += 4 + Math.ceil((m.content ?? "").length / 4);
|
|
51403
|
-
return n;
|
|
51404
|
-
}
|
|
51405
|
-
function estimateToolSchemaTokensLite(tools) {
|
|
51406
|
-
let n = 0;
|
|
51407
|
-
for (const t of tools) {
|
|
51408
|
-
n += Math.ceil((t.name ?? "").length / 4);
|
|
51409
|
-
n += Math.ceil((t.description ?? "").length / 4);
|
|
51410
|
-
n += Math.ceil(JSON.stringify(t.parameters ?? {}).length / 4);
|
|
51411
|
-
}
|
|
51412
|
-
return n + tools.length * 4;
|
|
51413
|
-
}
|
|
51414
|
-
function estimateConversationTokensLite(messages) {
|
|
51415
|
-
let n = 0;
|
|
51416
|
-
for (const m of messages) {
|
|
51417
|
-
n += 4 + Math.ceil((m.content ?? "").length / 4);
|
|
51418
|
-
if (m.toolCalls) {
|
|
51419
|
-
for (const tc of m.toolCalls) {
|
|
51420
|
-
n += Math.ceil(tc.name.length / 4) + Math.ceil(tc.id.length / 4);
|
|
51421
|
-
n += Math.ceil(JSON.stringify(tc.args ?? {}).length / 4);
|
|
51422
|
-
}
|
|
51423
|
-
}
|
|
51424
|
-
if (m.reasoningContent) n += Math.ceil(m.reasoningContent.length / 4);
|
|
51425
|
-
if (m.toolCallId) n += Math.ceil(m.toolCallId.length / 4);
|
|
51426
|
-
}
|
|
51427
|
-
return n;
|
|
51428
|
-
}
|
|
51429
|
-
var RESERVED_OUTPUT_TOKENS;
|
|
51430
|
-
var init_tokenBudget = __esm({
|
|
51431
|
-
"src/cli/budget/tokenBudget.ts"() {
|
|
51432
|
-
"use strict";
|
|
51433
|
-
init_envNumber();
|
|
51434
|
-
init_historyCompaction();
|
|
51435
|
-
init_observationStore();
|
|
51436
|
-
init_capabilities();
|
|
51437
|
-
RESERVED_OUTPUT_TOKENS = 8192;
|
|
51438
|
-
}
|
|
51439
|
-
});
|
|
51440
|
-
|
|
51441
51587
|
// src/cli/budget/requestMeter.ts
|
|
51442
51588
|
function estimateTokensLocal(text) {
|
|
51443
51589
|
if (!text) return 0;
|
|
@@ -52114,6 +52260,51 @@ var init_persistCompact = __esm({
|
|
|
52114
52260
|
}
|
|
52115
52261
|
});
|
|
52116
52262
|
|
|
52263
|
+
// src/cli/budget/contextProjection.ts
|
|
52264
|
+
function policyFromOccupancy(occupancy, thresholds = DEFAULT_THRESHOLDS) {
|
|
52265
|
+
if (occupancy >= thresholds.hardAt) return "hard";
|
|
52266
|
+
if (occupancy >= thresholds.compactAt) return "compact";
|
|
52267
|
+
if (occupancy >= thresholds.warnAt) return "warn";
|
|
52268
|
+
return "ok";
|
|
52269
|
+
}
|
|
52270
|
+
function recordFromBudget(budget, thresholds = DEFAULT_THRESHOLDS) {
|
|
52271
|
+
return {
|
|
52272
|
+
occupancy: budget.occupancy,
|
|
52273
|
+
estimatedHistoryTokens: budget.estimatedHistoryTokens,
|
|
52274
|
+
contextLimit: budget.contextLimit,
|
|
52275
|
+
...budget.contextPressureTokens !== void 0 ? { contextPressureTokens: budget.contextPressureTokens } : {},
|
|
52276
|
+
policy: policyFromOccupancy(budget.occupancy, thresholds)
|
|
52277
|
+
};
|
|
52278
|
+
}
|
|
52279
|
+
function thresholdsFor(model, provider) {
|
|
52280
|
+
return capabilitiesFor(model, provider).compaction;
|
|
52281
|
+
}
|
|
52282
|
+
function noteBudgetProjection(handle, record2) {
|
|
52283
|
+
try {
|
|
52284
|
+
handle.note("context.projection", {
|
|
52285
|
+
subject: "context.projection",
|
|
52286
|
+
occupancy: record2.occupancy,
|
|
52287
|
+
estimatedHistoryTokens: record2.estimatedHistoryTokens,
|
|
52288
|
+
contextLimit: record2.contextLimit,
|
|
52289
|
+
...record2.contextPressureTokens !== void 0 ? { contextPressureTokens: record2.contextPressureTokens } : {},
|
|
52290
|
+
policy: record2.policy
|
|
52291
|
+
});
|
|
52292
|
+
} catch {
|
|
52293
|
+
}
|
|
52294
|
+
}
|
|
52295
|
+
var DEFAULT_THRESHOLDS;
|
|
52296
|
+
var init_contextProjection = __esm({
|
|
52297
|
+
"src/cli/budget/contextProjection.ts"() {
|
|
52298
|
+
"use strict";
|
|
52299
|
+
init_capabilities();
|
|
52300
|
+
DEFAULT_THRESHOLDS = {
|
|
52301
|
+
warnAt: 0.7,
|
|
52302
|
+
compactAt: 0.85,
|
|
52303
|
+
hardAt: 0.95
|
|
52304
|
+
};
|
|
52305
|
+
}
|
|
52306
|
+
});
|
|
52307
|
+
|
|
52117
52308
|
// src/cli/budget/modelContextBuilder.ts
|
|
52118
52309
|
function messageWasRecompacted(message, history2) {
|
|
52119
52310
|
if (message.compactedFromSeq === void 0) return false;
|
|
@@ -52220,6 +52411,15 @@ async function buildModelContext(input) {
|
|
|
52220
52411
|
occupancy: Math.min(1, estimated / budget.contextLimit)
|
|
52221
52412
|
};
|
|
52222
52413
|
}
|
|
52414
|
+
if (input.budgetNoteHandle) {
|
|
52415
|
+
try {
|
|
52416
|
+
noteBudgetProjection(
|
|
52417
|
+
input.budgetNoteHandle,
|
|
52418
|
+
recordFromBudget(budget, thresholdsFor(input.model, input.provider))
|
|
52419
|
+
);
|
|
52420
|
+
} catch {
|
|
52421
|
+
}
|
|
52422
|
+
}
|
|
52223
52423
|
return {
|
|
52224
52424
|
history: history2,
|
|
52225
52425
|
requestTail,
|
|
@@ -52237,6 +52437,7 @@ var init_modelContextBuilder = __esm({
|
|
|
52237
52437
|
init_tokenBudget();
|
|
52238
52438
|
init_requestMeter();
|
|
52239
52439
|
init_persistCompact();
|
|
52440
|
+
init_contextProjection();
|
|
52240
52441
|
init_headlessSpine();
|
|
52241
52442
|
init_session();
|
|
52242
52443
|
}
|
|
@@ -63135,6 +63336,20 @@ function asNumber2(v) {
|
|
|
63135
63336
|
function asCallId(v, seq) {
|
|
63136
63337
|
return typeof v === "string" && v.length > 0 ? v : `seq:${seq}`;
|
|
63137
63338
|
}
|
|
63339
|
+
function parseProjection(data) {
|
|
63340
|
+
const policy = asString3(data.policy);
|
|
63341
|
+
return {
|
|
63342
|
+
contextChars: asNumber2(data.contextChars) ?? 0,
|
|
63343
|
+
returnedCount: asNumber2(data.returnedCount) ?? 0,
|
|
63344
|
+
occupancy: asNumber2(data.occupancy),
|
|
63345
|
+
estimatedHistoryTokens: asNumber2(data.estimatedHistoryTokens),
|
|
63346
|
+
contextLimit: asNumber2(data.contextLimit),
|
|
63347
|
+
contextPressureTokens: asNumber2(data.contextPressureTokens),
|
|
63348
|
+
durationMs: asNumber2(data.durationMs),
|
|
63349
|
+
backend: asString3(data.backend) || void 0,
|
|
63350
|
+
policy: policy === "ok" || policy === "warn" || policy === "compact" || policy === "hard" ? policy : void 0
|
|
63351
|
+
};
|
|
63352
|
+
}
|
|
63138
63353
|
function newTurn(index, userText) {
|
|
63139
63354
|
return {
|
|
63140
63355
|
index,
|
|
@@ -63216,17 +63431,14 @@ function deriveHarnessState(events) {
|
|
|
63216
63431
|
}
|
|
63217
63432
|
case "session.compacted": {
|
|
63218
63433
|
support.compactions += 1;
|
|
63219
|
-
const saved = asNumber2(e.data.tokensSaved);
|
|
63434
|
+
const saved = asNumber2(e.data.savedTokens) ?? asNumber2(e.data.tokensSaved);
|
|
63220
63435
|
if (saved !== void 0) tokensSaved = (tokensSaved ?? 0) + saved;
|
|
63221
63436
|
break;
|
|
63222
63437
|
}
|
|
63223
63438
|
case "note": {
|
|
63224
63439
|
const subject = asString3(e.data.subject);
|
|
63225
63440
|
if (subject === "context.projection") {
|
|
63226
|
-
support.contextProjections.push(
|
|
63227
|
-
contextChars: asNumber2(e.data.contextChars) ?? 0,
|
|
63228
|
-
returnedCount: asNumber2(e.data.returnedCount) ?? 0
|
|
63229
|
-
});
|
|
63441
|
+
support.contextProjections.push(parseProjection(e.data));
|
|
63230
63442
|
} else if (subject === "memory_event") {
|
|
63231
63443
|
support.memoryEvents += 1;
|
|
63232
63444
|
}
|
|
@@ -64177,6 +64389,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
64177
64389
|
toolSpecs: typeof toolRegistry.fingerprints === "function" ? toolRegistry.fingerprints() : void 0
|
|
64178
64390
|
});
|
|
64179
64391
|
spineHolder.current = spine;
|
|
64392
|
+
flushMemorySpineNotes(spineHolder);
|
|
64180
64393
|
const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
|
|
64181
64394
|
emitEvent(sessionStartedEvent(spine));
|
|
64182
64395
|
if (opts.orchestrationDecision) {
|
|
@@ -64314,6 +64527,8 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
64314
64527
|
tools,
|
|
64315
64528
|
sessionId: spine.sessionId,
|
|
64316
64529
|
providerStream,
|
|
64530
|
+
// T4-S2: budget occupancy/policy onto the spine (context.projection note).
|
|
64531
|
+
budgetNoteHandle: spine,
|
|
64317
64532
|
onCompactionMetric: (metrics) => recordCompactionMetrics(spine.sessionId, provider, model, metrics),
|
|
64318
64533
|
persistCompaction: async (payload) => {
|
|
64319
64534
|
await spine.appendEvent({
|
|
@@ -66058,6 +66273,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
66058
66273
|
workspace: cwd
|
|
66059
66274
|
});
|
|
66060
66275
|
spineHolder.current = spine;
|
|
66276
|
+
flushMemorySpineNotes(spineHolder);
|
|
66061
66277
|
const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
|
|
66062
66278
|
emitEvent(sessionStartedEvent(spine));
|
|
66063
66279
|
if (opts.orchestrationDecision) {
|
|
@@ -66097,6 +66313,8 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
66097
66313
|
tools: contextTools,
|
|
66098
66314
|
sessionId: spine.sessionId,
|
|
66099
66315
|
providerStream,
|
|
66316
|
+
// T4-S2: budget occupancy/policy onto the spine (context.projection note).
|
|
66317
|
+
budgetNoteHandle: spine,
|
|
66100
66318
|
onCompactionMetric: (metrics) => recordCompactionMetrics(spine.sessionId, provider, model, metrics),
|
|
66101
66319
|
persistCompaction: async (payload) => {
|
|
66102
66320
|
await spine.appendEvent({
|
|
@@ -66121,11 +66339,14 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
66121
66339
|
const { composeProjectContext: composeProjectContext2 } = await Promise.resolve().then(() => (init_composeContext(), composeContext_exports));
|
|
66122
66340
|
const { loadDurableContext: loadDurableContext2 } = await Promise.resolve().then(() => (init_loadDurableContext(), loadDurableContext_exports));
|
|
66123
66341
|
const durableState = await loadDurableContext2(cwd);
|
|
66342
|
+
const { resolveRetrievalPolicy: resolveRetrievalPolicy2 } = await Promise.resolve().then(() => (init_retrievalPolicy(), retrievalPolicy_exports));
|
|
66343
|
+
const retrieval = resolveRetrievalPolicy2(councilContext.budget.occupancy);
|
|
66124
66344
|
const memoryContext = nativeMemory ? (await nativeMemory.buildContext({
|
|
66125
66345
|
text: effectiveTask,
|
|
66126
66346
|
useGraph: true,
|
|
66127
|
-
maxChars:
|
|
66128
|
-
maxMemories:
|
|
66347
|
+
maxChars: retrieval.maxChars,
|
|
66348
|
+
maxMemories: retrieval.maxMemories,
|
|
66349
|
+
...retrieval.weights ? { weights: retrieval.weights } : {}
|
|
66129
66350
|
})).text : "";
|
|
66130
66351
|
const composed = composeProjectContext2({
|
|
66131
66352
|
mode: "council",
|
|
@@ -66312,6 +66533,8 @@ async function runHeadlessZelari(opts, provider, model, providerStream, extras)
|
|
|
66312
66533
|
tools: contextTools,
|
|
66313
66534
|
sessionId: spine.sessionId,
|
|
66314
66535
|
providerStream,
|
|
66536
|
+
// T4-S2: budget occupancy/policy onto the spine (context.projection note).
|
|
66537
|
+
budgetNoteHandle: spine,
|
|
66315
66538
|
onCompactionMetric: (metrics) => recordCompactionMetrics(spine.sessionId, provider, model, metrics),
|
|
66316
66539
|
persistCompaction: async (payload) => {
|
|
66317
66540
|
await spine.appendEvent({
|
|
@@ -70043,6 +70266,9 @@ __export(inspectSession_exports, {
|
|
|
70043
70266
|
});
|
|
70044
70267
|
import path89 from "node:path";
|
|
70045
70268
|
import { existsSync as existsSync56 } from "node:fs";
|
|
70269
|
+
function formatLimit(limit) {
|
|
70270
|
+
return `${Math.round(limit / 1e3)}k`;
|
|
70271
|
+
}
|
|
70046
70272
|
function renderInspectReport(state3) {
|
|
70047
70273
|
const lines = [
|
|
70048
70274
|
`session ${state3.session.sessionId} status=${state3.session.status} turns=${state3.execution.turnsTotal}`
|
|
@@ -70061,9 +70287,8 @@ function renderInspectReport(state3) {
|
|
|
70061
70287
|
lines.push("support lens:");
|
|
70062
70288
|
const projections = state3.support.contextProjections;
|
|
70063
70289
|
const last = projections[projections.length - 1];
|
|
70064
|
-
|
|
70065
|
-
|
|
70066
|
-
);
|
|
70290
|
+
const tail2 = !last ? "" : last.occupancy !== void 0 && last.contextLimit !== void 0 ? ` (last: ${Math.round(last.occupancy * 100)}% ${last.policy ?? "?"} (limit ${formatLimit(last.contextLimit)}))` : ` (last: ${last.contextChars} chars \u2192 ${last.returnedCount} items)`;
|
|
70291
|
+
lines.push(` context projections: ${projections.length}${tail2}`);
|
|
70067
70292
|
lines.push(` memory events: ${state3.support.memoryEvents}`);
|
|
70068
70293
|
const saved = state3.support.tokensSavedByCompaction;
|
|
70069
70294
|
lines.push(
|
|
@@ -73339,21 +73564,27 @@ function createPermissionAskHandler(opts) {
|
|
|
73339
73564
|
const catLabel = cats.length === 1 ? cats[0] : cats.join("+") || "action";
|
|
73340
73565
|
const title = `Allow tool "${req.toolName}"?`;
|
|
73341
73566
|
const detail = req.reason + (cats.length ? ` [${cats.join(", ")}]` : "");
|
|
73567
|
+
const claimLines = (req.claims ?? []).map((c) => `\xB7 ${c.summary}`);
|
|
73568
|
+
const note = req.policyNote ? `
|
|
73569
|
+
${req.policyNote}` : "";
|
|
73570
|
+
const claimsBlock = claimLines.length ? `
|
|
73571
|
+
Claims:
|
|
73572
|
+
${claimLines.join("\n")}` : "";
|
|
73342
73573
|
appendSystem2?.(
|
|
73343
73574
|
`[permission] ${title}
|
|
73344
|
-
${detail}
|
|
73575
|
+
${detail}${note}${claimsBlock}
|
|
73345
73576
|
\u2192 Allow once \xB7 Always (tool) \xB7 Always (${catLabel}) \xB7 Deny`,
|
|
73346
73577
|
Date.now()
|
|
73347
73578
|
);
|
|
73348
73579
|
let settled = false;
|
|
73349
73580
|
const askTimeoutMs = askUserTimeoutMs();
|
|
73350
73581
|
let cancelAskTimeout = () => void 0;
|
|
73351
|
-
const finish2 = (ok,
|
|
73582
|
+
const finish2 = (ok, note2) => {
|
|
73352
73583
|
if (settled) return;
|
|
73353
73584
|
settled = true;
|
|
73354
73585
|
cancelAskTimeout();
|
|
73355
73586
|
setPicker2(null);
|
|
73356
|
-
if (
|
|
73587
|
+
if (note2) appendSystem2?.(note2, Date.now());
|
|
73357
73588
|
resolve9(ok);
|
|
73358
73589
|
};
|
|
73359
73590
|
cancelAskTimeout = armPickerTimeout(
|
|
@@ -74487,6 +74718,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
74487
74718
|
let councilMemory;
|
|
74488
74719
|
let councilMemoryAutoWrite = false;
|
|
74489
74720
|
let nativeMemoryContext = "";
|
|
74721
|
+
let councilRetrievalBand = "low";
|
|
74490
74722
|
try {
|
|
74491
74723
|
const memoryFactory = await Promise.resolve().then(() => (init_serviceFactory(), serviceFactory_exports));
|
|
74492
74724
|
if (memoryFactory.isMemoryV2Enabled()) {
|
|
@@ -74501,11 +74733,17 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
74501
74733
|
});
|
|
74502
74734
|
councilMemoryAutoWrite = memoryFactory.isMemoryAutoWriteEnabled();
|
|
74503
74735
|
if (!overrides.ragContext) {
|
|
74736
|
+
const { resolveRetrievalPolicy: resolveRetrievalPolicy2 } = await Promise.resolve().then(() => (init_retrievalPolicy(), retrievalPolicy_exports));
|
|
74737
|
+
const retrieval = resolveRetrievalPolicy2(
|
|
74738
|
+
councilContext.budget.occupancy
|
|
74739
|
+
);
|
|
74740
|
+
councilRetrievalBand = retrieval.band;
|
|
74504
74741
|
nativeMemoryContext = (await councilMemory.buildContext({
|
|
74505
74742
|
text: effectiveText,
|
|
74506
74743
|
useGraph: true,
|
|
74507
|
-
maxChars:
|
|
74508
|
-
maxMemories:
|
|
74744
|
+
maxChars: retrieval.maxChars,
|
|
74745
|
+
maxMemories: retrieval.maxMemories,
|
|
74746
|
+
...retrieval.weights ? { weights: retrieval.weights } : {}
|
|
74509
74747
|
})).text;
|
|
74510
74748
|
}
|
|
74511
74749
|
}
|
|
@@ -76772,6 +77010,7 @@ async function handleKrakenGraph(ctx, prompt) {
|
|
|
76772
77010
|
onWarning: (warning) => appendSystem(ctx.setMessages, warning),
|
|
76773
77011
|
onEvent: memorySinkFor(tuiSpineHolder)
|
|
76774
77012
|
}) : void 0;
|
|
77013
|
+
flushMemorySpineNotes(tuiSpineHolder);
|
|
76775
77014
|
const audit = new AuditLogger();
|
|
76776
77015
|
const taskToolDeps = {
|
|
76777
77016
|
createSubAgentContext: createKrakenSubAgentContextFactory({
|