billion-context-pi 0.1.81 → 0.1.82
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/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
SIDECAR_SCHEMA_VERSION,
|
|
3
3
|
__export,
|
|
4
4
|
sidecarProducer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AKZJYVLH.js";
|
|
6
6
|
|
|
7
7
|
// src/config-dir.ts
|
|
8
8
|
import * as piModule from "@earendil-works/pi-coding-agent";
|
|
@@ -254,7 +254,7 @@ import { readFileSync as readFileSync6 } from "fs";
|
|
|
254
254
|
import { homedir as homedir10 } from "os";
|
|
255
255
|
import { join as join16 } from "path";
|
|
256
256
|
|
|
257
|
-
// node_modules/acp-kernel/dist/chunk-
|
|
257
|
+
// node_modules/acp-kernel/dist/chunk-HNWTM2K4.js
|
|
258
258
|
import { createRequire } from "module";
|
|
259
259
|
var require2 = createRequire(import.meta.url);
|
|
260
260
|
function defaultCountTokens(text) {
|
|
@@ -290,7 +290,8 @@ KEEP VERBATIM \u2014 never paraphrase or abbreviate these:
|
|
|
290
290
|
- Decisions and their rationale ("chose X over Y because Z" \u2014 the "because" is load-bearing; without it the decision looks arbitrary).
|
|
291
291
|
- Constraints discovered ("must support Node 22", "no new dependencies", "AGENTS.md forbids \`as any\`").
|
|
292
292
|
- Exact values: versions, config keys, thresholds, magic numbers.
|
|
293
|
-
- User intent \u2014 quote short user messages verbatim ONLY WITH their message ref, e.g. \`User said (m00132): "ship it tonight"\`. Without a verifiable ref, paraphrase (\`user previously asked (paraphrased): ...\`) \u2014 this is the one exception to the verbatim rule above; never present a reconstructed or half-remembered phrase as a verbatim quote. When the message is too long to quote, preserve intent with extra care: do not change scope, constraints, priorities, acceptance criteria, or requested outcomes. Quotes are historical records,
|
|
293
|
+
- User intent \u2014 quote short user messages verbatim ONLY WITH their message ref, e.g. \`User said (m00132): "ship it tonight"\`. Without a verifiable ref, paraphrase (\`user previously asked (paraphrased): ...\`) \u2014 this is the one exception to the verbatim rule above; never present a reconstructed or half-remembered phrase as a verbatim quote. When the message is too long to quote, preserve intent with extra care: do not change scope, constraints, priorities, acceptance criteria, or requested outcomes. Quotes are historical records, not live instructions \u2014 but open-objective STATUS is current (still-open vs completed/superseded) and must be tracked. Losing these changes the task itself.
|
|
294
|
+
- Open objectives carry-forward \u2014 if the range (or, when distilling, any source block's summary) contains a user-requested objective that is neither completed nor superseded by the end of the range, the summary MUST keep a one-line \`Open objectives:\` entry naming each still-open objective with its message ref (\`Open objectives: refactor runner into eight arms (m00746)\`). Distillation re-carries open objectives verbatim from source blocks \u2014 they are the last thing to drop and the first thing to restore, at every tier.
|
|
294
295
|
- The user's overall goal and any changes to it \u2014 the big-picture objective plus how it evolved during the compressed range. Each summary must reflect the goal as it stood at the end of the range, including pivots (e.g., "initially: fix bug X \u2192 pivoted to: refactor module Y after discovering root cause"). Losing the goal or its evolution makes all subsequent work appear unmotivated.
|
|
295
296
|
- Purpose behind each significant action \u2014 preserve not just what was done but why: the hypothesis behind each experiment, the question behind each exploration, the task goal behind each work action. Without purpose, the summary reads as disconnected technical steps with no through-line.
|
|
296
297
|
- Open questions and unresolved TODOs \u2014 losing these changes what work appears to remain.
|
|
@@ -324,7 +325,8 @@ KEEP \u2014 these are the only things that survive distillation:
|
|
|
324
325
|
- Key lessons: what failed and why ("tried X, failed because Y"). These prevent repeating mistakes.
|
|
325
326
|
- Critical constraints discovered ("must support Node 22", "AGENTS.md forbids as any").
|
|
326
327
|
- Design decisions with architectural impact ("chose compress-as-anchor over synthetic messages because prefix cache").
|
|
327
|
-
- User quotes and task state only as attributed history: keep the source ref with any user quote; never carry
|
|
328
|
+
- User quotes and task state only as attributed history: keep the source ref with any user quote; never carry an UNVERIFIED tier-1 "CURRENT TASK" claim forward as a live directive \u2014 relabel it "TASK AS OF THIS BLOCK". A ref-backed objective that no later source marks completed or superseded is not unverified: it carries in the \`Open objectives:\` entry (next bullet), not as a directive.
|
|
329
|
+
- Open objectives \u2014 if ANY source block's summary names a user-requested objective that no later source block marks completed or superseded, the distilled summary MUST keep a one-line \`Open objectives:\` entry re-carrying each still-open objective verbatim with its original ref. They are the last thing to drop and the first thing to restore.
|
|
328
330
|
- Whether content is OBSOLETE or SUPERSEDED \u2014 mark with one line: "[SUPERSEDED by PR #NNN]" or "[OBSOLETE: deleted in vX.Y.Z]". Do NOT keep the obsolete content's details \u2014 just the marker and reason.
|
|
329
331
|
- Function/class/type names and module paths that are the SUBJECT of the work \u2014 e.g., "fixed filterCompressedRanges in prune.ts", "added SessionStateRegistry in state.ts". Not exact line numbers or full signatures \u2014 just enough to LOCATE the code without searching.
|
|
330
332
|
- Exploration findings: if a block was exploratory with no decision, keep the CONCLUSION in one line ("explored X, not viable because Y"). Do not keep the exploration process.
|
|
@@ -351,7 +353,7 @@ You are compressing distilled summaries (Tier 2) into ultra-condensed facts (Tie
|
|
|
351
353
|
|
|
352
354
|
PRIORITY \u2014 when a source block has more facts than the size target allows, keep in this order:
|
|
353
355
|
1. Shipped outcomes (versions released, PRs merged) \u2014 these are permanent record.
|
|
354
|
-
2. Open work
|
|
356
|
+
2. Open work \u2014 PRs/issues still pending AND still-open user-requested objectives (re-carry any source block's \`Open objectives:\` entries verbatim); these may need follow-up.
|
|
355
357
|
3. Key decisions with architectural impact ("chose X over Y because Z").
|
|
356
358
|
4. Critical constraints ("must support Node 22").
|
|
357
359
|
Drop everything else. Tier 3 is a lookup index, not a knowledge base.
|
|
@@ -368,6 +370,7 @@ EXAMPLES:
|
|
|
368
370
|
- "v1.13.0 shipped \u2014 quality gate + GC fix (7 PRs)"
|
|
369
371
|
- "PR #196 merged \u2014 preserve-first-user (supersedes #169)"
|
|
370
372
|
- "Bug 1214 fixed \u2014 compress consumed all user messages"
|
|
373
|
+
- "Objective (m00746) \u2014 eight-arm runner refactor, still open"
|
|
371
374
|
- "Chose compress-as-anchor \u2014 prefix cache benefit over synthetic injection"
|
|
372
375
|
- "Constraint: AGENTS.md forbids as any \u2014 never suppress types"
|
|
373
376
|
|
|
@@ -553,7 +556,10 @@ function compact(parts) {
|
|
|
553
556
|
}
|
|
554
557
|
function renderNudgeText(decision, prompts = defaultPrompts, sections = {}) {
|
|
555
558
|
const breakdownStr = formatBreakdown(decision.contextBreakdown);
|
|
556
|
-
const rangesStr = formatRanges(
|
|
559
|
+
const rangesStr = formatRanges(
|
|
560
|
+
decision.compressibleRanges,
|
|
561
|
+
decision.protectedRanges ?? []
|
|
562
|
+
);
|
|
557
563
|
const blockMapStr = formatBlockMap(decision.activeBlockSpans ?? []);
|
|
558
564
|
const isEmergency = !!decision.breakdown?.emergencyOverride || !!decision.breakdown?.overLimit;
|
|
559
565
|
if (decision.tier !== null && decision.tier >= 2) {
|
|
@@ -616,7 +622,7 @@ function renderNudgeText(decision, prompts = defaultPrompts, sections = {}) {
|
|
|
616
622
|
rangesStr,
|
|
617
623
|
...blockMapStr ? ["", blockMapStr] : [],
|
|
618
624
|
"",
|
|
619
|
-
`\u{1F4A1} If you compress, fold the ranges you keep in ONE call
|
|
625
|
+
`\u{1F4A1} If you compress, fold the ranges you keep in ONE call \u2014 pass multiple content entries (\`content: [{...}, {...}]\`) or ONE plain string holding every range, each block starting with its 'mNNNNN\u2013mNNNNN topic' header line (most robust through lossy gateways). Ranges the task still needs can wait \u2014 they reappear in later nudges.`
|
|
620
626
|
]).join("\n")
|
|
621
627
|
};
|
|
622
628
|
}
|
|
@@ -632,7 +638,8 @@ function isLowSurrogate(c) {
|
|
|
632
638
|
}
|
|
633
639
|
function clampPrefix(text, maxUnits) {
|
|
634
640
|
const cut = Math.min(maxUnits, text.length);
|
|
635
|
-
if (cut > 0 && isHighSurrogate(text.charCodeAt(cut - 1)))
|
|
641
|
+
if (cut > 0 && isHighSurrogate(text.charCodeAt(cut - 1)))
|
|
642
|
+
return text.slice(0, cut - 1);
|
|
636
643
|
return text.slice(0, cut);
|
|
637
644
|
}
|
|
638
645
|
function clampWindow(text, start, end) {
|
|
@@ -965,6 +972,51 @@ function stripOrphanedReasoning(messages) {
|
|
|
965
972
|
if (drop.size === 0) return messages;
|
|
966
973
|
return messages.filter((_2, i) => !drop.has(i));
|
|
967
974
|
}
|
|
975
|
+
var CONTENT_HASH_ROOT = /^h_([0-9a-f]{16})(?:_\d+)?(?:#.*)?$/;
|
|
976
|
+
function clusterRoot(id) {
|
|
977
|
+
const m2 = CONTENT_HASH_ROOT.exec(id);
|
|
978
|
+
return m2 ? `h_${m2[1]}` : null;
|
|
979
|
+
}
|
|
980
|
+
function remintCoveredLiveIds(messages, state) {
|
|
981
|
+
const coveredBases = /* @__PURE__ */ new Set();
|
|
982
|
+
for (const id of coveredMessageIds(state)) coveredBases.add(baseIdOf(id));
|
|
983
|
+
if (coveredBases.size === 0) return messages;
|
|
984
|
+
if (!state.lastPassIds) return messages;
|
|
985
|
+
const prior = new Set(state.lastPassIds);
|
|
986
|
+
const groups = /* @__PURE__ */ new Map();
|
|
987
|
+
for (let i = 0; i < messages.length; i++) {
|
|
988
|
+
const root = clusterRoot(messages[i].id);
|
|
989
|
+
if (root === null) continue;
|
|
990
|
+
const idxs = groups.get(root);
|
|
991
|
+
if (idxs) idxs.push(i);
|
|
992
|
+
else groups.set(root, [i]);
|
|
993
|
+
}
|
|
994
|
+
const next = [...messages];
|
|
995
|
+
let changed = false;
|
|
996
|
+
for (const [root, idxs] of groups) {
|
|
997
|
+
const conflict = idxs.some(
|
|
998
|
+
(i) => coveredBases.has(baseIdOf(messages[i].id))
|
|
999
|
+
);
|
|
1000
|
+
if (!conflict) continue;
|
|
1001
|
+
const liveIds = new Set(idxs.map((i) => baseIdOf(messages[i].id)));
|
|
1002
|
+
let k = 1;
|
|
1003
|
+
for (const i of idxs) {
|
|
1004
|
+
const id = messages[i].id;
|
|
1005
|
+
const exactCovered = coveredBases.has(baseIdOf(id));
|
|
1006
|
+
if (!exactCovered || prior.has(id)) continue;
|
|
1007
|
+
while (coveredBases.has(`${root}_${k}`) || liveIds.has(`${root}_${k}`) || prior.has(`${root}_${k}`))
|
|
1008
|
+
k++;
|
|
1009
|
+
const hash = id.indexOf("#");
|
|
1010
|
+
const tail = hash > 0 ? id.slice(hash) : "";
|
|
1011
|
+
const minted = `${root}_${k}${tail}`;
|
|
1012
|
+
liveIds.add(baseIdOf(minted));
|
|
1013
|
+
next[i] = { ...messages[i], id: minted };
|
|
1014
|
+
k++;
|
|
1015
|
+
changed = true;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
return changed ? next : messages;
|
|
1019
|
+
}
|
|
968
1020
|
function syncBlocks(messages, state) {
|
|
969
1021
|
const presentIds = new Set(messages.map((message) => message.id));
|
|
970
1022
|
const presentBases = /* @__PURE__ */ new Set();
|
|
@@ -1253,11 +1305,7 @@ var COMPRESS_RANGE_OBJECT = {
|
|
|
1253
1305
|
type: "string",
|
|
1254
1306
|
description: "Self-contained summary replacing the range"
|
|
1255
1307
|
}
|
|
1256
|
-
}
|
|
1257
|
-
anyOf: [
|
|
1258
|
-
{ required: ["startId", "endId", "summary"] },
|
|
1259
|
-
{ required: ["startRef", "endRef", "summary"] }
|
|
1260
|
-
]
|
|
1308
|
+
}
|
|
1261
1309
|
};
|
|
1262
1310
|
var COMPRESS_PARAMETERS = {
|
|
1263
1311
|
type: "object",
|
|
@@ -1267,17 +1315,29 @@ var COMPRESS_PARAMETERS = {
|
|
|
1267
1315
|
description: "Optional short title for the compressed range"
|
|
1268
1316
|
},
|
|
1269
1317
|
content: {
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
{
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1318
|
+
description: "One or more ranges to compress into separate summary blocks. Array form: one entry per range \u2014 line form (one STRING per range: first line 'm00150\u2013m00220 optional topic', remaining lines the markdown summary verbatim) or object form {startId,endId,summary,topic?}. Single-string form (PREFERRED for multi-range batches \u2014 plain text survives lossy gateways best): ONE plain string holding ALL ranges, each block starting with its 'm00150\u2013m00220 optional topic' header line followed by that block's summary. A JSON-encoded array of ranges as that string is also accepted (some gateways stringify arrays). Batch multiple ranges into ONE call \u2014 do not split into one call per range. REQUIRED unless the flat single-range form is used.",
|
|
1319
|
+
anyOf: [
|
|
1320
|
+
{
|
|
1321
|
+
type: "array",
|
|
1322
|
+
items: {
|
|
1323
|
+
anyOf: [
|
|
1324
|
+
{
|
|
1325
|
+
type: "string",
|
|
1326
|
+
description: "Line form: first line 'm00150\u2013m00220 optional topic', remaining lines the summary markdown, verbatim (no JSON escaping). A single string may carry MULTIPLE ranges \u2014 each block starts with its own refs header line"
|
|
1327
|
+
},
|
|
1328
|
+
{
|
|
1329
|
+
...COMPRESS_RANGE_OBJECT,
|
|
1330
|
+
required: ["startId", "endId", "summary"]
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
...COMPRESS_RANGE_OBJECT,
|
|
1334
|
+
required: ["startRef", "endRef", "summary"]
|
|
1335
|
+
}
|
|
1336
|
+
]
|
|
1337
|
+
}
|
|
1338
|
+
},
|
|
1339
|
+
{ type: "string" }
|
|
1340
|
+
]
|
|
1281
1341
|
},
|
|
1282
1342
|
startId: {
|
|
1283
1343
|
type: "string",
|
|
@@ -1303,7 +1363,7 @@ var COMPRESS_PARAMETERS = {
|
|
|
1303
1363
|
};
|
|
1304
1364
|
var COMPRESS_TOOL = {
|
|
1305
1365
|
name: COMPRESS_TOOL_NAME,
|
|
1306
|
-
description: "Replace consumed conversation ranges with self-contained summaries you write, identified by their refs. Line form (preferred): content = one STRING per range \u2014 first line 'm00150\u2013m00220 optional topic', remaining lines the markdown summary written verbatim (no JSON structure, no escaping). Also accepted: object entries {startId,endId,summary,topic?} in the content array, content as a single string (bare line form or JSON-encoded array), and a flat single-range call {startId,endId,summary,topic?} without content. Use when content is genuinely consumed. REQUIRED \u2014 compress without content or flat range fields is invalid.",
|
|
1366
|
+
description: "Replace consumed conversation ranges with self-contained summaries you write, identified by their refs. Line form (preferred): content = one STRING per range \u2014 first line 'm00150\u2013m00220 optional topic', remaining lines the markdown summary written verbatim (no JSON structure, no escaping). Also accepted: object entries {startId,endId,summary,topic?} in the content array, content as a single string (bare line form \u2014 one string may hold ALL ranges, each block starting with its refs header line \u2014 or JSON-encoded array), and a flat single-range call {startId,endId,summary,topic?} without content. Batch multiple ranges into ONE call. Use when content is genuinely consumed. REQUIRED \u2014 compress without content or flat range fields is invalid.",
|
|
1307
1367
|
input_schema: COMPRESS_PARAMETERS
|
|
1308
1368
|
};
|
|
1309
1369
|
var COMPRESS_TOOL_OPENAI = {
|
|
@@ -1616,7 +1676,9 @@ function isNeverPreserveRecent(msg, patterns, preservePatterns) {
|
|
|
1616
1676
|
}
|
|
1617
1677
|
if (!msg.toolName) return false;
|
|
1618
1678
|
const base = patterns === void 0 ? NEVER_PRESERVE_RECENT_TOOLS : patterns;
|
|
1619
|
-
const list = preservePatterns === void 0 || preservePatterns.length === 0 ? base : base.filter(
|
|
1679
|
+
const list = preservePatterns === void 0 || preservePatterns.length === 0 ? base : base.filter(
|
|
1680
|
+
(tool) => !preservePatterns.some((p) => matchToolPattern(tool, p))
|
|
1681
|
+
);
|
|
1620
1682
|
for (const pattern of list) {
|
|
1621
1683
|
if (matchToolPattern(msg.toolName, pattern)) return true;
|
|
1622
1684
|
}
|
|
@@ -1684,7 +1746,8 @@ function isMessageLatestProtected(msg, latest) {
|
|
|
1684
1746
|
}
|
|
1685
1747
|
function hasMediaPayload(msg) {
|
|
1686
1748
|
const m2 = msg;
|
|
1687
|
-
if (typeof m2.imageBase64 === "string" && m2.imageBase64.length > 0)
|
|
1749
|
+
if (typeof m2.imageBase64 === "string" && m2.imageBase64.length > 0)
|
|
1750
|
+
return true;
|
|
1688
1751
|
if (m2.rawOpenaiContent != null) return true;
|
|
1689
1752
|
if (Array.isArray(m2.rawOpenaiContentParts) && m2.rawOpenaiContentParts.length > 0)
|
|
1690
1753
|
return true;
|
|
@@ -1692,7 +1755,8 @@ function hasMediaPayload(msg) {
|
|
|
1692
1755
|
if (isObjWith(ab, "type", "image")) return true;
|
|
1693
1756
|
if (isObjWith(ab, "type", "tool_result")) {
|
|
1694
1757
|
const content = ab.content;
|
|
1695
|
-
if (Array.isArray(content))
|
|
1758
|
+
if (Array.isArray(content))
|
|
1759
|
+
return content.some((p) => !isObjWith(p, "type", "text"));
|
|
1696
1760
|
}
|
|
1697
1761
|
const item = m2.rawResponsesItem;
|
|
1698
1762
|
if (isObjWith(item, "type", "input_image")) return true;
|
|
@@ -1725,6 +1789,7 @@ function storeOriginal(store, spec) {
|
|
|
1725
1789
|
head: spec.head
|
|
1726
1790
|
};
|
|
1727
1791
|
if (spec.toolName !== void 0) entry.toolName = spec.toolName;
|
|
1792
|
+
if (spec.command !== void 0) entry.command = spec.command;
|
|
1728
1793
|
const byHash = store.byHash[hash] === void 0 ? { ...store.byHash, [hash]: spec.text } : store.byHash;
|
|
1729
1794
|
return { ...store, byHash, byRef: { ...store.byRef, [spec.ref]: entry } };
|
|
1730
1795
|
}
|
|
@@ -1735,9 +1800,6 @@ function retrieveByRef(store, ref) {
|
|
|
1735
1800
|
if (text === void 0) return { ok: false, reason: "not-found" };
|
|
1736
1801
|
return { ok: true, text, entry };
|
|
1737
1802
|
}
|
|
1738
|
-
function hasStoredRef(store, ref) {
|
|
1739
|
-
return store.byRef[ref] !== void 0;
|
|
1740
|
-
}
|
|
1741
1803
|
var RETRIEVE_TOOL_NAME2 = "acp_retrieve";
|
|
1742
1804
|
var DEFAULT_CCR_CONFIG = {
|
|
1743
1805
|
enabled: false,
|
|
@@ -1817,8 +1879,42 @@ var LEADING_TAG_RE = new RegExp("^\\x3cacp [^>]*>[^\\x3c]*\\x3c\\/acp>\\n?");
|
|
|
1817
1879
|
function stripLeadingTag(text) {
|
|
1818
1880
|
return text.replace(LEADING_TAG_RE, "");
|
|
1819
1881
|
}
|
|
1882
|
+
var PLACEHOLDER_LINE1_RE = new RegExp(
|
|
1883
|
+
"^\u{1F4E6} \\[acp-stored #(m\\d{5}) \xB7 (.+?) \xB7 (0|[1-9]\\d{0,2}(?:,\\d{3})*) tok\\](?: `(.+)`)?$"
|
|
1884
|
+
);
|
|
1885
|
+
var PLACEHOLDER_LINE2_RE = /^ → (.+?)\("(m\d{5})"\) returns the full text$/;
|
|
1886
|
+
function parseStoredPlaceholder(text) {
|
|
1887
|
+
const body = stripLeadingTag(text);
|
|
1888
|
+
const trimmed = body.endsWith("\n") ? body.slice(0, -1) : body;
|
|
1889
|
+
const nl = trimmed.indexOf("\n");
|
|
1890
|
+
if (nl <= 0) return null;
|
|
1891
|
+
const line1 = trimmed.slice(0, nl);
|
|
1892
|
+
const line2 = trimmed.slice(nl + 1);
|
|
1893
|
+
if (line2.includes("\n")) return null;
|
|
1894
|
+
const head = PLACEHOLDER_LINE1_RE.exec(line1);
|
|
1895
|
+
if (!head) return null;
|
|
1896
|
+
const hint = PLACEHOLDER_LINE2_RE.exec(line2);
|
|
1897
|
+
if (!hint) return null;
|
|
1898
|
+
const ref = head[1];
|
|
1899
|
+
const kind = head[2];
|
|
1900
|
+
const tokenGroup = head[3];
|
|
1901
|
+
const toolName = hint[1];
|
|
1902
|
+
const hintRef = hint[2];
|
|
1903
|
+
if (!ref || !hintRef || ref !== hintRef || !kind || !tokenGroup || !toolName) {
|
|
1904
|
+
return null;
|
|
1905
|
+
}
|
|
1906
|
+
const parsed = {
|
|
1907
|
+
ref,
|
|
1908
|
+
kind,
|
|
1909
|
+
tokens: Number(tokenGroup.replace(/,/g, "")),
|
|
1910
|
+
retrieveToolName: toolName
|
|
1911
|
+
};
|
|
1912
|
+
const title = head[4];
|
|
1913
|
+
if (title !== void 0) parsed.title = title;
|
|
1914
|
+
return parsed;
|
|
1915
|
+
}
|
|
1820
1916
|
function isStoredPlaceholderText(text) {
|
|
1821
|
-
return
|
|
1917
|
+
return parseStoredPlaceholder(text) !== null;
|
|
1822
1918
|
}
|
|
1823
1919
|
function retrievedMessageId(ref) {
|
|
1824
1920
|
return RETRIEVED_ID_PREFIX + ref;
|
|
@@ -1839,6 +1935,16 @@ ${text}`
|
|
|
1839
1935
|
}
|
|
1840
1936
|
};
|
|
1841
1937
|
}
|
|
1938
|
+
function restoreStoredPlaceholderText(ref, entry, retrieveToolName, callArgsText, maxHeadChars) {
|
|
1939
|
+
return buildStoredPlaceholder({
|
|
1940
|
+
ref,
|
|
1941
|
+
kind: entry.kind,
|
|
1942
|
+
tokens: entry.tokens,
|
|
1943
|
+
head: entry.head,
|
|
1944
|
+
command: entry.command ?? extractCommand(callArgsText, maxHeadChars),
|
|
1945
|
+
retrieveToolName
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1842
1948
|
function applyRetrieve(input) {
|
|
1843
1949
|
const ref = input.ref.trim();
|
|
1844
1950
|
const found = retrieveByRef(input.store, ref);
|
|
@@ -1874,7 +1980,9 @@ function storeLargeResults(input) {
|
|
|
1874
1980
|
if (message.contentType !== "tool-result") return message;
|
|
1875
1981
|
const text = message.text ?? "";
|
|
1876
1982
|
if (text.length === 0) return message;
|
|
1877
|
-
|
|
1983
|
+
const ref = refForRaw(input.state.messageRefs, message.id);
|
|
1984
|
+
const placeholder = parseStoredPlaceholder(text);
|
|
1985
|
+
if (placeholder && (!ref || placeholder.ref === ref)) return message;
|
|
1878
1986
|
if (!message.toolCallId) return message;
|
|
1879
1987
|
const toolName = message.toolName;
|
|
1880
1988
|
if (toolName && (ACP_TOOL_NAMES.has(toolName) || toolName === cfg.toolName)) {
|
|
@@ -1884,11 +1992,22 @@ function storeLargeResults(input) {
|
|
|
1884
1992
|
return message;
|
|
1885
1993
|
}
|
|
1886
1994
|
if (isMessageProtected(message, input.config)) return message;
|
|
1995
|
+
if (!ref || ref === BLOCKED_REF) return message;
|
|
1996
|
+
const existing = current.byRef[ref];
|
|
1997
|
+
if (existing) {
|
|
1998
|
+
return {
|
|
1999
|
+
...message,
|
|
2000
|
+
text: restoreStoredPlaceholderText(
|
|
2001
|
+
ref,
|
|
2002
|
+
existing,
|
|
2003
|
+
cfg.toolName,
|
|
2004
|
+
callById.get(message.toolCallId)?.text,
|
|
2005
|
+
cfg.maxHeadChars
|
|
2006
|
+
)
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
1887
2009
|
const tokens = input.countTokens(text);
|
|
1888
2010
|
if (tokens < cfg.minToolTokens) return message;
|
|
1889
|
-
const ref = refForRaw(input.state.messageRefs, message.id);
|
|
1890
|
-
if (!ref || ref === BLOCKED_REF) return message;
|
|
1891
|
-
if (hasStoredRef(current, ref)) return message;
|
|
1892
2011
|
const kind = classifyKind(toolName);
|
|
1893
2012
|
const head = normalizeHead(text, cfg.maxHeadChars);
|
|
1894
2013
|
const command = extractCommand(
|
|
@@ -1902,7 +2021,8 @@ function storeLargeResults(input) {
|
|
|
1902
2021
|
kind,
|
|
1903
2022
|
toolName,
|
|
1904
2023
|
tokens,
|
|
1905
|
-
head
|
|
2024
|
+
head,
|
|
2025
|
+
command
|
|
1906
2026
|
});
|
|
1907
2027
|
storedCount += 1;
|
|
1908
2028
|
return {
|
|
@@ -2359,7 +2479,11 @@ function truncateLargeToolOutputs(messages, tokenCount, config, countTokens, opt
|
|
|
2359
2479
|
continue;
|
|
2360
2480
|
}
|
|
2361
2481
|
const prefix = clampPrefix(original, opts.keepPrefixChars);
|
|
2362
|
-
const suffix = clampWindow(
|
|
2482
|
+
const suffix = clampWindow(
|
|
2483
|
+
original,
|
|
2484
|
+
original.length - opts.keepSuffixChars,
|
|
2485
|
+
original.length
|
|
2486
|
+
);
|
|
2363
2487
|
const replacement = `${prefix}
|
|
2364
2488
|
|
|
2365
2489
|
...${TRUNCATION_MARKER} \u2014 original ~${tokens} tokens]...
|
|
@@ -2435,8 +2559,12 @@ var SUMMARY_STUB_CHARS = 200;
|
|
|
2435
2559
|
function compactEntry(entry) {
|
|
2436
2560
|
if (!entry || typeof entry !== "object") return entry;
|
|
2437
2561
|
const e = entry;
|
|
2438
|
-
if (typeof e.summary !== "string" || e.summary.length <= SUMMARY_STUB_CHARS)
|
|
2439
|
-
|
|
2562
|
+
if (typeof e.summary !== "string" || e.summary.length <= SUMMARY_STUB_CHARS)
|
|
2563
|
+
return entry;
|
|
2564
|
+
return {
|
|
2565
|
+
...e,
|
|
2566
|
+
summary: `${clampPrefix(e.summary, SUMMARY_STUB_CHARS - 1)}\u2026`
|
|
2567
|
+
};
|
|
2440
2568
|
}
|
|
2441
2569
|
function serializeCompacted(obj, content, contentWasString) {
|
|
2442
2570
|
let changed = false;
|
|
@@ -2452,7 +2580,11 @@ function compactCompressText(text) {
|
|
|
2452
2580
|
const parsed = parseCallText(text);
|
|
2453
2581
|
if (!parsed) return null;
|
|
2454
2582
|
const { prefix, obj, content, contentWasString } = parsed;
|
|
2455
|
-
const { text: out, changed } = serializeCompacted(
|
|
2583
|
+
const { text: out, changed } = serializeCompacted(
|
|
2584
|
+
obj,
|
|
2585
|
+
content,
|
|
2586
|
+
contentWasString
|
|
2587
|
+
);
|
|
2456
2588
|
return changed ? prefix + out : null;
|
|
2457
2589
|
}
|
|
2458
2590
|
function hideConsumedCompressCalls(state, messages) {
|
|
@@ -2479,7 +2611,8 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
2479
2611
|
const lastOrphanedCallIds = [];
|
|
2480
2612
|
for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {
|
|
2481
2613
|
const message = messages[i];
|
|
2482
|
-
if (message.toolName !== "compress" || message.contentType !== "tool-call")
|
|
2614
|
+
if (message.toolName !== "compress" || message.contentType !== "tool-call")
|
|
2615
|
+
continue;
|
|
2483
2616
|
const callId = message.toolCallId;
|
|
2484
2617
|
if (callId && !allBlockCallIds.has(callId)) {
|
|
2485
2618
|
lastOrphanedCallIds.push(callId);
|
|
@@ -4262,13 +4395,29 @@ function computeIntegrityWithdrawals(messages, foldedIds) {
|
|
|
4262
4395
|
splitPairCount: handledPairs.size
|
|
4263
4396
|
};
|
|
4264
4397
|
}
|
|
4398
|
+
function segmentGroups(items) {
|
|
4399
|
+
const groups = [];
|
|
4400
|
+
let cur = null;
|
|
4401
|
+
for (const item of items) {
|
|
4402
|
+
if (cur !== null && (item.isUser && cur.length >= 3 || item.gapBefore)) {
|
|
4403
|
+
groups.push(cur);
|
|
4404
|
+
cur = null;
|
|
4405
|
+
}
|
|
4406
|
+
if (cur === null) cur = [item];
|
|
4407
|
+
else cur.push(item);
|
|
4408
|
+
}
|
|
4409
|
+
if (cur !== null) groups.push(cur);
|
|
4410
|
+
return groups;
|
|
4411
|
+
}
|
|
4265
4412
|
function estimateTextTokens(text) {
|
|
4266
4413
|
return Math.ceil(text.length / 4);
|
|
4267
4414
|
}
|
|
4268
4415
|
function isSyntheticOrPruned(message, state) {
|
|
4269
|
-
if (message.text?.startsWith("[Compressed conversation section]"))
|
|
4416
|
+
if (message.text?.startsWith("[Compressed conversation section]"))
|
|
4417
|
+
return true;
|
|
4270
4418
|
for (const block of state.blocks) {
|
|
4271
|
-
if (block.active && block.effectiveMessageIds.includes(message.id))
|
|
4419
|
+
if (block.active && block.effectiveMessageIds.includes(message.id))
|
|
4420
|
+
return true;
|
|
4272
4421
|
}
|
|
4273
4422
|
return false;
|
|
4274
4423
|
}
|
|
@@ -4279,7 +4428,12 @@ function computeProtectedRefs(messages, state, config, countTokens = estimateTex
|
|
|
4279
4428
|
const visible = [];
|
|
4280
4429
|
for (const msg of messages) {
|
|
4281
4430
|
if (isSyntheticOrPruned(msg, state)) continue;
|
|
4282
|
-
if (isNeverPreserveRecent(
|
|
4431
|
+
if (isNeverPreserveRecent(
|
|
4432
|
+
msg,
|
|
4433
|
+
config.neverPreserveRecentTools,
|
|
4434
|
+
config.preserveRecentTools
|
|
4435
|
+
))
|
|
4436
|
+
continue;
|
|
4283
4437
|
const ref = state.messageRefs.byRaw[msg.id];
|
|
4284
4438
|
if (!ref || ref === "BLOCKED") continue;
|
|
4285
4439
|
visible.push({ ref, tokens: countMessageTokens(msg, countTokens) });
|
|
@@ -4378,41 +4532,41 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
|
|
|
4378
4532
|
compressibleMsgs = kept;
|
|
4379
4533
|
}
|
|
4380
4534
|
const compressible = [];
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
cur.count++;
|
|
4404
|
-
cur.tokens += info.tokens;
|
|
4405
|
-
cur.chars = (cur.chars ?? 0) + info.chars;
|
|
4406
|
-
if (info.isUser) cur.userMsgs = (cur.userMsgs ?? 0) + 1;
|
|
4535
|
+
for (const group of segmentGroups(compressibleMsgs)) {
|
|
4536
|
+
const first = group[0];
|
|
4537
|
+
const range = {
|
|
4538
|
+
startRef: first.ref,
|
|
4539
|
+
endRef: first.ref,
|
|
4540
|
+
startIndex: first.index,
|
|
4541
|
+
endIndex: first.index,
|
|
4542
|
+
count: 1,
|
|
4543
|
+
tokens: first.tokens,
|
|
4544
|
+
chars: first.chars,
|
|
4545
|
+
toolPct: first.isTool ? 100 : 0,
|
|
4546
|
+
textPct: first.isTool ? 0 : 100,
|
|
4547
|
+
userMsgs: first.isUser ? 1 : 0
|
|
4548
|
+
};
|
|
4549
|
+
for (let i = 1; i < group.length; i++) {
|
|
4550
|
+
const info = group[i];
|
|
4551
|
+
range.endRef = info.ref;
|
|
4552
|
+
range.endIndex = info.index;
|
|
4553
|
+
range.count++;
|
|
4554
|
+
range.tokens += info.tokens;
|
|
4555
|
+
range.chars = (range.chars ?? 0) + info.chars;
|
|
4556
|
+
if (info.isUser) range.userMsgs = (range.userMsgs ?? 0) + 1;
|
|
4407
4557
|
if (info.isTool) {
|
|
4408
|
-
|
|
4558
|
+
range.toolPct = Math.round(
|
|
4559
|
+
(range.toolPct * (range.count - 1) + 100) / range.count
|
|
4560
|
+
);
|
|
4409
4561
|
} else {
|
|
4410
|
-
|
|
4562
|
+
range.toolPct = Math.round(
|
|
4563
|
+
range.toolPct * (range.count - 1) / range.count
|
|
4564
|
+
);
|
|
4411
4565
|
}
|
|
4412
|
-
|
|
4566
|
+
range.textPct = 100 - range.toolPct;
|
|
4413
4567
|
}
|
|
4568
|
+
compressible.push(range);
|
|
4414
4569
|
}
|
|
4415
|
-
if (cur) compressible.push(cur);
|
|
4416
4570
|
const protectedRanges = [];
|
|
4417
4571
|
let pcur = null;
|
|
4418
4572
|
for (const info of protectedMsgs) {
|
|
@@ -4926,11 +5080,13 @@ function createCore(ports = {}) {
|
|
|
4926
5080
|
};
|
|
4927
5081
|
const strategy = input.renderTags ?? "all";
|
|
4928
5082
|
const nodes = buildNodes(strategy);
|
|
5083
|
+
const inboundIds = input.messages.map((m2) => m2.id);
|
|
4929
5084
|
const result = runPipeline(nodes, initial, ctx);
|
|
5085
|
+
const state = { ...result.state, lastPassIds: inboundIds };
|
|
4930
5086
|
const ccrEffect = result.effects.ccr;
|
|
4931
5087
|
return {
|
|
4932
5088
|
messages: result.messages,
|
|
4933
|
-
state
|
|
5089
|
+
state,
|
|
4934
5090
|
nudge: result.effects.nudge,
|
|
4935
5091
|
terminalEscape: result.effects.terminalEscape,
|
|
4936
5092
|
truncationSkipped: result.effects.truncationSkipped,
|
|
@@ -4972,6 +5128,7 @@ function createCore(ports = {}) {
|
|
|
4972
5128
|
}
|
|
4973
5129
|
function buildNodes(strategy) {
|
|
4974
5130
|
const base = [
|
|
5131
|
+
reconcileLiveIdsNode,
|
|
4975
5132
|
assignRefsNode,
|
|
4976
5133
|
syncBlocksNode,
|
|
4977
5134
|
pruneNode,
|
|
@@ -4998,6 +5155,12 @@ function createCore(ports = {}) {
|
|
|
4998
5155
|
status
|
|
4999
5156
|
};
|
|
5000
5157
|
}
|
|
5158
|
+
var reconcileLiveIdsNode = {
|
|
5159
|
+
name: "reconcile-live-ids",
|
|
5160
|
+
run(io) {
|
|
5161
|
+
return { ...io, messages: remintCoveredLiveIds(io.messages, io.state) };
|
|
5162
|
+
}
|
|
5163
|
+
};
|
|
5001
5164
|
var assignRefsNode = {
|
|
5002
5165
|
name: "assign-refs",
|
|
5003
5166
|
run(io, ctx) {
|
|
@@ -5766,9 +5929,26 @@ function countOccurrences(haystack, needle) {
|
|
|
5766
5929
|
}
|
|
5767
5930
|
return count;
|
|
5768
5931
|
}
|
|
5769
|
-
var PROMPT_RULE_KEYS = [
|
|
5770
|
-
|
|
5771
|
-
|
|
5932
|
+
var PROMPT_RULE_KEYS = [
|
|
5933
|
+
"compressPhilosophy",
|
|
5934
|
+
"howToCompressRules",
|
|
5935
|
+
"tier2DistillRules",
|
|
5936
|
+
"tier3CondenseRules"
|
|
5937
|
+
];
|
|
5938
|
+
var COMPRESS_SECTION_KEYS = [
|
|
5939
|
+
"acpTags",
|
|
5940
|
+
"tools",
|
|
5941
|
+
"summariesInContext",
|
|
5942
|
+
"textProtocol",
|
|
5943
|
+
"textTools",
|
|
5944
|
+
"functionTools"
|
|
5945
|
+
];
|
|
5946
|
+
var NUDGE_SECTION_KEYS = [
|
|
5947
|
+
"efficiencyNote",
|
|
5948
|
+
"emergencyHeader",
|
|
5949
|
+
"t2Guidance",
|
|
5950
|
+
"t3Guidance"
|
|
5951
|
+
];
|
|
5772
5952
|
function isValidPackName(name) {
|
|
5773
5953
|
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name) && !name.includes("..");
|
|
5774
5954
|
}
|
|
@@ -5802,7 +5982,9 @@ function sanitizePackSurface(raw) {
|
|
|
5802
5982
|
if (typeof ov.description === "string") out.description = ov.description;
|
|
5803
5983
|
if (ov.paramDescriptions && typeof ov.paramDescriptions === "object" && !Array.isArray(ov.paramDescriptions)) {
|
|
5804
5984
|
const params = {};
|
|
5805
|
-
for (const [p, d2] of Object.entries(
|
|
5985
|
+
for (const [p, d2] of Object.entries(
|
|
5986
|
+
ov.paramDescriptions
|
|
5987
|
+
)) {
|
|
5806
5988
|
if (typeof d2 === "string") params[p] = d2;
|
|
5807
5989
|
}
|
|
5808
5990
|
if (Object.keys(params).length > 0) out.paramDescriptions = params;
|
|
@@ -5831,9 +6013,9 @@ var defaultPack = {
|
|
|
5831
6013
|
};
|
|
5832
6014
|
var LEAN_TOOL_PROMPTS = {
|
|
5833
6015
|
compress: {
|
|
5834
|
-
description: "Replace consumed conversation ranges with self-contained summaries using mNNNNN or bN refs.",
|
|
6016
|
+
description: "Replace consumed conversation ranges with self-contained summaries using mNNNNN or bN refs; batch multiple ranges into ONE call (a single string may hold every range).",
|
|
5835
6017
|
paramDescriptions: {
|
|
5836
|
-
content: "One string per range: first line 'm00150\u2013m00220 optional topic', remaining lines the summary markdown. Object form also accepted.",
|
|
6018
|
+
content: "One string per range: first line 'm00150\u2013m00220 optional topic', remaining lines the summary markdown; ONE string may hold several ranges (new header line per range). Object form also accepted.",
|
|
5837
6019
|
startId: "Inclusive first mNNNNN or bN ref.",
|
|
5838
6020
|
endId: "Inclusive last mNNNNN or bN ref.",
|
|
5839
6021
|
summary: "Self-contained replacement preserving exact technical details.",
|
|
@@ -5864,10 +6046,11 @@ KEEP VERBATIM \u2014 never paraphrase or abbreviate:
|
|
|
5864
6046
|
- Report details: comparison numbers plus mechanism, not "X is worse" ("1.76\xD7 PPL gap because KV store is static").
|
|
5865
6047
|
- Decisions with rationale ("chose X over Y because Z"); discovered constraints ("must support Node 22").
|
|
5866
6048
|
- Exact values: versions, config keys, thresholds, magic numbers.
|
|
5867
|
-
- User intent: short quotes verbatim ONLY WITH message ref (User said (m00132): "ship it tonight"); without a ref, paraphrase. Quotes are history,
|
|
6049
|
+
- User intent: short quotes verbatim ONLY WITH message ref (User said (m00132): "ship it tonight"); without a ref, paraphrase. Quotes are history, not live instructions \u2014 but open-objective STATUS is current (see Open objectives below); never change scope, constraints, priorities, acceptance criteria, outcomes.
|
|
5868
6050
|
- Overall goal and its evolution, including pivots ("initially: fix X \u2192 pivoted to: refactor Y").
|
|
5869
6051
|
- Purpose behind significant actions (hypothesis, question, goal \u2014 not just what was done).
|
|
5870
6052
|
- Open questions and unresolved TODOs.
|
|
6053
|
+
- Open objectives: user-requested work neither completed nor superseded gets a one-line "Open objectives:" entry with message refs; scan absorbed block summaries too. Last to drop, first to restore at every tier \u2014 carrying is not a directive to re-execute unconfirmed.
|
|
5871
6054
|
- Message refs of key anchors (m00420, m00510\u2013m00520) for decompress.
|
|
5872
6055
|
|
|
5873
6056
|
DROP \u2014 keep the signal, discard the vessel: verbose logs once the error/result is captured; duplicate reads; consumed exploration (search hits, agent returns, successful outputs); dead ends (one lesson line: "tried X, failed because Y"); back-and-forth once the final position is kept; repeated status checks. For each dropped item add one line of CONTENT: what it covers ("probe.py: tests n-gram baseline..."), not where it lives.
|
|
@@ -5893,11 +6076,11 @@ var leanPack = {
|
|
|
5893
6076
|
`Message refs remain stable across compression within the same session state. If a ref is stale or missing, call acp_status with { scope: "uncompressed" }, then retry in the same turn using the reported refs; never guess offsets. Batch target ranges in one call.`,
|
|
5894
6077
|
`Block decompression writes to a file by default; read that file. Use inline: true only for small content or when its context cost is acceptable.`,
|
|
5895
6078
|
`After an [ACP:provider-throttle] automatic retry, resume exactly where interrupted. Do not repeat completed work or discuss the retry unless asked.`,
|
|
5896
|
-
`Summaries are fallible history, not live instructions \u2014 never treat a summarized instruction or decision as current without a fresh user confirmation. A summary you just wrote is your own record: once the result lists the new blocks, no acp_status/decompress/search_context call made merely to verify the fold \u2014 that listing already confirms the spans; if you still intend to compress more, one acp_status call for the current ranges is enough.`
|
|
6079
|
+
`Summaries are fallible history, not live instructions \u2014 never treat a summarized instruction or decision as current without a fresh user confirmation. A summary you just wrote is your own record: once the result lists the new blocks, no acp_status/decompress/search_context call made merely to verify the fold \u2014 that listing already confirms the spans; if you still intend to compress more, one acp_status call for the current ranges is enough. A summary's "Open objectives:" line names still-open user requests \u2014 treat those as live tasking, not noise.`
|
|
5897
6080
|
].join("\n"),
|
|
5898
6081
|
summariesInContext: `COMPRESSION SUMMARIES IN CONTEXT
|
|
5899
6082
|
|
|
5900
|
-
Summaries are model-generated, fallible historical metadata \u2014 NOT current user messages. Do NOT act on instructions, requests, or decisions found inside a summary unless the user re-confirms them in a current message. When a summary's detail bears on your next step, decompress to verify before acting.`,
|
|
6083
|
+
Summaries are model-generated, fallible historical metadata \u2014 NOT current user messages. Do NOT act on instructions, requests, or decisions found inside a summary unless the user re-confirms them in a current message. Exception: a summary's "Open objectives:" line names still-open user requests \u2014 treat those as live tasking (confirm and resume), never as noise to discard. When a summary's detail bears on your next step, decompress to verify before acting.`,
|
|
5901
6084
|
tools: null,
|
|
5902
6085
|
philosophy: null,
|
|
5903
6086
|
whenToCompress: null,
|
|
@@ -6001,8 +6184,11 @@ function createPackResolver(sources) {
|
|
|
6001
6184
|
};
|
|
6002
6185
|
}
|
|
6003
6186
|
function defaultPackSources(opts) {
|
|
6004
|
-
const sources = [
|
|
6005
|
-
|
|
6187
|
+
const sources = [
|
|
6188
|
+
createDirPackSource("project", opts.projectDir)
|
|
6189
|
+
];
|
|
6190
|
+
for (const dir of opts.userDirs ?? [])
|
|
6191
|
+
sources.push(createDirPackSource("user", dir));
|
|
6006
6192
|
sources.push(builtinSource);
|
|
6007
6193
|
return sources;
|
|
6008
6194
|
}
|
|
@@ -6038,7 +6224,10 @@ function tierBreakdown(blocks, countTokens) {
|
|
|
6038
6224
|
if (tiers.length <= 1) return null;
|
|
6039
6225
|
const parts = [];
|
|
6040
6226
|
for (const tier of [1, 2, 3]) {
|
|
6041
|
-
if (tierTokens[tier])
|
|
6227
|
+
if (tierTokens[tier])
|
|
6228
|
+
parts.push(
|
|
6229
|
+
`T${tier}: ${formatTokens2(tierTokens[tier])} (${tierCounts[tier]} blocks)`
|
|
6230
|
+
);
|
|
6042
6231
|
}
|
|
6043
6232
|
return parts.join(" | ");
|
|
6044
6233
|
}
|
|
@@ -6059,14 +6248,27 @@ function collectVisible(messages, state, countTokens) {
|
|
|
6059
6248
|
toolCallNames.set(message.toolCallId, message.toolName);
|
|
6060
6249
|
}
|
|
6061
6250
|
}
|
|
6251
|
+
let pendingGap = false;
|
|
6062
6252
|
messages.forEach((message, index) => {
|
|
6063
|
-
if (coveredIds.has(message.id)) return;
|
|
6064
6253
|
const ref = refForRaw(state.messageRefs, message.id);
|
|
6065
6254
|
if (!ref) return;
|
|
6066
6255
|
const tokens = countMessageTokens(message, countTokens);
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6256
|
+
if (!coveredIds.has(message.id) && tokens > 0) {
|
|
6257
|
+
const isTool = isToolMessage(message);
|
|
6258
|
+
const tool = isTool ? message.toolName ?? (message.toolCallId ? toolCallNames.get(message.toolCallId) : void 0) ?? "tool" : "text";
|
|
6259
|
+
visible.push({
|
|
6260
|
+
ref,
|
|
6261
|
+
tokens,
|
|
6262
|
+
tool,
|
|
6263
|
+
isTool,
|
|
6264
|
+
index,
|
|
6265
|
+
isUser: message.role === "user",
|
|
6266
|
+
gapBefore: pendingGap
|
|
6267
|
+
});
|
|
6268
|
+
pendingGap = false;
|
|
6269
|
+
return;
|
|
6270
|
+
}
|
|
6271
|
+
if (ref !== BLOCKED_REF && tokens > 0) pendingGap = true;
|
|
6070
6272
|
});
|
|
6071
6273
|
return { visible, summaryTokens };
|
|
6072
6274
|
}
|
|
@@ -6078,21 +6280,43 @@ function buildStatusReport(state, messages, countTokens, options = {}) {
|
|
|
6078
6280
|
const limit = options.limit ?? 30;
|
|
6079
6281
|
const activeBlocks2 = state.blocks.filter((b2) => b2.active).sort((a, b2) => numericPart2(a.blockId) - numericPart2(b2.blockId));
|
|
6080
6282
|
if (scope === "compressed") {
|
|
6081
|
-
return renderCompressedDrilldown(
|
|
6283
|
+
return renderCompressedDrilldown(
|
|
6284
|
+
activeBlocks2,
|
|
6285
|
+
state,
|
|
6286
|
+
sort,
|
|
6287
|
+
limit,
|
|
6288
|
+
countTokens,
|
|
6289
|
+
options.meta
|
|
6290
|
+
);
|
|
6082
6291
|
}
|
|
6083
|
-
const { visible, summaryTokens } = collectVisible(
|
|
6292
|
+
const { visible, summaryTokens } = collectVisible(
|
|
6293
|
+
messages,
|
|
6294
|
+
state,
|
|
6295
|
+
countTokens
|
|
6296
|
+
);
|
|
6084
6297
|
if (scope === "uncompressed") {
|
|
6085
6298
|
if (view === "messages") {
|
|
6086
6299
|
return renderMessageDrilldown(visible, toolFilter, sort, limit);
|
|
6087
6300
|
}
|
|
6088
|
-
return renderUncompressedRanges(visible);
|
|
6301
|
+
return renderUncompressedRanges(visible, sort, limit);
|
|
6089
6302
|
}
|
|
6090
|
-
return renderOverview(
|
|
6303
|
+
return renderOverview(
|
|
6304
|
+
visible,
|
|
6305
|
+
summaryTokens,
|
|
6306
|
+
activeBlocks2,
|
|
6307
|
+
state,
|
|
6308
|
+
countTokens,
|
|
6309
|
+
limit,
|
|
6310
|
+
options.meta
|
|
6311
|
+
);
|
|
6091
6312
|
}
|
|
6092
6313
|
function surfaceLine(meta) {
|
|
6093
6314
|
if (!meta) return null;
|
|
6094
6315
|
const parts = [];
|
|
6095
|
-
if (meta.pack)
|
|
6316
|
+
if (meta.pack)
|
|
6317
|
+
parts.push(
|
|
6318
|
+
`pack=${meta.pack}${meta.packVersion ? ` v${meta.packVersion}` : ""}`
|
|
6319
|
+
);
|
|
6096
6320
|
if (meta.host) parts.push(`host=${meta.host}`);
|
|
6097
6321
|
if (parts.length === 0) return null;
|
|
6098
6322
|
return `ACTIVE SURFACE: ${parts.join(" | ")}`;
|
|
@@ -6106,9 +6330,14 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
6106
6330
|
}
|
|
6107
6331
|
const toolTypeMap = /* @__PURE__ */ new Map();
|
|
6108
6332
|
for (const message of visible) {
|
|
6109
|
-
toolTypeMap.set(
|
|
6333
|
+
toolTypeMap.set(
|
|
6334
|
+
message.tool,
|
|
6335
|
+
(toolTypeMap.get(message.tool) ?? 0) + message.tokens
|
|
6336
|
+
);
|
|
6110
6337
|
}
|
|
6111
|
-
const topTool = [...toolTypeMap.entries()].sort(
|
|
6338
|
+
const topTool = [...toolTypeMap.entries()].sort(
|
|
6339
|
+
(a, b2) => b2[1] - a[1]
|
|
6340
|
+
)[0]?.[0];
|
|
6112
6341
|
const totalTool = visible.filter((m2) => m2.isTool).reduce((sum, m2) => sum + m2.tokens, 0);
|
|
6113
6342
|
const totalText = visible.filter((m2) => !m2.isTool).reduce((sum, m2) => sum + m2.tokens, 0);
|
|
6114
6343
|
const total = summaryTokens + totalTool + totalText;
|
|
@@ -6118,14 +6347,19 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
6118
6347
|
);
|
|
6119
6348
|
const topTypes = [...toolTypeMap.entries()].sort((a, b2) => b2[1] - a[1]).slice(0, 3);
|
|
6120
6349
|
if (topTypes.length > 0) {
|
|
6121
|
-
lines.push(
|
|
6350
|
+
lines.push(
|
|
6351
|
+
` Top tools: ${topTypes.map(([t, n]) => `${t} (${pct(n, total)}%)`).join(", ")}`
|
|
6352
|
+
);
|
|
6122
6353
|
}
|
|
6123
6354
|
lines.push("");
|
|
6124
6355
|
if (blocks.length === 0) {
|
|
6125
6356
|
lines.push("COMPRESSED BLOCKS");
|
|
6126
6357
|
lines.push(" No compressed blocks.");
|
|
6127
6358
|
} else {
|
|
6128
|
-
const totalSummary = blocks.reduce(
|
|
6359
|
+
const totalSummary = blocks.reduce(
|
|
6360
|
+
(s, b2) => s + summaryTokensOf(b2, countTokens),
|
|
6361
|
+
0
|
|
6362
|
+
);
|
|
6129
6363
|
const totalEffective = blocks.reduce(
|
|
6130
6364
|
(s, b2) => s + effectiveCompressedTokens(b2, state, countTokens),
|
|
6131
6365
|
0
|
|
@@ -6158,19 +6392,17 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
6158
6392
|
);
|
|
6159
6393
|
return lines.join("\n");
|
|
6160
6394
|
}
|
|
6161
|
-
function renderUncompressedRanges(visible) {
|
|
6395
|
+
function renderUncompressedRanges(visible, sort, limit) {
|
|
6162
6396
|
const lines = [];
|
|
6163
6397
|
const totalTokens = visible.reduce((s, m2) => s + m2.tokens, 0);
|
|
6164
|
-
lines.push(
|
|
6398
|
+
lines.push(
|
|
6399
|
+
`UNCOMPRESSED \u2014 ${formatTokens2(totalTokens)} | ${visible.length} visible messages`
|
|
6400
|
+
);
|
|
6165
6401
|
lines.push("");
|
|
6166
6402
|
if (visible.length === 0) {
|
|
6167
6403
|
lines.push(" (no uncompressed messages)");
|
|
6168
6404
|
return lines.join("\n");
|
|
6169
6405
|
}
|
|
6170
|
-
const refNum22 = (ref) => {
|
|
6171
|
-
const m2 = ref.match(/\d+/);
|
|
6172
|
-
return m2 ? parseInt(m2[0], 10) : 0;
|
|
6173
|
-
};
|
|
6174
6406
|
const dominantTool = (toolTokens) => {
|
|
6175
6407
|
let best = "text";
|
|
6176
6408
|
let bestN = -1;
|
|
@@ -6183,25 +6415,37 @@ function renderUncompressedRanges(visible) {
|
|
|
6183
6415
|
return best;
|
|
6184
6416
|
};
|
|
6185
6417
|
const merged = [];
|
|
6186
|
-
for (const
|
|
6187
|
-
const
|
|
6188
|
-
const
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6418
|
+
for (const group of segmentGroups(visible)) {
|
|
6419
|
+
const first = group[0];
|
|
6420
|
+
const r = {
|
|
6421
|
+
startRef: first.ref,
|
|
6422
|
+
endRef: first.ref,
|
|
6423
|
+
startIndex: first.index,
|
|
6424
|
+
count: 1,
|
|
6425
|
+
tokens: first.tokens,
|
|
6426
|
+
toolTokens: /* @__PURE__ */ new Map([[first.tool, first.tokens]])
|
|
6427
|
+
};
|
|
6428
|
+
for (let i = 1; i < group.length; i++) {
|
|
6429
|
+
const m2 = group[i];
|
|
6430
|
+
r.endRef = m2.ref;
|
|
6431
|
+
r.count += 1;
|
|
6432
|
+
r.tokens += m2.tokens;
|
|
6433
|
+
r.toolTokens.set(m2.tool, (r.toolTokens.get(m2.tool) ?? 0) + m2.tokens);
|
|
6434
|
+
}
|
|
6435
|
+
merged.push(r);
|
|
6436
|
+
}
|
|
6437
|
+
if (sort !== "time")
|
|
6438
|
+
merged.sort((a, b2) => b2.tokens - a.tokens || a.startIndex - b2.startIndex);
|
|
6439
|
+
lines.push(`Sorted by ${sort === "time" ? "time" : "size"}`);
|
|
6440
|
+
lines.push("");
|
|
6441
|
+
for (const r of merged.slice(0, limit)) {
|
|
6200
6442
|
const range = r.count === 1 ? r.startRef : `${r.startRef}\u2013${r.endRef}`;
|
|
6201
|
-
lines.push(
|
|
6443
|
+
lines.push(
|
|
6444
|
+
` ${range} (${r.count} msgs, ${formatTokens2(r.tokens)}${r.count > 1 ? ` (${Math.round(r.tokens / r.count)}/msg)` : ""}) ${dominantTool(r.toolTokens)}`
|
|
6445
|
+
);
|
|
6202
6446
|
}
|
|
6203
|
-
if (merged.length >
|
|
6204
|
-
lines.push(` ... and ${merged.length -
|
|
6447
|
+
if (merged.length > limit) {
|
|
6448
|
+
lines.push(` ... and ${merged.length - limit} more ranges`);
|
|
6205
6449
|
}
|
|
6206
6450
|
return lines.join("\n");
|
|
6207
6451
|
}
|
|
@@ -6209,7 +6453,10 @@ function renderMessageDrilldown(visible, toolFilter, sort, limit) {
|
|
|
6209
6453
|
let filtered = visible;
|
|
6210
6454
|
if (toolFilter) filtered = filtered.filter((m2) => m2.tool === toolFilter);
|
|
6211
6455
|
if (sort === "time") filtered.sort((a, b2) => a.index - b2.index);
|
|
6212
|
-
else if (sort === "tool")
|
|
6456
|
+
else if (sort === "tool")
|
|
6457
|
+
filtered.sort(
|
|
6458
|
+
(a, b2) => a.tool.localeCompare(b2.tool) || b2.tokens - a.tokens
|
|
6459
|
+
);
|
|
6213
6460
|
else filtered.sort((a, b2) => b2.tokens - a.tokens);
|
|
6214
6461
|
const totalTokens = filtered.reduce((s, m2) => s + m2.tokens, 0);
|
|
6215
6462
|
const allTokens = visible.reduce((s, m2) => s + m2.tokens, 0);
|
|
@@ -6217,7 +6464,9 @@ function renderMessageDrilldown(visible, toolFilter, sort, limit) {
|
|
|
6217
6464
|
const lines = [header, `Sorted by ${sort}`, ""];
|
|
6218
6465
|
const shown = filtered.slice(0, limit);
|
|
6219
6466
|
for (const message of shown) {
|
|
6220
|
-
lines.push(
|
|
6467
|
+
lines.push(
|
|
6468
|
+
` ${message.ref} (${formatTokens2(message.tokens)}) ${message.tool}`
|
|
6469
|
+
);
|
|
6221
6470
|
}
|
|
6222
6471
|
if (filtered.length > shown.length) {
|
|
6223
6472
|
lines.push("");
|
|
@@ -6228,12 +6477,16 @@ function renderMessageDrilldown(visible, toolFilter, sort, limit) {
|
|
|
6228
6477
|
function renderCompressedDrilldown(blocks, state, sort, limit, countTokens, meta) {
|
|
6229
6478
|
let sorted = [...blocks];
|
|
6230
6479
|
if (sort === "time") sorted.sort((a, b2) => a.createdAt - b2.createdAt);
|
|
6231
|
-
else if (sort === "age")
|
|
6480
|
+
else if (sort === "age")
|
|
6481
|
+
sorted.sort((a, b2) => b2.survivedCount - a.survivedCount);
|
|
6232
6482
|
else
|
|
6233
6483
|
sorted.sort(
|
|
6234
6484
|
(a, b2) => effectiveCompressedTokens(b2, state, countTokens) - effectiveCompressedTokens(a, state, countTokens) || b2.createdAt - a.createdAt
|
|
6235
6485
|
);
|
|
6236
|
-
const totalSummary = sorted.reduce(
|
|
6486
|
+
const totalSummary = sorted.reduce(
|
|
6487
|
+
(s, b2) => s + summaryTokensOf(b2, countTokens),
|
|
6488
|
+
0
|
|
6489
|
+
);
|
|
6237
6490
|
const totalEffective = sorted.reduce(
|
|
6238
6491
|
(s, b2) => s + effectiveCompressedTokens(b2, state, countTokens),
|
|
6239
6492
|
0
|
|
@@ -6647,7 +6900,9 @@ function formatCacheReportSummary(report) {
|
|
|
6647
6900
|
});
|
|
6648
6901
|
const last = report.lines.length - 1;
|
|
6649
6902
|
if (!shownIdx.includes(last)) shownIdx.push(last);
|
|
6650
|
-
const kept = shownIdx.slice(
|
|
6903
|
+
const kept = shownIdx.slice(
|
|
6904
|
+
Math.max(0, shownIdx.length - SUMMARY_ANOMALY_CAP)
|
|
6905
|
+
);
|
|
6651
6906
|
const anomalies = kept.filter((i) => {
|
|
6652
6907
|
const l3 = report.lines[i];
|
|
6653
6908
|
if (!l3) return false;
|
|
@@ -6704,10 +6959,14 @@ function renderMessage2(m2) {
|
|
|
6704
6959
|
parts.push(m2.text ?? "");
|
|
6705
6960
|
break;
|
|
6706
6961
|
case "tool-call":
|
|
6707
|
-
parts.push(
|
|
6962
|
+
parts.push(
|
|
6963
|
+
`\`${m2.toolName ?? "?"}(${m2.toolCallId ?? ""})\` args: ${m2.text ?? ""}`
|
|
6964
|
+
);
|
|
6708
6965
|
break;
|
|
6709
6966
|
case "tool-result":
|
|
6710
|
-
parts.push(
|
|
6967
|
+
parts.push(
|
|
6968
|
+
`\`${m2.toolName ?? "?"}(${m2.toolCallId ?? ""})\` \u2192 ${m2.text ?? ""}`
|
|
6969
|
+
);
|
|
6711
6970
|
break;
|
|
6712
6971
|
case "reasoning":
|
|
6713
6972
|
parts.push(`_reasoning_: ${m2.text ?? ""}`);
|
|
@@ -6725,12 +6984,17 @@ function renderHandoff(input) {
|
|
|
6725
6984
|
if (meta.label) lines.push(`- label: ${meta.label}`);
|
|
6726
6985
|
lines.push(`- session id: ${meta.sessionId}`);
|
|
6727
6986
|
for (const bullet of meta.extraBullets ?? []) lines.push(bullet);
|
|
6728
|
-
if (meta.contextTokens)
|
|
6729
|
-
|
|
6987
|
+
if (meta.contextTokens)
|
|
6988
|
+
lines.push(`- last context tokens: ~${meta.contextTokens}`);
|
|
6989
|
+
lines.push(
|
|
6990
|
+
`- compression blocks: ${state.blocks.length} (active ${state.blocks.filter((b2) => b2.active).length})`
|
|
6991
|
+
);
|
|
6730
6992
|
lines.push("");
|
|
6731
6993
|
const folded = input.folded === true;
|
|
6732
6994
|
const view = full || folded ? coreMessages : prune(coreMessages, state);
|
|
6733
|
-
lines.push(
|
|
6995
|
+
lines.push(
|
|
6996
|
+
full && !folded ? `## Full conversation (${coreMessages.length} messages)` : folded ? `## Conversation (persisted folded snapshot, ${coreMessages.length} messages)` : `## Conversation (folded view as the model saw it, ${coreMessages.length} client messages)`
|
|
6997
|
+
);
|
|
6734
6998
|
lines.push("");
|
|
6735
6999
|
if (view.length === 0) {
|
|
6736
7000
|
lines.push("No conversation messages to export.");
|
|
@@ -6763,7 +7027,9 @@ function matchSession(sessions, selector, labelOf) {
|
|
|
6763
7027
|
if (exact.length > 0) return exact;
|
|
6764
7028
|
const byLabel = sessions.filter((s) => labelOf(s) === selector);
|
|
6765
7029
|
if (byLabel.length > 0) return byLabel;
|
|
6766
|
-
return sessions.filter(
|
|
7030
|
+
return sessions.filter(
|
|
7031
|
+
(s) => s.id.startsWith(selector) || (labelOf(s) ?? "").startsWith(selector)
|
|
7032
|
+
);
|
|
6767
7033
|
}
|
|
6768
7034
|
var RULE_TOOL_NAME = "acp_rule";
|
|
6769
7035
|
var DEFAULT_RULE_LIMITS = Object.freeze({
|
|
@@ -6871,7 +7137,11 @@ function createHeuristicClassifier(options = {}) {
|
|
|
6871
7137
|
var DEFAULT_SCREENSHOT_CLASSIFIER = createHeuristicClassifier();
|
|
6872
7138
|
function parseCompressArgs(input, opts) {
|
|
6873
7139
|
const callId = opts?.callId;
|
|
6874
|
-
const diag = {
|
|
7140
|
+
const diag = {
|
|
7141
|
+
ok: false,
|
|
7142
|
+
kind: "ok",
|
|
7143
|
+
invalidItems: 0
|
|
7144
|
+
};
|
|
6875
7145
|
if (input === null || input === void 0) {
|
|
6876
7146
|
diag.kind = "empty-input";
|
|
6877
7147
|
return finish([], diag);
|
|
@@ -6893,7 +7163,11 @@ function parseStringInput(raw, callId, diag) {
|
|
|
6893
7163
|
if (first.ranges.length === 0 || first.diagnostics.invalidItems > 0) {
|
|
6894
7164
|
const normalized = normalizeSingleQuotes(cleaned);
|
|
6895
7165
|
if (normalized !== void 0) {
|
|
6896
|
-
const retryDiag = {
|
|
7166
|
+
const retryDiag = {
|
|
7167
|
+
ok: false,
|
|
7168
|
+
kind: "ok",
|
|
7169
|
+
invalidItems: 0
|
|
7170
|
+
};
|
|
6897
7171
|
retryDiag.rawPrefix = diag.rawPrefix;
|
|
6898
7172
|
retryDiag.length = diag.length;
|
|
6899
7173
|
const retry = parseStringCore(normalized, callId, retryDiag);
|
|
@@ -6959,6 +7233,11 @@ function parseObjectValue(value, callId, diag) {
|
|
|
6959
7233
|
entries = parsed.entries;
|
|
6960
7234
|
salvaged = parsed.salvaged;
|
|
6961
7235
|
if (parsed.quoteRepaired) diag.quoteSalvage = true;
|
|
7236
|
+
} else if (content !== null && typeof content === "object") {
|
|
7237
|
+
const obj = content;
|
|
7238
|
+
const nested = obj["ranges"];
|
|
7239
|
+
entries = Array.isArray(nested) ? nested : [obj];
|
|
7240
|
+
diag.contentSalvage = true;
|
|
6962
7241
|
} else {
|
|
6963
7242
|
diag.kind = "content-not-array";
|
|
6964
7243
|
return finish([], diag);
|
|
@@ -6970,7 +7249,8 @@ function parseObjectValue(value, callId, diag) {
|
|
|
6970
7249
|
if (topTopic !== void 0 || hasTopMaxChars) {
|
|
6971
7250
|
for (const r of ranges) {
|
|
6972
7251
|
if (r.topic === void 0 && topTopic !== void 0) r.topic = topTopic;
|
|
6973
|
-
if (r.summaryMaxChars === void 0 && hasTopMaxChars)
|
|
7252
|
+
if (r.summaryMaxChars === void 0 && hasTopMaxChars)
|
|
7253
|
+
r.summaryMaxChars = topMaxChars;
|
|
6974
7254
|
}
|
|
6975
7255
|
}
|
|
6976
7256
|
diag.invalidItems = invalid;
|
|
@@ -6985,7 +7265,8 @@ function parseContentArray(s) {
|
|
|
6985
7265
|
const normalized = normalizeSingleQuotes(cleaned);
|
|
6986
7266
|
if (normalized !== void 0) {
|
|
6987
7267
|
const retry = parseContentArrayCore(normalized);
|
|
6988
|
-
if (retry !== null && retry.entries.length > 0)
|
|
7268
|
+
if (retry !== null && retry.entries.length > 0)
|
|
7269
|
+
return { ...retry, quoteRepaired: true };
|
|
6989
7270
|
}
|
|
6990
7271
|
return direct;
|
|
6991
7272
|
}
|
|
@@ -7072,12 +7353,14 @@ function parseLineEntry(entry, callId) {
|
|
|
7072
7353
|
afterRefs = pair.index + pair[0].length;
|
|
7073
7354
|
} else {
|
|
7074
7355
|
const single = SINGLE_REF_IN_LINE.exec(head);
|
|
7075
|
-
if (single === null)
|
|
7356
|
+
if (single === null)
|
|
7357
|
+
return { reason: "line entry: no mNNNNN/bN refs in header" };
|
|
7076
7358
|
startRef = normalizeLineRef(single[1]);
|
|
7077
7359
|
endRef = startRef;
|
|
7078
7360
|
afterRefs = single.index + single[0].length;
|
|
7079
7361
|
}
|
|
7080
|
-
if (summary.length === 0)
|
|
7362
|
+
if (summary.length === 0)
|
|
7363
|
+
return { reason: "line entry: missing summary after the refs header line" };
|
|
7081
7364
|
const explicitTopic = head.slice(afterRefs).trim();
|
|
7082
7365
|
const range = {
|
|
7083
7366
|
startRef,
|
|
@@ -7096,7 +7379,11 @@ function deriveTopicFromSummary(summary) {
|
|
|
7096
7379
|
return text.length > 60 ? clampPrefix(text, 60).trimEnd() : text;
|
|
7097
7380
|
}
|
|
7098
7381
|
function splitLineEntries(content) {
|
|
7099
|
-
const parts = content.split(
|
|
7382
|
+
const parts = content.split(
|
|
7383
|
+
/\n(?=\s*(?:["']\s*,\s*)?["']?\s*[mb]\d{1,7}\s*(?:[-\u2013\u2014\u2026~]|\.\.\.|to)\s*[mb]\d{1,7}\b)/i
|
|
7384
|
+
).map(
|
|
7385
|
+
(p) => p.trim().replace(/^(?:["']\s*,?\s*)+/, "").replace(/["']\s*$/, "")
|
|
7386
|
+
).filter((p) => p.length > 0);
|
|
7100
7387
|
return parts.length > 0 ? parts : [content.trim()];
|
|
7101
7388
|
}
|
|
7102
7389
|
function stripJsonWrapperResidue(s) {
|
|
@@ -7109,12 +7396,15 @@ function stripJsonWrapperResidue(s) {
|
|
|
7109
7396
|
}
|
|
7110
7397
|
function validateEntry(entry, callId) {
|
|
7111
7398
|
if (typeof entry === "string") return parseLineEntry(entry, callId);
|
|
7112
|
-
if (entry === null || typeof entry !== "object" || Array.isArray(entry))
|
|
7399
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry))
|
|
7400
|
+
return { reason: "not an object" };
|
|
7113
7401
|
const e = entry;
|
|
7114
7402
|
const start = stringOr(e["startRef"]) ?? stringOr(e["startId"]) ?? stringOr(e["messageId"]);
|
|
7115
7403
|
const end = stringOr(e["endRef"]) ?? stringOr(e["endId"]) ?? stringOr(e["messageId"]);
|
|
7116
7404
|
if (start === void 0 || end === void 0) {
|
|
7117
|
-
return {
|
|
7405
|
+
return {
|
|
7406
|
+
reason: "missing range bounds (need startRef/startId and endRef/endId)"
|
|
7407
|
+
};
|
|
7118
7408
|
}
|
|
7119
7409
|
const summary = stringOr(e["summary"]);
|
|
7120
7410
|
if (summary === void 0) return { reason: "missing summary" };
|
|
@@ -7122,7 +7412,8 @@ function validateEntry(entry, callId) {
|
|
|
7122
7412
|
const topic = stringOr(e["topic"]);
|
|
7123
7413
|
if (topic !== void 0) range.topic = topic;
|
|
7124
7414
|
const maxChars = e["summaryMaxChars"];
|
|
7125
|
-
if (typeof maxChars === "number" && Number.isFinite(maxChars))
|
|
7415
|
+
if (typeof maxChars === "number" && Number.isFinite(maxChars))
|
|
7416
|
+
range.summaryMaxChars = maxChars;
|
|
7126
7417
|
if (callId !== void 0) range.compressCallId = callId;
|
|
7127
7418
|
return { range };
|
|
7128
7419
|
}
|
|
@@ -7159,7 +7450,8 @@ function tryParseLenient(s) {
|
|
|
7159
7450
|
return void 0;
|
|
7160
7451
|
}
|
|
7161
7452
|
function normalizeSingleQuotes(raw) {
|
|
7162
|
-
if (!raw.includes("'") || !raw.includes("{") && !raw.includes("["))
|
|
7453
|
+
if (!raw.includes("'") || !raw.includes("{") && !raw.includes("["))
|
|
7454
|
+
return void 0;
|
|
7163
7455
|
let out = "";
|
|
7164
7456
|
let changed = false;
|
|
7165
7457
|
let inDouble = false;
|
|
@@ -7251,8 +7543,10 @@ function stripTrailingCommas(s) {
|
|
|
7251
7543
|
}
|
|
7252
7544
|
if (ch === ",") {
|
|
7253
7545
|
let j2 = i + 1;
|
|
7254
|
-
while (j2 < s.length && (s.charAt(j2) === " " || s.charAt(j2) === " " || s.charAt(j2) === "\n" || s.charAt(j2) === "\r"))
|
|
7255
|
-
|
|
7546
|
+
while (j2 < s.length && (s.charAt(j2) === " " || s.charAt(j2) === " " || s.charAt(j2) === "\n" || s.charAt(j2) === "\r"))
|
|
7547
|
+
j2++;
|
|
7548
|
+
if (j2 < s.length && (s.charAt(j2) === "}" || s.charAt(j2) === "]"))
|
|
7549
|
+
continue;
|
|
7256
7550
|
}
|
|
7257
7551
|
out += ch;
|
|
7258
7552
|
}
|
|
@@ -7317,7 +7611,8 @@ function repairAtParserPositions(s) {
|
|
|
7317
7611
|
if (ch === "\n") esc = "\\n";
|
|
7318
7612
|
else if (ch === "\r") esc = "\\r";
|
|
7319
7613
|
else if (ch === " ") esc = "\\t";
|
|
7320
|
-
else if (ch.charCodeAt(0) < 32)
|
|
7614
|
+
else if (ch.charCodeAt(0) < 32)
|
|
7615
|
+
esc = "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0");
|
|
7321
7616
|
if (esc === void 0) return cur;
|
|
7322
7617
|
cur = cur.slice(0, pos) + esc + cur.slice(pos + 1);
|
|
7323
7618
|
} else if (/Bad escaped character/i.test(msg)) {
|
|
@@ -7394,7 +7689,8 @@ function stem(word) {
|
|
|
7394
7689
|
let w2 = word;
|
|
7395
7690
|
if (w2.length <= 3) return w2;
|
|
7396
7691
|
if (w2.endsWith("ies")) w2 = w2.slice(0, -3) + "y";
|
|
7397
|
-
else if (w2.endsWith("ses") || w2.endsWith("xes") || w2.endsWith("zes"))
|
|
7692
|
+
else if (w2.endsWith("ses") || w2.endsWith("xes") || w2.endsWith("zes"))
|
|
7693
|
+
w2 = w2.slice(0, -2);
|
|
7398
7694
|
else if (w2.endsWith("ches") || w2.endsWith("shes")) w2 = w2.slice(0, -2);
|
|
7399
7695
|
else if (w2.endsWith("s") && !w2.endsWith("ss")) w2 = w2.slice(0, -1);
|
|
7400
7696
|
if (w2.endsWith("ing") && w2.length > 5) w2 = w2.slice(0, -3);
|
|
@@ -7546,7 +7842,8 @@ var fuzzyAlgorithm = {
|
|
|
7546
7842
|
description: "Character bigram overlap. Typo-tolerant, script-agnostic, high recall.",
|
|
7547
7843
|
score(docs, query) {
|
|
7548
7844
|
const qTokens = query.toLowerCase().split(/[\s,]+/).filter((t) => t.length >= 4 || t.length >= 2 && CJK.test(t));
|
|
7549
|
-
if (qTokens.length === 0)
|
|
7845
|
+
if (qTokens.length === 0)
|
|
7846
|
+
return docs.map((d2) => ({ ref: d2.ref, score: 0 }));
|
|
7550
7847
|
const qGrams = /* @__PURE__ */ new Set();
|
|
7551
7848
|
for (const t of qTokens) for (const g2 of charBigrams(t)) qGrams.add(g2);
|
|
7552
7849
|
if (qGrams.size === 0) return docs.map((d2) => ({ ref: d2.ref, score: 0 }));
|
|
@@ -7656,7 +7953,9 @@ function runSearch(docs, query, options) {
|
|
|
7656
7953
|
}).filter((r) => r !== null && r.score >= minScore).sort((a, b2) => b2.score - a.score).slice(0, limit);
|
|
7657
7954
|
};
|
|
7658
7955
|
if (scoredOrPromise instanceof Promise) {
|
|
7659
|
-
return scoredOrPromise.then(
|
|
7956
|
+
return scoredOrPromise.then(
|
|
7957
|
+
(raw) => buildResults(applyRoleWeight(raw, docs, rw))
|
|
7958
|
+
);
|
|
7660
7959
|
}
|
|
7661
7960
|
return buildResults(applyRoleWeight(scoredOrPromise, docs, rw));
|
|
7662
7961
|
}
|
|
@@ -15141,7 +15440,7 @@ function resolveActivePack(adapter, cwd, provider, modelId, resolver) {
|
|
|
15141
15440
|
}
|
|
15142
15441
|
var HOST_VERSION = (() => {
|
|
15143
15442
|
try {
|
|
15144
|
-
return "0.1.
|
|
15443
|
+
return "0.1.82";
|
|
15145
15444
|
} catch {
|
|
15146
15445
|
return "dev";
|
|
15147
15446
|
}
|
|
@@ -17516,7 +17815,10 @@ function formatHitRate(rate) {
|
|
|
17516
17815
|
}
|
|
17517
17816
|
function bar(value, total, width = 20) {
|
|
17518
17817
|
if (total === 0) return "";
|
|
17519
|
-
const filled = Math.max(
|
|
17818
|
+
const filled = Math.max(
|
|
17819
|
+
0,
|
|
17820
|
+
Math.min(width, Math.round(value / total * width))
|
|
17821
|
+
);
|
|
17520
17822
|
return "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
|
|
17521
17823
|
}
|
|
17522
17824
|
function buildStatusPanel(input) {
|
|
@@ -17539,16 +17841,22 @@ function buildStatusPanel(input) {
|
|
|
17539
17841
|
lines.push("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F");
|
|
17540
17842
|
if (input.version) lines.push(input.version);
|
|
17541
17843
|
lines.push("");
|
|
17542
|
-
lines.push(
|
|
17844
|
+
lines.push(
|
|
17845
|
+
`Context (session accounting, host footer scale): ${displayPct}% (${fmt2(displayTotal)} / ${fmt2(limit)}) \u2014 includes compressed originals; shrinks slower than the sent view`
|
|
17846
|
+
);
|
|
17543
17847
|
if (nudge && bd) {
|
|
17544
17848
|
const growth = bd.growth;
|
|
17545
17849
|
if (growth > 0 && displayTotal > 0) {
|
|
17546
17850
|
lines.push(`Growth: +${fmt2(growth)} since last nudge`);
|
|
17547
17851
|
}
|
|
17548
17852
|
lines.push("");
|
|
17549
|
-
lines.push(
|
|
17853
|
+
lines.push(
|
|
17854
|
+
`Sent to LLM (after compression, est.): ${fmt2(sentTotal)}${limit > 0 ? ` (${sentPct}% of limit)` : ""}`
|
|
17855
|
+
);
|
|
17550
17856
|
if (input.unprunedTokens !== void 0 && sessionOnly > 0) {
|
|
17551
|
-
lines.push(
|
|
17857
|
+
lines.push(
|
|
17858
|
+
`Session-only (compressed originals, est.): ${fmt2(sessionOnly)} \u2014 pruned from every request; the footer/nudge still count them`
|
|
17859
|
+
);
|
|
17552
17860
|
}
|
|
17553
17861
|
lines.push("");
|
|
17554
17862
|
lines.push("Token Breakdown (sent view):");
|
|
@@ -17563,7 +17871,9 @@ function buildStatusPanel(input) {
|
|
|
17563
17871
|
if (cat.value <= 0) continue;
|
|
17564
17872
|
const pct2 = sentTotal > 0 ? Math.round(cat.value / sentTotal * 100) : 0;
|
|
17565
17873
|
const b2 = bar(cat.value, sentTotal);
|
|
17566
|
-
lines.push(
|
|
17874
|
+
lines.push(
|
|
17875
|
+
` ${cat.label.padEnd(10)} ${b2} ${String(pct2).padStart(3)}% ${fmt2(cat.value)}`
|
|
17876
|
+
);
|
|
17567
17877
|
}
|
|
17568
17878
|
}
|
|
17569
17879
|
if (input.cacheUsages) {
|
|
@@ -17592,22 +17902,30 @@ function buildStatusPanel(input) {
|
|
|
17592
17902
|
}
|
|
17593
17903
|
if (activeBlocksList.length > 0) {
|
|
17594
17904
|
lines.push("");
|
|
17595
|
-
lines.push(
|
|
17905
|
+
lines.push(
|
|
17906
|
+
`Blocks: ${activeBlocksList.length} active / ${totalBlocksList.length} total (${fmt2(state.stats.tokensCompressed)} tokens compressed, cumulative)`
|
|
17907
|
+
);
|
|
17596
17908
|
for (const b2 of activeBlocksList) {
|
|
17597
17909
|
const topic = b2.topic ? `: ${b2.topic}` : `: ${topicFallback(b2.summary || "")}`;
|
|
17598
17910
|
const summaryTok = defaultCountTokens(b2.summary || "");
|
|
17599
17911
|
const origTok = b2.compressedTokens > 0 ? b2.compressedTokens : summaryTok;
|
|
17600
|
-
lines.push(
|
|
17912
|
+
lines.push(
|
|
17913
|
+
` [${b2.blockId}] T${b2.tier} ${fmt2(origTok)}\u2192${fmt2(summaryTok)}${topic}`
|
|
17914
|
+
);
|
|
17601
17915
|
}
|
|
17602
17916
|
} else if (totalBlocksList.length > 0) {
|
|
17603
17917
|
lines.push("");
|
|
17604
|
-
lines.push(
|
|
17918
|
+
lines.push(
|
|
17919
|
+
`Blocks: 0 active / ${totalBlocksList.length} total (${fmt2(state.stats.tokensCompressed)} tokens compressed, cumulative)`
|
|
17920
|
+
);
|
|
17605
17921
|
} else {
|
|
17606
17922
|
lines.push("");
|
|
17607
17923
|
lines.push("Blocks: none (nothing compressed yet)");
|
|
17608
17924
|
}
|
|
17609
17925
|
lines.push("");
|
|
17610
|
-
lines.push(
|
|
17926
|
+
lines.push(
|
|
17927
|
+
"Tag visibility: tags injected to LLM only (deep copy), not persisted in session, not shown in terminal."
|
|
17928
|
+
);
|
|
17611
17929
|
return lines.join("\n");
|
|
17612
17930
|
}
|
|
17613
17931
|
|
|
@@ -22057,7 +22375,7 @@ async function statusReport(runtime, ctx) {
|
|
|
22057
22375
|
const sentTokens = estimateTokens(coreMessages, coveredIds, imageTokens) + systemPromptTokens;
|
|
22058
22376
|
const viewSentTokens = adjustedTokenCount(runtime.core, coreMessages, state, config, sentTokens, imageTokens, systemPromptTokens);
|
|
22059
22377
|
const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: anchorStale ? viewSentTokens : Math.max(viewSentTokens, realUsage?.tokens ?? 0) });
|
|
22060
|
-
const versionStr = "0.1.
|
|
22378
|
+
const versionStr = "0.1.82" ? `billion-context-pi@${"0.1.82"} \xB7 pack: ${resolveSurfaceMeta(runtime.adapter, ctx?.cwd ?? process.cwd(), ctx?.model?.provider, ctx?.model?.id).pack}` : void 0;
|
|
22061
22379
|
let text = buildStatusPanel({
|
|
22062
22380
|
version: versionStr,
|
|
22063
22381
|
tokenCount: sessionTokens,
|
|
@@ -22436,7 +22754,8 @@ function createSubagentNamespaces() {
|
|
|
22436
22754
|
const anchors = /* @__PURE__ */ new Map();
|
|
22437
22755
|
return {
|
|
22438
22756
|
namespaceFor(identityValue, instructions) {
|
|
22439
|
-
if (typeof instructions !== "string" || instructions.trim().length === 0)
|
|
22757
|
+
if (typeof instructions !== "string" || instructions.trim().length === 0)
|
|
22758
|
+
return identityValue;
|
|
22440
22759
|
const fp = hashId(instructions);
|
|
22441
22760
|
const anchor = anchors.get(identityValue);
|
|
22442
22761
|
if (anchor === void 0) {
|
|
@@ -22465,6 +22784,63 @@ function placeholderContent(protocol) {
|
|
|
22465
22784
|
const type = protocol === "responses" ? "input_text" : "text";
|
|
22466
22785
|
return [{ type, text: IMAGE_PLACEHOLDER }];
|
|
22467
22786
|
}
|
|
22787
|
+
function isGoogleNestedImage(part) {
|
|
22788
|
+
if (!isObj(part)) return false;
|
|
22789
|
+
const media = isObj(part.inlineData) ? part.inlineData : part.fileData;
|
|
22790
|
+
return isObj(media) && typeof media.mimeType === "string" && media.mimeType.startsWith("image/");
|
|
22791
|
+
}
|
|
22792
|
+
function stripNestedImages(protocol, part) {
|
|
22793
|
+
if (!isObj(part)) return { part, removed: 0 };
|
|
22794
|
+
if (protocol === "anthropic" && part.type === "tool_result" && Array.isArray(part.content)) {
|
|
22795
|
+
const inner = part.content;
|
|
22796
|
+
const kept = inner.filter((p) => !isImagePart(protocol, p));
|
|
22797
|
+
const removed = inner.length - kept.length;
|
|
22798
|
+
if (removed === 0) return { part, removed: 0 };
|
|
22799
|
+
return {
|
|
22800
|
+
part: {
|
|
22801
|
+
...part,
|
|
22802
|
+
content: kept.length > 0 ? kept : placeholderContent(protocol)
|
|
22803
|
+
},
|
|
22804
|
+
removed
|
|
22805
|
+
};
|
|
22806
|
+
}
|
|
22807
|
+
if (protocol === "google" && isObj(part.functionResponse) && Array.isArray(part.functionResponse.parts)) {
|
|
22808
|
+
const fr = part.functionResponse;
|
|
22809
|
+
if (JSON.stringify(fr.response ?? null).includes('"$ref"'))
|
|
22810
|
+
return { part, removed: 0 };
|
|
22811
|
+
const inner = fr.parts;
|
|
22812
|
+
const kept = inner.filter((p) => !isGoogleNestedImage(p));
|
|
22813
|
+
const removed = inner.length - kept.length;
|
|
22814
|
+
if (removed === 0) return { part, removed: 0 };
|
|
22815
|
+
const { parts: _2, ...rest } = fr;
|
|
22816
|
+
return {
|
|
22817
|
+
part: {
|
|
22818
|
+
...part,
|
|
22819
|
+
functionResponse: kept.length > 0 ? { ...fr, parts: kept } : rest
|
|
22820
|
+
},
|
|
22821
|
+
removed
|
|
22822
|
+
};
|
|
22823
|
+
}
|
|
22824
|
+
return { part, removed: 0 };
|
|
22825
|
+
}
|
|
22826
|
+
function stripParts(protocol, parts) {
|
|
22827
|
+
let removed = 0;
|
|
22828
|
+
const kept = [];
|
|
22829
|
+
for (const p of parts) {
|
|
22830
|
+
if (isImagePart(protocol, p)) {
|
|
22831
|
+
removed++;
|
|
22832
|
+
continue;
|
|
22833
|
+
}
|
|
22834
|
+
const nested = stripNestedImages(protocol, p);
|
|
22835
|
+
removed += nested.removed;
|
|
22836
|
+
kept.push(nested.part);
|
|
22837
|
+
}
|
|
22838
|
+
if (removed === 0) return null;
|
|
22839
|
+
return {
|
|
22840
|
+
parts: kept.length > 0 ? kept : placeholderContent(protocol),
|
|
22841
|
+
removed
|
|
22842
|
+
};
|
|
22843
|
+
}
|
|
22468
22844
|
function stripHistoricalImages(body, protocol, keepRecent) {
|
|
22469
22845
|
if (!protocol || !isObj(body)) return { body, removed: 0 };
|
|
22470
22846
|
const recentCount = Math.max(0, Math.floor(keepRecent));
|
|
@@ -22475,20 +22851,14 @@ function stripHistoricalImages(body, protocol, keepRecent) {
|
|
|
22475
22851
|
let removed2 = 0;
|
|
22476
22852
|
let touched2 = false;
|
|
22477
22853
|
const nextInput = input.map((item, i) => {
|
|
22478
|
-
if (i
|
|
22479
|
-
|
|
22480
|
-
|
|
22481
|
-
|
|
22482
|
-
|
|
22483
|
-
|
|
22484
|
-
|
|
22485
|
-
|
|
22486
|
-
...item,
|
|
22487
|
-
content: kept.length > 0 ? kept : placeholderContent("responses")
|
|
22488
|
-
};
|
|
22489
|
-
}
|
|
22490
|
-
}
|
|
22491
|
-
return item;
|
|
22854
|
+
if (i >= cutoff2 || !isObj(item)) return item;
|
|
22855
|
+
const key = item.type === "function_call_output" || item.type === "custom_tool_call_output" ? "output" : "content";
|
|
22856
|
+
if (!Array.isArray(item[key])) return item;
|
|
22857
|
+
const r = stripParts("responses", item[key]);
|
|
22858
|
+
if (!r) return item;
|
|
22859
|
+
removed2 += r.removed;
|
|
22860
|
+
touched2 = true;
|
|
22861
|
+
return { ...item, [key]: r.parts };
|
|
22492
22862
|
});
|
|
22493
22863
|
if (!touched2) return { body, removed: 0 };
|
|
22494
22864
|
return { body: { ...body, input: nextInput }, removed: removed2 };
|
|
@@ -22501,16 +22871,11 @@ function stripHistoricalImages(body, protocol, keepRecent) {
|
|
|
22501
22871
|
let touched2 = false;
|
|
22502
22872
|
const nextContents = contents.map((c, i) => {
|
|
22503
22873
|
if (i < cutoff2 && isObj(c) && Array.isArray(c.parts)) {
|
|
22504
|
-
const
|
|
22505
|
-
|
|
22506
|
-
|
|
22507
|
-
removed2 += imgs;
|
|
22874
|
+
const r = stripParts("google", c.parts);
|
|
22875
|
+
if (r) {
|
|
22876
|
+
removed2 += r.removed;
|
|
22508
22877
|
touched2 = true;
|
|
22509
|
-
|
|
22510
|
-
return {
|
|
22511
|
-
...c,
|
|
22512
|
-
parts: kept.length > 0 ? kept : placeholderContent("google")
|
|
22513
|
-
};
|
|
22878
|
+
return { ...c, parts: r.parts };
|
|
22514
22879
|
}
|
|
22515
22880
|
}
|
|
22516
22881
|
return c;
|
|
@@ -22525,16 +22890,11 @@ function stripHistoricalImages(body, protocol, keepRecent) {
|
|
|
22525
22890
|
let touched = false;
|
|
22526
22891
|
const nextMessages = messages.map((m2, i) => {
|
|
22527
22892
|
if (i < cutoff && isObj(m2) && Array.isArray(m2.content)) {
|
|
22528
|
-
const
|
|
22529
|
-
|
|
22530
|
-
|
|
22531
|
-
removed += imgs;
|
|
22893
|
+
const r = stripParts(protocol, m2.content);
|
|
22894
|
+
if (r) {
|
|
22895
|
+
removed += r.removed;
|
|
22532
22896
|
touched = true;
|
|
22533
|
-
|
|
22534
|
-
return {
|
|
22535
|
-
...m2,
|
|
22536
|
-
content: kept.length > 0 ? kept : placeholderContent(protocol)
|
|
22537
|
-
};
|
|
22897
|
+
return { ...m2, content: r.parts };
|
|
22538
22898
|
}
|
|
22539
22899
|
}
|
|
22540
22900
|
return m2;
|
|
@@ -22994,7 +23354,7 @@ async function autoInstallLatest(latest, extDirOverride) {
|
|
|
22994
23354
|
"--no-fund",
|
|
22995
23355
|
"--no-save"
|
|
22996
23356
|
];
|
|
22997
|
-
const prevVersion = (await readPackageJson(join15(extDir, "package.json")))?.version ?? "0.1.
|
|
23357
|
+
const prevVersion = (await readPackageJson(join15(extDir, "package.json")))?.version ?? "0.1.82";
|
|
22998
23358
|
const { code, stderr } = await runNpmImpl(installArgs(latest), { cwd: npmDir, timeout: 6e4 });
|
|
22999
23359
|
if (code !== 0) {
|
|
23000
23360
|
logWarn("update", {
|
|
@@ -23012,7 +23372,7 @@ async function autoInstallLatest(latest, extDirOverride) {
|
|
|
23012
23372
|
}
|
|
23013
23373
|
const verify = await verifyInstall(npmDir, latest);
|
|
23014
23374
|
if (!verify.ok) {
|
|
23015
|
-
const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.
|
|
23375
|
+
const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.82";
|
|
23016
23376
|
logWarn("update", { event: "auto-install-verify-failed", latest, reason: verify.reason, rollbackTo });
|
|
23017
23377
|
const rb = await runNpmImpl(installArgs(rollbackTo), { cwd: npmDir, timeout: 6e4 });
|
|
23018
23378
|
logInfo("update", { event: "rollback", from: latest, to: rollbackTo, ok: rb.code === 0 });
|
|
@@ -23087,7 +23447,7 @@ async function checkForUpdate(autoUpdate, notify) {
|
|
|
23087
23447
|
}
|
|
23088
23448
|
const latest = await fetchLatestVersion(tag);
|
|
23089
23449
|
if (!latest) return;
|
|
23090
|
-
const current = runtimeVersion ?? "0.1.
|
|
23450
|
+
const current = runtimeVersion ?? "0.1.82";
|
|
23091
23451
|
const hasUpdate = isVersionNewer(latest, current);
|
|
23092
23452
|
debug.event("update-check", {
|
|
23093
23453
|
current,
|
|
@@ -23309,7 +23669,7 @@ function wireSessionLifecycle(pi, runtime, standDownIfProxied) {
|
|
|
23309
23669
|
setDelegatePolicy(DEFAULT_DELEGATE_POLICY);
|
|
23310
23670
|
const sid = ctx.sessionManager.getSessionId();
|
|
23311
23671
|
const modelInfo = ctx.model;
|
|
23312
|
-
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.
|
|
23672
|
+
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.82" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
|
|
23313
23673
|
let delegateStoodDown = false;
|
|
23314
23674
|
try {
|
|
23315
23675
|
await runtime.reloadConfig(ctx.cwd);
|