billion-context-omp 0.1.0 → 0.1.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/dist/log.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ export declare function setDebugEnabled(enabled: boolean): void;
2
+ export type LogLevel = "error" | "warn" | "info" | "debug";
3
+ /** No-op: writeLine uses appendFileSync (stateless per call), so there is no
4
+ * stream to close. Kept as a hook in case the backend switches to a
5
+ * persistent write stream. Called on session_shutdown. */
6
+ export declare function closeLogStream(): void;
7
+ export declare function logError(scope: string, fields: Record<string, unknown>): void;
8
+ export declare function logWarn(scope: string, fields: Record<string, unknown>): void;
9
+ export declare function logInfo(scope: string, fields: Record<string, unknown>): void;
10
+ export declare function logThrow(scope: string, err: unknown, extra?: Record<string, unknown>): void;
11
+ export declare const debug: {
12
+ readonly enabled: boolean;
13
+ readonly logFile: string;
14
+ event(scope: string, fields: Record<string, unknown>): void;
15
+ };
16
+ export declare const logger: {
17
+ error: typeof logError;
18
+ warn: typeof logWarn;
19
+ info: typeof logInfo;
20
+ debug(scope: string, fields: Record<string, unknown>): void;
21
+ };
@@ -0,0 +1,65 @@
1
+ import type { SessionEntry, SessionMessageEntry } from "@oh-my-pi/pi-coding-agent";
2
+ import type { CoreMessage } from "acp-kernel";
3
+ type AgentMessage = SessionMessageEntry["message"];
4
+ export type { AgentMessage };
5
+ export declare function entriesToCoreMessages(entries: SessionEntry[]): CoreMessage[];
6
+ export declare function streamToCoreMessages(stream: AgentMessage[]): CoreMessage[];
7
+ /** Map of toolCallId → result text for tool results in the stream. Used to
8
+ * skip replaying compress calls that were REJECTED live ("No changes
9
+ * applied") — only calls that actually created blocks should rebuild them. */
10
+ export declare function toolResultTexts(stream: AgentMessage[]): Map<string, string>;
11
+ export interface StreamCompressCall {
12
+ id: string;
13
+ ranges: {
14
+ startRef: string;
15
+ endRef: string;
16
+ summary: string;
17
+ topic?: string;
18
+ summaryMaxChars?: number;
19
+ compressCallId: string;
20
+ }[];
21
+ }
22
+ export declare function findCompressCalls(message: AgentMessage): StreamCompressCall[];
23
+ export declare function extractText(content: unknown): string;
24
+ export declare function messageIdentity(message: unknown): string;
25
+ export declare function matchesStoredText(stored: string, visible: string): boolean;
26
+ export declare function coreOutToAgentMessages(coreOut: CoreMessage[], originalById: Map<string, AgentMessage>): AgentMessage[];
27
+ /** 1-based stream position encoded in a p-id ("p7" | "p7#tc1" → 7). */
28
+ export declare function rawPos(rawId: string): number;
29
+ /** Stable fingerprint of a covered span, computed from the deterministic core
30
+ * projection: hash of the first and last covered CoreMessages' content
31
+ * fields. Written into the compress tool's success result (which lives in
32
+ * the stream) and re-verified on fold replay — if a host-side rewrite
33
+ * (compaction, edit) shifted positions, the fingerprint mismatches and the
34
+ * call is skipped instead of silently compressing the wrong messages.
35
+ * Boundaries bind to the EXACT piece the ref names (parallel tool calls
36
+ * split one stream message into several pieces sharing a position —
37
+ * hashing "whatever is at that position" is position-collision-fragile). */
38
+ export declare function spanFingerprint(coreMessages: CoreMessage[], startId: string, endId: string): string;
39
+ export interface BlockLike {
40
+ blockId: string;
41
+ effectiveMessageIds: string[];
42
+ }
43
+ export declare function isBlockRef(ref: string): boolean;
44
+ /** Resolve a range boundary ref to the EXACT raw id of the piece it names.
45
+ * Message refs (mNNNNN) go through byRef; block refs (bN) resolve to the
46
+ * earliest (min) or latest (max) covered message's raw id. "" = unresolved. */
47
+ export declare function boundaryRaw(ref: string, byRef: Record<string, string>, blocks: BlockLike[], pick: "min" | "max"): string;
48
+ /** Ranges too small to carry a meaningful summary (kernel minSummaryLength
49
+ * is 50 chars; a 16-token message can't support one and nets a LOSS). The
50
+ * "compress all ranges in one call" nudge hint makes listing them a trap:
51
+ * the model bundles them, the batch fails atomically, nothing gets applied
52
+ * (observed live: 14-range batch rejected by a 43-char summary on a
53
+ * 16-token range). 200 tokens ≈ 800 chars of substance — comfortably above
54
+ * the summary floor while still listing every genuinely compressible range. */
55
+ export declare const VIABLE_RANGE_MIN_TOKENS = 200;
56
+ export declare function viableRanges<T extends {
57
+ tokens: number;
58
+ }>(ranges: T[]): T[];
59
+ /** One fingerprint per range (never filtered, "-" for unresolvable
60
+ * boundaries) so replay-side index lookup stays aligned even for mixed
61
+ * message/block boundary batches. Written into the compress tool result. */
62
+ export declare function rangeFingerprints(ranges: Array<{
63
+ startRef: string;
64
+ endRef: string;
65
+ }>, coreMessages: CoreMessage[], byRef: Record<string, string>, blocks: BlockLike[]): string[];
@@ -0,0 +1,34 @@
1
+ import type { ExtensionContext } from "@oh-my-pi/pi-coding-agent";
2
+ import { type CompressionCore, type CompressionState, type Config, type CoreMessage, type Prompts } from "acp-kernel";
3
+ import { type AdapterConfig } from "./config.js";
4
+ import { type AgentMessage } from "./messages.js";
5
+ export interface FoldResult {
6
+ state: CompressionState;
7
+ coreMessages: CoreMessage[];
8
+ originalById: Map<string, AgentMessage>;
9
+ streamLen: number;
10
+ }
11
+ export interface AcpRuntime {
12
+ core: CompressionCore;
13
+ adapter: AdapterConfig;
14
+ setAdapter(adapter: AdapterConfig): void;
15
+ prompts: Prompts;
16
+ setPrompts(prompts: Prompts): void;
17
+ liveContextLimit(ctx: ExtensionContext): number;
18
+ configFor(ctx: ExtensionContext): Config;
19
+ foldStream(ctx: ExtensionContext, stream: AgentMessage[]): FoldResult;
20
+ stateFor(ctx: ExtensionContext): Promise<{
21
+ state: CompressionState;
22
+ coreMessages: CoreMessage[];
23
+ }>;
24
+ commitFoldState(ctx: ExtensionContext, state: CompressionState, toolCallId?: string): void;
25
+ forgetSession(sid: string): void;
26
+ /** Rebuild blocks from the persisted session view at session_start so /acp
27
+ * and acp_status show them BEFORE the first LLM call of a resumed session.
28
+ * The slot is marked preview and always re-folded authoritatively at the
29
+ * first context event (the live stream is the truth source, not the
30
+ * persisted view). */
31
+ primeFold(ctx: ExtensionContext): void;
32
+ acquireLock(sid: string): Promise<() => void>;
33
+ }
34
+ export declare function createRuntime(adapter: AdapterConfig): AcpRuntime;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Search index — bridges pi's session log into acp-kernel's search.
3
+ *
4
+ * Builds SearchDoc[] from:
5
+ * 1. All compression blocks (active AND inactive) — via blockDocs()
6
+ * 2. Historical messages that compression folded into a block summary.
7
+ *
8
+ * Which messages are searchable? Those covered by SOME block's
9
+ * effectiveMessageIds — i.e. messages that were compressed into a summary and
10
+ * are no longer individually visible. Messages still live in context (not in
11
+ * any block) are skipped: the model can already see them.
12
+ *
13
+ * We deliberately do NOT use pi's buildContextEntries for the visible check:
14
+ * ACP prunes messages itself (no pi `compaction` entry is written), so pi
15
+ * reports ALL entries as in-context. The ACP state is the source of truth.
16
+ */
17
+ import { type CompressionState, type CoreMessage, type SearchDoc } from "acp-kernel";
18
+ export declare function buildSearchDocs(coreMessages: CoreMessage[], state: CompressionState): SearchDoc[];
@@ -0,0 +1,11 @@
1
+ import type { ToolDefinition } from "@oh-my-pi/pi-coding-agent";
2
+ import type { AcpRuntime } from "./runtime.js";
3
+ declare const SearchParams: import("@oh-my-pi/omptype").FluentType<{
4
+ limit?: number | undefined;
5
+ query: string;
6
+ }, {
7
+ limit?: number | undefined;
8
+ query: string;
9
+ }>;
10
+ export declare function makeSearchTool(runtime: AcpRuntime): ToolDefinition<typeof SearchParams>;
11
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { ToolDefinition } from "@oh-my-pi/pi-coding-agent";
2
+ import type { AcpRuntime } from "./runtime.js";
3
+ declare const StatusParams: import("@oh-my-pi/omptype").FluentType<{
4
+ limit?: number | undefined;
5
+ scope?: "compressed" | "uncompressed" | undefined;
6
+ sort?: "age" | "size" | "time" | "tool" | undefined;
7
+ tool?: string | undefined;
8
+ view?: "messages" | "ranges" | undefined;
9
+ }, {
10
+ limit?: number | undefined;
11
+ scope?: "compressed" | "uncompressed" | undefined;
12
+ sort?: "age" | "size" | "time" | "tool" | undefined;
13
+ tool?: string | undefined;
14
+ view?: "messages" | "ranges" | undefined;
15
+ }>;
16
+ export declare function makeStatusTool(runtime: AcpRuntime): ToolDefinition<typeof StatusParams>;
17
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { Prompts } from "acp-kernel";
2
+ export declare function buildAcpSystemPrompt(prompts: Prompts): string;
@@ -0,0 +1,16 @@
1
+ import { type CoreMessage } from "acp-kernel";
2
+ export declare function estimateTextTokens(text: string): number;
3
+ export declare function collectCoveredMessageIds(state: {
4
+ blocks: {
5
+ active: boolean;
6
+ effectiveMessageIds: string[];
7
+ }[];
8
+ }): Set<string>;
9
+ export declare function estimateTokens(messages: CoreMessage[], coveredIds?: Set<string>): number;
10
+ export declare function lastUserMessageId(entries: {
11
+ id: string;
12
+ message?: {
13
+ role?: string;
14
+ };
15
+ }[]): string | undefined;
16
+ export declare function formatTokens(n: number): string;
@@ -0,0 +1,13 @@
1
+ import { type ExtensionAPI, type ToolResultEvent } from "@oh-my-pi/pi-coding-agent";
2
+ import type { AcpRuntime } from "./runtime.js";
3
+ export type BashToolResultEvent = Extract<ToolResultEvent, {
4
+ toolName: "bash";
5
+ }>;
6
+ export declare function isBashToolResult(e: ToolResultEvent): e is BashToolResultEvent;
7
+ export declare function resolveBashTimeout(input: {
8
+ timeout?: number;
9
+ }, defaultTimeout: number | undefined): number | undefined;
10
+ export declare function capToolOutput(content: ToolResultEvent["content"], maxBytes: number | undefined, fullPath?: string): ToolResultEvent["content"] | undefined;
11
+ export declare function detectBashTimeout(content: ToolResultEvent["content"]): number | undefined;
12
+ export declare function appendTimeoutNotice(content: ToolResultEvent["content"], secs: number): ToolResultEvent["content"];
13
+ export declare function wireToolGuardrails(pi: ExtensionAPI, runtime: AcpRuntime): void;
@@ -0,0 +1,2 @@
1
+ export declare function findNpmRoot(extDir: string): string | undefined;
2
+ export declare function checkForUpdate(autoUpdate: boolean, notify?: (msg: string) => void): Promise<void>;
@@ -0,0 +1,26 @@
1
+ import type { Prompts } from "acp-kernel";
2
+ import type { AdapterConfig, CompressConfig, DelegateConfig } from "./config.js";
3
+ /** User-facing config keys (subset of AdapterConfig). Loaded from
4
+ * ~/.<CONFIG_DIR_NAME>/acp-omp.json (global) and <cwd>/.<CONFIG_DIR_NAME>/acp-omp.json
5
+ * (project-local overrides project-global). Project wins over global. */
6
+ export interface UserAcpConfig {
7
+ debug?: boolean;
8
+ autoUpdate?: boolean;
9
+ modelContextLimit?: number;
10
+ toolBashDefaultTimeout?: number;
11
+ toolOutputMaxBytes?: number;
12
+ delegate?: boolean | DelegateConfig;
13
+ compress?: CompressConfig;
14
+ displayUsage?: "merged" | "separate";
15
+ prompts?: Partial<Prompts>;
16
+ /** Model for /compact summaries, as "provider:modelId" (e.g.
17
+ * "zhipuai:glm-5.2"). Shortcut for compress.compressModel — normalized
18
+ * into the nested path at load time. */
19
+ compressModel?: string;
20
+ }
21
+ /** Read global + project acp-omp.json, project overrides global. Returns {} on any
22
+ * error (missing file, bad JSON) — never throws. */
23
+ export declare function loadUserConfig(cwd: string): Promise<UserAcpConfig>;
24
+ /** Merge user config onto an adapter config: user config wins for the keys it
25
+ * sets. Used at session_start to apply runtime-discovered config. */
26
+ export declare function applyUserConfig(adapter: AdapterConfig, user: UserAcpConfig): AdapterConfig;
package/package.json CHANGED
@@ -1,67 +1,76 @@
1
1
  {
2
- "name": "billion-context-omp",
3
- "version": "0.1.0",
4
- "description": "oh-my-pi (omp) client extension for billion-context. Routes omp's model traffic through a running billion-context proxy for incremental, reversible, prefix-cache-friendly context compression — and self-disables when it detects omp is already behind bili.",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
- }
14
- },
15
- "bin": {
16
- "bili-omp": "./dist/index.js"
17
- },
18
- "sideEffects": false,
19
- "files": [
20
- "dist",
21
- "README.md",
22
- "README.zh-CN.md",
23
- "LICENSE"
24
- ],
25
- "scripts": {
26
- "build": "tsup",
27
- "typecheck": "tsc --noEmit --project tsconfig.build.json",
28
- "prepublishOnly": "npm run build"
29
- },
30
- "keywords": [
31
- "context",
32
- "compression",
33
- "proxy",
34
- "acp",
35
- "acp-kernel",
36
- "ai",
37
- "agent",
38
- "omp",
39
- "oh-my-pi",
40
- "pi",
41
- "coding-agent",
42
- "cli",
43
- "anthropic",
44
- "openai"
45
- ],
46
- "license": "MIT",
47
- "author": "ranxianglei",
48
- "repository": {
49
- "type": "git",
50
- "url": "git+https://github.com/ranxianglei/billion-context-omp.git"
51
- },
52
- "homepage": "https://github.com/ranxianglei/billion-context-omp#readme",
53
- "bugs": {
54
- "url": "https://github.com/ranxianglei/billion-context-omp/issues"
55
- },
56
- "devDependencies": {
57
- "tsup": "^8.0.0",
58
- "typescript": "^5.5.0"
59
- },
60
- "engines": {
61
- "node": ">=20"
62
- },
63
- "publishConfig": {
64
- "access": "public",
65
- "registry": "https://registry.npmjs.org"
66
- }
2
+ "name": "billion-context-omp",
3
+ "version": "0.1.2",
4
+ "description": "One billion, not one million. Model-driven context management for the oh-my-pi (omp) coding agent.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "omp": {
14
+ "extensions": [
15
+ "./dist/index.js"
16
+ ]
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "README.zh-CN.md",
22
+ "LICENSE"
23
+ ],
24
+ "sideEffects": false,
25
+ "homepage": "https://github.com/ranxianglei/billion-context-omp",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/ranxianglei/billion-context-omp.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/ranxianglei/billion-context-omp/issues"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "scripts": {
40
+ "test": "bun scripts/test.ts",
41
+ "typecheck": "tsc --noEmit",
42
+ "typecheck:tests": "tsc --noEmit -p tsconfig.test.json",
43
+ "typecheck:all": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
44
+ "build": "tsup && tsc --emitDeclarationOnly"
45
+ },
46
+ "keywords": [
47
+ "pi",
48
+ "omp",
49
+ "oh-my-pi",
50
+ "acp",
51
+ "context",
52
+ "compression",
53
+ "context-management",
54
+ "llm",
55
+ "pi-package"
56
+ ],
57
+ "author": "ranxianglei",
58
+ "license": "MIT",
59
+ "type": "module",
60
+ "peerDependencies": {
61
+ "@oh-my-pi/pi-coding-agent": ">=17.0.0",
62
+ "@oh-my-pi/omptype": ">=17.0.0"
63
+ },
64
+ "devDependencies": {
65
+ "@oh-my-pi/omptype": "17.3.2",
66
+ "@oh-my-pi/pi-agent-core": "17.3.2",
67
+ "@oh-my-pi/pi-ai": "17.3.2",
68
+ "@oh-my-pi/pi-coding-agent": "17.3.2",
69
+ "@oh-my-pi/pi-utils": "17.3.2",
70
+ "@types/node": "^26.1.2",
71
+ "acp-kernel": "0.0.22",
72
+ "tsup": "^8.5.1",
73
+ "tsx": "^4.23.1",
74
+ "typescript": "^7.0.2"
75
+ }
67
76
  }