billion-context-pi 0.1.67-pr.380.166 → 0.1.67

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 CHANGED
@@ -24,12 +24,6 @@ The model decides <em>when</em> and <em>what</em> to compress — not a hard lim
24
24
 
25
25
  > **Host support:** this plugin is for **Pi**. It does **not** support **OMP (oh-my-pi)** — on an OMP host it refuses to run. OMP users: use [billion-context](https://github.com/ranxianglei/billion-context) instead (`bili omp`, built-in plugin). Full client → package table: see [Which do I need?](#which-do-i-need); OMP details: [docs/omp.md](./docs/omp.md).
26
26
 
27
- ## Community
28
-
29
- Discussion, help, and updates on QQ — one group covers all three projects (`billion-context`, `billion-context-pi`, `opencode-acp`):
30
-
31
- **QQ Group: 1056132097**
32
-
33
27
  ## Why?
34
28
 
35
29
  When conversations get long, the model runs out of context. Most tools hard-truncate — silently dropping earlier messages. **billion-context** gives the model a `compress` tool: the LLM decides **when** and **what** to compress into high-fidelity summaries, preserving critical details (file paths, decisions, error strings) while reclaiming context space.
package/README.zh-CN.md CHANGED
@@ -22,12 +22,6 @@
22
22
 
23
23
  > **宿主支持:** 本插件面向 **Pi**。它**不支持 OMP(oh-my-pi)** —— 在 OMP 宿主上会拒绝运行。OMP 用户请直接改用 [billion-context](https://github.com/ranxianglei/billion-context)(启动命令 bili omp);其他客户端的完整对照见[该选哪个?](#该选哪个)。OMP 详细说明:[docs/omp.zh-CN.md](./docs/omp.zh-CN.md)。
24
24
 
25
- ## 社区
26
-
27
- 交流、求助与更新都在 QQ——同一个群覆盖三个项目(`billion-context`、`billion-context-pi`、`opencode-acp`):
28
-
29
- **QQ 群:1056132097**
30
-
31
25
  ## 为什么选择 billion-context
32
26
 
33
27
  当对话变长,模型的上下文会耗尽。多数工具采用硬截断 —— 静默丢弃早期消息。**billion-context** 把 `compress` 工具交给模型:由 LLM 决定**何时**压缩、压缩**什么**,将内容压缩成高保真摘要,在回收上下文空间的同时保留关键细节(文件路径、决策、错误字符串)。
package/dist/config.d.ts CHANGED
@@ -232,14 +232,6 @@ export interface AdapterConfig {
232
232
  * boolean shorthand (`false` disables) or an object. Default: enabled,
233
233
  * minRun=200. */
234
234
  degenerationGuard?: boolean | DegenerationGuardConfig;
235
- /** Host multi-session turn-boundary policy (#364). Accepts a boolean
236
- * shorthand (`true` → count host-injected custom_message entries as turn
237
- * boundaries) or a HostSessionConfig object. Default: off — pi-native
238
- * behavior where only genuine user-role messages start a turn, so existing
239
- * single-session users' nudge cadence is unchanged. Enable for inline
240
- * multi-session hosts (Prime RLM & co.) whose injected agent messages must
241
- * delimit real turns. See docs/host-adapter.md. */
242
- hostSession?: boolean | HostSessionConfig;
243
235
  /** Legacy flat alias for `delegate.displayUsage`. Kept for backward
244
236
  * compatibility with existing acp.json files. Prefer `delegate.displayUsage`. */
245
237
  displayUsage?: "merged" | "separate";
@@ -275,21 +267,6 @@ export declare function resolveRepetitionGuard(adapter: AdapterConfig): {
275
267
  warn: number;
276
268
  abort: number;
277
269
  };
278
- /** Host multi-session turn-boundary policy (#364). See TurnBoundaryPolicy in
279
- * src/turn-boundary.ts for the semantics this resolves. */
280
- export interface HostSessionConfig {
281
- /** Count host-injected custom_message entries (agent_message) as turn
282
- * boundaries. Default: false (pi-native behavior). */
283
- countCustomMessages?: boolean;
284
- }
285
- export interface ResolvedHostSession {
286
- countCustomMessages: boolean;
287
- }
288
- /** Resolve the host-session turn-boundary policy from the adapter, handling
289
- * the boolean shorthand (`true` enables countCustomMessages). Invalid values
290
- * fall back to the pi-native default (off) with a logged warning — they never
291
- * fail the session. */
292
- export declare function resolveHostSession(adapter: AdapterConfig): ResolvedHostSession;
293
270
  /** Per-field deepest-wins merge of the three compression levels (global →
294
271
  * provider → model). An undefined field at a deeper level does NOT clear a
295
272
  * value set at a shallower level — only a defined value overrides. */
package/dist/index.d.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  import type { ExtensionFactory } from "@earendil-works/pi-coding-agent";
2
2
  import { type AdapterConfig } from "./config.js";
3
- export { createRuntime } from "./runtime.js";
4
- export type { AcpRuntime, SessionRef } from "./runtime.js";
5
- export { deriveChildState } from "./state.js";
6
3
  export declare function createAcpExtension(adapter?: AdapterConfig): ExtensionFactory;
7
4
  declare const _default: ExtensionFactory;
8
5
  export default _default;
package/dist/index.js CHANGED
@@ -4,13 +4,9 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/config-dir.ts
8
- import * as piModule from "@earendil-works/pi-coding-agent";
9
- var PI_CONFIG_DIR_NAME = piModule.CONFIG_DIR_NAME;
10
- var CONFIG_DIR_NAME2 = typeof PI_CONFIG_DIR_NAME === "string" && PI_CONFIG_DIR_NAME.length > 0 ? PI_CONFIG_DIR_NAME : ".pi";
11
-
12
7
  // src/index.ts
13
- import { readFileSync as readFileSync3 } from "fs";
8
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME5 } from "@earendil-works/pi-coding-agent";
9
+ import { readFileSync as readFileSync2 } from "fs";
14
10
  import { homedir as homedir8 } from "os";
15
11
  import { join as join12 } from "path";
16
12
 
@@ -3858,10 +3854,11 @@ function makePreview(text, query, len) {
3858
3854
  import { appendFileSync, mkdirSync, statSync, renameSync, existsSync } from "fs";
3859
3855
  import * as path from "path";
3860
3856
  import { homedir } from "os";
3857
+ import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent";
3861
3858
  var MAX_BYTES = 10 * 1024 * 1024;
3862
3859
  var ENV_DEBUG = process.env.ACP_DEBUG === "1" || process.env.ACP_DEBUG === "true";
3863
3860
  function resolveLogFile() {
3864
- return process.env.ACP_LOG_FILE ?? path.join(homedir(), CONFIG_DIR_NAME2, "acp.log");
3861
+ return process.env.ACP_LOG_FILE ?? path.join(homedir(), CONFIG_DIR_NAME, "acp.log");
3865
3862
  }
3866
3863
  var runtimeDebug = null;
3867
3864
  function setDebugEnabled(enabled) {
@@ -4022,20 +4019,6 @@ function resolveRepetitionGuard(adapter) {
4022
4019
  }
4023
4020
  return { enabled: true, warn: REPETITION_GUARD_DEFAULTS.warn, abort: REPETITION_GUARD_DEFAULTS.abort };
4024
4021
  }
4025
- function resolveHostSession(adapter) {
4026
- const h = adapter.hostSession;
4027
- if (h === true) return { countCustomMessages: true };
4028
- if (h && typeof h === "object") {
4029
- if (typeof h.countCustomMessages !== "boolean") {
4030
- logWarn("config", { event: "host-session-invalid", field: "countCustomMessages", value: String(h.countCustomMessages), fallback: "false" });
4031
- }
4032
- return { countCustomMessages: h.countCustomMessages === true };
4033
- }
4034
- if (h !== void 0 && h !== false) {
4035
- logWarn("config", { event: "host-session-invalid", value: String(h), fallback: "off" });
4036
- }
4037
- return { countCustomMessages: false };
4038
- }
4039
4022
  function mergeCompress(global, provider, model) {
4040
4023
  return {
4041
4024
  maxContextLimit: model?.maxContextLimit ?? provider?.maxContextLimit ?? global?.maxContextLimit,
@@ -4087,9 +4070,6 @@ function parsePercent(v2) {
4087
4070
  return Number(s);
4088
4071
  }
4089
4072
 
4090
- // src/runtime.ts
4091
- import { readFileSync } from "fs";
4092
-
4093
4073
  // src/reasoning-drop.ts
4094
4074
  var DEFAULT_COMPRESS_REASONING = { drop: true, threshold: 2048 };
4095
4075
  function resolveReasoningDrop(cfg) {
@@ -4187,14 +4167,11 @@ var REF_TAG_SOURCE = "(?:<acp\\s[^>]*>m\\d{5}</acp>|\\[m\\d{1,5}\\])";
4187
4167
  var REF_TAG = new RegExp(`^${REF_TAG_SOURCE}\\s?\\n?`);
4188
4168
  var TRAILING_REF_TAG = new RegExp(`\\n*${REF_TAG_SOURCE}\\s*$`);
4189
4169
  var ACP_STATUS_CUSTOM_TYPE = "acp-status";
4190
- function isCustomMessageEntry(entry) {
4191
- return entry.type === "custom_message" && entry.customType !== ACP_STATUS_CUSTOM_TYPE && extractText(entry.content).length > 0;
4192
- }
4193
4170
  function entriesToCoreMessages(entries) {
4194
4171
  const out = [];
4195
4172
  for (const entry of entries) {
4196
4173
  if (entry.type !== "message") {
4197
- if (isCustomMessageEntry(entry)) {
4174
+ if (entry.type === "custom_message" && entry.customType !== ACP_STATUS_CUSTOM_TYPE) {
4198
4175
  const text = extractText(entry.content);
4199
4176
  if (text.length > 0) {
4200
4177
  out.push({ id: entry.id, role: "user", contentType: "text", text });
@@ -4592,7 +4569,6 @@ var SessionStateStore = class {
4592
4569
  if (cached) return cached.state;
4593
4570
  let state = createInitialState();
4594
4571
  let liveRefOrigins = [];
4595
- let derivedFrom = null;
4596
4572
  if (file) {
4597
4573
  try {
4598
4574
  const raw = await fs.readFile(file, "utf8");
@@ -4600,7 +4576,6 @@ var SessionStateStore = class {
4600
4576
  if (parsed && Array.isArray(parsed.blocks)) {
4601
4577
  state = mergeInitialState(parsed);
4602
4578
  liveRefOrigins = parseLiveRefOrigins(parsed.liveRefOrigins);
4603
- derivedFrom = parseDerivedFrom(parsed.derivedFrom);
4604
4579
  }
4605
4580
  } catch (e) {
4606
4581
  const code = e.code;
@@ -4613,16 +4588,14 @@ var SessionStateStore = class {
4613
4588
  if (parentState) state = parentState;
4614
4589
  }
4615
4590
  }
4616
- this.cache.set(key, { state, liveRefOrigins, derivedFrom });
4591
+ this.cache.set(key, { state, liveRefOrigins });
4617
4592
  return state;
4618
4593
  }
4619
4594
  async save(state, sessionFile, sessionId) {
4620
4595
  const file = stateFileFor(sessionFile);
4621
4596
  const key = cacheKey(sessionFile, sessionId);
4622
- const prev = this.cache.get(key);
4623
- const liveRefOrigins = prev?.liveRefOrigins ?? [];
4624
- const derivedFrom = prev?.derivedFrom ?? null;
4625
- this.cache.set(key, { state, liveRefOrigins, derivedFrom });
4597
+ const liveRefOrigins = this.cache.get(key)?.liveRefOrigins ?? [];
4598
+ this.cache.set(key, { state, liveRefOrigins });
4626
4599
  if (!file) return;
4627
4600
  const dir = path2.dirname(file);
4628
4601
  await fs.mkdir(dir, { recursive: true }).catch((e) => {
@@ -4630,9 +4603,7 @@ var SessionStateStore = class {
4630
4603
  });
4631
4604
  const tmp = path2.join(dir, `.acp-tmp-${path2.basename(file)}`);
4632
4605
  try {
4633
- const payload = { ...state, liveRefOrigins };
4634
- if (derivedFrom) payload.derivedFrom = derivedFrom;
4635
- await fs.writeFile(tmp, JSON.stringify(payload), "utf8");
4606
+ await fs.writeFile(tmp, JSON.stringify({ ...state, liveRefOrigins }), "utf8");
4636
4607
  await fs.rename(tmp, file);
4637
4608
  } catch (e) {
4638
4609
  logError("state", { event: "save-failed", file, error: e instanceof Error ? e.message : String(e) });
@@ -4644,15 +4615,7 @@ var SessionStateStore = class {
4644
4615
  setLiveRefOrigins(sessionFile, sessionId, origins) {
4645
4616
  const key = cacheKey(sessionFile, sessionId);
4646
4617
  const slot = this.cache.get(key);
4647
- if (slot) this.cache.set(key, { state: slot.state, liveRefOrigins: [...origins], derivedFrom: slot.derivedFrom });
4648
- }
4649
- getDerivedFrom(sessionFile, sessionId) {
4650
- return this.cache.get(cacheKey(sessionFile, sessionId))?.derivedFrom ?? null;
4651
- }
4652
- setDerivedFrom(sessionFile, sessionId, mark) {
4653
- const key = cacheKey(sessionFile, sessionId);
4654
- const slot = this.cache.get(key);
4655
- if (slot) this.cache.set(key, { state: slot.state, liveRefOrigins: slot.liveRefOrigins, derivedFrom: mark });
4618
+ if (slot) this.cache.set(key, { state: slot.state, liveRefOrigins: [...origins] });
4656
4619
  }
4657
4620
  invalidate() {
4658
4621
  this.cache.clear();
@@ -4685,25 +4648,6 @@ var SessionStateStore = class {
4685
4648
  return void 0;
4686
4649
  }
4687
4650
  };
4688
- function parseDerivedFrom(value) {
4689
- if (!value || typeof value !== "object") return null;
4690
- const mark = value;
4691
- if (typeof mark.parentSessionId !== "string" || typeof mark.derivedAt !== "number") return null;
4692
- return { parentSessionId: mark.parentSessionId, derivedAt: mark.derivedAt };
4693
- }
4694
- function deriveChildState(parent) {
4695
- const fresh = createInitialState();
4696
- return {
4697
- blocks: structuredClone(parent.blocks),
4698
- messageRefs: { byRaw: { ...parent.messageRefs.byRaw }, byRef: { ...parent.messageRefs.byRef } },
4699
- tokenSnapshot: { ...parent.tokenSnapshot },
4700
- nudge: fresh.nudge,
4701
- stats: fresh.stats,
4702
- absorbed: [],
4703
- nextBlockId: parent.nextBlockId,
4704
- nextRunId: parent.nextRunId
4705
- };
4706
- }
4707
4651
  function parseLiveRefOrigins(value) {
4708
4652
  if (!Array.isArray(value)) return [];
4709
4653
  return value.filter((item) => {
@@ -4883,6 +4827,7 @@ function rebuildStateFromLog(input) {
4883
4827
  import { promises as fs2 } from "fs";
4884
4828
  import * as path3 from "path";
4885
4829
  import { homedir as homedir2 } from "os";
4830
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME2 } from "@earendil-works/pi-coding-agent";
4886
4831
  async function loadUserConfig(cwd) {
4887
4832
  const home = homedir2();
4888
4833
  const merged = {};
@@ -4922,8 +4867,7 @@ var KNOWN = /* @__PURE__ */ new Set([
4922
4867
  "repetitionGuard",
4923
4868
  "degenerationGuard",
4924
4869
  "prompts",
4925
- "acknowledgePromptsRisk",
4926
- "hostSession"
4870
+ "acknowledgePromptsRisk"
4927
4871
  ]);
4928
4872
  function pickKnown(parsed) {
4929
4873
  const out = {};
@@ -5534,27 +5478,6 @@ function createRuntime(adapter) {
5534
5478
  const sm = ctx.sessionManager;
5535
5479
  await store.save(state, sm.getSessionFile() ?? void 0, sm.getSessionId());
5536
5480
  }
5537
- function ownSidecarHasBlocks(sessionFile) {
5538
- try {
5539
- const parsed = JSON.parse(readFileSync(`${sessionFile}.acp.json`, "utf8"));
5540
- return Array.isArray(parsed.blocks) && parsed.blocks.length > 0;
5541
- } catch {
5542
- return false;
5543
- }
5544
- }
5545
- async function deriveChild(child, parent) {
5546
- if (!child.sessionFile) return false;
5547
- if (ownSidecarHasBlocks(child.sessionFile)) return false;
5548
- await store.load(child.sessionFile, child.sessionId);
5549
- if (store.getDerivedFrom(child.sessionFile, child.sessionId)) return false;
5550
- const parentState = await store.load(parent.sessionFile, parent.sessionId);
5551
- if (parentState.blocks.length === 0) return false;
5552
- const derived = deriveChildState(parentState);
5553
- store.setDerivedFrom(child.sessionFile, child.sessionId, { parentSessionId: parent.sessionId, derivedAt: Date.now() });
5554
- await store.save(derived, child.sessionFile, child.sessionId);
5555
- logInfo("state", { sid: child.sessionId, event: "child-state-derived", parentSid: parent.sessionId, blocks: derived.blocks.length });
5556
- return true;
5557
- }
5558
5481
  let refused = false;
5559
5482
  let refusalMessage = null;
5560
5483
  return { core, store, get refused() {
@@ -5573,7 +5496,7 @@ function createRuntime(adapter) {
5573
5496
  return promptsRef;
5574
5497
  }, setPrompts: (p) => {
5575
5498
  promptsRef = p;
5576
- }, markNudgeShown, nudgeShownFor, nudgeShownTokensFor, clearNudgeTracking, clearNudgeTokenStamps, noteCompressOutcomes, compressRetryCappedFor, clearCompressRetryTracking, liveContextLimit, configFor, reasoningDropFor, reloadConfig, stateFor, save, deriveChildState: deriveChild, acquireLock, overflowFor, overflowDrop, noteDeadCompress, clearDeadCompress, throttleFor, throttleDrop, noteTokenScale, dropTokenScale };
5499
+ }, markNudgeShown, nudgeShownFor, nudgeShownTokensFor, clearNudgeTracking, clearNudgeTokenStamps, noteCompressOutcomes, compressRetryCappedFor, clearCompressRetryTracking, liveContextLimit, configFor, reasoningDropFor, reloadConfig, stateFor, save, acquireLock, overflowFor, overflowDrop, noteDeadCompress, clearDeadCompress, throttleFor, throttleDrop, noteTokenScale, dropTokenScale };
5577
5500
  }
5578
5501
 
5579
5502
  // node_modules/typebox/build/system/memory/memory.mjs
@@ -10017,25 +9940,13 @@ function adjustedTokenCount(core, messages, state, config, prelim, imageTokensBy
10017
9940
  const view = sentViewTokenCount(core, messages, state, config, prelim, imageTokensById, systemPromptTokens);
10018
9941
  return view.drifted ? view.viewTokens : prelim;
10019
9942
  }
10020
-
10021
- // src/turn-boundary.ts
10022
- function isTurnBoundary(entry, policy = {}) {
10023
- if (entry.message?.role === "user") return true;
10024
- return policy.countCustomMessages === true && isCustomMessageEntry(entry);
10025
- }
10026
- function lastTurnBoundaryId(entries, policy) {
9943
+ function lastUserMessageId(entries) {
10027
9944
  for (let i = entries.length - 1; i >= 0; i--) {
10028
9945
  const e = entries[i];
10029
- if (isTurnBoundary(e, policy)) return e.id;
9946
+ if (e.message?.role === "user") return e.id;
10030
9947
  }
10031
9948
  return void 0;
10032
9949
  }
10033
- function lastTurnBoundaryIndex(entries, policy) {
10034
- for (let i = entries.length - 1; i >= 0; i--) {
10035
- if (isTurnBoundary(entries[i], policy)) return i;
10036
- }
10037
- return -1;
10038
- }
10039
9950
 
10040
9951
  // src/compat.ts
10041
9952
  function normalizeSystemPrompt(input) {
@@ -10055,12 +9966,13 @@ function getSystemPromptText(ctx) {
10055
9966
  }
10056
9967
 
10057
9968
  // src/omp.ts
10058
- var UNSUPPORTED_HOST_MESSAGE = [
10059
- "[billion-context-pi] Unsupported host: no buildContextEntries() API and no PI_ACP_FORK_HOST declaration \u2014 ACP has been disabled for this session.",
10060
- "Pi-compatible fork (e.g. Prime) running sessions in-process? Opt in explicitly:",
10061
- " PI_ACP_FORK_HOST=1 <your host command>",
10062
- 'Contract: docs/host-adapter.md \u2192 "Supported-host detection".',
10063
- "OMP (oh-my-pi)? Use the billion-context proxy instead \u2014 it runs compression server-side and works on OMP:",
9969
+ function isOmpHost(sm) {
9970
+ return !isPiHost(sm);
9971
+ }
9972
+ var OMP_UNSUPPORTED_MESSAGE = [
9973
+ "[billion-context-pi] This host is OMP (oh-my-pi), which is NOT supported \u2014 ACP has been disabled for this session.",
9974
+ `The in-process compression path is unreliable on OMP: the nudge's example refs diverge from the session's real refs, so compress calls fail with "does not exist in this session".`,
9975
+ "Use the billion-context proxy instead \u2014 it runs compression server-side and works on OMP:",
10064
9976
  " npm install -g billion-context",
10065
9977
  " bili omp",
10066
9978
  "Docs: https://github.com/ranxianglei/billion-context"
@@ -10104,7 +10016,7 @@ function makeCompressTool(runtime) {
10104
10016
  ],
10105
10017
  parameters: CompressParams,
10106
10018
  async execute(toolCallId, params, _signal, _onUpdate, ctx) {
10107
- if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? UNSUPPORTED_HOST_MESSAGE }] };
10019
+ if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? OMP_UNSUPPORTED_MESSAGE }] };
10108
10020
  let result;
10109
10021
  try {
10110
10022
  result = await handleCompress(params, runtime, ctx, toolCallId);
@@ -10305,7 +10217,7 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
10305
10217
  }
10306
10218
  return s.text === r.summary ? r : { ...r, summary: s.text };
10307
10219
  });
10308
- const turnKey = lastTurnBoundaryId(entries, resolveHostSession(runtime.adapter)) ?? sid;
10220
+ const turnKey = lastUserMessageId(entries) ?? sid;
10309
10221
  const snapshot = compressibleSnapshotText(turn.nudge);
10310
10222
  if (runtime.compressRetryCappedFor(sid, turnKey)) {
10311
10223
  logWarn("compress", { sid, event: "capped-reject", turnKey });
@@ -10432,7 +10344,7 @@ function makeDecompressTool(runtime) {
10432
10344
  ],
10433
10345
  parameters: DecompressParams,
10434
10346
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
10435
- if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? UNSUPPORTED_HOST_MESSAGE }] };
10347
+ if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? OMP_UNSUPPORTED_MESSAGE }] };
10436
10348
  let result;
10437
10349
  try {
10438
10350
  result = await handleDecompress(params, runtime, ctx);
@@ -10672,7 +10584,7 @@ function makeSearchTool(runtime) {
10672
10584
  ],
10673
10585
  parameters: SearchParams,
10674
10586
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
10675
- if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? UNSUPPORTED_HOST_MESSAGE }] };
10587
+ if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? OMP_UNSUPPORTED_MESSAGE }] };
10676
10588
  let result;
10677
10589
  try {
10678
10590
  result = await handleSearch(params, runtime, ctx);
@@ -12559,7 +12471,7 @@ function makeStatusTool(runtime) {
12559
12471
  ],
12560
12472
  parameters: StatusParams,
12561
12473
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
12562
- if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? UNSUPPORTED_HOST_MESSAGE }] };
12474
+ if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? OMP_UNSUPPORTED_MESSAGE }] };
12563
12475
  let result;
12564
12476
  try {
12565
12477
  result = await handleStatus(params, runtime, ctx);
@@ -16761,6 +16673,7 @@ async function openFleetInspector(ctx) {
16761
16673
  import * as fs5 from "fs";
16762
16674
  import * as os2 from "os";
16763
16675
  import * as path7 from "path";
16676
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME3 } from "@earendil-works/pi-coding-agent";
16764
16677
  var ACP_TOOLS2 = ["compress", "decompress", "search_context", "acp_status"];
16765
16678
  function resolveAgentDir() {
16766
16679
  const envDir = process.env.PI_CODING_AGENT_DIR;
@@ -16769,7 +16682,7 @@ function resolveAgentDir() {
16769
16682
  if (envDir.startsWith("~/")) return path7.join(os2.homedir(), envDir.slice(2));
16770
16683
  return envDir;
16771
16684
  }
16772
- return path7.join(os2.homedir(), CONFIG_DIR_NAME2, "agent");
16685
+ return path7.join(os2.homedir(), CONFIG_DIR_NAME3, "agent");
16773
16686
  }
16774
16687
  function parseFrontmatterTools(content) {
16775
16688
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
@@ -16795,11 +16708,11 @@ function parseFrontmatterTools(content) {
16795
16708
  function findPiSubagentsInstall(agentDir, cwd) {
16796
16709
  const candidates = [
16797
16710
  path7.join(agentDir, "npm", "node_modules", "pi-subagents"),
16798
- path7.join(cwd, CONFIG_DIR_NAME2, "npm", "node_modules", "pi-subagents")
16711
+ path7.join(cwd, CONFIG_DIR_NAME3, "npm", "node_modules", "pi-subagents")
16799
16712
  ];
16800
16713
  const extensionRoots = [
16801
16714
  path7.join(agentDir, "extensions"),
16802
- path7.join(cwd, CONFIG_DIR_NAME2, "extensions")
16715
+ path7.join(cwd, CONFIG_DIR_NAME3, "extensions")
16803
16716
  ];
16804
16717
  for (const dir of candidates) {
16805
16718
  if (fs5.existsSync(path7.join(dir, "package.json"))) return dir;
@@ -17353,12 +17266,12 @@ When a background delegate finishes, an automated completion notification is inj
17353
17266
 
17354
17267
  // src/tool-guardrails.ts
17355
17268
  import { createHash } from "crypto";
17269
+ import {
17270
+ isToolCallEventType
17271
+ } from "@earendil-works/pi-coding-agent";
17356
17272
  function isBashToolResult(e) {
17357
17273
  return e.toolName === "bash";
17358
17274
  }
17359
- function isBashToolCall(event) {
17360
- return event.toolName === "bash";
17361
- }
17362
17275
  function resolveBashTimeout(input, defaultTimeout) {
17363
17276
  if (input.timeout !== void 0) return void 0;
17364
17277
  const d2 = defaultTimeout ?? DEFAULT_TOOL_BASH_TIMEOUT;
@@ -17494,7 +17407,7 @@ function wireToolGuardrails(pi, runtime) {
17494
17407
  const trackers = /* @__PURE__ */ new Map();
17495
17408
  const pendingWarns = /* @__PURE__ */ new Map();
17496
17409
  pi.on("tool_call", (event, ctx) => {
17497
- if (isBashToolCall(event)) {
17410
+ if (isToolCallEventType("bash", event)) {
17498
17411
  const t = resolveBashTimeout(event.input, runtime.adapter.toolBashDefaultTimeout);
17499
17412
  if (t !== void 0) {
17500
17413
  event.input.timeout = t;
@@ -17567,6 +17480,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
17567
17480
  import { execFile } from "child_process";
17568
17481
  import { homedir as homedir7 } from "os";
17569
17482
  import { createHash as createHash2 } from "crypto";
17483
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME4 } from "@earendil-works/pi-coding-agent";
17570
17484
  var PACKAGE_NAME = "billion-context-pi";
17571
17485
  var registryUrl = (tag) => `https://registry.npmjs.org/${PACKAGE_NAME}/${encodeURIComponent(tag)}`;
17572
17486
  var SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/;
@@ -17576,10 +17490,10 @@ function locationKey(location) {
17576
17490
  }
17577
17491
  var throttleFileFor = (extDir) => {
17578
17492
  if (process.env.ACP_UPDATE_THROTTLE_FILE) return process.env.ACP_UPDATE_THROTTLE_FILE;
17579
- const base = join11(homedir7(), CONFIG_DIR_NAME2, "agent");
17493
+ const base = join11(homedir7(), CONFIG_DIR_NAME4, "agent");
17580
17494
  return extDir ? join11(base, `.billion-context-pi-update-check-${locationKey(extDir)}`) : join11(base, ".billion-context-pi-update-check");
17581
17495
  };
17582
- var readOnlyMarkerFile = (extDir) => join11(homedir7(), CONFIG_DIR_NAME2, "agent", `.billion-context-pi-readonly-${locationKey(extDir)}`);
17496
+ var readOnlyMarkerFile = (extDir) => join11(homedir7(), CONFIG_DIR_NAME4, "agent", `.billion-context-pi-readonly-${locationKey(extDir)}`);
17583
17497
  var updateInFlight = false;
17584
17498
  var runNpm = async (args, opts) => {
17585
17499
  return new Promise((resolve3) => {
@@ -17929,15 +17843,6 @@ async function getInstalledSpec() {
17929
17843
  return hostPkg?.dependencies?.[PACKAGE_NAME];
17930
17844
  }
17931
17845
 
17932
- // src/host.ts
17933
- function isDeclaredForkHost() {
17934
- const v2 = process.env.PI_ACP_FORK_HOST;
17935
- return v2 === "1" || v2?.toLowerCase() === "true";
17936
- }
17937
- function isUnsupportedHost(sm) {
17938
- return !isPiHost(sm) && !isDeclaredForkHost();
17939
- }
17940
-
17941
17846
  // src/proxy-detect.ts
17942
17847
  function isBiliProxyBaseUrl(baseUrl) {
17943
17848
  if (!baseUrl) return false;
@@ -18004,9 +17909,9 @@ function createAcpExtension(adapter = {}) {
18004
17909
  var index_default = createAcpExtension();
18005
17910
  function userConfigDisabled(cwd) {
18006
17911
  let disabled;
18007
- for (const base of [join12(homedir8(), CONFIG_DIR_NAME2), join12(cwd, CONFIG_DIR_NAME2)]) {
17912
+ for (const base of [join12(homedir8(), CONFIG_DIR_NAME5), join12(cwd, CONFIG_DIR_NAME5)]) {
18008
17913
  try {
18009
- const parsed = JSON.parse(readFileSync3(join12(base, "acp.json"), "utf8"));
17914
+ const parsed = JSON.parse(readFileSync2(join12(base, "acp.json"), "utf8"));
18010
17915
  if (parsed && typeof parsed === "object") {
18011
17916
  const v2 = parsed.enabled;
18012
17917
  if (v2 === true || v2 === false) disabled = v2;
@@ -18037,14 +17942,14 @@ function wireDelegateReadTracking(pi) {
18037
17942
  function wireSessionLifecycle(pi, runtime, standDownIfProxied) {
18038
17943
  let ompWarned = false;
18039
17944
  pi.on("session_start", async (_event, ctx) => {
18040
- if (isUnsupportedHost(ctx.sessionManager)) {
17945
+ if (isOmpHost(ctx.sessionManager)) {
18041
17946
  runtime.refused = true;
18042
17947
  if (!ompWarned) {
18043
17948
  ompWarned = true;
18044
17949
  const sid2 = ctx.sessionManager.getSessionId();
18045
- logWarn("host", { event: "host-unsupported", sid: sid2, action: "refused" });
18046
- if (ctx.hasUI) ctx.ui.notify(UNSUPPORTED_HOST_MESSAGE, "warning");
18047
- else console.error(UNSUPPORTED_HOST_MESSAGE);
17950
+ logWarn("host", { event: "omp-unsupported", sid: sid2, action: "refused" });
17951
+ if (ctx.hasUI) ctx.ui.notify(OMP_UNSUPPORTED_MESSAGE, "warning");
17952
+ else console.error(OMP_UNSUPPORTED_MESSAGE);
18048
17953
  }
18049
17954
  return;
18050
17955
  }
@@ -18236,9 +18141,8 @@ function wireContextTransform(pi, runtime, standDownIfProxied) {
18236
18141
  }
18237
18142
  }
18238
18143
  const debugOn2 = debug.enabled;
18239
- const turnPolicy = resolveHostSession(runtime.adapter);
18240
- const turnKey = lastTurnBoundaryId(entries, turnPolicy) ?? sid;
18241
- const compressOutcomes = collectCompressOutcomes(entries, lastTurnBoundaryIndex(entries, turnPolicy));
18144
+ const turnKey = lastUserMessageId(entries) ?? sid;
18145
+ const compressOutcomes = collectCompressOutcomes(entries, turnStartIndex(entries));
18242
18146
  const outcome = compressOutcomes.length > 0 ? runtime.noteCompressOutcomes(sid, turnKey, compressOutcomes) : null;
18243
18147
  const adaptiveGrowth = !config.modelContextLimit || config.modelContextLimit <= 0 ? config.nudge.growthFloor : Math.min(
18244
18148
  config.nudge.growthCap,
@@ -18401,6 +18305,12 @@ function collectOriginals(entries) {
18401
18305
  }
18402
18306
  return map;
18403
18307
  }
18308
+ function turnStartIndex(entries) {
18309
+ for (let i = entries.length - 1; i >= 0; i--) {
18310
+ if (entries[i].message?.role === "user") return i;
18311
+ }
18312
+ return -1;
18313
+ }
18404
18314
  function collectCompressOutcomes(entries, startIndex) {
18405
18315
  const out = [];
18406
18316
  for (let i = Math.max(startIndex, -1) + 1; i < entries.length; i++) {
@@ -18439,8 +18349,6 @@ function nudgeMessage(nudge, blocks, prompts) {
18439
18349
  }
18440
18350
  export {
18441
18351
  createAcpExtension,
18442
- createRuntime,
18443
- index_default as default,
18444
- deriveChildState
18352
+ index_default as default
18445
18353
  };
18446
18354
  //# sourceMappingURL=index.js.map