zelari-code 1.41.0 → 1.42.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/llmCompact.js +97 -83
- package/dist/cli/budget/llmCompact.js.map +1 -1
- package/dist/cli/budget/requestMeter.js +138 -0
- package/dist/cli/budget/requestMeter.js.map +1 -0
- package/dist/cli/budget/requestSnapshotStore.js +55 -0
- package/dist/cli/budget/requestSnapshotStore.js.map +1 -0
- package/dist/cli/budget/tokenBudget.js +147 -15
- package/dist/cli/budget/tokenBudget.js.map +1 -1
- package/dist/cli/hooks/conversationContext.js +4 -0
- package/dist/cli/hooks/conversationContext.js.map +1 -1
- package/dist/cli/hooks/historyCompaction.js +76 -21
- package/dist/cli/hooks/historyCompaction.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +90 -23
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +468 -219
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/provider/openai-compatible.js +11 -1
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -1468,27 +1468,27 @@ function readStore() {
|
|
|
1468
1468
|
}
|
|
1469
1469
|
return { providers: {} };
|
|
1470
1470
|
}
|
|
1471
|
-
function writeStore(
|
|
1471
|
+
function writeStore(store4) {
|
|
1472
1472
|
const file2 = getKeyStorePath();
|
|
1473
1473
|
mkdirSync2(path3.dirname(file2), { recursive: true });
|
|
1474
|
-
writeFileSync2(file2, JSON.stringify(
|
|
1474
|
+
writeFileSync2(file2, JSON.stringify(store4, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1475
1475
|
}
|
|
1476
1476
|
function setApiKey(providerId, key) {
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1479
|
-
writeStore(
|
|
1477
|
+
const store4 = readStore();
|
|
1478
|
+
store4.providers[providerId] = { apiKey: key };
|
|
1479
|
+
writeStore(store4);
|
|
1480
1480
|
}
|
|
1481
1481
|
function clearApiKey(providerId) {
|
|
1482
|
-
const
|
|
1483
|
-
delete
|
|
1484
|
-
writeStore(
|
|
1482
|
+
const store4 = readStore();
|
|
1483
|
+
delete store4.providers[providerId];
|
|
1484
|
+
writeStore(store4);
|
|
1485
1485
|
}
|
|
1486
1486
|
function getStoredApiKey(providerId) {
|
|
1487
|
-
const
|
|
1488
|
-
return
|
|
1487
|
+
const store4 = readStore();
|
|
1488
|
+
return store4.providers[providerId]?.apiKey ?? null;
|
|
1489
1489
|
}
|
|
1490
1490
|
function setOAuthToken(providerId, token) {
|
|
1491
|
-
const
|
|
1491
|
+
const store4 = readStore();
|
|
1492
1492
|
const entry = { apiKey: token.apiKey };
|
|
1493
1493
|
if (typeof token.expiresAt === "number" && Number.isFinite(token.expiresAt)) {
|
|
1494
1494
|
entry.expiresAt = token.expiresAt;
|
|
@@ -1502,12 +1502,12 @@ function setOAuthToken(providerId, token) {
|
|
|
1502
1502
|
if (typeof token.idToken === "string" && token.idToken.length > 0) {
|
|
1503
1503
|
entry.idToken = token.idToken;
|
|
1504
1504
|
}
|
|
1505
|
-
|
|
1506
|
-
writeStore(
|
|
1505
|
+
store4.providers[providerId] = entry;
|
|
1506
|
+
writeStore(store4);
|
|
1507
1507
|
}
|
|
1508
1508
|
function getOAuthToken(providerId) {
|
|
1509
|
-
const
|
|
1510
|
-
return
|
|
1509
|
+
const store4 = readStore();
|
|
1510
|
+
return store4.providers[providerId] ?? null;
|
|
1511
1511
|
}
|
|
1512
1512
|
function resolveApiKey(providerId) {
|
|
1513
1513
|
const spec = getProviderSpec(providerId);
|
|
@@ -1566,8 +1566,8 @@ async function forceRefreshOAuth(providerId, options = {}) {
|
|
|
1566
1566
|
function readStoreDirect() {
|
|
1567
1567
|
return readStore();
|
|
1568
1568
|
}
|
|
1569
|
-
function writeStoreDirect(
|
|
1570
|
-
writeStore(
|
|
1569
|
+
function writeStoreDirect(store4) {
|
|
1570
|
+
writeStore(store4);
|
|
1571
1571
|
}
|
|
1572
1572
|
function maskKey(key) {
|
|
1573
1573
|
if (key.length <= 12) return "****";
|
|
@@ -21214,6 +21214,79 @@ var init_types = __esm({
|
|
|
21214
21214
|
}
|
|
21215
21215
|
});
|
|
21216
21216
|
|
|
21217
|
+
// packages/core/dist/core/requestSnapshot.js
|
|
21218
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
21219
|
+
function stableStringify(value) {
|
|
21220
|
+
if (value === null || typeof value !== "object")
|
|
21221
|
+
return JSON.stringify(value) ?? "null";
|
|
21222
|
+
if (Array.isArray(value)) {
|
|
21223
|
+
const items = value.map((v) => stableStringify(v));
|
|
21224
|
+
return `[${items.join(",")}]`;
|
|
21225
|
+
}
|
|
21226
|
+
const obj = value;
|
|
21227
|
+
const keys = Object.keys(obj).filter((k) => obj[k] !== void 0).sort();
|
|
21228
|
+
const parts = keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`);
|
|
21229
|
+
return `{${parts.join(",")}}`;
|
|
21230
|
+
}
|
|
21231
|
+
function sha256Hex(input) {
|
|
21232
|
+
return createHash2("sha256").update(input, "utf8").digest("hex").slice(0, 32);
|
|
21233
|
+
}
|
|
21234
|
+
function cloneMessages(messages) {
|
|
21235
|
+
return structuredClone(messages);
|
|
21236
|
+
}
|
|
21237
|
+
function canonicalTools(tools) {
|
|
21238
|
+
return [...tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
21239
|
+
}
|
|
21240
|
+
function createRoutedRequestSnapshot(params) {
|
|
21241
|
+
let split = 0;
|
|
21242
|
+
while (split < params.messages.length && params.messages[split].role === "system") {
|
|
21243
|
+
split++;
|
|
21244
|
+
}
|
|
21245
|
+
const systemMessages = cloneMessages(params.messages.slice(0, split));
|
|
21246
|
+
const conversation = cloneMessages(params.messages.slice(split));
|
|
21247
|
+
const tools = canonicalTools(params.tools).map((t) => structuredClone(t));
|
|
21248
|
+
const header = stableStringify({
|
|
21249
|
+
provider: params.provider,
|
|
21250
|
+
model: params.model,
|
|
21251
|
+
systemMessages,
|
|
21252
|
+
tools
|
|
21253
|
+
});
|
|
21254
|
+
const request = stableStringify({
|
|
21255
|
+
provider: params.provider,
|
|
21256
|
+
model: params.model,
|
|
21257
|
+
systemMessages,
|
|
21258
|
+
tools,
|
|
21259
|
+
conversation
|
|
21260
|
+
});
|
|
21261
|
+
return {
|
|
21262
|
+
provider: params.provider,
|
|
21263
|
+
model: params.model,
|
|
21264
|
+
systemMessages,
|
|
21265
|
+
conversation,
|
|
21266
|
+
tools,
|
|
21267
|
+
headerFingerprint: sha256Hex(header),
|
|
21268
|
+
requestFingerprint: sha256Hex(request),
|
|
21269
|
+
createdAt: Date.now()
|
|
21270
|
+
};
|
|
21271
|
+
}
|
|
21272
|
+
function compareReplayPrefix(snapshot, messages) {
|
|
21273
|
+
const base = snapshot.conversation;
|
|
21274
|
+
const n = Math.min(base.length, messages.length);
|
|
21275
|
+
let matching = 0;
|
|
21276
|
+
for (let i = 0; i < n; i++) {
|
|
21277
|
+
if (stableStringify(base[i]) !== stableStringify(messages[i])) {
|
|
21278
|
+
return { exact: false, matchingMessages: matching, mismatchIndex: i };
|
|
21279
|
+
}
|
|
21280
|
+
matching++;
|
|
21281
|
+
}
|
|
21282
|
+
return { exact: true, matchingMessages: matching };
|
|
21283
|
+
}
|
|
21284
|
+
var init_requestSnapshot = __esm({
|
|
21285
|
+
"packages/core/dist/core/requestSnapshot.js"() {
|
|
21286
|
+
"use strict";
|
|
21287
|
+
}
|
|
21288
|
+
});
|
|
21289
|
+
|
|
21217
21290
|
// packages/core/dist/core/textLoopDetect.js
|
|
21218
21291
|
function isStatusTheaterUnit(unit) {
|
|
21219
21292
|
const u = normalizeLoopUnit(unit).toLowerCase();
|
|
@@ -21412,10 +21485,10 @@ var init_textLoopDetect = __esm({
|
|
|
21412
21485
|
|
|
21413
21486
|
// packages/core/dist/core/AgentHarness.js
|
|
21414
21487
|
function hashToolCall(toolName, args) {
|
|
21415
|
-
const canonical =
|
|
21488
|
+
const canonical = stableStringify2(args);
|
|
21416
21489
|
return `${toolName}::${canonical}`;
|
|
21417
21490
|
}
|
|
21418
|
-
function
|
|
21491
|
+
function stableStringify2(value) {
|
|
21419
21492
|
return JSON.stringify(value, (_k, v) => {
|
|
21420
21493
|
if (v && typeof v === "object" && !Array.isArray(v)) {
|
|
21421
21494
|
const sorted = {};
|
|
@@ -21648,6 +21721,7 @@ var init_AgentHarness = __esm({
|
|
|
21648
21721
|
"packages/core/dist/core/AgentHarness.js"() {
|
|
21649
21722
|
"use strict";
|
|
21650
21723
|
init_events();
|
|
21724
|
+
init_requestSnapshot();
|
|
21651
21725
|
init_textLoopDetect();
|
|
21652
21726
|
init_textLoopDetect();
|
|
21653
21727
|
AgentHarness = class {
|
|
@@ -22084,6 +22158,23 @@ ${shared2.content}`,
|
|
|
22084
22158
|
yield agentEnd;
|
|
22085
22159
|
this.activeController = null;
|
|
22086
22160
|
}
|
|
22161
|
+
/**
|
|
22162
|
+
* v1.36.0: capture a deterministic snapshot of the routed request just
|
|
22163
|
+
* before it goes out. Never throws into the request path.
|
|
22164
|
+
*/
|
|
22165
|
+
emitSnapshot(tools, generation) {
|
|
22166
|
+
if (!this.config.onRequestSnapshot)
|
|
22167
|
+
return;
|
|
22168
|
+
try {
|
|
22169
|
+
this.config.onRequestSnapshot(createRoutedRequestSnapshot({
|
|
22170
|
+
messages: this.config.messages,
|
|
22171
|
+
model: this.config.model,
|
|
22172
|
+
provider: this.config.provider,
|
|
22173
|
+
tools
|
|
22174
|
+
}), generation);
|
|
22175
|
+
} catch {
|
|
22176
|
+
}
|
|
22177
|
+
}
|
|
22087
22178
|
/**
|
|
22088
22179
|
* Run a single provider turn for the current message buffer.
|
|
22089
22180
|
* Streams from the provider, dispatches deltas to events, executes
|
|
@@ -22101,6 +22192,7 @@ ${shared2.content}`,
|
|
|
22101
22192
|
*/
|
|
22102
22193
|
async *runSingleTurn(messageId, finishRef, usageRef) {
|
|
22103
22194
|
try {
|
|
22195
|
+
this.emitSnapshot(this.config.tools);
|
|
22104
22196
|
const stream = this.config.providerStream({
|
|
22105
22197
|
messages: this.config.messages,
|
|
22106
22198
|
model: this.config.model,
|
|
@@ -22391,6 +22483,7 @@ ${cached2}`
|
|
|
22391
22483
|
const finishRef = { value: "stop" };
|
|
22392
22484
|
const usageRef = { value: null };
|
|
22393
22485
|
try {
|
|
22486
|
+
this.emitSnapshot([]);
|
|
22394
22487
|
const stream = this.config.providerStream({
|
|
22395
22488
|
messages: this.config.messages,
|
|
22396
22489
|
model: this.config.model,
|
|
@@ -22971,7 +23064,10 @@ __export(harness_exports, {
|
|
|
22971
23064
|
SessionJsonlWriter: () => SessionJsonlWriter,
|
|
22972
23065
|
TEXT_LOOP_RECOVERY_SYSTEM: () => TEXT_LOOP_RECOVERY_SYSTEM,
|
|
22973
23066
|
TEXT_LOOP_RECOVERY_USER_PROMPT: () => TEXT_LOOP_RECOVERY_USER_PROMPT,
|
|
23067
|
+
canonicalTools: () => canonicalTools,
|
|
22974
23068
|
collapseLoopedAssistantText: () => collapseLoopedAssistantText,
|
|
23069
|
+
compareReplayPrefix: () => compareReplayPrefix,
|
|
23070
|
+
createRoutedRequestSnapshot: () => createRoutedRequestSnapshot,
|
|
22975
23071
|
detectAssistantTextLoop: () => detectAssistantTextLoop,
|
|
22976
23072
|
detectAssistantTextLoopWindow: () => detectAssistantTextLoopWindow,
|
|
22977
23073
|
hashToolCall: () => hashToolCall,
|
|
@@ -22983,6 +23079,8 @@ __export(harness_exports, {
|
|
|
22983
23079
|
parseMinimaxStyleToolCalls: () => parseMinimaxStyleToolCalls,
|
|
22984
23080
|
parseTextToolCalls: () => parseTextToolCalls,
|
|
22985
23081
|
readSession: () => readSession,
|
|
23082
|
+
sha256Hex: () => sha256Hex,
|
|
23083
|
+
stableStringify: () => stableStringify,
|
|
22986
23084
|
toolMatches: () => toolMatches,
|
|
22987
23085
|
wrapLegacyStream: () => wrapLegacyStream
|
|
22988
23086
|
});
|
|
@@ -22991,6 +23089,7 @@ var init_harness = __esm({
|
|
|
22991
23089
|
"use strict";
|
|
22992
23090
|
init_AgentHarness();
|
|
22993
23091
|
init_providerStream();
|
|
23092
|
+
init_requestSnapshot();
|
|
22994
23093
|
init_sessionJsonl();
|
|
22995
23094
|
init_hooks();
|
|
22996
23095
|
}
|
|
@@ -27902,6 +28001,7 @@ __export(dist_exports, {
|
|
|
27902
28001
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
27903
28002
|
buildSystemPromptSplit: () => buildSystemPromptSplit,
|
|
27904
28003
|
canRunParallel: () => canRunParallel,
|
|
28004
|
+
canonicalTools: () => canonicalTools,
|
|
27905
28005
|
captureFailure: () => captureFailure,
|
|
27906
28006
|
checkImplementationCompletion: () => checkImplementationCompletion,
|
|
27907
28007
|
checkImplementationDelivery: () => checkImplementationDelivery,
|
|
@@ -27913,6 +28013,7 @@ __export(dist_exports, {
|
|
|
27913
28013
|
clearCustomTools: () => clearCustomTools,
|
|
27914
28014
|
cliToolToEnhanced: () => cliToolToEnhanced,
|
|
27915
28015
|
collapseLoopedAssistantText: () => collapseLoopedAssistantText,
|
|
28016
|
+
compareReplayPrefix: () => compareReplayPrefix,
|
|
27916
28017
|
computeAgentSkills: () => computeAgentSkills,
|
|
27917
28018
|
computeAgentTools: () => computeAgentTools,
|
|
27918
28019
|
councilModeBanner: () => councilModeBanner,
|
|
@@ -27922,6 +28023,7 @@ __export(dist_exports, {
|
|
|
27922
28023
|
createBrainEvent: () => createBrainEvent,
|
|
27923
28024
|
createDefaultSystemPromptConfig: () => createDefaultSystemPromptConfig,
|
|
27924
28025
|
createGraph: () => createGraph,
|
|
28026
|
+
createRoutedRequestSnapshot: () => createRoutedRequestSnapshot,
|
|
27925
28027
|
defaultPersonaParse: () => defaultPersonaParse,
|
|
27926
28028
|
detectAssistantTextLoop: () => detectAssistantTextLoop,
|
|
27927
28029
|
detectAssistantTextLoopWindow: () => detectAssistantTextLoopWindow,
|
|
@@ -28038,9 +28140,11 @@ __export(dist_exports, {
|
|
|
28038
28140
|
scrubProprietaryLeak: () => scrubProprietaryLeak,
|
|
28039
28141
|
selectParallelWave: () => selectParallelWave,
|
|
28040
28142
|
setWorkspaceStubs: () => setWorkspaceStubs,
|
|
28143
|
+
sha256Hex: () => sha256Hex,
|
|
28041
28144
|
shouldRetryMember: () => shouldRetryMember,
|
|
28042
28145
|
slugify: () => slugify2,
|
|
28043
28146
|
specificityFromAssumptions: () => specificityFromAssumptions,
|
|
28147
|
+
stableStringify: () => stableStringify,
|
|
28044
28148
|
stripClarificationProtocol: () => stripClarificationProtocol,
|
|
28045
28149
|
swapMembers: () => swapMembers,
|
|
28046
28150
|
systemMessagesFromSplit: () => systemMessagesFromSplit,
|
|
@@ -28403,6 +28507,7 @@ function openaiCompatibleProvider(config2) {
|
|
|
28403
28507
|
if (cacheable) messageMappingCache.set(m, mapped);
|
|
28404
28508
|
return mapped;
|
|
28405
28509
|
});
|
|
28510
|
+
const generation = params.generation;
|
|
28406
28511
|
const body = {
|
|
28407
28512
|
// Use `params.model` (per-call override from AgentHarness, e.g. for
|
|
28408
28513
|
// `agentModels` config) rather than the closed-over `config.model`
|
|
@@ -28410,7 +28515,7 @@ function openaiCompatibleProvider(config2) {
|
|
|
28410
28515
|
model: params.model,
|
|
28411
28516
|
messages,
|
|
28412
28517
|
stream: true,
|
|
28413
|
-
temperature: 0.7,
|
|
28518
|
+
temperature: generation?.temperature ?? 0.7,
|
|
28414
28519
|
// Task G.4.2 — request the provider to send real token usage in
|
|
28415
28520
|
// the final chunk (gated by `stream_options.include_usage` on the
|
|
28416
28521
|
// OpenAI-compatible API). Providers that don't honor this (some
|
|
@@ -28418,6 +28523,9 @@ function openaiCompatibleProvider(config2) {
|
|
|
28418
28523
|
// the harness will fall back to the ~4-char/token approximation.
|
|
28419
28524
|
stream_options: { include_usage: true }
|
|
28420
28525
|
};
|
|
28526
|
+
if (typeof generation?.maxTokens === "number" && generation.maxTokens > 0) {
|
|
28527
|
+
body.max_tokens = generation.maxTokens;
|
|
28528
|
+
}
|
|
28421
28529
|
const thinkingSpec = config2.thinking ?? "auto";
|
|
28422
28530
|
if (config2.providerId === "deepseek" && thinkingSpec === "auto") {
|
|
28423
28531
|
const thinking = resolveDeepSeekThinking();
|
|
@@ -29312,7 +29420,7 @@ var init_resolveStream = __esm({
|
|
|
29312
29420
|
});
|
|
29313
29421
|
|
|
29314
29422
|
// packages/core/dist/core/tools/toolOutputSpill.js
|
|
29315
|
-
import { createHash as
|
|
29423
|
+
import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
|
|
29316
29424
|
import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync11 } from "node:fs";
|
|
29317
29425
|
import { homedir as homedir3, tmpdir } from "node:os";
|
|
29318
29426
|
import { join as join11 } from "node:path";
|
|
@@ -29342,7 +29450,7 @@ function spillToolOutput(fullText, meta3) {
|
|
|
29342
29450
|
if (!existsSync12(dir)) {
|
|
29343
29451
|
mkdirSync7(dir, { recursive: true });
|
|
29344
29452
|
}
|
|
29345
|
-
const hash3 =
|
|
29453
|
+
const hash3 = createHash3("sha256").update(fullText).digest("hex").slice(0, 12);
|
|
29346
29454
|
const stamp = Date.now().toString(36);
|
|
29347
29455
|
const rnd = randomBytes2(3).toString("hex");
|
|
29348
29456
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
@@ -31749,9 +31857,9 @@ var init_store = __esm({
|
|
|
31749
31857
|
import { promises as fs12, existsSync as existsSync17, readFileSync as readFileSync17 } from "node:fs";
|
|
31750
31858
|
import { homedir as homedir5 } from "node:os";
|
|
31751
31859
|
import path23 from "node:path";
|
|
31752
|
-
import { createHash as
|
|
31860
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
31753
31861
|
function getIndexPath(root) {
|
|
31754
|
-
const hash3 =
|
|
31862
|
+
const hash3 = createHash4("sha1").update(path23.resolve(root)).digest("hex").slice(0, 16);
|
|
31755
31863
|
return process.env.ZELARI_SEMANTIC_FILE ?? path23.join(homedir5(), ".tmp", "zelari-code", "semantic", `${hash3}.json`);
|
|
31756
31864
|
}
|
|
31757
31865
|
async function collectSourceFiles(root, maxFiles = 1500) {
|
|
@@ -33232,11 +33340,11 @@ function readStore3() {
|
|
|
33232
33340
|
return DEFAULT_STORE;
|
|
33233
33341
|
}
|
|
33234
33342
|
}
|
|
33235
|
-
function writeStore3(
|
|
33343
|
+
function writeStore3(store4) {
|
|
33236
33344
|
const p3 = trustStorePath();
|
|
33237
33345
|
try {
|
|
33238
33346
|
mkdirSync11(path28.dirname(p3), { recursive: true });
|
|
33239
|
-
writeFileSync13(p3, JSON.stringify(
|
|
33347
|
+
writeFileSync13(p3, JSON.stringify(store4, null, 2), "utf8");
|
|
33240
33348
|
} catch (err) {
|
|
33241
33349
|
throw new Error(
|
|
33242
33350
|
`failed to persist trust store ${p3}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -33260,21 +33368,21 @@ function isFolderTrusted(folderPath) {
|
|
|
33260
33368
|
return readStore3().folders.some((f) => normalize(f.path) === target);
|
|
33261
33369
|
}
|
|
33262
33370
|
function trustFolder(folderPath) {
|
|
33263
|
-
const
|
|
33371
|
+
const store4 = readStore3();
|
|
33264
33372
|
const normalized = path28.resolve(folderPath);
|
|
33265
|
-
if (!
|
|
33266
|
-
|
|
33267
|
-
writeStore3(
|
|
33373
|
+
if (!store4.folders.some((f) => normalize(f.path) === normalize(normalized))) {
|
|
33374
|
+
store4.folders.push({ path: normalized, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
33375
|
+
writeStore3(store4);
|
|
33268
33376
|
}
|
|
33269
33377
|
return { ok: true, path: normalized };
|
|
33270
33378
|
}
|
|
33271
33379
|
function untrustFolder(folderPath) {
|
|
33272
|
-
const
|
|
33380
|
+
const store4 = readStore3();
|
|
33273
33381
|
const target = normalize(folderPath);
|
|
33274
|
-
const before =
|
|
33275
|
-
|
|
33276
|
-
if (
|
|
33277
|
-
writeStore3(
|
|
33382
|
+
const before = store4.folders.length;
|
|
33383
|
+
store4.folders = store4.folders.filter((f) => normalize(f.path) !== target);
|
|
33384
|
+
if (store4.folders.length === before) return { ok: true, removed: false };
|
|
33385
|
+
writeStore3(store4);
|
|
33278
33386
|
return { ok: true, removed: true };
|
|
33279
33387
|
}
|
|
33280
33388
|
function listTrustedFolders() {
|
|
@@ -33375,7 +33483,7 @@ var init_lifecycleHooks = __esm({
|
|
|
33375
33483
|
});
|
|
33376
33484
|
|
|
33377
33485
|
// src/cli/toolResultCache.ts
|
|
33378
|
-
import { createHash as
|
|
33486
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
33379
33487
|
import { promises as fs14 } from "node:fs";
|
|
33380
33488
|
import path29 from "node:path";
|
|
33381
33489
|
function isToolCacheEnabled() {
|
|
@@ -33388,7 +33496,7 @@ function resolveToolCacheTtlMs() {
|
|
|
33388
33496
|
return Number.isFinite(n) && n >= 0 ? n : TOOL_CACHE_DEFAULT_TTL_MS;
|
|
33389
33497
|
}
|
|
33390
33498
|
function hashKey(parts) {
|
|
33391
|
-
return
|
|
33499
|
+
return createHash5("sha256").update(JSON.stringify(parts), "utf8").digest("hex");
|
|
33392
33500
|
}
|
|
33393
33501
|
function resultBytes(result) {
|
|
33394
33502
|
try {
|
|
@@ -34069,7 +34177,7 @@ var init_toolRegistry = __esm({
|
|
|
34069
34177
|
});
|
|
34070
34178
|
|
|
34071
34179
|
// src/cli/state/fileStateStore.ts
|
|
34072
|
-
import { createHash as
|
|
34180
|
+
import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
|
|
34073
34181
|
import { promises as fs15 } from "node:fs";
|
|
34074
34182
|
import * as path30 from "node:path";
|
|
34075
34183
|
function shortId() {
|
|
@@ -34112,16 +34220,16 @@ function isStateEnabled(env = process.env) {
|
|
|
34112
34220
|
}
|
|
34113
34221
|
async function getStateStore(projectRoot, env = process.env) {
|
|
34114
34222
|
if (!isStateEnabled(env)) return new NoopDurableStateStore();
|
|
34115
|
-
const
|
|
34223
|
+
const store4 = new FileDurableStateStore();
|
|
34116
34224
|
try {
|
|
34117
|
-
await
|
|
34118
|
-
return
|
|
34225
|
+
await store4.init(projectRoot);
|
|
34226
|
+
return store4;
|
|
34119
34227
|
} catch {
|
|
34120
34228
|
return new NoopDurableStateStore();
|
|
34121
34229
|
}
|
|
34122
34230
|
}
|
|
34123
34231
|
function hashStablePrompt(stable) {
|
|
34124
|
-
return
|
|
34232
|
+
return createHash6("sha256").update(stable, "utf8").digest("hex").slice(0, 16);
|
|
34125
34233
|
}
|
|
34126
34234
|
var DEFAULT_MATERIALIZE_CHARS, FileDurableStateStore, NoopDurableStateStore;
|
|
34127
34235
|
var init_fileStateStore = __esm({
|
|
@@ -34452,29 +34560,6 @@ function extractiveHistorySummary(dropped, opts) {
|
|
|
34452
34560
|
}
|
|
34453
34561
|
return out;
|
|
34454
34562
|
}
|
|
34455
|
-
function formatDroppedForLlm(dropped) {
|
|
34456
|
-
const lines = [];
|
|
34457
|
-
for (const m of dropped) {
|
|
34458
|
-
if (m.role === "user") {
|
|
34459
|
-
lines.push(`USER: ${oneLine(m.content, 400)}`);
|
|
34460
|
-
} else if (m.role === "assistant") {
|
|
34461
|
-
const tools = m.toolCalls?.map((t) => t.name).join(",") || "";
|
|
34462
|
-
const body2 = oneLine(m.content, 300);
|
|
34463
|
-
lines.push(
|
|
34464
|
-
tools ? `ASSISTANT(tools=${tools}): ${body2}` : `ASSISTANT: ${body2}`
|
|
34465
|
-
);
|
|
34466
|
-
} else if (m.role === "tool") {
|
|
34467
|
-
lines.push(`TOOL(${m.toolCallId ?? "?"}): ${oneLine(m.content, 160)}`);
|
|
34468
|
-
} else if (m.role === "system") {
|
|
34469
|
-
lines.push(`SYSTEM: ${oneLine(m.content, 200)}`);
|
|
34470
|
-
}
|
|
34471
|
-
}
|
|
34472
|
-
let body = lines.join("\n");
|
|
34473
|
-
if (body.length > MAX_LLM_INPUT_CHARS) {
|
|
34474
|
-
body = body.slice(body.length - MAX_LLM_INPUT_CHARS);
|
|
34475
|
-
}
|
|
34476
|
-
return body;
|
|
34477
|
-
}
|
|
34478
34563
|
function oneLine(s, max) {
|
|
34479
34564
|
const t = s.replace(/\s+/g, " ").trim();
|
|
34480
34565
|
if (t.length <= max) return t;
|
|
@@ -34500,12 +34585,11 @@ function collectPathsFromText(text, out) {
|
|
|
34500
34585
|
n += 1;
|
|
34501
34586
|
}
|
|
34502
34587
|
}
|
|
34503
|
-
var MAX_SUMMARY_CHARS
|
|
34588
|
+
var MAX_SUMMARY_CHARS;
|
|
34504
34589
|
var init_historySummary = __esm({
|
|
34505
34590
|
"src/cli/budget/historySummary.ts"() {
|
|
34506
34591
|
"use strict";
|
|
34507
34592
|
MAX_SUMMARY_CHARS = 3500;
|
|
34508
|
-
MAX_LLM_INPUT_CHARS = 24e3;
|
|
34509
34593
|
}
|
|
34510
34594
|
});
|
|
34511
34595
|
|
|
@@ -34515,92 +34599,87 @@ function isLlmCompactEnabled() {
|
|
|
34515
34599
|
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
34516
34600
|
return true;
|
|
34517
34601
|
}
|
|
34518
|
-
|
|
34519
|
-
|
|
34520
|
-
|
|
34521
|
-
|
|
34522
|
-
|
|
34523
|
-
|
|
34524
|
-
|
|
34525
|
-
|
|
34602
|
+
function compactModelOverride() {
|
|
34603
|
+
const v = process.env.ZELARI_COMPACT_MODEL?.trim();
|
|
34604
|
+
return v ? v : void 0;
|
|
34605
|
+
}
|
|
34606
|
+
async function llmSummarizeHistoryReplay(input) {
|
|
34607
|
+
const override = input.overrideModel ?? compactModelOverride();
|
|
34608
|
+
const model = override ?? input.model;
|
|
34609
|
+
const cacheReuseExpected = !override;
|
|
34610
|
+
if (!isLlmCompactEnabled()) return { summary: null, model, cacheReuseExpected };
|
|
34611
|
+
if (input.droppedMessages.length === 0) {
|
|
34612
|
+
return { summary: null, model, cacheReuseExpected };
|
|
34526
34613
|
}
|
|
34527
|
-
|
|
34528
|
-
|
|
34614
|
+
const messages = [
|
|
34615
|
+
...input.systemMessages,
|
|
34616
|
+
...input.droppedMessages,
|
|
34617
|
+
{
|
|
34618
|
+
role: "user",
|
|
34619
|
+
content: COMPACTION_INSTRUCTION
|
|
34620
|
+
}
|
|
34621
|
+
];
|
|
34529
34622
|
const controller = new AbortController();
|
|
34530
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
34623
|
+
const timeout = setTimeout(() => controller.abort(), REPLAY_TIMEOUT_MS);
|
|
34531
34624
|
const onOuterAbort = () => controller.abort();
|
|
34532
34625
|
input.signal?.addEventListener("abort", onOuterAbort, { once: true });
|
|
34533
34626
|
try {
|
|
34534
|
-
|
|
34535
|
-
|
|
34536
|
-
|
|
34627
|
+
let text = "";
|
|
34628
|
+
let emittedToolCall = false;
|
|
34629
|
+
for await (const delta of input.providerStream({
|
|
34630
|
+
provider: input.provider,
|
|
34631
|
+
model,
|
|
34632
|
+
messages,
|
|
34633
|
+
// Tools stay advertised: dropping them would change the prefix token
|
|
34634
|
+
// sequence and destroy cache reuse (explicit DSH decision). They are
|
|
34635
|
+
// sorted canonically (same discipline as the live routed request and
|
|
34636
|
+
// the snapshot fingerprints) so the replay prefix is byte-identical.
|
|
34637
|
+
tools: [...input.tools].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0),
|
|
34537
34638
|
signal: controller.signal,
|
|
34538
|
-
|
|
34539
|
-
|
|
34540
|
-
authorization: `Bearer ${config2.apiKey}`
|
|
34541
|
-
},
|
|
34542
|
-
body: JSON.stringify({
|
|
34543
|
-
model,
|
|
34639
|
+
generation: {
|
|
34640
|
+
purpose: "compaction",
|
|
34544
34641
|
temperature: 0.1,
|
|
34545
|
-
|
|
34546
|
-
|
|
34547
|
-
|
|
34548
|
-
|
|
34549
|
-
|
|
34550
|
-
|
|
34551
|
-
|
|
34552
|
-
|
|
34553
|
-
|
|
34554
|
-
Transcript of dropped turns:
|
|
34555
|
-
${input.droppedTranscript}`
|
|
34556
|
-
}
|
|
34557
|
-
]
|
|
34558
|
-
})
|
|
34559
|
-
});
|
|
34560
|
-
if (!res.ok) return null;
|
|
34561
|
-
const json2 = await res.json();
|
|
34562
|
-
const text = json2.choices?.[0]?.message?.content?.trim();
|
|
34563
|
-
if (!text) return null;
|
|
34564
|
-
return "[history-summary \xB7 llm]\n" + text + "\n\nContinue from the recent messages below; honor decisions already made above.";
|
|
34642
|
+
maxTokens: 900
|
|
34643
|
+
}
|
|
34644
|
+
})) {
|
|
34645
|
+
if (delta.kind === "text") text += delta.delta;
|
|
34646
|
+
if (delta.kind === "tool_call") emittedToolCall = true;
|
|
34647
|
+
}
|
|
34648
|
+
if (emittedToolCall) return { summary: null, model, cacheReuseExpected };
|
|
34649
|
+
if (!text.trim()) return { summary: null, model, cacheReuseExpected };
|
|
34650
|
+
return { summary: text.trim(), model, cacheReuseExpected };
|
|
34565
34651
|
} catch {
|
|
34566
|
-
return null;
|
|
34652
|
+
return { summary: null, model, cacheReuseExpected };
|
|
34567
34653
|
} finally {
|
|
34568
34654
|
clearTimeout(timeout);
|
|
34569
34655
|
input.signal?.removeEventListener("abort", onOuterAbort);
|
|
34570
34656
|
}
|
|
34571
34657
|
}
|
|
34572
|
-
|
|
34573
|
-
const active = getProviderConfig().activeProviderId;
|
|
34574
|
-
const meta3 = await resolveApiKeyWithMeta(active);
|
|
34575
|
-
const apiKey = meta3?.apiKey;
|
|
34576
|
-
if (!apiKey) return null;
|
|
34577
|
-
const custom2 = getCustomEndpoint(active);
|
|
34578
|
-
let baseUrl = custom2 || (active === "openai-compatible" || active === "custom" ? process.env.OPENAI_BASE_URL ?? PROVIDER_ENDPOINTS[active] : PROVIDER_ENDPOINTS[active]);
|
|
34579
|
-
if (!baseUrl) return null;
|
|
34580
|
-
const model = getModelForProvider(active);
|
|
34581
|
-
return {
|
|
34582
|
-
apiKey,
|
|
34583
|
-
baseUrl,
|
|
34584
|
-
model,
|
|
34585
|
-
providerId: active
|
|
34586
|
-
};
|
|
34587
|
-
}
|
|
34588
|
-
var COMPACT_SYSTEM;
|
|
34658
|
+
var COMPACTION_INSTRUCTION, REPLAY_TIMEOUT_MS;
|
|
34589
34659
|
var init_llmCompact = __esm({
|
|
34590
34660
|
"src/cli/budget/llmCompact.ts"() {
|
|
34591
34661
|
"use strict";
|
|
34592
|
-
|
|
34593
|
-
|
|
34594
|
-
|
|
34595
|
-
|
|
34596
|
-
|
|
34597
|
-
|
|
34598
|
-
|
|
34599
|
-
|
|
34600
|
-
|
|
34601
|
-
|
|
34662
|
+
COMPACTION_INSTRUCTION = `
|
|
34663
|
+
You are now acting as a compaction engine for this coding-agent session.
|
|
34664
|
+
|
|
34665
|
+
Condense the conversation ABOVE into a compact checkpoint sufficient to continue the task.
|
|
34666
|
+
|
|
34667
|
+
Preserve:
|
|
34668
|
+
- user's goal and evolving intent
|
|
34669
|
+
- decisions already made
|
|
34670
|
+
- exact file paths and identifiers
|
|
34671
|
+
- code changes already completed
|
|
34672
|
+
- commands/errors that still matter
|
|
34673
|
+
- constraints
|
|
34674
|
+
- unfinished work
|
|
34675
|
+
- the single most likely next action
|
|
34602
34676
|
|
|
34603
|
-
|
|
34677
|
+
Do not call tools.
|
|
34678
|
+
Do not mention this summarization request.
|
|
34679
|
+
Output only the checkpoint.
|
|
34680
|
+
Be concise.
|
|
34681
|
+
`.trim();
|
|
34682
|
+
REPLAY_TIMEOUT_MS = 6e4;
|
|
34604
34683
|
}
|
|
34605
34684
|
});
|
|
34606
34685
|
|
|
@@ -34639,6 +34718,7 @@ function resolveMaxMessages(opts) {
|
|
|
34639
34718
|
turns = Math.min(turns, 3);
|
|
34640
34719
|
}
|
|
34641
34720
|
if (turns <= 0) return 0;
|
|
34721
|
+
if (opts?.force && opts?.maxMessages) return Math.max(1, opts.maxMessages);
|
|
34642
34722
|
return turns * 4;
|
|
34643
34723
|
}
|
|
34644
34724
|
function findValidCutIndex(messages, naiveCut) {
|
|
@@ -34704,12 +34784,18 @@ function pruneToolResultsDetailed(messages, opts) {
|
|
|
34704
34784
|
function compactHistory(messages, opts) {
|
|
34705
34785
|
return compactHistoryDetailed(messages, opts).messages;
|
|
34706
34786
|
}
|
|
34787
|
+
function buildCheckpointMessage(summaryText) {
|
|
34788
|
+
return {
|
|
34789
|
+
role: "user",
|
|
34790
|
+
content: CHECKPOINT_WRAPPER_PREFIX + "\n\n<compacted-summary>\n" + summaryText + "\n</compacted-summary>"
|
|
34791
|
+
};
|
|
34792
|
+
}
|
|
34707
34793
|
function compactHistoryDetailed(messages, opts) {
|
|
34708
34794
|
const maxMessages = resolveMaxMessages(opts);
|
|
34709
34795
|
if (maxMessages === 0) {
|
|
34710
34796
|
return { messages: [], compacted: true, messagesRemoved: messages.length, summary: "" };
|
|
34711
34797
|
}
|
|
34712
|
-
if (messages.length <= maxMessages * 2) {
|
|
34798
|
+
if (messages.length <= maxMessages * 2 && !opts?.force) {
|
|
34713
34799
|
return {
|
|
34714
34800
|
messages,
|
|
34715
34801
|
compacted: false,
|
|
@@ -34717,7 +34803,7 @@ function compactHistoryDetailed(messages, opts) {
|
|
|
34717
34803
|
summary: ""
|
|
34718
34804
|
};
|
|
34719
34805
|
}
|
|
34720
|
-
const naiveCut = messages.length - maxMessages;
|
|
34806
|
+
const naiveCut = Math.max(0, messages.length - maxMessages);
|
|
34721
34807
|
const cut = findValidCutIndex(messages, naiveCut);
|
|
34722
34808
|
if (cut === 0) {
|
|
34723
34809
|
return {
|
|
@@ -34731,10 +34817,9 @@ function compactHistoryDetailed(messages, opts) {
|
|
|
34731
34817
|
const pruned = pruneToolResultsDetailed(messages.slice(cut));
|
|
34732
34818
|
const kept = pruned.messages;
|
|
34733
34819
|
const summaryText = extractiveHistorySummary(droppedMsgs);
|
|
34734
|
-
const summary =
|
|
34735
|
-
|
|
34736
|
-
|
|
34737
|
-
};
|
|
34820
|
+
const summary = buildCheckpointMessage(
|
|
34821
|
+
summaryText || `${COMPACT_MARKER} ${cut} earlier message(s) dropped.`
|
|
34822
|
+
);
|
|
34738
34823
|
return {
|
|
34739
34824
|
messages: [summary, ...kept],
|
|
34740
34825
|
compacted: true,
|
|
@@ -34749,29 +34834,58 @@ async function compactHistoryAsync(messages, opts) {
|
|
|
34749
34834
|
const cut = base.messagesRemoved;
|
|
34750
34835
|
const droppedMsgs = messages.slice(0, cut);
|
|
34751
34836
|
const extractive = extractiveHistorySummary(droppedMsgs);
|
|
34752
|
-
const droppedTranscript = formatDroppedForLlm(droppedMsgs);
|
|
34753
34837
|
let summaryText = extractive;
|
|
34754
|
-
|
|
34755
|
-
|
|
34756
|
-
|
|
34757
|
-
|
|
34758
|
-
|
|
34759
|
-
|
|
34760
|
-
|
|
34761
|
-
|
|
34838
|
+
let cacheReuseExpected;
|
|
34839
|
+
let replayExactPrefix;
|
|
34840
|
+
const canReplay = !!(opts?.providerStream && opts?.requestSnapshot);
|
|
34841
|
+
if (canReplay) {
|
|
34842
|
+
try {
|
|
34843
|
+
const replay = await llmSummarizeHistoryReplay({
|
|
34844
|
+
providerStream: opts.providerStream,
|
|
34845
|
+
provider: opts.requestSnapshot.provider,
|
|
34846
|
+
model: opts.requestSnapshot.model,
|
|
34847
|
+
systemMessages: opts.requestSnapshot.systemMessages,
|
|
34848
|
+
tools: opts.requestSnapshot.tools,
|
|
34849
|
+
droppedMessages: droppedMsgs,
|
|
34850
|
+
signal: opts?.signal
|
|
34851
|
+
});
|
|
34852
|
+
cacheReuseExpected = replay.cacheReuseExpected;
|
|
34853
|
+
if (replay.summary && replay.summary.trim().length > 40) {
|
|
34854
|
+
const sourceTokens = roughTokens(droppedMsgs);
|
|
34855
|
+
const summaryTok = Math.ceil(replay.summary.length / 4);
|
|
34856
|
+
if (summaryTok < sourceTokens) {
|
|
34857
|
+
summaryText = replay.summary.trim();
|
|
34858
|
+
}
|
|
34859
|
+
}
|
|
34860
|
+
} catch {
|
|
34861
|
+
}
|
|
34762
34862
|
}
|
|
34763
34863
|
const pruned = pruneToolResultsDetailed(messages.slice(cut));
|
|
34764
34864
|
const kept = pruned.messages;
|
|
34765
|
-
const summary =
|
|
34865
|
+
const summary = buildCheckpointMessage(summaryText);
|
|
34766
34866
|
return {
|
|
34767
34867
|
messages: [summary, ...kept],
|
|
34768
34868
|
compacted: true,
|
|
34769
34869
|
messagesRemoved: cut,
|
|
34770
34870
|
summary: summaryText,
|
|
34771
|
-
prunedToolResults: pruned.stats.pruned
|
|
34871
|
+
prunedToolResults: pruned.stats.pruned,
|
|
34872
|
+
cacheReuseExpected,
|
|
34873
|
+
replayExactPrefix
|
|
34772
34874
|
};
|
|
34773
34875
|
}
|
|
34774
|
-
|
|
34876
|
+
function roughTokens(msgs) {
|
|
34877
|
+
let n = 0;
|
|
34878
|
+
for (const m of msgs) {
|
|
34879
|
+
n += Math.ceil((m.content ?? "").length / 4);
|
|
34880
|
+
if (m.toolCalls) {
|
|
34881
|
+
for (const tc of m.toolCalls) {
|
|
34882
|
+
n += Math.ceil(JSON.stringify(tc.args ?? {}).length / 4);
|
|
34883
|
+
}
|
|
34884
|
+
}
|
|
34885
|
+
}
|
|
34886
|
+
return Math.max(1, n);
|
|
34887
|
+
}
|
|
34888
|
+
var COMPACT_MARKER, CHECKPOINT_WRAPPER_PREFIX;
|
|
34775
34889
|
var init_historyCompaction = __esm({
|
|
34776
34890
|
"src/cli/hooks/historyCompaction.ts"() {
|
|
34777
34891
|
"use strict";
|
|
@@ -34779,6 +34893,30 @@ var init_historyCompaction = __esm({
|
|
|
34779
34893
|
init_llmCompact();
|
|
34780
34894
|
init_envNumber();
|
|
34781
34895
|
COMPACT_MARKER = "[history] Earlier turns were compacted to stay within the context budget.";
|
|
34896
|
+
CHECKPOINT_WRAPPER_PREFIX = "This is an automatically generated checkpoint of earlier conversation. Treat it as established context and continue directly.";
|
|
34897
|
+
}
|
|
34898
|
+
});
|
|
34899
|
+
|
|
34900
|
+
// src/cli/budget/requestSnapshotStore.ts
|
|
34901
|
+
function recordRequestSnapshot(sessionId, snapshot) {
|
|
34902
|
+
store3.set(sessionId, { snapshot });
|
|
34903
|
+
}
|
|
34904
|
+
function recordRequestUsage(sessionId, usage) {
|
|
34905
|
+
const entry = store3.get(sessionId);
|
|
34906
|
+
if (!entry) return;
|
|
34907
|
+
entry.usage = usage;
|
|
34908
|
+
}
|
|
34909
|
+
function getRequestSnapshotWithUsage(sessionId) {
|
|
34910
|
+
return store3.get(sessionId) ?? null;
|
|
34911
|
+
}
|
|
34912
|
+
function clearAllRequestSnapshots() {
|
|
34913
|
+
store3.clear();
|
|
34914
|
+
}
|
|
34915
|
+
var store3;
|
|
34916
|
+
var init_requestSnapshotStore = __esm({
|
|
34917
|
+
"src/cli/budget/requestSnapshotStore.ts"() {
|
|
34918
|
+
"use strict";
|
|
34919
|
+
store3 = /* @__PURE__ */ new Map();
|
|
34782
34920
|
}
|
|
34783
34921
|
});
|
|
34784
34922
|
|
|
@@ -34823,6 +34961,7 @@ function appendMessages(msgs) {
|
|
|
34823
34961
|
function clearHistory() {
|
|
34824
34962
|
history = [];
|
|
34825
34963
|
lastClarification = null;
|
|
34964
|
+
clearAllRequestSnapshots();
|
|
34826
34965
|
clearSessionTodos();
|
|
34827
34966
|
clearSessionPermissionGrants();
|
|
34828
34967
|
}
|
|
@@ -34981,6 +35120,7 @@ var init_conversationContext = __esm({
|
|
|
34981
35120
|
init_toolPermissions();
|
|
34982
35121
|
init_sessionTodos();
|
|
34983
35122
|
init_historyCompaction();
|
|
35123
|
+
init_requestSnapshotStore();
|
|
34984
35124
|
history = [];
|
|
34985
35125
|
lastClarification = null;
|
|
34986
35126
|
SHORT_CONTINUE = /^(procedi|continua|continue|go\s*ahead|go|ok|okay|sì|si|yes|vai|avanti|next|proceed|conferma|confermo|applica|fai|scrivi|esegui|implementa|vai pure|fai pure|ok procedi|sì procedi|si procedi)$/i;
|
|
@@ -35379,7 +35519,7 @@ import {
|
|
|
35379
35519
|
} from "node:fs";
|
|
35380
35520
|
import { join as join18, basename } from "node:path";
|
|
35381
35521
|
import { homedir as homedir9 } from "node:os";
|
|
35382
|
-
import { createHash as
|
|
35522
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
35383
35523
|
function resolveWorkspaceRoot(projectRoot = process.cwd()) {
|
|
35384
35524
|
const candidates = [
|
|
35385
35525
|
join18(projectRoot, ".zelari"),
|
|
@@ -35395,7 +35535,7 @@ function resolveWorkspaceRoot(projectRoot = process.cwd()) {
|
|
|
35395
35535
|
return candidates[0];
|
|
35396
35536
|
}
|
|
35397
35537
|
function hashProject(projectPath) {
|
|
35398
|
-
return
|
|
35538
|
+
return createHash7("sha1").update(realpathSync(projectPath)).digest("hex").slice(0, 12);
|
|
35399
35539
|
}
|
|
35400
35540
|
function isWritableDir(dir) {
|
|
35401
35541
|
try {
|
|
@@ -35986,8 +36126,8 @@ async function loadDurableContext(projectRoot, opts) {
|
|
|
35986
36126
|
return cache.text;
|
|
35987
36127
|
}
|
|
35988
36128
|
try {
|
|
35989
|
-
const
|
|
35990
|
-
const text = await
|
|
36129
|
+
const store4 = await getStateStore(projectRoot, env);
|
|
36130
|
+
const text = await store4.materializeContext(void 0, opts?.maxChars);
|
|
35991
36131
|
cache = { text: text || "", at: now, projectRoot };
|
|
35992
36132
|
return cache.text;
|
|
35993
36133
|
} catch {
|
|
@@ -37907,7 +38047,7 @@ __export(agentsMd_exports, {
|
|
|
37907
38047
|
updateAgentsMd: () => updateAgentsMd
|
|
37908
38048
|
});
|
|
37909
38049
|
import { existsSync as existsSync32, readFileSync as readFileSync28, writeFileSync as writeFileSync18 } from "node:fs";
|
|
37910
|
-
import { createHash as
|
|
38050
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
37911
38051
|
import { join as join27 } from "node:path";
|
|
37912
38052
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
37913
38053
|
async function readPackageJson2(projectRoot) {
|
|
@@ -38122,7 +38262,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
38122
38262
|
return { changed: true, sections: changedSections };
|
|
38123
38263
|
}
|
|
38124
38264
|
function hash2(s) {
|
|
38125
|
-
return
|
|
38265
|
+
return createHash8("sha256").update(s).digest("hex").slice(0, 16);
|
|
38126
38266
|
}
|
|
38127
38267
|
var AUTO_SECTIONS, MARKER_OPEN, MARKER_CLOSE, GENERATORS;
|
|
38128
38268
|
var init_agentsMd = __esm({
|
|
@@ -38933,7 +39073,7 @@ __export(commitHelpers_exports, {
|
|
|
38933
39073
|
});
|
|
38934
39074
|
async function tryStateCommit(args) {
|
|
38935
39075
|
try {
|
|
38936
|
-
const
|
|
39076
|
+
const store4 = args.store ?? await getStateStore(args.projectRoot, args.env);
|
|
38937
39077
|
let workspaceCheckpointId = args.workspaceCheckpointId;
|
|
38938
39078
|
if (!workspaceCheckpointId && args.withCheckpoint && (args.env ?? process.env).ZELARI_CHECKPOINT !== "0") {
|
|
38939
39079
|
const cp = await createCheckpoint(
|
|
@@ -38942,7 +39082,7 @@ async function tryStateCommit(args) {
|
|
|
38942
39082
|
);
|
|
38943
39083
|
if (cp.ok) workspaceCheckpointId = cp.value.id;
|
|
38944
39084
|
}
|
|
38945
|
-
const meta3 = await
|
|
39085
|
+
const meta3 = await store4.commit({
|
|
38946
39086
|
mode: args.mode,
|
|
38947
39087
|
label: args.label,
|
|
38948
39088
|
layer: args.layer,
|
|
@@ -44491,7 +44631,7 @@ import {
|
|
|
44491
44631
|
} from "node:fs";
|
|
44492
44632
|
import { join as join36 } from "node:path";
|
|
44493
44633
|
import { homedir as homedir13 } from "node:os";
|
|
44494
|
-
import { createHash as
|
|
44634
|
+
import { createHash as createHash9, randomBytes as randomBytes5, timingSafeEqual } from "node:crypto";
|
|
44495
44635
|
function getZelariHome() {
|
|
44496
44636
|
return join36(homedir13(), ".zelari-code");
|
|
44497
44637
|
}
|
|
@@ -44567,8 +44707,8 @@ function loadOrCreateToken(explicit) {
|
|
|
44567
44707
|
}
|
|
44568
44708
|
function tokenMatches(expected, provided) {
|
|
44569
44709
|
if (!provided) return false;
|
|
44570
|
-
const a =
|
|
44571
|
-
const b =
|
|
44710
|
+
const a = createHash9("sha256").update(expected).digest();
|
|
44711
|
+
const b = createHash9("sha256").update(provided).digest();
|
|
44572
44712
|
try {
|
|
44573
44713
|
return timingSafeEqual(a, b);
|
|
44574
44714
|
} catch {
|
|
@@ -49235,34 +49375,58 @@ function phaseKnobs(phase2) {
|
|
|
49235
49375
|
})
|
|
49236
49376
|
};
|
|
49237
49377
|
}
|
|
49238
|
-
|
|
49239
|
-
const estimated = estimateHistoryTokens(hist);
|
|
49240
|
-
const occupancy = Math.min(1, (estimated + sessionExtra) / contextLimit);
|
|
49241
|
-
return { estimated, occupancy };
|
|
49242
|
-
}
|
|
49378
|
+
var RESERVED_OUTPUT_TOKENS = 8192;
|
|
49243
49379
|
async function applyBudgetPolicyAsync(history2, phase2, opts) {
|
|
49244
49380
|
const contextLimit = resolveContextLimit(opts?.model);
|
|
49245
49381
|
const sessionExtra = opts?.sessionTokens ?? 0;
|
|
49246
49382
|
const warnings = [];
|
|
49247
49383
|
let { historyTurns, maxToolLoopIterations } = phaseKnobs(phase2);
|
|
49384
|
+
const envelope = opts?.requestSnapshot ?? null;
|
|
49385
|
+
const replayBase = envelope ? {
|
|
49386
|
+
provider: envelope.snapshot.provider,
|
|
49387
|
+
model: envelope.snapshot.model,
|
|
49388
|
+
systemMessages: envelope.snapshot.systemMessages,
|
|
49389
|
+
tools: envelope.snapshot.tools
|
|
49390
|
+
} : opts?.providerStream ? { provider: "local", model: opts?.model ?? "unknown", systemMessages: [], tools: [] } : null;
|
|
49391
|
+
const headerTokens = envelope ? estimateSystemTokensLite(envelope.snapshot.systemMessages) + estimateToolSchemaTokensLite(envelope.snapshot.tools) : 0;
|
|
49392
|
+
const convTokensOf = (h) => estimateConversationTokensLite(h);
|
|
49248
49393
|
let hist = history2;
|
|
49249
|
-
let
|
|
49394
|
+
let estimated = envelope ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
49395
|
+
let occupancy = Math.min(1, estimated / contextLimit);
|
|
49250
49396
|
let compactSummary = "";
|
|
49251
49397
|
let messagesRemoved = 0;
|
|
49398
|
+
let cacheReuseExpected;
|
|
49399
|
+
let prunedTotal = 0;
|
|
49252
49400
|
if (occupancy >= 0.7 && occupancy < 0.85) {
|
|
49253
49401
|
warnings.push(
|
|
49254
|
-
`[budget] context ~${Math.round(occupancy * 100)}% full (${estimated
|
|
49402
|
+
`[budget] context ~${Math.round(occupancy * 100)}% full (${estimated}/${contextLimit} tok full-request est.) \u2014 consider /compact or shorter replies.`
|
|
49255
49403
|
);
|
|
49256
49404
|
}
|
|
49405
|
+
if (occupancy >= 0.8) {
|
|
49406
|
+
const pruned = pruneToolResultsDetailed(hist);
|
|
49407
|
+
if (pruned.stats.pruned > 0) {
|
|
49408
|
+
hist = pruned.messages;
|
|
49409
|
+
prunedTotal += pruned.stats.pruned;
|
|
49410
|
+
estimated = envelope ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
49411
|
+
occupancy = Math.min(1, estimated / contextLimit);
|
|
49412
|
+
warnings.push(
|
|
49413
|
+
`[budget] pruned ${pruned.stats.pruned} oversized tool result(s) \u2192 ${Math.round(occupancy * 100)}% (${estimated} tok).`
|
|
49414
|
+
);
|
|
49415
|
+
}
|
|
49416
|
+
}
|
|
49257
49417
|
const fold = (r, label, forcedTurns) => {
|
|
49258
49418
|
hist = r.messages;
|
|
49259
49419
|
if (r.compacted) {
|
|
49260
49420
|
messagesRemoved += r.messagesRemoved;
|
|
49261
49421
|
if (r.summary) compactSummary = r.summary;
|
|
49422
|
+
if (r.cacheReuseExpected !== void 0) {
|
|
49423
|
+
cacheReuseExpected = r.cacheReuseExpected;
|
|
49424
|
+
}
|
|
49262
49425
|
}
|
|
49263
|
-
|
|
49426
|
+
estimated = envelope ? headerTokens + convTokensOf(hist) + RESERVED_OUTPUT_TOKENS : estimateHistoryTokens(hist) + sessionExtra;
|
|
49427
|
+
occupancy = Math.min(1, estimated / contextLimit);
|
|
49264
49428
|
warnings.push(
|
|
49265
|
-
`[budget] ${label}
|
|
49429
|
+
`[budget] ${label} \u2014 kept ~${forcedTurns} turns (${estimated} tok est.` + (r.messagesRemoved ? `, removed ${r.messagesRemoved} msgs` : "") + (r.cacheReuseExpected === false ? ", cache reuse NOT expected (model override)" : "") + ")."
|
|
49266
49430
|
);
|
|
49267
49431
|
};
|
|
49268
49432
|
if (occupancy >= 0.85) {
|
|
@@ -49272,39 +49436,91 @@ async function applyBudgetPolicyAsync(history2, phase2, opts) {
|
|
|
49272
49436
|
maxToolLoopIterations,
|
|
49273
49437
|
phase2 === "plan" ? 24 : 40
|
|
49274
49438
|
);
|
|
49275
|
-
|
|
49276
|
-
maxMessages: forcedTurns * 4,
|
|
49277
|
-
|
|
49278
|
-
|
|
49279
|
-
|
|
49439
|
+
let r = await compactHistoryAsync(hist, {
|
|
49440
|
+
maxMessages: Math.max(2, forcedTurns * 4),
|
|
49441
|
+
force: true,
|
|
49442
|
+
signal: opts?.signal,
|
|
49443
|
+
...replayBase ? { requestSnapshot: replayBase, providerStream: opts?.providerStream } : {}
|
|
49444
|
+
});
|
|
49445
|
+
if (!r.compacted) {
|
|
49446
|
+
r = await compactHistoryAsync(hist, {
|
|
49447
|
+
maxMessages: 2,
|
|
49448
|
+
force: true,
|
|
49449
|
+
signal: opts?.signal,
|
|
49450
|
+
...replayBase ? { requestSnapshot: replayBase, providerStream: opts?.providerStream } : {}
|
|
49451
|
+
});
|
|
49452
|
+
}
|
|
49453
|
+
const label = r.cacheReuseExpected === false ? "llm-compact (model override)" : "auto-compact";
|
|
49280
49454
|
fold(r, label, forcedTurns);
|
|
49281
49455
|
}
|
|
49282
49456
|
if (occupancy >= 0.95) {
|
|
49283
49457
|
const hard = await compactHistoryAsync(hist, {
|
|
49284
|
-
maxMessages:
|
|
49458
|
+
maxMessages: 2,
|
|
49459
|
+
force: true,
|
|
49285
49460
|
signal: opts?.signal
|
|
49286
49461
|
});
|
|
49287
|
-
fold(hard, hard.summary.includes("\xB7 llm") ? "llm-compact" : "
|
|
49462
|
+
fold(hard, hard.summary.includes("\xB7 llm") ? "llm-compact" : "HARD trim", 2);
|
|
49288
49463
|
historyTurns = 2;
|
|
49289
49464
|
maxToolLoopIterations = Math.min(maxToolLoopIterations, 16);
|
|
49290
49465
|
warnings.push(
|
|
49291
|
-
|
|
49466
|
+
"[budget] HARD context pressure (\u226595%) \u2014 prefer /clear or a new session if quality drops."
|
|
49292
49467
|
);
|
|
49293
49468
|
}
|
|
49469
|
+
const cacheMetricsLine = envelope ? [
|
|
49470
|
+
"compaction meter:",
|
|
49471
|
+
`provider/model: ${envelope.snapshot.provider}/${envelope.snapshot.model}`,
|
|
49472
|
+
`headerFingerprint: ${envelope.snapshot.headerFingerprint.slice(0, 12)}`,
|
|
49473
|
+
`occupancy: ${Math.round(occupancy * 100)}% (${estimated}/${contextLimit})`,
|
|
49474
|
+
...envelope.usage?.cachedPromptTokens !== void 0 ? [`cachedPromptTokens: ${envelope.usage.cachedPromptTokens}`] : [],
|
|
49475
|
+
...cacheReuseExpected !== void 0 ? [`cacheReuseExpected: ${cacheReuseExpected}`] : []
|
|
49476
|
+
].join(" | ") : void 0;
|
|
49294
49477
|
return {
|
|
49295
49478
|
history: hist,
|
|
49296
49479
|
warnings,
|
|
49297
49480
|
maxToolLoopIterations,
|
|
49298
49481
|
historyTurns,
|
|
49299
|
-
estimatedHistoryTokens: estimated,
|
|
49482
|
+
estimatedHistoryTokens: envelope ? convTokensOf(hist) : estimated,
|
|
49300
49483
|
contextLimit,
|
|
49301
49484
|
occupancy,
|
|
49302
49485
|
compactSummary: compactSummary || void 0,
|
|
49303
|
-
messagesRemoved: messagesRemoved || void 0
|
|
49486
|
+
messagesRemoved: messagesRemoved || void 0,
|
|
49487
|
+
...envelope ? { contextPressureTokens: estimated } : {},
|
|
49488
|
+
...cacheReuseExpected !== void 0 ? { cacheReuseExpected } : {},
|
|
49489
|
+
...cacheMetricsLine ? { cacheMetricsLine } : {}
|
|
49304
49490
|
};
|
|
49305
49491
|
}
|
|
49492
|
+
function estimateSystemTokensLite(systemMessages) {
|
|
49493
|
+
let n = 0;
|
|
49494
|
+
for (const m of systemMessages) n += 4 + Math.ceil((m.content ?? "").length / 4);
|
|
49495
|
+
return n;
|
|
49496
|
+
}
|
|
49497
|
+
function estimateToolSchemaTokensLite(tools) {
|
|
49498
|
+
let n = 0;
|
|
49499
|
+
for (const t of tools) {
|
|
49500
|
+
n += Math.ceil((t.name ?? "").length / 4);
|
|
49501
|
+
n += Math.ceil((t.description ?? "").length / 4);
|
|
49502
|
+
n += Math.ceil(JSON.stringify(t.parameters ?? {}).length / 4);
|
|
49503
|
+
}
|
|
49504
|
+
return n + tools.length * 4;
|
|
49505
|
+
}
|
|
49506
|
+
function estimateConversationTokensLite(messages) {
|
|
49507
|
+
let n = 0;
|
|
49508
|
+
for (const m of messages) {
|
|
49509
|
+
n += 4 + Math.ceil((m.content ?? "").length / 4);
|
|
49510
|
+
if (m.toolCalls) {
|
|
49511
|
+
for (const tc of m.toolCalls) {
|
|
49512
|
+
n += Math.ceil(tc.name.length / 4) + Math.ceil(tc.id.length / 4);
|
|
49513
|
+
n += Math.ceil(JSON.stringify(tc.args ?? {}).length / 4);
|
|
49514
|
+
}
|
|
49515
|
+
}
|
|
49516
|
+
if (m.reasoningContent) n += Math.ceil(m.reasoningContent.length / 4);
|
|
49517
|
+
if (m.toolCallId) n += Math.ceil(m.toolCallId.length / 4);
|
|
49518
|
+
}
|
|
49519
|
+
return n;
|
|
49520
|
+
}
|
|
49306
49521
|
|
|
49307
49522
|
// src/cli/hooks/useChatTurn.ts
|
|
49523
|
+
init_requestSnapshotStore();
|
|
49308
49524
|
function useChatTurn(params) {
|
|
49309
49525
|
const {
|
|
49310
49526
|
sessionId,
|
|
@@ -49331,17 +49547,9 @@ function useChatTurn(params) {
|
|
|
49331
49547
|
let envConfig;
|
|
49332
49548
|
let harness;
|
|
49333
49549
|
let historySeedLen = 0;
|
|
49550
|
+
let systemPrefixLen = 0;
|
|
49334
49551
|
let turnSucceeded = false;
|
|
49335
49552
|
try {
|
|
49336
|
-
compactInPlace();
|
|
49337
|
-
const budget = await applyBudgetPolicyAsync(getHistory(), getPhase(), {
|
|
49338
|
-
model: getActiveModel()
|
|
49339
|
-
});
|
|
49340
|
-
setHistory(budget.history);
|
|
49341
|
-
for (const w of budget.warnings) {
|
|
49342
|
-
appendSystem(setMessages, w, Date.now());
|
|
49343
|
-
}
|
|
49344
|
-
historySeedLen = getHistory().length;
|
|
49345
49553
|
const anchored = maybeAnchorShortAnswer(userText);
|
|
49346
49554
|
const effectiveUserText = anchored ?? userText;
|
|
49347
49555
|
const localCli = (process.env.ZELARI_LOCAL_CLI ?? "").trim();
|
|
@@ -49436,6 +49644,33 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
49436
49644
|
});
|
|
49437
49645
|
}
|
|
49438
49646
|
const cwd = process.cwd();
|
|
49647
|
+
const budget = await applyBudgetPolicyAsync(getHistory(), getPhase(), {
|
|
49648
|
+
model: getActiveModel(),
|
|
49649
|
+
sessionId,
|
|
49650
|
+
// v1.36.0: envelope for full-request metering + cache-aware
|
|
49651
|
+
// compaction replay (last warm prefix + provider usage anchor).
|
|
49652
|
+
requestSnapshot: getRequestSnapshotWithUsage(sessionId),
|
|
49653
|
+
providerStream
|
|
49654
|
+
});
|
|
49655
|
+
setHistory(budget.history);
|
|
49656
|
+
for (const w of budget.warnings) {
|
|
49657
|
+
appendSystem(setMessages, w, Date.now());
|
|
49658
|
+
}
|
|
49659
|
+
if ((budget.messagesRemoved ?? 0) > 0) {
|
|
49660
|
+
const envelope = getRequestSnapshotWithUsage(sessionId);
|
|
49661
|
+
const compactionEvent = createBrainEvent("session_compacted", sessionId, {
|
|
49662
|
+
summary: budget.compactSummary ?? "",
|
|
49663
|
+
messagesRemoved: budget.messagesRemoved ?? 0,
|
|
49664
|
+
...envelope ? {
|
|
49665
|
+
sourceRequestFingerprint: envelope.snapshot.requestFingerprint,
|
|
49666
|
+
headerFingerprint: envelope.snapshot.headerFingerprint
|
|
49667
|
+
} : {},
|
|
49668
|
+
...budget.contextPressureTokens !== void 0 ? { sourceEstimatedTokens: budget.contextPressureTokens } : {},
|
|
49669
|
+
...budget.cacheReuseExpected !== void 0 ? { cacheReuseExpected: budget.cacheReuseExpected } : {}
|
|
49670
|
+
});
|
|
49671
|
+
void writerRef.current?.append(compactionEvent);
|
|
49672
|
+
}
|
|
49673
|
+
historySeedLen = getHistory().length;
|
|
49439
49674
|
let composedWorkspace = "";
|
|
49440
49675
|
let composedInstructions = "";
|
|
49441
49676
|
let hasPlan = false;
|
|
@@ -49593,6 +49828,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
49593
49828
|
lastStableHash = hashStablePrompt(fallback);
|
|
49594
49829
|
systemMessages = [{ role: "system", content: fallback }];
|
|
49595
49830
|
}
|
|
49831
|
+
systemPrefixLen = systemMessages.length;
|
|
49596
49832
|
const maxToolCallsPerTurn = envNumber(process.env.ZELARI_MAX_TOOL_CALLS, {
|
|
49597
49833
|
default: 25,
|
|
49598
49834
|
min: 1
|
|
@@ -49605,7 +49841,10 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
49605
49841
|
});
|
|
49606
49842
|
const harness2 = new AgentHarness({
|
|
49607
49843
|
model: envConfig.model,
|
|
49608
|
-
|
|
49844
|
+
// v1.36.0 (P0.2): real provider identity — the harness used to
|
|
49845
|
+
// hardcode "openai-compatible" (the transport family) so snapshots
|
|
49846
|
+
// and telemetry mislabeled deepseek/glm/minimax routing.
|
|
49847
|
+
provider: envConfig.providerId,
|
|
49609
49848
|
messages: [
|
|
49610
49849
|
...systemMessages,
|
|
49611
49850
|
// v1.8.0: shared rolling history (agent/council/zelari) so short
|
|
@@ -49624,6 +49863,9 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
49624
49863
|
cwd,
|
|
49625
49864
|
maxToolCallsPerTurn,
|
|
49626
49865
|
maxToolLoopIterations,
|
|
49866
|
+
// v1.36.0: routed-request snapshots feed the meter (occupancy) and
|
|
49867
|
+
// the cache-aware compaction replay (last warm prefix).
|
|
49868
|
+
onRequestSnapshot: (snap) => recordRequestSnapshot(sessionId, snap),
|
|
49627
49869
|
...maxToolLoopHardCap > 0 ? { maxToolLoopHardCap } : {}
|
|
49628
49870
|
});
|
|
49629
49871
|
harnessRef.current = harness2;
|
|
@@ -49638,6 +49880,14 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
49638
49880
|
for await (const event of harness2.run()) {
|
|
49639
49881
|
if (event.type === "message_end") {
|
|
49640
49882
|
if (event.usage) realUsage = event.usage;
|
|
49883
|
+
if (event.usage) {
|
|
49884
|
+
recordRequestUsage(sessionId, {
|
|
49885
|
+
promptTokens: event.usage.promptTokens,
|
|
49886
|
+
completionTokens: event.usage.completionTokens,
|
|
49887
|
+
totalTokens: event.usage.totalTokens,
|
|
49888
|
+
cachedPromptTokens: event.usage.cachedPromptTokens
|
|
49889
|
+
});
|
|
49890
|
+
}
|
|
49641
49891
|
if (streamContent) {
|
|
49642
49892
|
const sealed = streamScrub.finalize(streamContent);
|
|
49643
49893
|
if (useLiveModel) setStreaming(commitStreaming, sealed, event.ts);
|
|
@@ -49797,18 +50047,17 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
49797
50047
|
const h = harnessRef.current;
|
|
49798
50048
|
if (h && turnSucceeded) {
|
|
49799
50049
|
const all = h.getMessages();
|
|
49800
|
-
const seedLen =
|
|
50050
|
+
const seedLen = systemPrefixLen + historySeedLen + 1;
|
|
49801
50051
|
if (all.length > seedLen) {
|
|
49802
50052
|
appendMessages(
|
|
49803
|
-
all.slice(seedLen).map(
|
|
49804
|
-
(m
|
|
49805
|
-
|
|
49806
|
-
|
|
49807
|
-
|
|
49808
|
-
|
|
49809
|
-
|
|
49810
|
-
|
|
49811
|
-
)
|
|
50053
|
+
all.slice(seedLen).map((m) => {
|
|
50054
|
+
if (m.role !== "assistant" || !m.content) return m;
|
|
50055
|
+
const cleaned = cleanAgentContent(m.content, {
|
|
50056
|
+
stripQuestion: false,
|
|
50057
|
+
stripThink: false
|
|
50058
|
+
});
|
|
50059
|
+
return cleaned === m.content ? m : { ...m, content: cleaned };
|
|
50060
|
+
})
|
|
49812
50061
|
);
|
|
49813
50062
|
}
|
|
49814
50063
|
}
|
|
@@ -51751,12 +52000,12 @@ init_fileStateStore();
|
|
|
51751
52000
|
async function restoreDurableState(opts) {
|
|
51752
52001
|
const restoreTree = opts.restoreTree !== false;
|
|
51753
52002
|
try {
|
|
51754
|
-
const
|
|
52003
|
+
const store4 = opts.store ?? await getStateStore(opts.projectRoot);
|
|
51755
52004
|
let meta3;
|
|
51756
52005
|
if (opts.commitId) {
|
|
51757
|
-
meta3 = await
|
|
52006
|
+
meta3 = await store4.setHead(opts.commitId);
|
|
51758
52007
|
} else {
|
|
51759
|
-
meta3 = await
|
|
52008
|
+
meta3 = await store4.head();
|
|
51760
52009
|
if (!meta3) {
|
|
51761
52010
|
return {
|
|
51762
52011
|
ok: false,
|
|
@@ -51809,8 +52058,8 @@ function ago2(ms) {
|
|
|
51809
52058
|
return `${Math.round(s / 3600)}h ago`;
|
|
51810
52059
|
}
|
|
51811
52060
|
async function handleStateStatus(ctx) {
|
|
51812
|
-
const
|
|
51813
|
-
const head = await
|
|
52061
|
+
const store4 = await getStateStore(ctx.cwd);
|
|
52062
|
+
const head = await store4.head();
|
|
51814
52063
|
if (!head) {
|
|
51815
52064
|
appendSystem(
|
|
51816
52065
|
ctx.setMessages,
|
|
@@ -51818,9 +52067,9 @@ async function handleStateStatus(ctx) {
|
|
|
51818
52067
|
);
|
|
51819
52068
|
return;
|
|
51820
52069
|
}
|
|
51821
|
-
const discoveries = await
|
|
52070
|
+
const discoveries = await store4.loadDiscoveries(head.id);
|
|
51822
52071
|
const reusable = discoveries.filter((d) => d.reusable).length;
|
|
51823
|
-
const recent = await
|
|
52072
|
+
const recent = await store4.list(8);
|
|
51824
52073
|
const lines = recent.map((c, i) => {
|
|
51825
52074
|
const ver2 = c.verification.ran ? c.verification.ok ? "ok" : "fail" : "n/a";
|
|
51826
52075
|
return ` ${i === 0 ? "\u2192" : " "} ${c.id} ${ago2(c.createdAt)} ${c.label} ver=${ver2}` + (c.layer ? ` [${c.layer}]` : "") + (c.stablePromptHash ? ` hash=${c.stablePromptHash.slice(0, 8)}` : "");
|
|
@@ -51839,9 +52088,9 @@ async function handleStateStatus(ctx) {
|
|
|
51839
52088
|
);
|
|
51840
52089
|
}
|
|
51841
52090
|
async function handleStateCommit(ctx, label) {
|
|
51842
|
-
const
|
|
52091
|
+
const store4 = await getStateStore(ctx.cwd);
|
|
51843
52092
|
try {
|
|
51844
|
-
const meta3 = await
|
|
52093
|
+
const meta3 = await store4.commit({
|
|
51845
52094
|
mode: "agent",
|
|
51846
52095
|
label: label?.trim() || "manual state commit",
|
|
51847
52096
|
layer: "manual",
|
|
@@ -51868,8 +52117,8 @@ async function handleStateCommit(ctx, label) {
|
|
|
51868
52117
|
}
|
|
51869
52118
|
}
|
|
51870
52119
|
async function handleStateShow(ctx, id) {
|
|
51871
|
-
const
|
|
51872
|
-
const meta3 = id ? await
|
|
52120
|
+
const store4 = await getStateStore(ctx.cwd);
|
|
52121
|
+
const meta3 = id ? await store4.get(id) : await store4.head();
|
|
51873
52122
|
if (!meta3) {
|
|
51874
52123
|
appendSystem(
|
|
51875
52124
|
ctx.setMessages,
|
|
@@ -51877,7 +52126,7 @@ async function handleStateShow(ctx, id) {
|
|
|
51877
52126
|
);
|
|
51878
52127
|
return;
|
|
51879
52128
|
}
|
|
51880
|
-
const text = await
|
|
52129
|
+
const text = await store4.materializeContext(meta3.id, 6e3);
|
|
51881
52130
|
appendSystem(ctx.setMessages, `[state] show ${meta3.id}
|
|
51882
52131
|
${text}`);
|
|
51883
52132
|
}
|
|
@@ -53386,14 +53635,14 @@ async function handleSkillCompare(ctx, ids, fallbackMessage) {
|
|
|
53386
53635
|
}
|
|
53387
53636
|
function handleCouncilFeedback(ctx, memberId, score, note) {
|
|
53388
53637
|
try {
|
|
53389
|
-
const
|
|
53390
|
-
const entry =
|
|
53638
|
+
const store4 = new FeedbackStore();
|
|
53639
|
+
const entry = store4.record({
|
|
53391
53640
|
memberId,
|
|
53392
53641
|
score,
|
|
53393
53642
|
...note ? { note } : {},
|
|
53394
53643
|
...ctx.sessionId ? { sessionId: ctx.sessionId } : {}
|
|
53395
53644
|
});
|
|
53396
|
-
const stats =
|
|
53645
|
+
const stats = store4.getStats(memberId);
|
|
53397
53646
|
appendSystem(
|
|
53398
53647
|
ctx.setMessages,
|
|
53399
53648
|
`[council-feedback] ${memberId} rated ${entry.score}/5 \u2014 running avg ${stats.avg.toFixed(2)} over ${stats.count} rating(s).`
|