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 +0 -6
- package/README.zh-CN.md +0 -6
- package/dist/config.d.ts +0 -23
- package/dist/index.d.ts +0 -3
- package/dist/index.js +53 -145
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +0 -15
- package/dist/omp.d.ts +16 -7
- package/dist/runtime.d.ts +0 -17
- package/dist/state.d.ts +0 -19
- package/dist/tokens.d.ts +8 -0
- package/dist/user-config.d.ts +1 -2
- package/package.json +1 -1
- package/dist/config-dir.d.ts +0 -1
- package/dist/host.d.ts +0 -15
- package/dist/turn-boundary.d.ts +0 -43
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 {
|
|
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(),
|
|
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 (
|
|
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
|
|
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
|
|
4623
|
-
|
|
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
|
-
|
|
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]
|
|
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,
|
|
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 (
|
|
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
|
-
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
|
|
10063
|
-
|
|
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 ??
|
|
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 =
|
|
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 ??
|
|
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 ??
|
|
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 ??
|
|
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(),
|
|
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,
|
|
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,
|
|
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 (
|
|
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(),
|
|
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(),
|
|
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(),
|
|
17912
|
+
for (const base of [join12(homedir8(), CONFIG_DIR_NAME5), join12(cwd, CONFIG_DIR_NAME5)]) {
|
|
18008
17913
|
try {
|
|
18009
|
-
const parsed = JSON.parse(
|
|
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 (
|
|
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: "
|
|
18046
|
-
if (ctx.hasUI) ctx.ui.notify(
|
|
18047
|
-
else console.error(
|
|
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
|
|
18240
|
-
const
|
|
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
|
-
|
|
18443
|
-
index_default as default,
|
|
18444
|
-
deriveChildState
|
|
18352
|
+
index_default as default
|
|
18445
18353
|
};
|
|
18446
18354
|
//# sourceMappingURL=index.js.map
|