billion-context-pi-lean 0.2.0 → 0.2.1
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/README.md +1 -1
- package/dist/{chunk-PPYOZRUP.js → chunk-EYDKO7YM.js} +2 -2
- package/dist/config-dir.d.ts +4 -29
- package/dist/config.d.ts +0 -33
- package/dist/contract.js +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +112 -714
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +1 -8
- package/dist/reasoning-drop.d.ts +2 -2
- package/dist/runtime.d.ts +6 -36
- package/dist/session-log.d.ts +4 -15
- package/dist/state.d.ts +0 -28
- package/dist/tool-guardrails.d.ts +0 -4
- package/dist/turn-boundary.d.ts +10 -39
- package/dist/user-config.d.ts +1 -2
- package/lean/index.ts +1 -1
- package/package.json +1 -1
- package/dist/compat.d.ts +0 -23
- package/dist/host.d.ts +0 -15
- package/dist/omp.d.ts +0 -19
- package/dist/sequence-match.d.ts +0 -7
- /package/dist/{chunk-PPYOZRUP.js.map → chunk-EYDKO7YM.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -2,46 +2,14 @@ import {
|
|
|
2
2
|
SIDECAR_SCHEMA_VERSION,
|
|
3
3
|
__export,
|
|
4
4
|
sidecarProducer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EYDKO7YM.js";
|
|
6
6
|
|
|
7
7
|
// src/config-dir.ts
|
|
8
|
-
import
|
|
9
|
-
import { existsSync } from "fs";
|
|
8
|
+
import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent";
|
|
10
9
|
import { homedir } from "os";
|
|
11
10
|
import * as path from "path";
|
|
12
|
-
var PI_CONFIG_DIR_NAME = ".pi";
|
|
13
|
-
function isDirName(value) {
|
|
14
|
-
return typeof value === "string" && value.length > 0 && value !== "." && value !== ".." && !/[\\/]/.test(value);
|
|
15
|
-
}
|
|
16
|
-
function dirNameFromAgentDir(getAgentDir, home) {
|
|
17
|
-
if (typeof getAgentDir !== "function") return void 0;
|
|
18
|
-
let agentDir;
|
|
19
|
-
try {
|
|
20
|
-
agentDir = getAgentDir();
|
|
21
|
-
} catch {
|
|
22
|
-
return void 0;
|
|
23
|
-
}
|
|
24
|
-
if (typeof agentDir !== "string" || agentDir.length === 0) return void 0;
|
|
25
|
-
const resolved = path.resolve(agentDir);
|
|
26
|
-
if (path.basename(resolved) !== "agent") return void 0;
|
|
27
|
-
const root = path.dirname(resolved);
|
|
28
|
-
if (path.dirname(root) !== path.resolve(home)) return void 0;
|
|
29
|
-
const name = path.basename(root);
|
|
30
|
-
return isDirName(name) ? name : void 0;
|
|
31
|
-
}
|
|
32
|
-
function resolveConfigDirName(host, home) {
|
|
33
|
-
if (isDirName(host.CONFIG_DIR_NAME)) return host.CONFIG_DIR_NAME;
|
|
34
|
-
return dirNameFromAgentDir(host.getAgentDir, home) ?? PI_CONFIG_DIR_NAME;
|
|
35
|
-
}
|
|
36
|
-
var CONFIG_DIR_NAME = resolveConfigDirName(piModule, homedir());
|
|
37
|
-
function userConfigPathIn(name, root, ...segments) {
|
|
38
|
-
const own = path.join(root, name, ...segments);
|
|
39
|
-
if (name === PI_CONFIG_DIR_NAME || existsSync(own)) return own;
|
|
40
|
-
const legacy = path.join(root, PI_CONFIG_DIR_NAME, ...segments);
|
|
41
|
-
return existsSync(legacy) ? legacy : own;
|
|
42
|
-
}
|
|
43
11
|
function userConfigPath(root, ...segments) {
|
|
44
|
-
return
|
|
12
|
+
return path.join(root, CONFIG_DIR_NAME, ...segments);
|
|
45
13
|
}
|
|
46
14
|
function acpJsonFiles(cwd) {
|
|
47
15
|
return [userConfigPath(homedir(), "acp.json"), userConfigPath(cwd, "acp.json")];
|
|
@@ -50,10 +18,10 @@ function acpJsonFiles(cwd) {
|
|
|
50
18
|
// src/user-config.ts
|
|
51
19
|
import { promises as fs } from "fs";
|
|
52
20
|
import { homedir as homedir3 } from "os";
|
|
53
|
-
import { dirname as
|
|
21
|
+
import { dirname as dirname2 } from "path";
|
|
54
22
|
|
|
55
23
|
// src/log.ts
|
|
56
|
-
import { appendFileSync, mkdirSync, statSync, renameSync, existsSync
|
|
24
|
+
import { appendFileSync, mkdirSync, statSync, renameSync, existsSync } from "fs";
|
|
57
25
|
import * as path2 from "path";
|
|
58
26
|
import { homedir as homedir2 } from "os";
|
|
59
27
|
var MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -86,7 +54,7 @@ function ts() {
|
|
|
86
54
|
function writeLine(level, scope, fields) {
|
|
87
55
|
const file = resolveLogFile();
|
|
88
56
|
try {
|
|
89
|
-
if (
|
|
57
|
+
if (existsSync(file) && statSync(file).size >= MAX_BYTES) {
|
|
90
58
|
renameSync(file, file + ".old");
|
|
91
59
|
}
|
|
92
60
|
} catch {
|
|
@@ -222,7 +190,6 @@ var KNOWN = /* @__PURE__ */ new Set([
|
|
|
222
190
|
"promptSections",
|
|
223
191
|
"nudgeSections",
|
|
224
192
|
"toolPrompts",
|
|
225
|
-
"hostSession",
|
|
226
193
|
"rules",
|
|
227
194
|
"compressionModelId"
|
|
228
195
|
]);
|
|
@@ -306,7 +273,7 @@ async function writeGlobalAcpConfig(mutate) {
|
|
|
306
273
|
if (e.code !== "ENOENT") throw e;
|
|
307
274
|
}
|
|
308
275
|
mutate(current);
|
|
309
|
-
await fs.mkdir(
|
|
276
|
+
await fs.mkdir(dirname2(file), { recursive: true });
|
|
310
277
|
await fs.writeFile(file, `${JSON.stringify(current, null, 2)}
|
|
311
278
|
`, "utf8");
|
|
312
279
|
}
|
|
@@ -4308,7 +4275,7 @@ var DESIRED_KITTY_KEYBOARD_PROTOCOL_FLAGS = 7;
|
|
|
4308
4275
|
var KITTY_KEYBOARD_PROTOCOL_QUERY = `\x1B[>${DESIRED_KITTY_KEYBOARD_PROTOCOL_FLAGS}u\x1B[?u\x1B[c`;
|
|
4309
4276
|
|
|
4310
4277
|
// src/index.ts
|
|
4311
|
-
import { readFileSync as
|
|
4278
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
4312
4279
|
|
|
4313
4280
|
// node_modules/acp-kernel/dist/chunk-Q3P5Z2PV.js
|
|
4314
4281
|
import { createRequire as createRequire3 } from "module";
|
|
@@ -10251,7 +10218,7 @@ function readPackFile(file) {
|
|
|
10251
10218
|
}
|
|
10252
10219
|
}
|
|
10253
10220
|
function createDirPackSource(id, dir) {
|
|
10254
|
-
const
|
|
10221
|
+
const resolve3 = (name) => {
|
|
10255
10222
|
if (!isValidPackName(name)) return null;
|
|
10256
10223
|
const file = path6.join(dir, `${name}.json`);
|
|
10257
10224
|
const raw = readPackFile(file);
|
|
@@ -10266,7 +10233,7 @@ function createDirPackSource(id, dir) {
|
|
|
10266
10233
|
};
|
|
10267
10234
|
return {
|
|
10268
10235
|
id,
|
|
10269
|
-
resolve:
|
|
10236
|
+
resolve: resolve3,
|
|
10270
10237
|
list() {
|
|
10271
10238
|
let names;
|
|
10272
10239
|
try {
|
|
@@ -10276,7 +10243,7 @@ function createDirPackSource(id, dir) {
|
|
|
10276
10243
|
}
|
|
10277
10244
|
const out = [];
|
|
10278
10245
|
for (const f of names) {
|
|
10279
|
-
const pack =
|
|
10246
|
+
const pack = resolve3(f.slice(0, -5));
|
|
10280
10247
|
if (pack) out.push(pack);
|
|
10281
10248
|
}
|
|
10282
10249
|
return out;
|
|
@@ -12171,33 +12138,6 @@ function resolveRepetitionGuard(adapter) {
|
|
|
12171
12138
|
}
|
|
12172
12139
|
return { enabled: true, warn: REPETITION_GUARD_DEFAULTS.warn, abort: REPETITION_GUARD_DEFAULTS.abort };
|
|
12173
12140
|
}
|
|
12174
|
-
function resolveHostSession(adapter) {
|
|
12175
|
-
const h = adapter.hostSession;
|
|
12176
|
-
if (h === true) return { countCustomMessages: true };
|
|
12177
|
-
if (h && typeof h === "object") {
|
|
12178
|
-
if (typeof h.countCustomMessages !== "boolean") {
|
|
12179
|
-
logWarn("config", { event: "host-session-invalid", field: "countCustomMessages", value: String(h.countCustomMessages), fallback: "false" });
|
|
12180
|
-
}
|
|
12181
|
-
const count = h.countCustomMessages === true;
|
|
12182
|
-
let types;
|
|
12183
|
-
if (h.customMessageTypes !== void 0) {
|
|
12184
|
-
const raw = h.customMessageTypes;
|
|
12185
|
-
const valid = Array.isArray(raw) && raw.every((t) => typeof t === "string" && t.length > 0);
|
|
12186
|
-
if (!valid) {
|
|
12187
|
-
logWarn("config", { event: "host-session-invalid", field: "customMessageTypes", value: JSON.stringify(raw), fallback: "unset" });
|
|
12188
|
-
} else if (!count) {
|
|
12189
|
-
logWarn("config", { event: "host-session-invalid", field: "customMessageTypes", value: JSON.stringify(raw), fallback: "ignored", reason: "requires-countCustomMessages" });
|
|
12190
|
-
} else {
|
|
12191
|
-
types = raw;
|
|
12192
|
-
}
|
|
12193
|
-
}
|
|
12194
|
-
return types === void 0 ? { countCustomMessages: count } : { countCustomMessages: count, customMessageTypes: types };
|
|
12195
|
-
}
|
|
12196
|
-
if (h !== void 0 && h !== false) {
|
|
12197
|
-
logWarn("config", { event: "host-session-invalid", value: String(h), fallback: "off" });
|
|
12198
|
-
}
|
|
12199
|
-
return { countCustomMessages: false };
|
|
12200
|
-
}
|
|
12201
12141
|
function mergeCompress(global, provider, model) {
|
|
12202
12142
|
return {
|
|
12203
12143
|
maxContextLimit: model?.maxContextLimit ?? provider?.maxContextLimit ?? global?.maxContextLimit,
|
|
@@ -12256,10 +12196,6 @@ function parsePercent(v2) {
|
|
|
12256
12196
|
return Number(s);
|
|
12257
12197
|
}
|
|
12258
12198
|
|
|
12259
|
-
// src/runtime.ts
|
|
12260
|
-
import { createHash as createHash2 } from "crypto";
|
|
12261
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
12262
|
-
|
|
12263
12199
|
// src/tag-tokens.ts
|
|
12264
12200
|
function formatTokens3(tokens) {
|
|
12265
12201
|
if (tokens < 1e3) return String(tokens);
|
|
@@ -12458,62 +12394,7 @@ function countImageBlocks(content) {
|
|
|
12458
12394
|
}
|
|
12459
12395
|
return n;
|
|
12460
12396
|
}
|
|
12461
|
-
function messageIdentity(message) {
|
|
12462
|
-
return JSON.stringify(normalizeIdentityValue(message, true));
|
|
12463
|
-
}
|
|
12464
|
-
function messageRef(message) {
|
|
12465
|
-
if (message === null || typeof message !== "object" || !("content" in message)) return void 0;
|
|
12466
|
-
const content = message.content;
|
|
12467
|
-
const texts = typeof content === "string" ? [content] : Array.isArray(content) ? content.flatMap((block) => {
|
|
12468
|
-
const value = block;
|
|
12469
|
-
return value.type === "text" && typeof value.text === "string" ? [value.text] : [];
|
|
12470
|
-
}) : [];
|
|
12471
|
-
for (const text of texts) {
|
|
12472
|
-
const tag = text.match(REF_TAG)?.[0] ?? text.match(TRAILING_REF_TAG)?.[0];
|
|
12473
|
-
const ref = tag?.match(/m\d{1,7}/)?.[0];
|
|
12474
|
-
if (ref) return ref;
|
|
12475
|
-
}
|
|
12476
|
-
return void 0;
|
|
12477
|
-
}
|
|
12478
|
-
function normalizeIdentityValue(value, message = false) {
|
|
12479
|
-
if (Array.isArray(value)) {
|
|
12480
|
-
return value.flatMap((item) => {
|
|
12481
|
-
if (!item || typeof item !== "object") return [normalizeIdentityValue(item)];
|
|
12482
|
-
const block = item;
|
|
12483
|
-
if (block.type === "text" && typeof block.text === "string") {
|
|
12484
|
-
const stripped = stripRefTag(block.text);
|
|
12485
|
-
if (block.text !== stripped && stripped === "") return [];
|
|
12486
|
-
}
|
|
12487
|
-
return [normalizeIdentityValue(item)];
|
|
12488
|
-
});
|
|
12489
|
-
}
|
|
12490
|
-
if (value === null || typeof value !== "object") return value;
|
|
12491
|
-
const out = {};
|
|
12492
|
-
for (const key of Object.keys(value).sort()) {
|
|
12493
|
-
if (message && key === "timestamp") continue;
|
|
12494
|
-
const item = value[key];
|
|
12495
|
-
if (message && key === "content" && typeof item === "string") {
|
|
12496
|
-
out[key] = [{ text: stripRefTag(item), type: "text" }];
|
|
12497
|
-
} else if (key === "text" && typeof item === "string" && value.type === "text") {
|
|
12498
|
-
out[key] = stripRefTag(item);
|
|
12499
|
-
} else {
|
|
12500
|
-
out[key] = normalizeIdentityValue(item);
|
|
12501
|
-
}
|
|
12502
|
-
}
|
|
12503
|
-
return out;
|
|
12504
|
-
}
|
|
12505
12397
|
var TRUNCATION_MARKER2 = "[truncated for context space]";
|
|
12506
|
-
function matchesStoredText(stored, visible) {
|
|
12507
|
-
const marker = `...${TRUNCATION_MARKER2} \u2014 original ~`;
|
|
12508
|
-
const markerStart = visible.indexOf(marker);
|
|
12509
|
-
if (markerStart < 2 || visible.slice(markerStart - 2, markerStart) !== "\n\n") return false;
|
|
12510
|
-
const suffixMarker = " tokens]...\n\n";
|
|
12511
|
-
const suffixStart = visible.indexOf(suffixMarker, markerStart + marker.length);
|
|
12512
|
-
if (suffixStart < 0 || !/^\d+$/.test(visible.slice(markerStart + marker.length, suffixStart))) return false;
|
|
12513
|
-
const prefix = visible.slice(0, markerStart - 2);
|
|
12514
|
-
const suffix = visible.slice(suffixStart + suffixMarker.length);
|
|
12515
|
-
return prefix.length > 0 && suffix.length > 0 && stored.startsWith(prefix) && stored.endsWith(suffix);
|
|
12516
|
-
}
|
|
12517
12398
|
function allToolCalls(content) {
|
|
12518
12399
|
if (!Array.isArray(content)) return [];
|
|
12519
12400
|
const calls = [];
|
|
@@ -12893,8 +12774,6 @@ var SessionStateStore = class {
|
|
|
12893
12774
|
const cached = this.cache.get(key);
|
|
12894
12775
|
if (cached) return cached.state;
|
|
12895
12776
|
let state = createInitialState();
|
|
12896
|
-
let liveRefOrigins = [];
|
|
12897
|
-
let derivedFrom = null;
|
|
12898
12777
|
let activePack;
|
|
12899
12778
|
if (file) {
|
|
12900
12779
|
try {
|
|
@@ -12905,8 +12784,6 @@ var SessionStateStore = class {
|
|
|
12905
12784
|
}
|
|
12906
12785
|
if (parsed && Array.isArray(parsed.blocks)) {
|
|
12907
12786
|
state = mergeInitialState(parsed);
|
|
12908
|
-
liveRefOrigins = parseLiveRefOrigins(parsed.liveRefOrigins);
|
|
12909
|
-
derivedFrom = parseDerivedFrom(parsed.derivedFrom);
|
|
12910
12787
|
if (typeof parsed.activePack === "string" && parsed.activePack) activePack = parsed.activePack;
|
|
12911
12788
|
}
|
|
12912
12789
|
} catch (e) {
|
|
@@ -12920,7 +12797,7 @@ var SessionStateStore = class {
|
|
|
12920
12797
|
if (parentState) state = parentState;
|
|
12921
12798
|
}
|
|
12922
12799
|
}
|
|
12923
|
-
this.cache.set(key, { state,
|
|
12800
|
+
this.cache.set(key, { state, activePack });
|
|
12924
12801
|
return state;
|
|
12925
12802
|
}
|
|
12926
12803
|
/** Stamp the effective prompt pack for the live session (audit trail:
|
|
@@ -12937,19 +12814,15 @@ var SessionStateStore = class {
|
|
|
12937
12814
|
const file = stateFileFor(sessionFile);
|
|
12938
12815
|
const key = cacheKey(sessionFile, sessionId);
|
|
12939
12816
|
const prev = this.cache.get(key);
|
|
12940
|
-
const liveRefOrigins = prev?.liveRefOrigins ?? [];
|
|
12941
|
-
const derivedFrom = prev?.derivedFrom ?? null;
|
|
12942
12817
|
const activePack = prev?.activePack;
|
|
12943
|
-
this.cache.set(key, { state,
|
|
12818
|
+
this.cache.set(key, { state, activePack });
|
|
12944
12819
|
if (!file) return;
|
|
12945
12820
|
const dir = path7.dirname(file);
|
|
12946
12821
|
const payload = {
|
|
12947
12822
|
...state,
|
|
12948
|
-
liveRefOrigins,
|
|
12949
12823
|
schemaVersion: SIDECAR_SCHEMA_VERSION,
|
|
12950
12824
|
producer: sidecarProducer()
|
|
12951
12825
|
};
|
|
12952
|
-
if (derivedFrom) payload.derivedFrom = derivedFrom;
|
|
12953
12826
|
if (activePack) payload.activePack = activePack;
|
|
12954
12827
|
const body = JSON.stringify(payload);
|
|
12955
12828
|
const prevWrite = this.writes.get(file) ?? Promise.resolve();
|
|
@@ -12973,22 +12846,6 @@ var SessionStateStore = class {
|
|
|
12973
12846
|
if (this.writes.get(file) === write) this.writes.delete(file);
|
|
12974
12847
|
}
|
|
12975
12848
|
}
|
|
12976
|
-
getLiveRefOrigins(sessionFile, sessionId) {
|
|
12977
|
-
return [...this.cache.get(cacheKey(sessionFile, sessionId))?.liveRefOrigins ?? []];
|
|
12978
|
-
}
|
|
12979
|
-
setLiveRefOrigins(sessionFile, sessionId, origins) {
|
|
12980
|
-
const key = cacheKey(sessionFile, sessionId);
|
|
12981
|
-
const slot = this.cache.get(key);
|
|
12982
|
-
if (slot) this.cache.set(key, { state: slot.state, liveRefOrigins: [...origins], derivedFrom: slot.derivedFrom });
|
|
12983
|
-
}
|
|
12984
|
-
getDerivedFrom(sessionFile, sessionId) {
|
|
12985
|
-
return this.cache.get(cacheKey(sessionFile, sessionId))?.derivedFrom ?? null;
|
|
12986
|
-
}
|
|
12987
|
-
setDerivedFrom(sessionFile, sessionId, mark) {
|
|
12988
|
-
const key = cacheKey(sessionFile, sessionId);
|
|
12989
|
-
const slot = this.cache.get(key);
|
|
12990
|
-
if (slot) this.cache.set(key, { state: slot.state, liveRefOrigins: slot.liveRefOrigins, derivedFrom: mark });
|
|
12991
|
-
}
|
|
12992
12849
|
invalidate() {
|
|
12993
12850
|
this.cache.clear();
|
|
12994
12851
|
}
|
|
@@ -13020,42 +12877,6 @@ var SessionStateStore = class {
|
|
|
13020
12877
|
return void 0;
|
|
13021
12878
|
}
|
|
13022
12879
|
};
|
|
13023
|
-
function parseDerivedFrom(value) {
|
|
13024
|
-
if (!value || typeof value !== "object") return null;
|
|
13025
|
-
const mark = value;
|
|
13026
|
-
if (typeof mark.parentSessionId !== "string" || typeof mark.derivedAt !== "number") return null;
|
|
13027
|
-
return { parentSessionId: mark.parentSessionId, derivedAt: mark.derivedAt };
|
|
13028
|
-
}
|
|
13029
|
-
function deriveChildState(parent) {
|
|
13030
|
-
const fresh = createInitialState();
|
|
13031
|
-
return {
|
|
13032
|
-
blocks: structuredClone(parent.blocks),
|
|
13033
|
-
messageRefs: { byRaw: { ...parent.messageRefs.byRaw }, byRef: { ...parent.messageRefs.byRef } },
|
|
13034
|
-
tokenSnapshot: { ...parent.tokenSnapshot },
|
|
13035
|
-
nudge: fresh.nudge,
|
|
13036
|
-
stats: fresh.stats,
|
|
13037
|
-
absorbed: [],
|
|
13038
|
-
rules: structuredClone(parent.rules ?? []),
|
|
13039
|
-
nextRuleId: parent.nextRuleId ?? fresh.nextRuleId,
|
|
13040
|
-
// Ref space is NOT re-issued on derive (byRaw/byRef carry verbatim), so the
|
|
13041
|
-
// image ledgers stay valid for inherited content: imageShrinks gates
|
|
13042
|
-
// image_full for inherited shrunk refs, imageFullRestored keeps
|
|
13043
|
-
// parent-restored refs at full resolution. The kernel's MUST-clear
|
|
13044
|
-
// (resetImageFullState) applies only to ref-reissue resets.
|
|
13045
|
-
imageFullRestored: structuredClone(parent.imageFullRestored ?? []),
|
|
13046
|
-
imageShrinks: structuredClone(parent.imageShrinks ?? []),
|
|
13047
|
-
nextBlockId: parent.nextBlockId,
|
|
13048
|
-
nextRunId: parent.nextRunId
|
|
13049
|
-
};
|
|
13050
|
-
}
|
|
13051
|
-
function parseLiveRefOrigins(value) {
|
|
13052
|
-
if (!Array.isArray(value)) return [];
|
|
13053
|
-
return value.filter((item) => {
|
|
13054
|
-
if (!item || typeof item !== "object") return false;
|
|
13055
|
-
const origin = item;
|
|
13056
|
-
return typeof origin.rawId === "string" && typeof origin.identity === "string";
|
|
13057
|
-
});
|
|
13058
|
-
}
|
|
13059
12880
|
function mergeInitialState(parsed) {
|
|
13060
12881
|
const fresh = createInitialState();
|
|
13061
12882
|
return {
|
|
@@ -17529,13 +17350,22 @@ import {
|
|
|
17529
17350
|
convertToLlm
|
|
17530
17351
|
} from "@earendil-works/pi-coding-agent";
|
|
17531
17352
|
|
|
17532
|
-
// src/
|
|
17533
|
-
function
|
|
17534
|
-
|
|
17535
|
-
return v2 === "1" || v2?.toLowerCase() === "true";
|
|
17353
|
+
// src/turn-boundary.ts
|
|
17354
|
+
function isTurnBoundary(entry) {
|
|
17355
|
+
return entry.message?.role === "user";
|
|
17536
17356
|
}
|
|
17537
|
-
function
|
|
17538
|
-
|
|
17357
|
+
function lastTurnBoundaryId(entries) {
|
|
17358
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
17359
|
+
const e = entries[i];
|
|
17360
|
+
if (isTurnBoundary(e)) return e.id;
|
|
17361
|
+
}
|
|
17362
|
+
return void 0;
|
|
17363
|
+
}
|
|
17364
|
+
function lastTurnBoundaryIndex(entries) {
|
|
17365
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
17366
|
+
if (isTurnBoundary(entries[i])) return i;
|
|
17367
|
+
}
|
|
17368
|
+
return -1;
|
|
17539
17369
|
}
|
|
17540
17370
|
|
|
17541
17371
|
// src/tokens.ts
|
|
@@ -17766,39 +17596,33 @@ function assertNotAborted(signal) {
|
|
|
17766
17596
|
throw err;
|
|
17767
17597
|
}
|
|
17768
17598
|
|
|
17769
|
-
// src/
|
|
17770
|
-
function
|
|
17771
|
-
if (
|
|
17772
|
-
|
|
17773
|
-
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17777
|
-
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
|
|
17782
|
-
const result = ctx.getSystemPrompt?.();
|
|
17783
|
-
return normalizeSystemPrompt(result);
|
|
17599
|
+
// src/proxy-detect.ts
|
|
17600
|
+
function isBiliProxyBaseUrl(baseUrl) {
|
|
17601
|
+
if (!baseUrl) return false;
|
|
17602
|
+
try {
|
|
17603
|
+
const url = new URL(baseUrl);
|
|
17604
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
17605
|
+
const segments = url.pathname.split("/").filter((s) => s.length > 0);
|
|
17606
|
+
if (segments[0] !== "bili") return false;
|
|
17607
|
+
const rest = url.pathname.slice(url.pathname.indexOf("bili") + "bili".length);
|
|
17608
|
+
return /^\/https?:\/\//.test(rest);
|
|
17609
|
+
} catch {
|
|
17610
|
+
return false;
|
|
17611
|
+
}
|
|
17784
17612
|
}
|
|
17785
|
-
|
|
17786
|
-
|
|
17787
|
-
|
|
17788
|
-
"
|
|
17789
|
-
"Pi-compatible fork (e.g. Prime) running sessions in-process? Opt in explicitly:",
|
|
17790
|
-
" PI_ACP_FORK_HOST=1 <your host command>",
|
|
17791
|
-
'Contract: docs/host-adapter.md \u2192 "Supported-host detection".',
|
|
17792
|
-
"OMP (oh-my-pi)? Use the billion-context proxy instead \u2014 it runs compression server-side and works on OMP:",
|
|
17793
|
-
" npm install -g billion-context",
|
|
17794
|
-
" bili omp",
|
|
17613
|
+
var PROXY_STAND_DOWN_MESSAGE = [
|
|
17614
|
+
"[billion-context-pi] Model baseUrl routes through the billion-context wire proxy (/bili/ prefix) \u2014 ACP client-side compression has been disabled for this session to avoid double compression.",
|
|
17615
|
+
"The proxy runs the same compression pipeline server-side and owns the ref coordinate space; nothing else to configure.",
|
|
17616
|
+
"If your traffic reaches the proxy via HTTPS_PROXY instead (no /bili/ prefix in the URL), export BILLION_CONTEXT_PROXY=1 before starting pi.",
|
|
17795
17617
|
"Docs: https://github.com/ranxianglei/billion-context"
|
|
17796
17618
|
].join("\n");
|
|
17797
|
-
|
|
17798
|
-
|
|
17799
|
-
|
|
17800
|
-
|
|
17801
|
-
|
|
17619
|
+
function nativeStandDownMessage(host) {
|
|
17620
|
+
return [
|
|
17621
|
+
`[billion-context-pi] billion-context native host detected (BILLION_CONTEXT_NATIVE=${host}) \u2014 the in-process native plugin proxies model API traffic and owns compression.`,
|
|
17622
|
+
"ACP client-side compression has been disabled for this session to avoid double compression; nothing else to configure.",
|
|
17623
|
+
"Docs: https://github.com/ranxianglei/billion-context"
|
|
17624
|
+
].join("\n");
|
|
17625
|
+
}
|
|
17802
17626
|
|
|
17803
17627
|
// src/compress-model.ts
|
|
17804
17628
|
var SESSION_MODEL_REF = "session";
|
|
@@ -18041,7 +17865,7 @@ function makeCompressTool(runtime, overrides, pi) {
|
|
|
18041
17865
|
],
|
|
18042
17866
|
parameters: CompressParams,
|
|
18043
17867
|
async execute(toolCallId, params, signal, _onUpdate, ctx) {
|
|
18044
|
-
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ??
|
|
17868
|
+
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? PROXY_STAND_DOWN_MESSAGE }] };
|
|
18045
17869
|
let result;
|
|
18046
17870
|
const details = {};
|
|
18047
17871
|
try {
|
|
@@ -18274,17 +18098,6 @@ function refIsDead(ref, state, visibleIds) {
|
|
|
18274
18098
|
if (visibleIds.has(rawId)) return false;
|
|
18275
18099
|
return !hasActiveOwner(state, [rawId], visibleIds);
|
|
18276
18100
|
}
|
|
18277
|
-
function refDriftSignal(ref, state, visibleIds) {
|
|
18278
|
-
const trimmed = ref.trim();
|
|
18279
|
-
if (/^b\d+$/i.test(trimmed)) return "alive";
|
|
18280
|
-
const m2 = trimmed.match(/^m(\d+)$/i);
|
|
18281
|
-
if (!m2) return "unknown";
|
|
18282
|
-
const rawId = state.messageRefs.byRef[trimmed] ?? state.messageRefs.byRef[paddedRef(Number(m2[1]))];
|
|
18283
|
-
if (!rawId) return "unknown";
|
|
18284
|
-
if (rawId.startsWith("live-")) return "live";
|
|
18285
|
-
if (!visibleIds.has(rawId) && !hasActiveOwner(state, [rawId], visibleIds)) return "persistent-dangling";
|
|
18286
|
-
return "alive";
|
|
18287
|
-
}
|
|
18288
18101
|
function compressibleSnapshotText(nudge) {
|
|
18289
18102
|
const ranges = viableRanges(nudge?.compressibleRanges ?? []);
|
|
18290
18103
|
if (ranges.length === 0) {
|
|
@@ -18352,7 +18165,7 @@ async function handleCompress(args, runtime, ctx, toolCallId, signal, tools = []
|
|
|
18352
18165
|
assertNotAborted(signal);
|
|
18353
18166
|
const config = runtime.configFor(ctx);
|
|
18354
18167
|
const modelId = ctx.model?.id ?? "default";
|
|
18355
|
-
const systemPromptText =
|
|
18168
|
+
const systemPromptText = ctx.getSystemPrompt?.() ?? "";
|
|
18356
18169
|
const systemPromptTokens = systemPromptText ? defaultCountTokens(systemPromptText) : 0;
|
|
18357
18170
|
const imageTokens = collectImageTokens(entries, modelSupportsImages(ctx.model));
|
|
18358
18171
|
const sentTokens = estimateTokens(coreMessages, collectCoveredMessageIds(initialState), imageTokens) + systemPromptTokens;
|
|
@@ -18378,7 +18191,7 @@ async function handleCompress(args, runtime, ctx, toolCallId, signal, tools = []
|
|
|
18378
18191
|
}
|
|
18379
18192
|
return s.text === r.summary ? r : { ...r, summary: s.text };
|
|
18380
18193
|
});
|
|
18381
|
-
const turnKey =
|
|
18194
|
+
const turnKey = lastTurnBoundaryId(entries) ?? sid;
|
|
18382
18195
|
const snapshot = compressibleSnapshotText(turn.nudge);
|
|
18383
18196
|
if (runtime.compressRetryCappedFor(sid, turnKey)) {
|
|
18384
18197
|
logWarn("compress", { sid, event: "capped-reject", turnKey });
|
|
@@ -18491,17 +18304,6 @@ async function handleCompress(args, runtime, ctx, toolCallId, signal, tools = []
|
|
|
18491
18304
|
});
|
|
18492
18305
|
if (errors.length > 0) {
|
|
18493
18306
|
logError("compress", { sid: ctx.sessionManager.getSessionId(), event: "errors", count: errors.length, errors: errors.slice(0, 5) });
|
|
18494
|
-
if (blocksCreated === 0 && isDeclaredForkHost() && !isPiHost(ctx.sessionManager) && /does not exist|cannot be anchored|is unknown|unknown refs/i.test(errors.join(" "))) {
|
|
18495
|
-
const signals = ranges.flatMap((r) => [
|
|
18496
|
-
refDriftSignal(r.startId, state, visibleIds),
|
|
18497
|
-
refDriftSignal(r.endId, state, visibleIds)
|
|
18498
|
-
]);
|
|
18499
|
-
if (signals.includes("live") || signals.includes("unknown")) {
|
|
18500
|
-
logWarn("compress", { sid, event: "fork-ref-drift-suspected", seeIssue: "#459", errors: errors.slice(0, 3) });
|
|
18501
|
-
} else if (signals.includes("persistent-dangling")) {
|
|
18502
|
-
logWarn("compress", { sid, event: "anchor-rejected-hidden-orphan", errors: errors.slice(0, 3) });
|
|
18503
|
-
}
|
|
18504
|
-
}
|
|
18505
18307
|
}
|
|
18506
18308
|
if (warnings.length > 0) {
|
|
18507
18309
|
logWarn("compress", { sid: ctx.sessionManager.getSessionId(), event: "warnings", count: warnings.length, warnings: warnings.slice(0, 5) });
|
|
@@ -18560,7 +18362,7 @@ async function writeDedicatedSummaries(input) {
|
|
|
18560
18362
|
}
|
|
18561
18363
|
}
|
|
18562
18364
|
}
|
|
18563
|
-
const sessionSystemPrompt = isSession ?
|
|
18365
|
+
const sessionSystemPrompt = isSession ? input.ctx.getSystemPrompt?.() ?? "" : "";
|
|
18564
18366
|
const planned = prefix ? /* @__PURE__ */ new Map() : plannedFolds(input, ranges);
|
|
18565
18367
|
let used = 0;
|
|
18566
18368
|
const failed = [];
|
|
@@ -18968,119 +18770,10 @@ async function abortableSleep(ms, signal) {
|
|
|
18968
18770
|
if (signal.aborted) return "aborted";
|
|
18969
18771
|
const remaining = end - Date.now();
|
|
18970
18772
|
if (remaining <= 0) return "ok";
|
|
18971
|
-
await new Promise((
|
|
18773
|
+
await new Promise((resolve3) => setTimeout(resolve3, Math.min(250, remaining)));
|
|
18972
18774
|
}
|
|
18973
18775
|
}
|
|
18974
18776
|
|
|
18975
|
-
// src/sequence-match.ts
|
|
18976
|
-
function findUniqueLongestRun(candidates, live) {
|
|
18977
|
-
if (candidates.length === 0 || live.length === 0) return void 0;
|
|
18978
|
-
const ids = /* @__PURE__ */ new Map();
|
|
18979
|
-
const intern = (key) => {
|
|
18980
|
-
const existing = ids.get(key);
|
|
18981
|
-
if (existing !== void 0) return existing;
|
|
18982
|
-
const id = ids.size + 1;
|
|
18983
|
-
ids.set(key, id);
|
|
18984
|
-
return id;
|
|
18985
|
-
};
|
|
18986
|
-
const candidateIds = candidates.map(intern);
|
|
18987
|
-
const liveIds = live.map(intern);
|
|
18988
|
-
const separator = ids.size + 1;
|
|
18989
|
-
const sequence = [...candidateIds, separator, ...liveIds];
|
|
18990
|
-
const suffixArray = buildSuffixArray(sequence);
|
|
18991
|
-
const lcp = buildLcp(sequence, suffixArray);
|
|
18992
|
-
const candidateLength = candidates.length;
|
|
18993
|
-
const liveOffset = candidateLength + 1;
|
|
18994
|
-
const sourceOf = (suffix) => {
|
|
18995
|
-
if (suffix < candidateLength) return 0;
|
|
18996
|
-
if (suffix >= liveOffset) return 1;
|
|
18997
|
-
return void 0;
|
|
18998
|
-
};
|
|
18999
|
-
let bestLength = 0;
|
|
19000
|
-
for (let index = 1; index < suffixArray.length; index++) {
|
|
19001
|
-
const leftSource = sourceOf(suffixArray[index - 1]);
|
|
19002
|
-
const rightSource = sourceOf(suffixArray[index]);
|
|
19003
|
-
if (leftSource === void 0 || rightSource === void 0 || leftSource === rightSource) continue;
|
|
19004
|
-
bestLength = Math.max(bestLength, lcp[index]);
|
|
19005
|
-
}
|
|
19006
|
-
if (bestLength === 0) return void 0;
|
|
19007
|
-
let pairCount = 0;
|
|
19008
|
-
let uniqueCandidateStart = -1;
|
|
19009
|
-
let uniqueLiveStart = -1;
|
|
19010
|
-
for (let start = 0; start < suffixArray.length; ) {
|
|
19011
|
-
let end = start;
|
|
19012
|
-
while (end + 1 < suffixArray.length && lcp[end + 1] >= bestLength) end++;
|
|
19013
|
-
if (end > start) {
|
|
19014
|
-
const candidateStarts = [];
|
|
19015
|
-
const liveStarts = [];
|
|
19016
|
-
for (let index = start; index <= end; index++) {
|
|
19017
|
-
const suffix = suffixArray[index];
|
|
19018
|
-
const source = sourceOf(suffix);
|
|
19019
|
-
if (source === 0) candidateStarts.push(suffix);
|
|
19020
|
-
else if (source === 1) liveStarts.push(suffix - liveOffset);
|
|
19021
|
-
}
|
|
19022
|
-
const groupPairs = candidateStarts.length * liveStarts.length;
|
|
19023
|
-
pairCount += groupPairs;
|
|
19024
|
-
if (groupPairs === 1) {
|
|
19025
|
-
uniqueCandidateStart = candidateStarts[0];
|
|
19026
|
-
uniqueLiveStart = liveStarts[0];
|
|
19027
|
-
}
|
|
19028
|
-
if (pairCount > 1) return void 0;
|
|
19029
|
-
}
|
|
19030
|
-
start = end + 1;
|
|
19031
|
-
}
|
|
19032
|
-
return pairCount === 1 ? { candidateStart: uniqueCandidateStart, liveStart: uniqueLiveStart, length: bestLength } : void 0;
|
|
19033
|
-
}
|
|
19034
|
-
function findPositionalPrefixRun(candidates, live) {
|
|
19035
|
-
if (candidates.length === 0 || live.length === 0) return void 0;
|
|
19036
|
-
const max = Math.min(candidates.length, live.length);
|
|
19037
|
-
for (let length = max; length > 0; length--) {
|
|
19038
|
-
const candidateStart = candidates.length - length;
|
|
19039
|
-
let ok = true;
|
|
19040
|
-
for (let i = 0; i < length; i++) {
|
|
19041
|
-
if (candidates[candidateStart + i] !== live[i]) {
|
|
19042
|
-
ok = false;
|
|
19043
|
-
break;
|
|
19044
|
-
}
|
|
19045
|
-
}
|
|
19046
|
-
if (ok) return { candidateStart, liveStart: 0, length };
|
|
19047
|
-
}
|
|
19048
|
-
return void 0;
|
|
19049
|
-
}
|
|
19050
|
-
function buildSuffixArray(sequence) {
|
|
19051
|
-
const suffixArray = sequence.map((_2, index) => index);
|
|
19052
|
-
let ranks = [...sequence];
|
|
19053
|
-
for (let width = 1; width < sequence.length; width *= 2) {
|
|
19054
|
-
suffixArray.sort((left, right) => ranks[left] - ranks[right] || (ranks[left + width] ?? -1) - (ranks[right + width] ?? -1));
|
|
19055
|
-
const nextRanks = Array(sequence.length);
|
|
19056
|
-
nextRanks[suffixArray[0]] = 0;
|
|
19057
|
-
for (let index = 1; index < suffixArray.length; index++) {
|
|
19058
|
-
const previous = suffixArray[index - 1];
|
|
19059
|
-
const current = suffixArray[index];
|
|
19060
|
-
const differs = ranks[previous] !== ranks[current] || (ranks[previous + width] ?? -1) !== (ranks[current + width] ?? -1);
|
|
19061
|
-
nextRanks[current] = nextRanks[previous] + (differs ? 1 : 0);
|
|
19062
|
-
}
|
|
19063
|
-
ranks = nextRanks;
|
|
19064
|
-
if (ranks[suffixArray.at(-1)] === sequence.length - 1) break;
|
|
19065
|
-
}
|
|
19066
|
-
return suffixArray;
|
|
19067
|
-
}
|
|
19068
|
-
function buildLcp(sequence, suffixArray) {
|
|
19069
|
-
const positions = Array(sequence.length);
|
|
19070
|
-
for (let index = 0; index < suffixArray.length; index++) positions[suffixArray[index]] = index;
|
|
19071
|
-
const lcp = Array(sequence.length).fill(0);
|
|
19072
|
-
let length = 0;
|
|
19073
|
-
for (let start = 0; start < sequence.length; start++) {
|
|
19074
|
-
const position = positions[start];
|
|
19075
|
-
if (position === 0) continue;
|
|
19076
|
-
const previous = suffixArray[position - 1];
|
|
19077
|
-
while (start + length < sequence.length && previous + length < sequence.length && sequence[start + length] === sequence[previous + length]) length++;
|
|
19078
|
-
lcp[position] = length;
|
|
19079
|
-
if (length > 0) length--;
|
|
19080
|
-
}
|
|
19081
|
-
return lcp;
|
|
19082
|
-
}
|
|
19083
|
-
|
|
19084
18777
|
// src/overflow-selfheal.ts
|
|
19085
18778
|
var OVERFLOW_MARKER = /prompt is too long|prompt_too_long|prompt_is_too_long|prompt too long; exceeded (?:max )?context length|request_too_large|exceeds the context window|exceeds the (maximum |model['’]s )?limit|maximum context length|maximum context size|max context length|context length exceeded|context[_ ]length[_ ]exceeded|exceeded model token limit|input token count.*exceeds|reduce the length of the messages|token limit exceeded|input is too long for requested model|maximum prompt length is|exceeds the maximum allowed input length|is longer than the model['’]?s context length|exceeds the available context size|greater than the context length|context window exceeds limit|too large for model with \d+ maximum context length|but the configured context size is|model_context_window_exceeded|range of input length should be/i;
|
|
19086
18779
|
function inspectOverflowMessage(haystack) {
|
|
@@ -19204,28 +18897,6 @@ var OverflowEpisode = class {
|
|
|
19204
18897
|
}
|
|
19205
18898
|
};
|
|
19206
18899
|
|
|
19207
|
-
// src/turn-boundary.ts
|
|
19208
|
-
function isTurnBoundary(entry, policy = {}) {
|
|
19209
|
-
if (entry.message?.role === "user") return true;
|
|
19210
|
-
if (policy.countCustomMessages !== true || !isCustomMessageEntry(entry)) return false;
|
|
19211
|
-
const allowed = policy.customMessageTypes;
|
|
19212
|
-
if (allowed === void 0) return true;
|
|
19213
|
-
return entry.customType !== void 0 && allowed.includes(entry.customType);
|
|
19214
|
-
}
|
|
19215
|
-
function lastTurnBoundaryId(entries, policy) {
|
|
19216
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
19217
|
-
const e = entries[i];
|
|
19218
|
-
if (isTurnBoundary(e, policy)) return e.id;
|
|
19219
|
-
}
|
|
19220
|
-
return void 0;
|
|
19221
|
-
}
|
|
19222
|
-
function lastTurnBoundaryIndex(entries, policy) {
|
|
19223
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
19224
|
-
if (isTurnBoundary(entries[i], policy)) return i;
|
|
19225
|
-
}
|
|
19226
|
-
return -1;
|
|
19227
|
-
}
|
|
19228
|
-
|
|
19229
18900
|
// src/branch-guard.ts
|
|
19230
18901
|
var marks = /* @__PURE__ */ new WeakMap();
|
|
19231
18902
|
function baseIdOf2(id) {
|
|
@@ -19292,116 +18963,6 @@ function withBranchGuard(core) {
|
|
|
19292
18963
|
}
|
|
19293
18964
|
|
|
19294
18965
|
// src/runtime.ts
|
|
19295
|
-
function readContextEntries(sm) {
|
|
19296
|
-
const source = sm;
|
|
19297
|
-
if (typeof source.buildContextEntries === "function") return source.buildContextEntries();
|
|
19298
|
-
if (typeof source.getBranch === "function") return source.getBranch();
|
|
19299
|
-
return [];
|
|
19300
|
-
}
|
|
19301
|
-
function isPiHost(sm) {
|
|
19302
|
-
const source = sm;
|
|
19303
|
-
return typeof source.buildContextEntries === "function";
|
|
19304
|
-
}
|
|
19305
|
-
function retryBreakerKey(sm, policy) {
|
|
19306
|
-
return lastTurnBoundaryId(readContextEntries(sm), policy);
|
|
19307
|
-
}
|
|
19308
|
-
function mergeLiveEntries(entries, live, state, origins) {
|
|
19309
|
-
const persisted = entries.filter((e) => e.type === "message");
|
|
19310
|
-
const liveIdentities = live.map(messageIdentity);
|
|
19311
|
-
const persistedIdentities = persisted.map((entry) => messageIdentity(entry.message));
|
|
19312
|
-
const normalizedKeys = normalizePersistedMatchKeys(persisted, persistedIdentities, live, liveIdentities);
|
|
19313
|
-
const persistedRange = findUniqueLongestRun(persistedIdentities, normalizedKeys) ?? findPositionalPrefixRun(persistedIdentities, normalizedKeys);
|
|
19314
|
-
const originRange = findUniqueLongestRun(origins.map((origin) => origin.identity), liveIdentities);
|
|
19315
|
-
const identityRanks = /* @__PURE__ */ new Map();
|
|
19316
|
-
for (const identity of persistedIdentities) identityRanks.set(identity, (identityRanks.get(identity) ?? 0) + 1);
|
|
19317
|
-
const out = [];
|
|
19318
|
-
const nextOrigins = [];
|
|
19319
|
-
for (let i = 0; i < live.length; i++) {
|
|
19320
|
-
const msg = live[i];
|
|
19321
|
-
const entry = valueInRange(persisted, persistedRange, i);
|
|
19322
|
-
const origin = valueInRange(origins, originRange, i);
|
|
19323
|
-
if (entry) {
|
|
19324
|
-
if (origin) migrateLiveRefs(state, origin.rawId, entry.id);
|
|
19325
|
-
else migrateTaggedRef(state, msg, entry.id);
|
|
19326
|
-
out.push(entry);
|
|
19327
|
-
continue;
|
|
19328
|
-
}
|
|
19329
|
-
const identity = liveIdentities[i];
|
|
19330
|
-
const rank = identityRanks.get(identity) ?? 0;
|
|
19331
|
-
identityRanks.set(identity, rank + 1);
|
|
19332
|
-
const id = origin?.rawId ?? stableLiveId(identity, rank);
|
|
19333
|
-
out.push({ type: "message", id, parentId: null, timestamp: String(msg.timestamp ?? Date.now()), message: msg });
|
|
19334
|
-
nextOrigins.push({ rawId: id, identity });
|
|
19335
|
-
}
|
|
19336
|
-
origins.splice(0, origins.length, ...nextOrigins);
|
|
19337
|
-
const unmatched = live.length - (persistedRange?.length ?? 0);
|
|
19338
|
-
if (unmatched > 0) logInfo("runtime", { event: "merge-live-entries", live: live.length, unmatched });
|
|
19339
|
-
return out;
|
|
19340
|
-
}
|
|
19341
|
-
function stableLiveId(identity, rank) {
|
|
19342
|
-
return `live-${createHash2("sha256").update(`${identity}\0${rank}`).digest("hex").slice(0, 16)}`;
|
|
19343
|
-
}
|
|
19344
|
-
function migrateTaggedRef(state, message, stableId) {
|
|
19345
|
-
const ref = messageRef(message);
|
|
19346
|
-
const rawId = ref ? state.messageRefs.byRef[ref] : void 0;
|
|
19347
|
-
if (rawId?.startsWith("live-")) migrateLiveRefs(state, rawId, stableId);
|
|
19348
|
-
}
|
|
19349
|
-
function migrateLiveRefs(state, liveId, stableId) {
|
|
19350
|
-
const rootId = liveId.split("#", 1)[0];
|
|
19351
|
-
if (!rootId.startsWith("live-")) return;
|
|
19352
|
-
for (const [rawId, ref] of Object.entries(state.messageRefs.byRaw)) {
|
|
19353
|
-
if (rawId !== rootId && !rawId.startsWith(`${rootId}#`)) continue;
|
|
19354
|
-
const stableRawId = `${stableId}${rawId.slice(rootId.length)}`;
|
|
19355
|
-
if (state.messageRefs.byRaw[stableRawId] === void 0) {
|
|
19356
|
-
state.messageRefs.byRaw[stableRawId] = ref;
|
|
19357
|
-
state.messageRefs.byRef[ref] = stableRawId;
|
|
19358
|
-
} else if (state.messageRefs.byRef[ref] === rawId) {
|
|
19359
|
-
delete state.messageRefs.byRef[ref];
|
|
19360
|
-
}
|
|
19361
|
-
delete state.messageRefs.byRaw[rawId];
|
|
19362
|
-
}
|
|
19363
|
-
}
|
|
19364
|
-
var NO_PERSISTED_MATCH = /* @__PURE__ */ Symbol("no-persisted-match");
|
|
19365
|
-
function normalizePersistedMatchKeys(persisted, persistedIdentities, live, liveIdentities) {
|
|
19366
|
-
const persistedByStructure = /* @__PURE__ */ new Map();
|
|
19367
|
-
for (let index = 0; index < persisted.length; index++) {
|
|
19368
|
-
const key = toolResultStructureKey(persisted[index].message);
|
|
19369
|
-
if (key === void 0) continue;
|
|
19370
|
-
persistedByStructure.set(key, persistedByStructure.has(key) ? -1 : index);
|
|
19371
|
-
}
|
|
19372
|
-
return live.map((message, liveIndex) => {
|
|
19373
|
-
const key = toolResultStructureKey(message);
|
|
19374
|
-
const candidateIndex = key === void 0 ? void 0 : persistedByStructure.get(key);
|
|
19375
|
-
if (candidateIndex === void 0) return liveIdentities[liveIndex];
|
|
19376
|
-
if (candidateIndex < 0) return NO_PERSISTED_MATCH;
|
|
19377
|
-
return sameToolResult(persisted[candidateIndex].message, message) ? persistedIdentities[candidateIndex] : liveIdentities[liveIndex];
|
|
19378
|
-
});
|
|
19379
|
-
}
|
|
19380
|
-
function toolResultStructureKey(message) {
|
|
19381
|
-
if (message.role !== "toolResult") return void 0;
|
|
19382
|
-
return `${message.toolName}\0${message.toolCallId}`;
|
|
19383
|
-
}
|
|
19384
|
-
function valueInRange(values, range, liveIndex) {
|
|
19385
|
-
if (!range || liveIndex < range.liveStart || liveIndex >= range.liveStart + range.length) return void 0;
|
|
19386
|
-
return values[range.candidateStart + liveIndex - range.liveStart];
|
|
19387
|
-
}
|
|
19388
|
-
function sameToolResult(stored, visible) {
|
|
19389
|
-
if (stored.role !== "toolResult" || visible.role !== "toolResult") return false;
|
|
19390
|
-
return sameNonTextBlocks(stored.content, visible.content) && matchesStoredText(extractText(stored.content), extractText(visible.content));
|
|
19391
|
-
}
|
|
19392
|
-
function sameNonTextBlocks(a, b2) {
|
|
19393
|
-
const nonText = (blocks) => blocks.filter((block) => {
|
|
19394
|
-
if (!block || typeof block !== "object" || !("type" in block)) return true;
|
|
19395
|
-
return block.type !== "text";
|
|
19396
|
-
});
|
|
19397
|
-
try {
|
|
19398
|
-
const na = Array.isArray(a) ? nonText(a) : [];
|
|
19399
|
-
const nb = Array.isArray(b2) ? nonText(b2) : [];
|
|
19400
|
-
return JSON.stringify(na) === JSON.stringify(nb);
|
|
19401
|
-
} catch {
|
|
19402
|
-
return false;
|
|
19403
|
-
}
|
|
19404
|
-
}
|
|
19405
18966
|
function pruneOrphanRefs(state, messages) {
|
|
19406
18967
|
const retainedRawIds = new Set(messages.map((message) => message.id));
|
|
19407
18968
|
for (const block of state.blocks) {
|
|
@@ -19653,8 +19214,8 @@ function createRuntime(adapter) {
|
|
|
19653
19214
|
async function acquireLock(sid) {
|
|
19654
19215
|
const prev = locks.get(sid) ?? Promise.resolve();
|
|
19655
19216
|
let resolveNext;
|
|
19656
|
-
const next = new Promise((
|
|
19657
|
-
resolveNext =
|
|
19217
|
+
const next = new Promise((resolve3) => {
|
|
19218
|
+
resolveNext = resolve3;
|
|
19658
19219
|
});
|
|
19659
19220
|
const tail = prev.then(() => next);
|
|
19660
19221
|
locks.set(sid, tail);
|
|
@@ -19716,20 +19277,16 @@ function createRuntime(adapter) {
|
|
|
19716
19277
|
logWarn("runtime", { event: "config-reload-failed", error: e instanceof Error ? e.message : String(e) });
|
|
19717
19278
|
}
|
|
19718
19279
|
}
|
|
19719
|
-
const lastLiveBySession = /* @__PURE__ */ new Map();
|
|
19720
19280
|
const projectionCaches = /* @__PURE__ */ new Map();
|
|
19721
19281
|
function dropProjectionCache(sid) {
|
|
19722
19282
|
projectionCaches.delete(sid);
|
|
19723
19283
|
}
|
|
19724
|
-
async function stateFor(ctx
|
|
19284
|
+
async function stateFor(ctx) {
|
|
19725
19285
|
const sm = ctx.sessionManager;
|
|
19726
19286
|
const sessionFile = sm.getSessionFile() ?? void 0;
|
|
19727
19287
|
const sessionId = sm.getSessionId();
|
|
19728
|
-
const piHost = isPiHost(sm);
|
|
19729
|
-
if (!piHost && liveMessages && liveMessages.length > 0) lastLiveBySession.set(sessionId, [...liveMessages]);
|
|
19730
|
-
const live = piHost ? void 0 : liveMessages ?? lastLiveBySession.get(sessionId);
|
|
19731
19288
|
let state = await store.load(sessionFile, sessionId);
|
|
19732
|
-
const entries =
|
|
19289
|
+
const entries = sm.buildContextEntries();
|
|
19733
19290
|
if (sessionFile && state.blocks.length === 0 && hasCompressHistory(entries)) {
|
|
19734
19291
|
const rebuilt = rebuildStateFromLog({ entries, state, config: configFor(ctx), core });
|
|
19735
19292
|
if (rebuilt.report.blocks > 0) {
|
|
@@ -19744,22 +19301,14 @@ function createRuntime(adapter) {
|
|
|
19744
19301
|
});
|
|
19745
19302
|
}
|
|
19746
19303
|
}
|
|
19747
|
-
if (!piHost && live && live.length > 0) {
|
|
19748
|
-
const origins = store.getLiveRefOrigins(sessionFile, sessionId);
|
|
19749
|
-
const merged = mergeLiveEntries(entries, live, state, origins);
|
|
19750
|
-
store.setLiveRefOrigins(sessionFile, sessionId, origins);
|
|
19751
|
-
const coreMessages2 = entriesToCoreMessages(merged);
|
|
19752
|
-
pruneOrphanRefs(state, coreMessages2);
|
|
19753
|
-
return { state, coreMessages: coreMessages2, entries: merged };
|
|
19754
|
-
}
|
|
19755
19304
|
let projection = projectionCaches.get(sessionId);
|
|
19756
19305
|
if (!projection) {
|
|
19757
19306
|
projection = new EntryProjectionCache();
|
|
19758
19307
|
projectionCaches.set(sessionId, projection);
|
|
19759
19308
|
}
|
|
19760
19309
|
const coreMessages = projection.project(entries);
|
|
19761
|
-
|
|
19762
|
-
|
|
19310
|
+
pruneOrphanRefs(state, coreMessages);
|
|
19311
|
+
guardBranch(sm, sessionId, state, coreMessages);
|
|
19763
19312
|
return { state, coreMessages, entries };
|
|
19764
19313
|
}
|
|
19765
19314
|
const offBranchLogged = /* @__PURE__ */ new Map();
|
|
@@ -19777,27 +19326,6 @@ function createRuntime(adapter) {
|
|
|
19777
19326
|
const sm = ctx.sessionManager;
|
|
19778
19327
|
await store.save(state, sm.getSessionFile() ?? void 0, sm.getSessionId());
|
|
19779
19328
|
}
|
|
19780
|
-
function ownSidecarHasBlocks(sessionFile) {
|
|
19781
|
-
try {
|
|
19782
|
-
const parsed = JSON.parse(readFileSync3(`${sessionFile}.acp.json`, "utf8"));
|
|
19783
|
-
return Array.isArray(parsed.blocks) && parsed.blocks.length > 0;
|
|
19784
|
-
} catch {
|
|
19785
|
-
return false;
|
|
19786
|
-
}
|
|
19787
|
-
}
|
|
19788
|
-
async function deriveChild(child, parent) {
|
|
19789
|
-
if (!child.sessionFile) return false;
|
|
19790
|
-
if (ownSidecarHasBlocks(child.sessionFile)) return false;
|
|
19791
|
-
await store.load(child.sessionFile, child.sessionId);
|
|
19792
|
-
if (store.getDerivedFrom(child.sessionFile, child.sessionId)) return false;
|
|
19793
|
-
const parentState = await store.load(parent.sessionFile, parent.sessionId);
|
|
19794
|
-
if (parentState.blocks.length === 0) return false;
|
|
19795
|
-
const derived = deriveChildState(parentState);
|
|
19796
|
-
store.setDerivedFrom(child.sessionFile, child.sessionId, { parentSessionId: parent.sessionId, derivedAt: Date.now() });
|
|
19797
|
-
await store.save(derived, child.sessionFile, child.sessionId);
|
|
19798
|
-
logInfo("state", { sid: child.sessionId, event: "child-state-derived", parentSid: parent.sessionId, blocks: derived.blocks.length });
|
|
19799
|
-
return true;
|
|
19800
|
-
}
|
|
19801
19329
|
let refused = false;
|
|
19802
19330
|
let refusalMessage = null;
|
|
19803
19331
|
return { core, store, get refused() {
|
|
@@ -19816,7 +19344,7 @@ function createRuntime(adapter) {
|
|
|
19816
19344
|
return promptsRef;
|
|
19817
19345
|
}, setPrompts: (p) => {
|
|
19818
19346
|
promptsRef = p;
|
|
19819
|
-
}, markNudgeShown, nudgeShownFor, nudgeShownTokensFor, clearNudgeTracking, clearNudgeTokenStamps, markNudgeRecorded, nudgeRecordedFor, noteCompressOutcomes, compressRetryCappedFor, clearCompressRetryTracking, liveContextLimit, configFor, reasoningDropFor, reloadConfig, stateFor, save,
|
|
19347
|
+
}, markNudgeShown, nudgeShownFor, nudgeShownTokensFor, clearNudgeTracking, clearNudgeTokenStamps, markNudgeRecorded, nudgeRecordedFor, noteCompressOutcomes, compressRetryCappedFor, clearCompressRetryTracking, liveContextLimit, configFor, reasoningDropFor, reloadConfig, stateFor, save, acquireLock, overflowFor, overflowDrop, noteSentViewCount, peekSentViewCount, dropSentViewCount, dropProjectionCache, noteDeadCompress, clearDeadCompress, throttleFor, throttleDrop, noteTokenScale, dropTokenScale, noteHostUsage, dropHostUsageSamples, noteSizeDivergence, dropSizeDivergence, noteTerminalEscape, dropTerminalEscape, noteTruncationSkipped, dropTruncationSkipped, stripImagesFor, getCompressionModelRef, setCompressionModelRef, setLastSentMessages, getLastSentMessages, dropLastSentMessages };
|
|
19820
19348
|
}
|
|
19821
19349
|
|
|
19822
19350
|
// src/session-log.ts
|
|
@@ -19858,66 +19386,20 @@ async function loadAncestorEntries(sessionFile, wantedBaseIds) {
|
|
|
19858
19386
|
}
|
|
19859
19387
|
return [...found.values()];
|
|
19860
19388
|
}
|
|
19861
|
-
async function loadLiveRefEntries(sessionFile, wantedRawIds) {
|
|
19862
|
-
const wanted = new Set([...wantedRawIds].filter((id) => id.startsWith("live-")));
|
|
19863
|
-
const found = /* @__PURE__ */ new Map();
|
|
19864
|
-
if (!sessionFile || wanted.size === 0) return found;
|
|
19865
|
-
const seen = /* @__PURE__ */ new Set([sessionFile]);
|
|
19866
|
-
let current = sessionFile;
|
|
19867
|
-
for (let depth = 0; current !== void 0 && depth <= MAX_CHAIN_DEPTH && found.size < wanted.size; depth++) {
|
|
19868
|
-
const file = current;
|
|
19869
|
-
const identities = /* @__PURE__ */ new Map();
|
|
19870
|
-
try {
|
|
19871
|
-
const raw = await fs5.readFile(`${file}${STATE_SUFFIX}`, "utf8");
|
|
19872
|
-
const parsed = JSON.parse(raw);
|
|
19873
|
-
for (const origin of parseLiveRefOrigins(parsed.liveRefOrigins)) {
|
|
19874
|
-
if (!wanted.has(origin.rawId)) continue;
|
|
19875
|
-
const list = identities.get(origin.identity);
|
|
19876
|
-
if (list) list.push(origin.rawId);
|
|
19877
|
-
else identities.set(origin.identity, [origin.rawId]);
|
|
19878
|
-
}
|
|
19879
|
-
} catch (e) {
|
|
19880
|
-
const code = e.code;
|
|
19881
|
-
if (code !== "ENOENT") logWarn("session-log", { event: "live-ref-sidecar-failed", file, error: e instanceof Error ? e.message : String(e) });
|
|
19882
|
-
}
|
|
19883
|
-
if (identities.size > 0) {
|
|
19884
|
-
let text;
|
|
19885
|
-
try {
|
|
19886
|
-
text = await fs5.readFile(file, "utf8");
|
|
19887
|
-
} catch (e) {
|
|
19888
|
-
const code = e.code;
|
|
19889
|
-
if (code !== "ENOENT") logWarn("session-log", { event: "live-ref-log-failed", file, error: e instanceof Error ? e.message : String(e) });
|
|
19890
|
-
}
|
|
19891
|
-
if (text !== void 0) {
|
|
19892
|
-
for (const entry of parseSessionLog(text)) {
|
|
19893
|
-
if (entry.type !== "message") continue;
|
|
19894
|
-
const rawIds = identities.get(messageIdentity(entry.message));
|
|
19895
|
-
if (!rawIds) continue;
|
|
19896
|
-
for (const rawId of rawIds) if (!found.has(rawId)) found.set(rawId, entry);
|
|
19897
|
-
}
|
|
19898
|
-
}
|
|
19899
|
-
}
|
|
19900
|
-
const parent = await readParentSessionPath(file);
|
|
19901
|
-
if (!parent || seen.has(parent)) break;
|
|
19902
|
-
seen.add(parent);
|
|
19903
|
-
current = parent;
|
|
19904
|
-
}
|
|
19905
|
-
return found;
|
|
19906
|
-
}
|
|
19907
19389
|
|
|
19908
19390
|
// src/decompress-tool.ts
|
|
19909
19391
|
import { writeFile, mkdir } from "fs/promises";
|
|
19910
|
-
import { existsSync as
|
|
19911
|
-
import { resolve
|
|
19392
|
+
import { existsSync as existsSync2, lstatSync, readlinkSync, realpathSync } from "fs";
|
|
19393
|
+
import { resolve, relative, isAbsolute as isAbsolute2, join as join9, basename as basename2, dirname as dirname7 } from "path";
|
|
19912
19394
|
import { tmpdir, homedir as homedir6 } from "os";
|
|
19913
|
-
import { createHash as
|
|
19395
|
+
import { createHash as createHash2 } from "crypto";
|
|
19914
19396
|
var AUTO_DIR = join9(homedir6() || tmpdir(), ".cache", "pi", "acp-decompress");
|
|
19915
19397
|
var PREVIEW_CHARS = 600;
|
|
19916
19398
|
var MESSAGE_INLINE_THRESHOLD = 2e3;
|
|
19917
19399
|
var DecompressParams = typebox_exports.Object({
|
|
19918
19400
|
blockId: typebox_exports.String({ description: 'Block id to restore, e.g. "b5". Also accepts a message ref (UUID) from search_context results \u2014 resolves to the owning block automatically.' }),
|
|
19919
19401
|
full: typebox_exports.Optional(typebox_exports.Boolean({ description: "If true, recurse through all nested blocks to original messages. Default: false (restores one tier up \u2014 nested block summaries shown, direct messages in full)." })),
|
|
19920
|
-
toFile: typebox_exports.Optional(typebox_exports.String({ description: "Write restored content to this file path (must be under /tmp
|
|
19402
|
+
toFile: typebox_exports.Optional(typebox_exports.String({ description: "Write restored content to this file path (must be under /tmp or ~/.cache/pi) instead of the default auto-generated path. Block stays compressed." })),
|
|
19921
19403
|
inline: typebox_exports.Optional(typebox_exports.Boolean({ description: "If true, return content inline as this tool's result (appends to context). Default: false \u2014 content is written to an auto-generated file to avoid context bloat. Only set true when the content is small or you accept the context cost." }))
|
|
19922
19404
|
});
|
|
19923
19405
|
function makeDecompressTool(runtime, overrides) {
|
|
@@ -19934,7 +19416,7 @@ function makeDecompressTool(runtime, overrides) {
|
|
|
19934
19416
|
],
|
|
19935
19417
|
parameters: DecompressParams,
|
|
19936
19418
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
19937
|
-
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ??
|
|
19419
|
+
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? PROXY_STAND_DOWN_MESSAGE }] };
|
|
19938
19420
|
let result;
|
|
19939
19421
|
try {
|
|
19940
19422
|
const release = await runtime.acquireLock(ctx.sessionManager.getSessionId());
|
|
@@ -19959,26 +19441,25 @@ function refoldHint(blockId, result) {
|
|
|
19959
19441
|
}
|
|
19960
19442
|
var ALLOWED_DIRS = [
|
|
19961
19443
|
tmpdir(),
|
|
19962
|
-
join9(homedir6(), ".cache", "opencode"),
|
|
19963
19444
|
join9(homedir6(), ".cache", "pi")
|
|
19964
19445
|
];
|
|
19965
19446
|
function resolveToFilePath(targetPath) {
|
|
19966
19447
|
const expanded = targetPath.startsWith("~/") ? join9(homedir6(), targetPath.slice(2)) : targetPath;
|
|
19967
|
-
const resolved =
|
|
19448
|
+
const resolved = resolve(expanded);
|
|
19968
19449
|
let probe = resolved;
|
|
19969
19450
|
const suffix = [];
|
|
19970
|
-
while (!
|
|
19971
|
-
suffix.unshift(
|
|
19972
|
-
probe =
|
|
19451
|
+
while (!existsSync2(probe) && probe !== dirname7(probe)) {
|
|
19452
|
+
suffix.unshift(basename2(probe));
|
|
19453
|
+
probe = dirname7(probe);
|
|
19973
19454
|
}
|
|
19974
|
-
const real =
|
|
19455
|
+
const real = existsSync2(probe) ? realpathSync(probe) : probe;
|
|
19975
19456
|
let checked = real;
|
|
19976
19457
|
for (const part of suffix) {
|
|
19977
19458
|
checked = join9(checked, part);
|
|
19978
19459
|
try {
|
|
19979
19460
|
if (lstatSync(checked).isSymbolicLink()) {
|
|
19980
19461
|
const target = readlinkSync(checked);
|
|
19981
|
-
checked = isAbsolute2(target) ?
|
|
19462
|
+
checked = isAbsolute2(target) ? resolve(target) : resolve(dirname7(checked), target);
|
|
19982
19463
|
}
|
|
19983
19464
|
} catch {
|
|
19984
19465
|
}
|
|
@@ -19995,14 +19476,14 @@ function resolveToFilePath(targetPath) {
|
|
|
19995
19476
|
return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
|
|
19996
19477
|
});
|
|
19997
19478
|
if (!isAllowed) {
|
|
19998
|
-
return { error: `Error: toFile path must be under ${tmpdir()}
|
|
19479
|
+
return { error: `Error: toFile path must be under ${tmpdir()} or ~/.cache/pi. Got: ${targetPath}` };
|
|
19999
19480
|
}
|
|
20000
19481
|
return checked;
|
|
20001
19482
|
}
|
|
20002
19483
|
function messageFileStem(ref) {
|
|
20003
19484
|
if (/^[A-Za-z0-9._-]{1,80}$/.test(ref)) return `msg-${ref}`;
|
|
20004
19485
|
const readable = ref.replace(/[^A-Za-z0-9._-]+/g, "_").slice(0, 40);
|
|
20005
|
-
return `msg-${readable}-${
|
|
19486
|
+
return `msg-${readable}-${createHash2("sha256").update(ref).digest("hex").slice(0, 10)}`;
|
|
20006
19487
|
}
|
|
20007
19488
|
function autoFilePath(blockId) {
|
|
20008
19489
|
return join9(AUTO_DIR, `${blockId}-${Date.now()}.txt`);
|
|
@@ -20035,25 +19516,10 @@ async function resolveBlockMessages(block, coreMessages, ctx) {
|
|
|
20035
19516
|
const coveredBaseIds = new Set([...coreMessages, ...extra].map((m2) => m2.id.split("#")[0]));
|
|
20036
19517
|
const stillMissing = [...neededBaseIds].filter((id) => !coveredBaseIds.has(id));
|
|
20037
19518
|
if (stillMissing.length > 0) {
|
|
20038
|
-
const
|
|
20039
|
-
if (
|
|
20040
|
-
|
|
20041
|
-
|
|
20042
|
-
logInfo("decompress", { sid: ctx.sessionManager.getSessionId(), event: "ancestor-fallback", missing: ancestorMissing.length, found: ancestors.length });
|
|
20043
|
-
for (const entry of ancestors) extra.push(...entriesToCoreMessages([entry]));
|
|
20044
|
-
}
|
|
20045
|
-
}
|
|
20046
|
-
const liveMissing = stillMissing.filter((id) => id.startsWith("live-"));
|
|
20047
|
-
if (liveMissing.length > 0) {
|
|
20048
|
-
const recovered = await loadLiveRefEntries(ctx.sessionManager.getSessionFile(), new Set(liveMissing));
|
|
20049
|
-
if (recovered.size > 0) {
|
|
20050
|
-
logInfo("decompress", { sid: ctx.sessionManager.getSessionId(), event: "live-ref-recovery", missing: liveMissing.length, found: recovered.size });
|
|
20051
|
-
for (const [rawId, entry] of recovered) {
|
|
20052
|
-
for (const cm of entriesToCoreMessages([entry])) {
|
|
20053
|
-
extra.push({ ...cm, id: rawId + cm.id.slice(entry.id.length) });
|
|
20054
|
-
}
|
|
20055
|
-
}
|
|
20056
|
-
}
|
|
19519
|
+
const ancestors = await loadAncestorEntries(ctx.sessionManager.getSessionFile(), new Set(stillMissing));
|
|
19520
|
+
if (ancestors.length > 0) {
|
|
19521
|
+
logInfo("decompress", { sid: ctx.sessionManager.getSessionId(), event: "ancestor-fallback", missing: stillMissing.length, found: ancestors.length });
|
|
19522
|
+
for (const entry of ancestors) extra.push(...entriesToCoreMessages([entry]));
|
|
20057
19523
|
}
|
|
20058
19524
|
}
|
|
20059
19525
|
return [...coreMessages, ...extra];
|
|
@@ -20068,23 +19534,9 @@ async function findAncestorMessage(ref, ctx) {
|
|
|
20068
19534
|
}
|
|
20069
19535
|
return null;
|
|
20070
19536
|
}
|
|
20071
|
-
async function findLiveRefMessage(ref, ctx) {
|
|
20072
|
-
const baseId = ref.split("#")[0];
|
|
20073
|
-
const recovered = await loadLiveRefEntries(ctx.sessionManager.getSessionFile(), /* @__PURE__ */ new Set([baseId]));
|
|
20074
|
-
const entry = recovered.get(baseId);
|
|
20075
|
-
if (!entry) return null;
|
|
20076
|
-
const suffix = ref.slice(baseId.length);
|
|
20077
|
-
for (const cm of entriesToCoreMessages([entry])) {
|
|
20078
|
-
if (cm.id === entry.id + suffix) return { text: cm.text ?? "", role: cm.role };
|
|
20079
|
-
}
|
|
20080
|
-
return null;
|
|
20081
|
-
}
|
|
20082
19537
|
async function handleMessageRef(ref, ownerBlockId, args, ctx) {
|
|
20083
19538
|
let found = findMessageContent(ref, ctx);
|
|
20084
|
-
if (!found)
|
|
20085
|
-
const baseId = ref.split("#")[0];
|
|
20086
|
-
found = baseId.startsWith("live-") ? await findLiveRefMessage(ref, ctx) : await findAncestorMessage(ref, ctx);
|
|
20087
|
-
}
|
|
19539
|
+
if (!found) found = await findAncestorMessage(ref, ctx);
|
|
20088
19540
|
if (!found || !found.text) {
|
|
20089
19541
|
return `Message ${ref} (in block ${ownerBlockId}) has no restorable text content in the session log.`;
|
|
20090
19542
|
}
|
|
@@ -20246,7 +19698,7 @@ function makeSearchTool(runtime, overrides) {
|
|
|
20246
19698
|
],
|
|
20247
19699
|
parameters: SearchParams,
|
|
20248
19700
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20249
|
-
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ??
|
|
19701
|
+
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? PROXY_STAND_DOWN_MESSAGE }] };
|
|
20250
19702
|
let result;
|
|
20251
19703
|
try {
|
|
20252
19704
|
result = await handleSearch(params, runtime, ctx);
|
|
@@ -20298,7 +19750,7 @@ function formatSize(tokens) {
|
|
|
20298
19750
|
}
|
|
20299
19751
|
|
|
20300
19752
|
// src/prompt-pack.ts
|
|
20301
|
-
import { readFileSync as
|
|
19753
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
20302
19754
|
import { homedir as homedir7 } from "os";
|
|
20303
19755
|
function defaultPackSources2(cwd) {
|
|
20304
19756
|
return defaultPackSources({
|
|
@@ -20321,7 +19773,7 @@ function resolveActivePack(adapter, cwd, provider, modelId, resolver) {
|
|
|
20321
19773
|
}
|
|
20322
19774
|
var HOST_VERSION = (() => {
|
|
20323
19775
|
try {
|
|
20324
|
-
return "0.2.
|
|
19776
|
+
return "0.2.1";
|
|
20325
19777
|
} catch {
|
|
20326
19778
|
return "dev";
|
|
20327
19779
|
}
|
|
@@ -20416,7 +19868,7 @@ function readToolSurfaceWithPacks(cwd) {
|
|
|
20416
19868
|
let packName = "default";
|
|
20417
19869
|
for (const file of acpJsonFiles(cwd)) {
|
|
20418
19870
|
try {
|
|
20419
|
-
const parsed = JSON.parse(
|
|
19871
|
+
const parsed = JSON.parse(readFileSync3(file, "utf8"));
|
|
20420
19872
|
if (parsed && typeof parsed === "object") {
|
|
20421
19873
|
const rec = parsed;
|
|
20422
19874
|
if (rec.toolPrompts) inline = sanitizeToolPrompts(rec.toolPrompts);
|
|
@@ -20492,7 +19944,7 @@ function makeStatusTool(runtime, overrides) {
|
|
|
20492
19944
|
],
|
|
20493
19945
|
parameters: StatusParams,
|
|
20494
19946
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20495
|
-
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ??
|
|
19947
|
+
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? PROXY_STAND_DOWN_MESSAGE }] };
|
|
20496
19948
|
let result;
|
|
20497
19949
|
try {
|
|
20498
19950
|
result = await handleStatus(params, runtime, ctx);
|
|
@@ -20508,7 +19960,7 @@ async function handleStatus(args, runtime, ctx) {
|
|
|
20508
19960
|
const { state, coreMessages, entries } = await runtime.stateFor(ctx);
|
|
20509
19961
|
const config = applyOutputHeadroom(runtime.configFor(ctx), ctx.model, resolveOutputHeadroomCap(runtime.adapter.outputHeadroomMaxPct));
|
|
20510
19962
|
const coveredIds = collectCoveredMessageIds(state);
|
|
20511
|
-
const systemPromptText =
|
|
19963
|
+
const systemPromptText = ctx.getSystemPrompt?.() ?? "";
|
|
20512
19964
|
const systemPromptTokens = systemPromptText ? defaultCountTokens(systemPromptText) : 0;
|
|
20513
19965
|
const imageTokens = collectImageTokens(entries, modelSupportsImages(ctx.model));
|
|
20514
19966
|
const sentTokens = estimateTokens(coreMessages, coveredIds, imageTokens) + systemPromptTokens;
|
|
@@ -20615,7 +20067,7 @@ function makeCacheTool(runtime, overrides) {
|
|
|
20615
20067
|
],
|
|
20616
20068
|
parameters: CacheParams,
|
|
20617
20069
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20618
|
-
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ??
|
|
20070
|
+
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? PROXY_STAND_DOWN_MESSAGE }] };
|
|
20619
20071
|
try {
|
|
20620
20072
|
const text = await cacheReportText(runtime, ctx, params.detail === "full" ? "full" : "summary");
|
|
20621
20073
|
return { details: void 0, content: [{ type: "text", text }] };
|
|
@@ -20638,7 +20090,7 @@ function makeRuleTool(runtime) {
|
|
|
20638
20090
|
description: "Record a short, principle-level reminder that must survive context compression. Use it for behavioral corrections the user has had to repeat more than once, project invariants the user explicitly asked you to remember, and pitfalls you ran into once and must not run into again. Keep each rule short and principle-level. Recorded rules are hard-protected from compression and stay visible in the conversation. Omit the rule argument to list recorded rules.",
|
|
20639
20091
|
parameters: RuleParams,
|
|
20640
20092
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
20641
|
-
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ??
|
|
20093
|
+
if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? PROXY_STAND_DOWN_MESSAGE }] };
|
|
20642
20094
|
try {
|
|
20643
20095
|
const release = await runtime.acquireLock(ctx.sessionManager.getSessionId());
|
|
20644
20096
|
let text;
|
|
@@ -21228,7 +20680,7 @@ async function statusReport(runtime, ctx) {
|
|
|
21228
20680
|
const config = applyOutputHeadroom(runtime.configFor(ctx), ctx.model, resolveOutputHeadroomCap(runtime.adapter.outputHeadroomMaxPct));
|
|
21229
20681
|
const realUsage = ctx.getContextUsage?.();
|
|
21230
20682
|
const anchorStale = usageAnchorPredatesCompression(entries ?? []);
|
|
21231
|
-
const systemPromptText =
|
|
20683
|
+
const systemPromptText = ctx.getSystemPrompt?.() ?? "";
|
|
21232
20684
|
const systemPromptTokens = systemPromptText ? defaultCountTokens(systemPromptText) : 0;
|
|
21233
20685
|
const imageTokens = collectImageTokens(entries, modelSupportsImages(ctx.model));
|
|
21234
20686
|
const imageTokensTotal = [...imageTokens.values()].reduce((a, b2) => a + b2, 0);
|
|
@@ -21238,7 +20690,7 @@ async function statusReport(runtime, ctx) {
|
|
|
21238
20690
|
const sentTokens = estimateTokens(coreMessages, coveredIds, imageTokens) + systemPromptTokens;
|
|
21239
20691
|
const viewSentTokens = adjustedTokenCount(runtime.core, coreMessages, state, config, sentTokens, imageTokens, systemPromptTokens);
|
|
21240
20692
|
const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: anchorStale ? viewSentTokens : Math.max(viewSentTokens, realUsage?.tokens ?? 0) });
|
|
21241
|
-
const versionStr = "0.2.
|
|
20693
|
+
const versionStr = "0.2.1" ? `billion-context-pi@${"0.2.1"} \xB7 pack: ${resolveSurfaceMeta(runtime.adapter, ctx?.cwd ?? process.cwd(), ctx?.model?.provider, ctx?.model?.id).pack}` : void 0;
|
|
21242
20694
|
const text = buildStatusPanel({
|
|
21243
20695
|
version: versionStr,
|
|
21244
20696
|
tokenCount: sessionTokens,
|
|
@@ -21602,9 +21054,9 @@ function degenerationNotice(runs) {
|
|
|
21602
21054
|
}
|
|
21603
21055
|
|
|
21604
21056
|
// node_modules/acp-kernel/dist/wire/index.js
|
|
21605
|
-
import { createHash as
|
|
21057
|
+
import { createHash as createHash3 } from "crypto";
|
|
21606
21058
|
function hashId(s) {
|
|
21607
|
-
return
|
|
21059
|
+
return createHash3("sha256").update(s, "utf8").digest("hex").slice(0, 16);
|
|
21608
21060
|
}
|
|
21609
21061
|
function createSubagentNamespaces() {
|
|
21610
21062
|
const anchors = /* @__PURE__ */ new Map();
|
|
@@ -21784,13 +21236,11 @@ function applyStripImages(body, api, settings2) {
|
|
|
21784
21236
|
}
|
|
21785
21237
|
|
|
21786
21238
|
// src/tool-guardrails.ts
|
|
21787
|
-
import { createHash as
|
|
21788
|
-
|
|
21789
|
-
|
|
21790
|
-
|
|
21791
|
-
|
|
21792
|
-
return event.toolName === "bash";
|
|
21793
|
-
}
|
|
21239
|
+
import { createHash as createHash4 } from "crypto";
|
|
21240
|
+
import {
|
|
21241
|
+
isBashToolResult,
|
|
21242
|
+
isToolCallEventType
|
|
21243
|
+
} from "@earendil-works/pi-coding-agent";
|
|
21794
21244
|
function resolveBashTimeout(input, defaultTimeout) {
|
|
21795
21245
|
if (input.timeout !== void 0) return void 0;
|
|
21796
21246
|
const d2 = defaultTimeout ?? DEFAULT_TOOL_BASH_TIMEOUT;
|
|
@@ -21885,7 +21335,7 @@ function canonicalStringify(value) {
|
|
|
21885
21335
|
function repetitionFingerprint(toolName, input) {
|
|
21886
21336
|
const payload = `${toolName}\0${canonicalStringify(input ?? {})}`;
|
|
21887
21337
|
try {
|
|
21888
|
-
return
|
|
21338
|
+
return createHash4("sha1").update(payload).digest("hex");
|
|
21889
21339
|
} catch {
|
|
21890
21340
|
return `unhashable:${toolName}`;
|
|
21891
21341
|
}
|
|
@@ -21926,7 +21376,7 @@ function wireToolGuardrails(pi, runtime) {
|
|
|
21926
21376
|
const trackers = /* @__PURE__ */ new Map();
|
|
21927
21377
|
const pendingWarns = /* @__PURE__ */ new Map();
|
|
21928
21378
|
pi.on("tool_call", (event, ctx) => {
|
|
21929
|
-
if (
|
|
21379
|
+
if (isToolCallEventType("bash", event)) {
|
|
21930
21380
|
const t = resolveBashTimeout(event.input, runtime.adapter.toolBashDefaultTimeout);
|
|
21931
21381
|
if (t !== void 0) {
|
|
21932
21382
|
event.input.timeout = t;
|
|
@@ -22437,34 +21887,6 @@ function inheritedNote(id, effective) {
|
|
|
22437
21887
|
return "";
|
|
22438
21888
|
}
|
|
22439
21889
|
|
|
22440
|
-
// src/proxy-detect.ts
|
|
22441
|
-
function isBiliProxyBaseUrl(baseUrl) {
|
|
22442
|
-
if (!baseUrl) return false;
|
|
22443
|
-
try {
|
|
22444
|
-
const url = new URL(baseUrl);
|
|
22445
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
22446
|
-
const segments = url.pathname.split("/").filter((s) => s.length > 0);
|
|
22447
|
-
if (segments[0] !== "bili") return false;
|
|
22448
|
-
const rest = url.pathname.slice(url.pathname.indexOf("bili") + "bili".length);
|
|
22449
|
-
return /^\/https?:\/\//.test(rest);
|
|
22450
|
-
} catch {
|
|
22451
|
-
return false;
|
|
22452
|
-
}
|
|
22453
|
-
}
|
|
22454
|
-
var PROXY_STAND_DOWN_MESSAGE = [
|
|
22455
|
-
"[billion-context-pi] Model baseUrl routes through the billion-context wire proxy (/bili/ prefix) \u2014 ACP client-side compression has been disabled for this session to avoid double compression.",
|
|
22456
|
-
"The proxy runs the same compression pipeline server-side and owns the ref coordinate space; nothing else to configure.",
|
|
22457
|
-
"If your traffic reaches the proxy via HTTPS_PROXY instead (no /bili/ prefix in the URL), export BILLION_CONTEXT_PROXY=1 before starting pi.",
|
|
22458
|
-
"Docs: https://github.com/ranxianglei/billion-context"
|
|
22459
|
-
].join("\n");
|
|
22460
|
-
function nativeStandDownMessage(host) {
|
|
22461
|
-
return [
|
|
22462
|
-
`[billion-context-pi] billion-context native host detected (BILLION_CONTEXT_NATIVE=${host}) \u2014 the in-process native plugin proxies model API traffic and owns compression.`,
|
|
22463
|
-
"ACP client-side compression has been disabled for this session to avoid double compression; nothing else to configure.",
|
|
22464
|
-
"Docs: https://github.com/ranxianglei/billion-context"
|
|
22465
|
-
].join("\n");
|
|
22466
|
-
}
|
|
22467
|
-
|
|
22468
21890
|
// src/index.ts
|
|
22469
21891
|
var latestUserOverLimit = /* @__PURE__ */ new Set();
|
|
22470
21892
|
function createAcpExtension(adapter = {}) {
|
|
@@ -22520,7 +21942,7 @@ function userConfigDisabled(cwd) {
|
|
|
22520
21942
|
for (const file of acpJsonFiles(cwd)) {
|
|
22521
21943
|
let text;
|
|
22522
21944
|
try {
|
|
22523
|
-
text =
|
|
21945
|
+
text = readFileSync4(file, "utf8");
|
|
22524
21946
|
} catch {
|
|
22525
21947
|
continue;
|
|
22526
21948
|
}
|
|
@@ -22549,29 +21971,7 @@ function wireCompactionDisable(pi, runtime) {
|
|
|
22549
21971
|
});
|
|
22550
21972
|
}
|
|
22551
21973
|
function wireSessionLifecycle(pi, runtime, standDownIfProxied) {
|
|
22552
|
-
let ompWarned = false;
|
|
22553
|
-
let forkWarned = false;
|
|
22554
21974
|
pi.on("session_start", async (_event, ctx) => {
|
|
22555
|
-
if (isUnsupportedHost(ctx.sessionManager)) {
|
|
22556
|
-
runtime.refused = true;
|
|
22557
|
-
if (!ompWarned) {
|
|
22558
|
-
ompWarned = true;
|
|
22559
|
-
const sid2 = ctx.sessionManager.getSessionId();
|
|
22560
|
-
logWarn("host", { event: "host-unsupported", sid: sid2, action: "refused" });
|
|
22561
|
-
if (ctx.hasUI) ctx.ui.notify(UNSUPPORTED_HOST_MESSAGE, "warning");
|
|
22562
|
-
else console.error(UNSUPPORTED_HOST_MESSAGE);
|
|
22563
|
-
}
|
|
22564
|
-
return;
|
|
22565
|
-
}
|
|
22566
|
-
if (isDeclaredForkHost() && !isPiHost(ctx.sessionManager)) {
|
|
22567
|
-
const sid2 = ctx.sessionManager.getSessionId();
|
|
22568
|
-
logWarn("host", { event: "fork-host-admitted", sid: sid2, hardening: "#459", proxy: "billion-context" });
|
|
22569
|
-
if (!forkWarned) {
|
|
22570
|
-
forkWarned = true;
|
|
22571
|
-
if (ctx.hasUI) ctx.ui.notify(FORK_HOST_WARNING_MESSAGE, "warning");
|
|
22572
|
-
else console.error(FORK_HOST_WARNING_MESSAGE);
|
|
22573
|
-
}
|
|
22574
|
-
}
|
|
22575
21975
|
if (standDownIfProxied(ctx)) return;
|
|
22576
21976
|
runtime.store.invalidate();
|
|
22577
21977
|
runtime.clearNudgeTracking(ctx.sessionManager.getSessionId());
|
|
@@ -22586,7 +21986,7 @@ function wireSessionLifecycle(pi, runtime, standDownIfProxied) {
|
|
|
22586
21986
|
dropLiveOnlyTailCache(ctx.sessionManager.getSessionId());
|
|
22587
21987
|
const sid = ctx.sessionManager.getSessionId();
|
|
22588
21988
|
const modelInfo = ctx.model;
|
|
22589
|
-
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.2.
|
|
21989
|
+
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.2.1" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
|
|
22590
21990
|
try {
|
|
22591
21991
|
await runtime.reloadConfig(ctx.cwd);
|
|
22592
21992
|
} catch (e) {
|
|
@@ -22648,7 +22048,7 @@ function wireContextTransform(pi, runtime, standDownIfProxied, idle) {
|
|
|
22648
22048
|
try {
|
|
22649
22049
|
await runtime.reloadConfig(ctx.cwd);
|
|
22650
22050
|
const modelId = ctx.model?.id ?? "default";
|
|
22651
|
-
const { state, coreMessages, entries } = await runtime.stateFor(ctx
|
|
22051
|
+
const { state, coreMessages, entries } = await runtime.stateFor(ctx);
|
|
22652
22052
|
const configBase = runtime.configFor(ctx);
|
|
22653
22053
|
const ov = runtime.overflowFor(sid);
|
|
22654
22054
|
let config = configBase;
|
|
@@ -22665,7 +22065,7 @@ function wireContextTransform(pi, runtime, standDownIfProxied, idle) {
|
|
|
22665
22065
|
}
|
|
22666
22066
|
const coveredIds = collectCoveredMessageIds(state);
|
|
22667
22067
|
const realUsage = ctx.getContextUsage?.();
|
|
22668
|
-
const systemPromptText =
|
|
22068
|
+
const systemPromptText = ctx.getSystemPrompt?.() ?? "";
|
|
22669
22069
|
const systemPromptTokens = systemPromptText ? defaultCountTokens(systemPromptText) : 0;
|
|
22670
22070
|
const imageTokens = collectImageTokens(entries, modelSupportsImages(ctx.model));
|
|
22671
22071
|
const compressThinkingTokens = keptCompressThinkingTokens(
|
|
@@ -22847,11 +22247,9 @@ function wireContextTransform(pi, runtime, standDownIfProxied, idle) {
|
|
|
22847
22247
|
}
|
|
22848
22248
|
}
|
|
22849
22249
|
const debugOn2 = debug.enabled;
|
|
22850
|
-
const
|
|
22851
|
-
const
|
|
22852
|
-
const
|
|
22853
|
-
const compressOutcomes = collectCompressOutcomes(entries, lastTurnBoundaryIndex(entries, turnPolicy));
|
|
22854
|
-
const outcome = compressOutcomes.length > 0 ? runtime.noteCompressOutcomes(sid, retryTurnKey, compressOutcomes) : null;
|
|
22250
|
+
const turnKey = lastTurnBoundaryId(entries) ?? sid;
|
|
22251
|
+
const compressOutcomes = collectCompressOutcomes(entries, lastTurnBoundaryIndex(entries));
|
|
22252
|
+
const outcome = compressOutcomes.length > 0 ? runtime.noteCompressOutcomes(sid, turnKey, compressOutcomes) : null;
|
|
22855
22253
|
const adaptiveGrowth = !config.modelContextLimit || config.modelContextLimit <= 0 ? config.nudge.growthFloor : Math.min(
|
|
22856
22254
|
config.nudge.growthCap,
|
|
22857
22255
|
Math.max(config.nudge.growthFloor, Math.round(config.modelContextLimit * config.nudge.growthRatio))
|
|
@@ -22867,7 +22265,7 @@ function wireContextTransform(pi, runtime, standDownIfProxied, idle) {
|
|
|
22867
22265
|
if (turn.nudge?.shouldInject) {
|
|
22868
22266
|
const emergency = turn.nudge.breakdown?.emergencyOverride === 1;
|
|
22869
22267
|
turn.nudge.compressibleRanges = viableRanges(turn.nudge.compressibleRanges);
|
|
22870
|
-
const retryCapped = runtime.compressRetryCappedFor(sid,
|
|
22268
|
+
const retryCapped = runtime.compressRetryCappedFor(sid, turnKey);
|
|
22871
22269
|
const reInjectReady = shownAt === void 0 || tokenCount - shownAt >= reInjectFloor;
|
|
22872
22270
|
const alreadyShown = retryCapped || !emergency && runtime.nudgeShownFor(sid, turnKey) && !reInjectReady;
|
|
22873
22271
|
if (!alreadyShown) {
|
|
@@ -22983,7 +22381,9 @@ function wireSystemPrompt(pi, runtime) {
|
|
|
22983
22381
|
lastIgnoredPromptKeys = key;
|
|
22984
22382
|
}
|
|
22985
22383
|
const prompt = buildAcpSystemPrompt(runtime.prompts, merged.promptSections);
|
|
22986
|
-
return { systemPrompt:
|
|
22384
|
+
return { systemPrompt: `${event.systemPrompt}
|
|
22385
|
+
|
|
22386
|
+
${prompt}` };
|
|
22987
22387
|
});
|
|
22988
22388
|
}
|
|
22989
22389
|
var DEDICATED_CALLER_RULES = `HOW TO COMPRESS (dedicated summary model active)
|
|
@@ -23161,9 +22561,7 @@ function formatNudgeRecord(nudge, emergency) {
|
|
|
23161
22561
|
}
|
|
23162
22562
|
export {
|
|
23163
22563
|
createAcpExtension,
|
|
23164
|
-
createRuntime,
|
|
23165
22564
|
index_default as default,
|
|
23166
|
-
deriveChildState,
|
|
23167
22565
|
formatNudgeRecord
|
|
23168
22566
|
};
|
|
23169
22567
|
//# sourceMappingURL=index.js.map
|