billion-context-pi 0.1.80-pr.557.382 → 0.1.80

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
@@ -145,7 +145,7 @@ billion-context-pi is built for the **Pi** coding agent (`@earendil-works/pi-cod
145
145
  | `search_context` | Search compressed block summaries (and visible messages) by keyword |
146
146
  | `acp_status` | Show context usage, compressed blocks, compressible ranges |
147
147
  | `acp_cache` | Prompt-cache reconciliation: grand ledger (input/cached/hit rate), per-request miss attribution, per-fold economics |
148
- | `acp_rule` | Manage short, principle-level reminders that survive compression: record / list / delete by id / clear all (opt-in: `"rules": true`; humans: `/acp-rule`) |
148
+ | `acp_rule` | Record a short, principle-level reminder that survives compression (opt-in: `"rules": true`) |
149
149
  | `acp_delegate` | Spawn a clean-context sub-agent for a task (review / research / implement / plan / advise) |
150
150
  | `acp_delegate_wait` | Block until a delegate run finishes (returns its result; times out otherwise) |
151
151
  | `acp_delegate_cancel` | Cancel a running delegate by runId |
@@ -216,21 +216,6 @@ Blocks: 3 active (3.7K summary, 15.2K original compressed)
216
216
  b3 (T2) 3.3K→1.0K age=1m "Architecture review"
217
217
  ```
218
218
 
219
- ## `/acp-rule` command
220
-
221
- Human-side access to the same persistent session rules the model manages with `acp_rule` (requires `"rules": true`; otherwise every subcommand shows the enablement hint):
222
-
223
- ```
224
- /acp-rule # list all recorded rules
225
- /acp-rule <text> # record a rule directly (same echo as the tool: Recorded ruleN: …)
226
- /acp-rule remove <id> # remove one rule by id (e.g. remove rule3)
227
- /acp-rule clear # remove every recorded rule
228
- ```
229
-
230
- One operation per call; mixed operations are rejected without mutating anything. Rules live in the session's ACP state sidecar next to pi's session file, so tool-side and command-side edits see each other and survive restarts. Kernel validation errors (unknown id, over-limit record) surface verbatim.
231
-
232
- **If you also run the [`billion-context`](https://github.com/ranxianglei/billion-context) thin plugin with rules enabled:** both plugins register an `acp_rule` tool in pi, and pi dedupes tools by name — **first registration per name wins**, the other is silently ignored. Which implementation answers then depends on extension load order, and the two back different stores (this adapter writes the pi session sidecar; the proxy keeps its own session state). Enable rules on only one side. (When the proxy is detectable — `BILLION_CONTEXT_PROXY` exported or a `/bili/` baseURL — this adapter stands down entirely, so the collision can only arise from an undetectable transparent-proxy setup; see the reverse-collision note above.)
233
-
234
219
  ## `/acp-subagents` command
235
220
 
236
221
  **Optional, one-time setup — only if you also use [pi-subagents](https://github.com/nicobailon/pi-subagents).**
package/README.zh-CN.md CHANGED
@@ -133,7 +133,7 @@ billion-context-pi 面向 **Pi** 编码代理(`@earendil-works/pi-coding-agent`)
133
133
  | `decompress` | 恢复之前压缩的块内容 |
134
134
  | `search_context` | 按关键词搜索已压缩块摘要(及可见消息) |
135
135
  | `acp_status` | 显示上下文用量、已压缩块、可压缩范围 |
136
- | `acp_rule` | 管理穿越压缩保留的简短、原则性提醒:记录 / 列表 / 按 id 删除 / 全部清空(可选:`"rules": true`;人类侧:`/acp-rule`) |
136
+ | `acp_rule` | 记录一条简短、原则性的提醒,穿越压缩保留(可选:`"rules": true`) |
137
137
  | `acp_delegate` | 为某个任务派生一个干净上下文的子代理(审查 / 调研 / 实现 / 规划 / 建议) |
138
138
  | `acp_delegate_wait` | 阻塞等待委派任务完成(返回结果,否则超时) |
139
139
  | `acp_delegate_cancel` | 按 runId 取消正在运行的委派任务 |
@@ -203,21 +203,6 @@ Blocks: 3 active (3.7K summary, 15.2K original compressed)
203
203
  b3 (T2) 3.3K→1.0K age=1m "Architecture review"
204
204
  ```
205
205
 
206
- ## `/acp-rule` 命令
207
-
208
- 人类侧访问与模型通过 `acp_rule` 管理的同一份持久会话规则(需要 `"rules": true`;否则每个子命令都会显示启用提示):
209
-
210
- ```
211
- /acp-rule # 列出所有已记录的规则
212
- /acp-rule <text> # 直接记录一条规则(与工具端相同的回显:Recorded ruleN: …)
213
- /acp-rule remove <id> # 按 id 删除一条规则(例如 remove rule3)
214
- /acp-rule clear # 删除所有已记录的规则
215
- ```
216
-
217
- 每次调用仅执行一个操作;混合操作会被拒绝且不会产生任何变更。规则存储在会话的 ACP state sidecar 中,与 pi 的会话文件并列存放,因此工具侧和命令侧的编辑彼此可见,且在重启后仍然保留。内核校验错误(未知 id、超出上限的记录)会原样呈现。
218
-
219
- **如果你同时运行了启用规则的 [`billion-context`](https://github.com/ranxianglei/billion-context) 薄插件:** 两个插件都会在 pi 中注册一个 `acp_rule` 工具,而 pi 按名称对工具去重——**同名以首次注册为准**,另一个会被静默忽略。最终哪个实现响应取决于扩展加载顺序,且两者背后是不同的存储(本适配器写入 pi 会话 sidecar;代理维护自己的会话状态)。请只在一侧启用规则。(当代理可被检测到时——导出了 `BILLION_CONTEXT_PROXY` 或 baseURL 带 `/bili/` 前缀——billion-context-pi 会整体让位,因此该冲突只能出现在无法检测的透明代理配置中;详见上方反向冲突说明。)
220
-
221
206
  ## `/acp-subagents` 命令
222
207
 
223
208
  **可选、一次性设置——仅当你同时使用 [pi-subagents](https://github.com/nicobailon/pi-subagents) 时需要。**
package/dist/index.js CHANGED
@@ -8772,12 +8772,23 @@ When context usage passes a threshold, the system appends a breakdown showing wh
8772
8772
  A provider rate-limit error (e.g. "Too many tokens, please wait before trying again.") may appear as a failed assistant response followed by a [ACP:provider-throttle] note. The interruption was transient and the system is retrying automatically. After such an interruption, resume the interrupted step exactly where it left off: do not re-run completed steps, do not re-read content already in context, and do not discuss the interruption unless asked.
8773
8773
  Retries are capped; when the cap is reached the error is surfaced to the user unchanged. If the user sends new input during a retry wait, the retry is cancelled.`]
8774
8774
  ];
8775
- var SECTION_KEYS = new Set(SECTIONS.map(([key]) => key));
8775
+ var PROMPT_SECTION_KEYS = /* @__PURE__ */ new Set([
8776
+ "acpTags",
8777
+ "summariesInContext",
8778
+ "tools",
8779
+ "whenToCompress",
8780
+ "whenNotToCompress",
8781
+ "multiTierIntro",
8782
+ "decompressPhilosophy",
8783
+ "contextBreakdown",
8784
+ "throttleRetry"
8785
+ ]);
8786
+ var RULE_SLOT_KEYS = /* @__PURE__ */ new Set(["philosophy", "howToCompress", "tier2", "tier3"]);
8776
8787
  function sanitizePromptSections(raw) {
8777
8788
  if (!raw || typeof raw !== "object") return {};
8778
8789
  const out = {};
8779
8790
  for (const [k, v2] of Object.entries(raw)) {
8780
- if (SECTION_KEYS.has(k) && (typeof v2 === "string" || v2 === null)) {
8791
+ if ((PROMPT_SECTION_KEYS.has(k) || RULE_SLOT_KEYS.has(k)) && (typeof v2 === "string" || v2 === null)) {
8781
8792
  out[k] = v2;
8782
8793
  }
8783
8794
  }
@@ -17246,21 +17257,18 @@ function makeCacheTool(runtime, overrides) {
17246
17257
 
17247
17258
  // src/rule-tool.ts
17248
17259
  var RuleParams = typebox_exports.Object({
17249
- rule: typebox_exports.Optional(typebox_exports.String({ description: "Short principle-level reminder to record. Omit to list recorded rules." })),
17250
- delete: typebox_exports.Optional(typebox_exports.String({ description: 'Id of a recorded rule to remove (e.g. "rule3"). Mutually exclusive with rule and clear.' })),
17251
- clear: typebox_exports.Optional(typebox_exports.Boolean({ description: "Remove every recorded rule at once. Mutually exclusive with rule and delete." }))
17260
+ rule: typebox_exports.Optional(typebox_exports.String({ description: "The reminder to record \u2014 short and principle-level. Omit this argument to list all recorded rules instead." }))
17252
17261
  });
17253
- var ONE_OP_PER_CALL = "Use one operation per call: record (rule), remove one (delete), remove all (clear: true), or list (no arguments).";
17254
17262
  function makeRuleTool(runtime) {
17255
17263
  return {
17256
17264
  name: RULE_TOOL_NAME,
17257
17265
  label: "ACP Rule",
17258
- description: 'Record a short, principle-level reminder so it survives context compression \u2014 the call and its result are protected and stay in context. Record when: the user calls out or repeatedly emphasizes a lesson; the user asks you to remember or follow a behavior; you personally hit a major pitfall worth remembering long-term. Keep each rule to one short line. Omit the rule argument to list recorded rules. To remove a recorded rule pass delete with its id (e.g. "rule3"); to remove every recorded rule pass clear: true. delete and clear are mutually exclusive with each other and with rule \u2014 use one operation per call.',
17266
+ 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.",
17259
17267
  parameters: RuleParams,
17260
17268
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
17261
17269
  if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? UNSUPPORTED_HOST_MESSAGE }] };
17262
17270
  try {
17263
- const text = await handleRule(params.rule, params.delete, params.clear, runtime, ctx);
17271
+ const text = await handleRule(params.rule, runtime, ctx);
17264
17272
  return { details: void 0, content: [{ type: "text", text }] };
17265
17273
  } catch (e) {
17266
17274
  logThrow("rule", e, { sid: ctx.sessionManager.getSessionId() });
@@ -17269,32 +17277,15 @@ function makeRuleTool(runtime) {
17269
17277
  }
17270
17278
  };
17271
17279
  }
17272
- async function handleRule(rule, del, clear, runtime, ctx) {
17280
+ async function handleRule(rule, runtime, ctx) {
17273
17281
  const sid = ctx.sessionManager.getSessionId();
17274
17282
  const { state } = await runtime.stateFor(ctx);
17275
- const text = typeof rule === "string" ? rule.trim() : "";
17276
- const delId = typeof del === "string" ? del.trim() : "";
17277
- const wantsClear = clear === true;
17278
- const ops = [delId.length > 0, wantsClear, text.length > 0].filter(Boolean).length;
17279
- if (ops > 1) return ONE_OP_PER_CALL;
17280
- if (wantsClear) {
17281
- const result2 = clearRules(state);
17282
- await runtime.save(state, ctx);
17283
- logInfo("rule", { sid, event: "cleared", count: result2.count });
17284
- return result2.count === 0 ? "No rules to clear." : `Cleared ${result2.count} rule(s).`;
17285
- }
17286
- if (delId.length > 0) {
17287
- const result2 = removeRule(state, delId);
17288
- if (!result2.ok) return result2.error;
17289
- await runtime.save(state, ctx);
17290
- logInfo("rule", { sid, event: "removed", id: result2.rule.id, remaining: listRules(state).length });
17291
- return `Removed ${result2.rule.id}: ${result2.rule.text}`;
17292
- }
17293
- if (text.length === 0) {
17283
+ if (rule === void 0) {
17294
17284
  const rules = listRules(state);
17295
- return rules.length === 0 ? "No rules recorded." : formatRulesList(rules);
17285
+ if (rules.length === 0) return "No rules recorded.";
17286
+ return formatRulesList(rules);
17296
17287
  }
17297
- const result = addRule(state, text, resolveRuleLimits(runtime.configFor(ctx)));
17288
+ const result = addRule(state, rule, resolveRuleLimits(runtime.configFor(ctx)));
17298
17289
  if (!result.ok) return result.error;
17299
17290
  await runtime.save(state, ctx);
17300
17291
  logInfo("rule", { sid, event: "recorded", id: result.rule.id, chars: result.rule.text.length, total: listRules(state).length });