billion-context-dsh 0.1.4 → 0.1.6
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.en.md +10 -8
- package/README.md +10 -8
- package/dist/config.d.ts +6 -2
- package/dist/index.d.ts +37 -6
- package/dist/index.js +379 -70
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +8 -0
- package/dist/nudge.d.ts +7 -1
- package/dist/region.d.ts +88 -1
- package/dist/state.d.ts +7 -0
- package/dist/system-prompt.d.ts +1 -1
- package/dist/tools.d.ts +4 -0
- package/dist/window.d.ts +32 -0
- package/package.json +1 -1
package/dist/region.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* decompress/search/status can rebuild everything from the log.
|
|
11
11
|
* @module billion-context-dsh/region
|
|
12
12
|
*/
|
|
13
|
-
import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
|
|
13
|
+
import type { Session, SessionEvent, SessionEventMap } from '@deepseek-ai/dsh-session';
|
|
14
14
|
import { type ContentBlock } from '@deepseek-ai/dsh-llm';
|
|
15
15
|
/** One durable ACP block as rebuilt from the session log. */
|
|
16
16
|
export interface AcpBlockLedgerEntry {
|
|
@@ -21,6 +21,19 @@ export interface AcpBlockLedgerEntry {
|
|
|
21
21
|
readonly shadowedTokenCount: number;
|
|
22
22
|
readonly start: number;
|
|
23
23
|
readonly end: number;
|
|
24
|
+
/** Compression tier: 1 (message range), 2 (distills tier-1 blocks), 3 (distills tier-2 blocks). Legacy blocks default to 1. */
|
|
25
|
+
readonly tier: 1 | 2 | 3;
|
|
26
|
+
/** Compaction ids of the blocks this block distilled (parents). Empty for tier-1 blocks. */
|
|
27
|
+
readonly parentBlockIds: readonly string[];
|
|
28
|
+
/** The acp-kernel block id (`bN`) created for this transaction — absent for legacy blocks (synthesised by order). */
|
|
29
|
+
readonly kernelBlockId?: string;
|
|
30
|
+
/** The surface seq of this block's checkpoint summary node (derived from the log; null when the node is gone). */
|
|
31
|
+
readonly summarySeq?: number;
|
|
32
|
+
/** The kernel block's raw direct/effective message ids at creation (recorded since the tier feature; absent for legacy). */
|
|
33
|
+
readonly directMessageIds?: readonly string[];
|
|
34
|
+
readonly effectiveMessageIds?: readonly string[];
|
|
35
|
+
/** Unix epoch ms of the compaction/summary event. */
|
|
36
|
+
readonly createdAt: number;
|
|
24
37
|
}
|
|
25
38
|
/** The open turn number, or null when the log ends between turns. */
|
|
26
39
|
export declare function findOpenTurn(events: readonly SessionEvent[]): number | null;
|
|
@@ -51,7 +64,40 @@ export interface CompactionTransactionInput {
|
|
|
51
64
|
readonly shadowedTokenCount: number;
|
|
52
65
|
readonly provider: string;
|
|
53
66
|
readonly model: string;
|
|
67
|
+
/** Compression tier of this block (default 1). */
|
|
68
|
+
readonly tier?: 1 | 2 | 3;
|
|
69
|
+
/** The acp-kernel block id (`bN`) created by the kernel for this transaction. */
|
|
70
|
+
readonly kernelBlockId?: string;
|
|
71
|
+
/** Compaction ids of the blocks distilled into this one. */
|
|
72
|
+
readonly parentBlockIds?: readonly string[];
|
|
73
|
+
/** The kernel block's direct/effective message ids (raw CoreMessage ids) — recorded for faithful rehydration. */
|
|
74
|
+
readonly directMessageIds?: readonly string[];
|
|
75
|
+
readonly effectiveMessageIds?: readonly string[];
|
|
54
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* ACP tier extension fields carried on `compaction/summary` events. The
|
|
79
|
+
* upstream dsh-compaction event type does not know them, so reads and writes
|
|
80
|
+
* go through this precise intersection (never `any`).
|
|
81
|
+
*/
|
|
82
|
+
export interface AcpCompactionSummaryFields {
|
|
83
|
+
/** Compression tier (1/2/3) — 1 = message range, 2 = distills tier-1, 3 = distills tier-2. */
|
|
84
|
+
readonly tier?: 1 | 2 | 3;
|
|
85
|
+
/** The acp-kernel block id (`bN`) created for this transaction. */
|
|
86
|
+
readonly kernelBlockId?: string;
|
|
87
|
+
/** Durable compaction ids of the blocks distilled into this one. */
|
|
88
|
+
readonly parentBlockIds?: readonly string[];
|
|
89
|
+
/**
|
|
90
|
+
* The kernel block's direct message ids (raw CoreMessage ids) at creation —
|
|
91
|
+
* recorded so a restarted engine rehydrates the SAME coverage (a tier-2
|
|
92
|
+
* block's coverage is its parents' originals, not the checkpoint node).
|
|
93
|
+
*/
|
|
94
|
+
readonly directMessageIds?: readonly string[];
|
|
95
|
+
/** The kernel block's effective message ids (raw CoreMessage ids) at creation. */
|
|
96
|
+
readonly effectiveMessageIds?: readonly string[];
|
|
97
|
+
}
|
|
98
|
+
type CompactionSummaryData = SessionEventMap['compaction/summary'];
|
|
99
|
+
/** Read a `compaction/summary` event's data including the ACP tier extension fields. */
|
|
100
|
+
export declare function readCompactionSummary(event: SessionEvent): CompactionSummaryData & AcpCompactionSummaryFields;
|
|
55
101
|
/**
|
|
56
102
|
* Run one durable compression transaction. Throws on invalid state; on success
|
|
57
103
|
* the four events are in the log and the surface has one summary node.
|
|
@@ -90,3 +136,44 @@ export declare function buildCompressibleSeqRanges(session: Session, opts?: {
|
|
|
90
136
|
* without blind probing.
|
|
91
137
|
*/
|
|
92
138
|
export declare function surfaceSummary(session: Session): string;
|
|
139
|
+
/** One block as seen by the tier machinery: durable id ↔ kernel ref (`bN`). */
|
|
140
|
+
export interface AcpBlockRegistryEntry {
|
|
141
|
+
/** The durable compaction id. */
|
|
142
|
+
readonly blockId: string;
|
|
143
|
+
/** The acp-kernel block ref (`bN`); synthesised by log order for legacy blocks. */
|
|
144
|
+
readonly kernelBlockId: string;
|
|
145
|
+
readonly tier: 1 | 2 | 3;
|
|
146
|
+
/** The surface seq of this block's checkpoint summary node (null when gone). */
|
|
147
|
+
readonly summarySeq: number | null;
|
|
148
|
+
/** True until a LATER block distills this one. Only active blocks are distillable. */
|
|
149
|
+
readonly active: boolean;
|
|
150
|
+
readonly parentBlockIds: readonly string[];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Rebuild the compactionId ↔ kernel-block-ref registry from the durable log.
|
|
154
|
+
* Legacy blocks (pre-tier, no recorded `kernelBlockId`) are synthesised as
|
|
155
|
+
* `b1`, `b2`, … in log order; recorded ids are kept as-is. A block is active
|
|
156
|
+
* until a later block lists it as a parent.
|
|
157
|
+
*/
|
|
158
|
+
export declare function blockRegistry(session: Session): AcpBlockRegistryEntry[];
|
|
159
|
+
/**
|
|
160
|
+
* The kernel block ref (`bN`) for a surface seq, when that seq is the
|
|
161
|
+
* checkpoint summary node of a block — the edge the model must use to
|
|
162
|
+
* distill (T2/T3). Active blocks distill; a stale (already-distilled) node
|
|
163
|
+
* still maps to its `bN` so the kernel reports "already compressed" instead
|
|
164
|
+
* of silently folding the summary as a plain message. Returns null for
|
|
165
|
+
* anything else (plain messages, non-checkpoint nodes).
|
|
166
|
+
*/
|
|
167
|
+
export declare function blockRefForSummarySeq(session: Session, seq: number): string | null;
|
|
168
|
+
/** The durable compaction ids distilled by the given kernel block refs (`bN`). */
|
|
169
|
+
export declare function compactionIdsOfKernelBlocks(session: Session, kernelBlockIds: readonly string[]): string[];
|
|
170
|
+
/** The checkpoint summary seq of an ACTIVE kernel block (`bN`), or null. */
|
|
171
|
+
export declare function summarySeqOfKernelBlock(session: Session, kernelBlockId: string): number | null;
|
|
172
|
+
/**
|
|
173
|
+
* The shadowed seqs of a block, recursing into distilled parent blocks: a
|
|
174
|
+
* tier-2 block shadows its parent's checkpoint node, so recovering its
|
|
175
|
+
* originals requires expanding that node into the parent block's own shadowed
|
|
176
|
+
* seqs. Cycle-safe (a block can never be its own ancestor).
|
|
177
|
+
*/
|
|
178
|
+
export declare function expandShadowedSeqs(session: Session, blockId: string): number[];
|
|
179
|
+
export {};
|
package/dist/state.d.ts
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
* summary re-derive the block ledger (`rebuildBlockLedger` in region.ts), so a
|
|
8
8
|
* restarted engine can answer decompress/search/status from the session log
|
|
9
9
|
* alone — DSH's "log is the source of truth" model.
|
|
10
|
+
*
|
|
11
|
+
* Tier-2/3 distillation additionally requires the kernel state to KNOW the
|
|
12
|
+
* blocks: `syncBlocks` deactivates a block whose consumed messages are absent
|
|
13
|
+
* from the message array, and `resolveBoundaries` refuses to anchor a block
|
|
14
|
+
* ref it cannot find — so on first access for a session that already has
|
|
15
|
+
* durable blocks (e.g. after a server restart), the kernel blocks are
|
|
16
|
+
* REHYDRATED from the ledger before use. Live updates continue through `set`.
|
|
10
17
|
* @module billion-context-dsh/state
|
|
11
18
|
*/
|
|
12
19
|
import type { Session } from '@deepseek-ai/dsh-session';
|
package/dist/system-prompt.d.ts
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
* to compress (never "compress now").
|
|
7
7
|
* @module billion-context-dsh/system-prompt
|
|
8
8
|
*/
|
|
9
|
-
export declare const ACP_SYSTEM_PROMPT = "Active Context Pruning \u2014 model-driven context management\n\nYOU decide whether and when to compress context. Nothing forces you: the injected \"nudge\" is a suggestion, not an order, and you may ignore it when compression would not help. Compress only ranges you have genuinely consumed (read tool outputs, finished explorations, superseded steps) that the current work no longer needs verbatim.\n\nCompression Philosophy:\n- All compression serves the primary task, but be frugal.\n- Context capacity is precious. Save context by compressing consumed outputs, not by avoiding tools.\n- Compress by need, not by percentage.\n- Work from summaries, not raw tool outputs. All listed ranges (user prompts, tool outputs, code, logs, exploration, intermediate steps) should be compressed to summary format \u2014 the ONLY exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct.\n\nCompression tools (refs are SURFACE SEQS, not ids):\n- compress: replace one or more seq ranges, each with your own dense summary. Single range: compress({ content: [{ startSeq, endSeq, summary }] }). Batch multiple unrelated segments in one call (each entry becomes its own block): compress({ content: [{ startSeq: 1, endSeq: 5, summary: '...' }, { startSeq: 12, endSeq: 18, summary: '...' }] }). Keep ranges disjoint \u2014 overlapping entries in one batch are skipped. Edges are auto-balanced to tool-call/result boundaries; a trailing #callId fragment in a seq is ignored. Ranges must be on the current surface \u2014 stale seqs fail with guidance.\n- decompress: recover a compressed block's original content, read-only. decompress({ blockId }).\n- search_context: find information inside compressed blocks BEFORE decompressing. search_context({ query }).\n- acp_status: current context usage and the live compressible-range list. Run it before compressing when in doubt.\n\nWhen you write a summary, it becomes the ONLY record of that range: keep file paths, signatures, exact values, decisions, and error strings verbatim so a later reader (or you, after decompress) can continue without the original. Never reuse historical seqs \u2014 the surface moves as messages land and compress; verify with acp_status.";
|
|
9
|
+
export declare const ACP_SYSTEM_PROMPT = "Active Context Pruning \u2014 model-driven context management\n\nYOU decide whether and when to compress context. Nothing forces you: the injected \"nudge\" is a suggestion, not an order, and you may ignore it when compression would not help. Compress only ranges you have genuinely consumed (read tool outputs, finished explorations, superseded steps) that the current work no longer needs verbatim.\n\nCompression Philosophy:\n- All compression serves the primary task, but be frugal.\n- Context capacity is precious. Save context by compressing consumed outputs, not by avoiding tools.\n- Compress by need, not by percentage.\n- Work from summaries, not raw tool outputs. All listed ranges (user prompts, tool outputs, code, logs, exploration, intermediate steps) should be compressed to summary format \u2014 the ONLY exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct.\n\nCompression tools (refs are SURFACE SEQS, not ids):\n- compress: replace one or more seq ranges, each with your own dense summary. Single range: compress({ content: [{ startSeq, endSeq, summary }] }). Batch multiple unrelated segments in one call (each entry becomes its own block): compress({ content: [{ startSeq: 1, endSeq: 5, summary: '...' }, { startSeq: 12, endSeq: 18, summary: '...' }] }). Keep ranges disjoint \u2014 overlapping entries in one batch are skipped. Edges are auto-balanced to tool-call/result boundaries; a trailing #callId fragment in a seq is ignored. Ranges must be on the current surface \u2014 stale seqs fail with guidance.\n- decompress: recover a compressed block's original content, read-only. decompress({ blockId }).\n- search_context: find information inside compressed blocks BEFORE decompressing. search_context({ query }).\n- acp_status: current context usage and the live compressible-range list. Run it before compressing when in doubt.\n\nTiered compression: each compressed block appears on the surface as one summary node. Compressing that node again DISTILLS the block (tier 2): the parent summary folds into your new summary and the original messages are freed. Distilling a tier-2 block yields tier 3. Distill when a summary itself is consumed \u2014 decompress on the tier-2 block recovers the full originals.\n\nWhen you write a summary, it becomes the ONLY record of that range: keep file paths, signatures, exact values, decisions, and error strings verbatim so a later reader (or you, after decompress) can continue without the original. Never reuse historical seqs \u2014 the surface moves as messages land and compress; verify with acp_status.";
|
|
10
10
|
/** System-prompt section order: tool guidance lives in 100–199. */
|
|
11
11
|
export declare const ACP_SYSTEM_PROMPT_ORDER = 150;
|
package/dist/tools.d.ts
CHANGED
|
@@ -11,11 +11,15 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { type ToolDefinition } from '@deepseek-ai/dsh-tools';
|
|
13
13
|
import { type CompressionCore } from 'acp-kernel';
|
|
14
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
14
15
|
import type { AcpStateStore } from './state.ts';
|
|
15
16
|
import { type KernelConfigInput } from './config.ts';
|
|
17
|
+
import { type AcpWindow } from './window.ts';
|
|
16
18
|
export interface ToolEnvironment extends KernelConfigInput {
|
|
17
19
|
readonly kernel: CompressionCore;
|
|
18
20
|
readonly store: AcpStateStore;
|
|
21
|
+
/** Resolve the effective context window for an agent (optional: status falls back to modelContextLimit). */
|
|
22
|
+
readonly windowFor?: (agent: Agent) => Promise<AcpWindow>;
|
|
19
23
|
}
|
|
20
24
|
/** Build the four ACP model tools bound to one engine. */
|
|
21
25
|
export declare function makeTools(env: ToolEnvironment): ToolDefinition[];
|
package/dist/window.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto context-window detection — resolve the model's real context window
|
|
3
|
+
* from the host LLM runtime instead of trusting a hardcoded config default.
|
|
4
|
+
*
|
|
5
|
+
* `agent.ctx.llm` (the cordis `LlmRuntime` service) exposes
|
|
6
|
+
* `resolveModelInfo(provider, model)` → `{ context: { contextWindow } }`, the
|
|
7
|
+
* exact-route capacity the adapter learned from the provider API (pi-ai reads
|
|
8
|
+
* `context_window`/`context_length` during discovery). Probing is a standalone
|
|
9
|
+
* capability query — no request is sent.
|
|
10
|
+
* @module billion-context-dsh/window
|
|
11
|
+
*/
|
|
12
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
13
|
+
/** Fallback window when auto-detection is unavailable. Same default as acp-kernel's `defaultConfig`. */
|
|
14
|
+
export declare const DEFAULT_CONTEXT_WINDOW = 128000;
|
|
15
|
+
/** The effective context window plus where it came from. */
|
|
16
|
+
export interface AcpWindow {
|
|
17
|
+
/** Effective context window in tokens. */
|
|
18
|
+
readonly limit: number;
|
|
19
|
+
/** Where the limit came from. */
|
|
20
|
+
readonly source: 'explicit' | 'auto' | 'default';
|
|
21
|
+
/** Route the auto window was resolved for (auto source only). */
|
|
22
|
+
readonly provider?: string;
|
|
23
|
+
readonly model?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Human label for an AcpWindow's source (used by acp_status). */
|
|
26
|
+
export declare function windowSourceLabel(window: AcpWindow): string;
|
|
27
|
+
/**
|
|
28
|
+
* Probe the model's real context window. Returns null when the host provides
|
|
29
|
+
* no llm service, the adapter discloses no window, or the probe throws —
|
|
30
|
+
* callers fall back to DEFAULT_CONTEXT_WINDOW. Never throws.
|
|
31
|
+
*/
|
|
32
|
+
export declare function detectContextWindow(agent: Agent, provider: string, model: string): Promise<number | null>;
|
package/package.json
CHANGED