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/dist/index.js CHANGED
@@ -2,46 +2,14 @@ import {
2
2
  SIDECAR_SCHEMA_VERSION,
3
3
  __export,
4
4
  sidecarProducer
5
- } from "./chunk-PPYOZRUP.js";
5
+ } from "./chunk-EYDKO7YM.js";
6
6
 
7
7
  // src/config-dir.ts
8
- import * as piModule from "@earendil-works/pi-coding-agent";
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 userConfigPathIn(CONFIG_DIR_NAME, root, ...segments);
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 dirname3 } from "path";
21
+ import { dirname as dirname2 } from "path";
54
22
 
55
23
  // src/log.ts
56
- import { appendFileSync, mkdirSync, statSync, renameSync, existsSync as existsSync2 } from "fs";
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 (existsSync2(file) && statSync(file).size >= MAX_BYTES) {
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(dirname3(file), { recursive: true });
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 readFileSync5 } from "fs";
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 resolve4 = (name) => {
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: resolve4,
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 = resolve4(f.slice(0, -5));
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, liveRefOrigins, derivedFrom, activePack });
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, liveRefOrigins, derivedFrom, activePack });
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/host.ts
17533
- function isDeclaredForkHost() {
17534
- const v2 = process.env.PI_ACP_FORK_HOST;
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 isUnsupportedHost(sm) {
17538
- return !isPiHost(sm) && !isDeclaredForkHost();
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/compat.ts
17770
- function normalizeSystemPrompt(input) {
17771
- if (input === void 0) return "";
17772
- if (Array.isArray(input)) return input.join("\n");
17773
- return input;
17774
- }
17775
- function formatSystemPromptForEvent(base, append) {
17776
- const normalized = normalizeSystemPrompt(base);
17777
- return `${normalized}
17778
-
17779
- ${append}`;
17780
- }
17781
- function getSystemPromptText(ctx) {
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
- // src/omp.ts
17787
- var UNSUPPORTED_HOST_MESSAGE = [
17788
- "[billion-context-pi] Unsupported host: no buildContextEntries() API and no PI_ACP_FORK_HOST declaration \u2014 ACP has been disabled for this session.",
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
- var FORK_HOST_WARNING_MESSAGE = [
17798
- '[billion-context-pi] Running on a declared fork host (PI_ACP_FORK_HOST). Live-tail refs are content-stable (#459); if compress ever fails with "does not exist in this session", this host rewrites its in-flight view \u2014 prefer the billion-context proxy for long sessions:',
17799
- " npm install -g billion-context",
17800
- " bili omp"
17801
- ].join("\n");
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 ?? UNSUPPORTED_HOST_MESSAGE }] };
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 = getSystemPromptText(ctx);
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 = retryBreakerKey(ctx.sessionManager, resolveHostSession(runtime.adapter)) ?? sid;
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 ? getSystemPromptText(input.ctx) : "";
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((resolve4) => setTimeout(resolve4, Math.min(250, remaining)));
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((resolve4) => {
19657
- resolveNext = resolve4;
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, liveMessages) {
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 = readContextEntries(sm);
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
- if (live === void 0) pruneOrphanRefs(state, coreMessages);
19762
- if (piHost) guardBranch(sm, sessionId, state, coreMessages);
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, deriveChildState: deriveChild, 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 };
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 existsSync3, lstatSync, readlinkSync, realpathSync } from "fs";
19911
- import { resolve as resolve2, relative, isAbsolute as isAbsolute2, join as join9, basename as basename3, dirname as dirname8 } from "path";
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 createHash3 } from "crypto";
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, ~/.cache/opencode, or ~/.cache/pi) instead of the default auto-generated path. Block stays compressed." })),
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 ?? UNSUPPORTED_HOST_MESSAGE }] };
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 = resolve2(expanded);
19448
+ const resolved = resolve(expanded);
19968
19449
  let probe = resolved;
19969
19450
  const suffix = [];
19970
- while (!existsSync3(probe) && probe !== dirname8(probe)) {
19971
- suffix.unshift(basename3(probe));
19972
- probe = dirname8(probe);
19451
+ while (!existsSync2(probe) && probe !== dirname7(probe)) {
19452
+ suffix.unshift(basename2(probe));
19453
+ probe = dirname7(probe);
19973
19454
  }
19974
- const real = existsSync3(probe) ? realpathSync(probe) : probe;
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) ? resolve2(target) : resolve2(dirname8(checked), 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()}, ~/.cache/opencode, or ~/.cache/pi. Got: ${targetPath}` };
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}-${createHash3("sha256").update(ref).digest("hex").slice(0, 10)}`;
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 ancestorMissing = stillMissing.filter((id) => !id.startsWith("live-"));
20039
- if (ancestorMissing.length > 0) {
20040
- const ancestors = await loadAncestorEntries(ctx.sessionManager.getSessionFile(), new Set(ancestorMissing));
20041
- if (ancestors.length > 0) {
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 ?? UNSUPPORTED_HOST_MESSAGE }] };
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 readFileSync4 } from "fs";
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.0";
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(readFileSync4(file, "utf8"));
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 ?? UNSUPPORTED_HOST_MESSAGE }] };
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 = getSystemPromptText(ctx);
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 ?? UNSUPPORTED_HOST_MESSAGE }] };
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 ?? UNSUPPORTED_HOST_MESSAGE }] };
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 = getSystemPromptText(ctx);
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.0" ? `billion-context-pi@${"0.2.0"} \xB7 pack: ${resolveSurfaceMeta(runtime.adapter, ctx?.cwd ?? process.cwd(), ctx?.model?.provider, ctx?.model?.id).pack}` : void 0;
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 createHash4 } from "crypto";
21057
+ import { createHash as createHash3 } from "crypto";
21606
21058
  function hashId(s) {
21607
- return createHash4("sha256").update(s, "utf8").digest("hex").slice(0, 16);
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 createHash5 } from "crypto";
21788
- function isBashToolResult(e) {
21789
- return e.toolName === "bash";
21790
- }
21791
- function isBashToolCall(event) {
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 createHash5("sha1").update(payload).digest("hex");
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 (isBashToolCall(event)) {
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 = readFileSync5(file, "utf8");
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.0" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
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, event.messages);
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 = getSystemPromptText(ctx);
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 turnPolicy = resolveHostSession(runtime.adapter);
22851
- const turnKey = lastTurnBoundaryId(entries, turnPolicy) ?? sid;
22852
- const retryTurnKey = retryBreakerKey(ctx.sessionManager, turnPolicy) ?? sid;
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, retryTurnKey);
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: formatSystemPromptForEvent(event.systemPrompt, prompt) };
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