billion-context-omp 0.3.0 → 0.3.2

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
@@ -144,7 +144,6 @@ Create `~/.omp/acp-omp.json` (global) and/or `<project>/.omp/acp-omp.json` (proj
144
144
  | Key | Default | Description |
145
145
  |-----|---------|-------------|
146
146
  | `debug` | `false` | Enable verbose **debug-level** events in the log. The always-on log (lifecycle events, errors, warnings) is written regardless; `debug` only adds extra diagnostics. Also enabled by env `ACP_DEBUG=1`. |
147
- | `transformMode` | unset (resolved per API) or explicit `"provider"` / `"context"` — where the compression surgery intercepts. Unset: `provider` where the host applies the wire-payload replacement AND the wire body has a codec path (anthropic-messages, ollama-chat; openai-completions on hosts >= 17.3.8 — upstream PR can1357/oh-my-pi#8717, issue #83); `context` everywhere else (issue #79). Explicit: always honored. `provider` transforms the provider wire payload (request-local, structurally immune to feedback re-entry); `context` rewrites the context event (legacy mode). |
148
147
  | `autoUpdate` | `true` | On session start (throttled to one check per 3 minutes), check npm for a newer version and auto-install it. Disable to avoid all startup network calls. |
149
148
  | `modelContextLimit` | *(auto)* | Override the context limit (in tokens). Defaults to the model's `contextWindow`. |
150
149
  | `toolBashDefaultTimeout` | `60` | Seconds injected into the `bash` tool when the model omits `timeout`. Without this a forgotten timeout can hang for thousands of seconds. `0` restores unbounded behavior. |
package/README.zh-CN.md CHANGED
@@ -146,7 +146,6 @@ billion-context-omp 开箱即用,无需配置。可选键写入 JSON 配置文
146
146
  | `debug` | `false` | 开启**debug 级**详细日志事件。常开日志(生命周期事件、错误、警告)无论如何都会写;`debug` 只增加诊断信息。也可用环境变量 `ACP_DEBUG=1` 开启。 |
147
147
  | `autoUpdate` | `true` | 会话启动时(节流为每 3 分钟最多一次)检查 npm 是否有新版本并自动安装。关闭可避免所有启动期网络请求。 |
148
148
  | `modelContextLimit` | *(自动)* | 覆盖上下文上限(token 数)。默认取模型的 `contextWindow`。 |
149
- | `transformMode` | 未设置(按 API 解析)或显式 `"provider"` / `"context"` | 压缩手术拦截位置。未设置:host 会应用 wire 载荷替换且 wire 体有编解码路径的 API 用 `provider`(anthropic-messages、ollama-chat;openai-completions 需 host >= 17.3.8,上游 PR can1357/oh-my-pi#8717,issue #83),其余用 `context`(issue #79)。显式设置总是生效。`provider` 变换 provider wire 载荷(请求局部,结构性免疫回灌环路);`context` 改写 context 事件(旧版模式)。 |
150
149
  | `toolBashDefaultTimeout` | `60` | 模型省略 `timeout` 时注入 `bash` 工具的秒数。没有它,一次忘记的 timeout 可能挂起数千秒。`0` 恢复无限制。 |
151
150
  | `toolOutputMaxBytes` | `200000` | 工具结果文本的硬字节上限(经 `tool_result` 钩子实施)。拦截 omp 自身上限管不住的失控输出。触发时模型会被告知完整输出在哪;调低(如 `8192`)可更省上下文,`0` 禁用。 |
152
151
  | `compress.maxContextLimit` | `"75%"` | 触发**强制压缩**提醒的上下文用量阈值(绕过增长门控与节拍)。接受比例(`0.75`)或百分比字符串(`"75%"`)。越低 = 越早/越激进压缩。 |
package/dist/config.d.ts CHANGED
@@ -12,6 +12,17 @@ export interface DelegateConfig {
12
12
  * counted as part of the main session totals. */
13
13
  displayUsage?: "merged" | "separate";
14
14
  }
15
+ /** Fold-state persistence (issue #130): checkpoint the live fold slot to
16
+ * disk so a restarted session restores its compression blocks without
17
+ * waiting for the first provider request to refold the wire. */
18
+ export interface FoldPersistenceConfig {
19
+ /** Default: enabled. `false` keeps the fold memory-only — restart falls
20
+ * back to the primeFold mirror. */
21
+ enabled?: boolean;
22
+ /** Directory for fold checkpoints. Default `~/.omp/acp-omp-folds/`
23
+ * (env `ACP_OMP_FOLD_DIR` overrides). */
24
+ dir?: string;
25
+ }
15
26
  /** Compression tuning. All fields accept a ratio (0.75) or percent string
16
27
  * ("75%") where noted. */
17
28
  export interface CompressConfig {
@@ -27,22 +38,6 @@ export interface CompressConfig {
27
38
  * (live model context window, protected tools, state persistence).
28
39
  */
29
40
  export interface AdapterConfig {
30
- /** Where the compression surgery intercepts (issue #52). "provider"
31
- * leaves the agent array untouched and transforms the WIRE payload at
32
- * before_provider_request — request-local, no re-entry, structurally
33
- * immune to omp's feedback-view loops (the recap / subagent re-feed
34
- * pathology, issues #22/#52). Unknown provider formats pass through
35
- * untransformed (fail-open). "context" rewrites the context event —
36
- * battle-tested legacy mode, kept for compat.
37
- * When omitted, the mode is resolved per model API (issue #79):
38
- * "provider" where the host actually applies the wire-payload
39
- * replacement AND the wire body has a codec path — anthropic-messages,
40
- * ollama-chat, and openai-completions on hosts >= 17.3.8 (upstream PR
41
- * can1357/oh-my-pi#8717, issue #83); "context" everywhere else
42
- * (older hosts drop the replacement; bedrock/cursor/responses/google
43
- * bodies have no codec path yet). Explicit pinning in
44
- * ~/.omp/acp-omp.json always wins. */
45
- transformMode?: "context" | "provider";
46
41
  /** When omitted, the adapter reads `ctx.model.contextWindow` live each turn.
47
42
  * Set explicitly for tests/headless runs. */
48
43
  modelContextLimit?: number;
@@ -73,10 +68,14 @@ export interface AdapterConfig {
73
68
  * head-truncated with a notice telling the model how to see the full output
74
69
  * (bash: read BashToolDetails.fullOutputPath). */
75
70
  toolOutputMaxBytes?: number;
76
- /** Delegate sub-agent config. Accepts a boolean shorthand (`true`
71
+ /** Delegate sub-agent config. Accepts a boolean shorthand (`true`
77
72
  * `{ enabled: true }`, `false` → `{ enabled: false }`) or a DelegateConfig
78
73
  * object. Default: enabled. */
79
74
  delegate?: boolean | DelegateConfig;
75
+ /** Fold-state persistence (issue #130). Accepts a boolean shorthand (`true`
76
+ * → `{ enabled: true }`, `false` → `{ enabled: false }`) or a
77
+ * FoldPersistenceConfig object. Default: enabled. */
78
+ foldPersistence?: boolean | FoldPersistenceConfig;
80
79
  /** Compression tuning. */
81
80
  compress?: CompressConfig;
82
81
  /** Legacy flat alias for `delegate.displayUsage`. Kept for backward
@@ -104,5 +103,11 @@ export declare function resolveDelegate(adapter: AdapterConfig): {
104
103
  enabled: boolean;
105
104
  displayUsage: "merged" | "separate";
106
105
  };
106
+ /** Resolve fold persistence config from the adapter, handling the boolean
107
+ * shorthand. */
108
+ export declare function resolveFoldPersistence(adapter: AdapterConfig): {
109
+ enabled: boolean;
110
+ dir?: string;
111
+ };
107
112
  export declare function resolveConfig(adapter: AdapterConfig, liveContextLimit: number): Config;
108
113
  export declare function parsePercent(v: number | string): number;
@@ -0,0 +1,69 @@
1
+ import { StateStore } from "acp-kernel/persist";
2
+ import type { CompressionState, CoreMessage } from "acp-kernel";
3
+ /**
4
+ * Fold-state persistence: the restart checkpoint for the core-space fold
5
+ * (issue #130).
6
+ *
7
+ * The live fold is the truth source — it runs on the WIRE payload at
8
+ * `before_provider_request`, and that payload is request-local: at
9
+ * session_start omp does not have it yet. primeFold mirrors the fold from
10
+ * the session view instead, but the view→wire projection is host-owned
11
+ * (pi-ai's transformMessages + convertMessages: cross-model thinking
12
+ * demotion, developer→user mapping, empty-message drops). A mirror that
13
+ * guesses that projection lands in a different ref/fingerprint space, every
14
+ * in-stream compress replay fails the span guard, and /acp lies
15
+ * "Blocks: none" until the first provider request refolds the real wire
16
+ * (observed live: 1988 mirror pieces vs 1692 live pieces, 0/14 anchors).
17
+ *
18
+ * The fix: checkpoint the LIVE fold slot — identities in the wire's own
19
+ * content-hash space (coreIdentity is a pure function of content, so the
20
+ * next process recomputes the same ids from the same wire), the block
21
+ * ledger, assigned refs, and the folded stream itself. On restart the slot
22
+ * is restored directly; the first live fold then validates it through the
23
+ * normal LCP check instead of trusting the mirror.
24
+ *
25
+ * Storage MECHANISM lives in `acp-kernel/persist` (StateStore: atomic
26
+ * write, rename retries, debounce, per-id serialization, corrupt-tolerant
27
+ * load). This module is omp POLICY: where state lives, what shape it has,
28
+ * when it is saved.
29
+ *
30
+ * The store never deletes files: sessions outlive processes, and cleanup is
31
+ * a downstream/user policy decision (kernel position — see store.ts).
32
+ */
33
+ /** Snapshot schema. Bump when the payload shape changes; older snapshots
34
+ * fail validation on load and the restart falls back to the primeFold
35
+ * mirror (fail-open, blocks rebuilt from the stream at the first live
36
+ * fold). */
37
+ export declare const FOLD_SCHEMA_VERSION = 1;
38
+ /** On-disk snapshot of a live FoldSlot (runtime.ts). `preview` is not
39
+ * persisted — only live folds are checkpointed; `appliedCallIds` is a Set
40
+ * in memory and a plain array on disk. */
41
+ export interface FoldSnapshot {
42
+ identities: string[];
43
+ foldedLen: number;
44
+ state: CompressionState;
45
+ coreMessages: CoreMessage[];
46
+ appliedCallIds: string[];
47
+ rejectStreak: number;
48
+ }
49
+ /** Restore shape: everything a FoldSlot carries except `preview` (the
50
+ * runtime sets it — restored slots are live, not mirror junk). */
51
+ export interface RestoredFoldSlot {
52
+ identities: string[];
53
+ foldedLen: number;
54
+ state: CompressionState;
55
+ coreMessages: CoreMessage[];
56
+ appliedCallIds: Set<string>;
57
+ rejectStreak: number;
58
+ }
59
+ /** Persisted-state directory. Default `~/.omp/acp-omp-folds/` (sibling of
60
+ * the acp-omp log), overridable per adapter config or env for tests and
61
+ * sandboxes. */
62
+ export declare function foldPersistDir(configured?: string): string;
63
+ /** Build the store for a directory. `enabled: false` (persistence off in
64
+ * adapter config) keeps the store a silent no-op — loads miss, writes drop. */
65
+ export declare function createFoldStore(dir: string, enabled: boolean): StateStore<FoldSnapshot>;
66
+ /** Rehydrate a validated snapshot into slot fields. The state runs through
67
+ * the kernel's mergeCompressionState so a snapshot written by an older
68
+ * version with missing fields still loads (forward-compat fill). */
69
+ export declare function restoreFoldSnapshot(payload: FoldSnapshot): RestoredFoldSlot;