billion-context-dsh 0.1.9 → 0.2.0

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/nudge.d.ts CHANGED
@@ -10,10 +10,13 @@ import { type UserMessage } from '@deepseek-ai/dsh-llm';
10
10
  import type { Agent } from '@deepseek-ai/dsh-agent';
11
11
  import { AcpStateStore } from './state.ts';
12
12
  import { type KernelConfigInput } from './config.ts';
13
+ import { type ResolvedPrompts } from './prompts.ts';
13
14
  /** Kernel inputs the nudge path shares with the compress tool. */
14
15
  export interface NudgeEnvironment extends KernelConfigInput {
15
16
  readonly kernel: CompressionCore;
16
17
  readonly store: AcpStateStore;
18
+ /** Resolved prompt templates (optional: falls back to DEFAULT_RESOLVED). */
19
+ readonly prompts?: ResolvedPrompts;
17
20
  }
18
21
  export interface NudgeOutcome {
19
22
  readonly message: UserMessage;
@@ -38,7 +41,7 @@ export declare function resolveTokenCount(agent: Agent, coreMessages: CoreMessag
38
41
  * Computed directly from the surface (not the kernel's ref map, which can
39
42
  * drift and hide large tool results) — see buildCompressibleSeqRanges.
40
43
  */
41
- export declare function rangeTable(session: import('@deepseek-ai/dsh-session').Session): string;
44
+ export declare function rangeTable(session: import('@deepseek-ai/dsh-session').Session, prompts?: ResolvedPrompts): string;
42
45
  /**
43
46
  * Decide and build one nudge message for the agent's next pre-step. Returns
44
47
  * null when the kernel recommends no nudge or one was already injected for the
@@ -52,4 +55,4 @@ export declare function buildNudge(agent: Agent, env: NudgeEnvironment, lastNudg
52
55
  * when to compress. Full guidance (tools, philosophy, summary rules) lives in
53
56
  * the system prompt once, not in every nudge.
54
57
  */
55
- export declare function buildNudgeText(nudge: NudgeDecision, emergency: boolean, session: import('@deepseek-ai/dsh-session').Session): string;
58
+ export declare function buildNudgeText(nudge: NudgeDecision, emergency: boolean, session: import('@deepseek-ai/dsh-session').Session, prompts?: ResolvedPrompts): string;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * M4 — configurable prompt templates: the per-stage model-visible texts
3
+ * (nudge frames, range table, system prompt, tool descriptions) rendered from
4
+ * `config.prompts` templates with named placeholders.
5
+ *
6
+ * Design: docs/configurable-prompts-design.md (v4).
7
+ * - placeholders are `{identifier}` only; literal braces like
8
+ * `compress({ content: [...] })` are left untouched (spaces/commas break the
9
+ * identifier rule);
10
+ * - resolvePrompts merges user overrides over DEFAULT_PROMPTS per key
11
+ * (null/undefined → default, string → override; group-level null → whole
12
+ * group default for YAML hosts) and validates unknown placeholders at
13
+ * construction time (fail-fast, no silent typos);
14
+ * - renderTemplate throws when a known placeholder has no value — callers
15
+ * must provide every value (e.g. tokens via a typeof fallback).
16
+ * @module billion-context-dsh/prompts
17
+ */
18
+ /** 用户可写值:字符串模板,或 null(= 用默认,等价于不写)。YAML 宿主写 null 是合法输入。 */
19
+ export type PromptInput = string | null;
20
+ /** 按组生成"每键可选、可 null"的覆盖类型。 */
21
+ export type PromptOverride<T> = {
22
+ [K in keyof T]?: PromptInput;
23
+ };
24
+ export interface NudgePrompts {
25
+ /** 普通档首句。占位符:{pct} */
26
+ normal: string;
27
+ /** 紧急档首句。占位符:{pct} */
28
+ emergency: string;
29
+ /** 指导行。无占位符 */
30
+ guidance: string;
31
+ /** tier 蒸馏行。占位符:{tier} {count} {prevTier} {tokens} {seqs} */
32
+ tier: string;
33
+ }
34
+ export interface RangeTablePrompts {
35
+ /** 表头。占位符:{surface} */
36
+ header: string;
37
+ /** 标题。占位符:{count}(表格行数) */
38
+ title: string;
39
+ /** 每行。占位符:{start} {end} {count} {tokens} */
40
+ line: string;
41
+ /** 表尾调用语法。无占位符 */
42
+ footer: string;
43
+ }
44
+ export interface ToolPrompts {
45
+ /** 工具描述(纯文本,无占位符) */
46
+ compress: string;
47
+ decompress: string;
48
+ searchContext: string;
49
+ acpStatus: string;
50
+ }
51
+ export interface AcpPrompts {
52
+ readonly nudge?: PromptOverride<NudgePrompts>;
53
+ readonly rangeTable?: PromptOverride<RangeTablePrompts>;
54
+ readonly tools?: PromptOverride<ToolPrompts>;
55
+ /** 整段 system prompt 模板;`{philosophy}` 引用 kernel 的 COMPRESS_PHILOSOPHY */
56
+ readonly systemPrompt?: PromptInput;
57
+ }
58
+ /** 解析结果 —— 所有字段已填满(纯 string,无 null)、已校验。构造一次,全程复用。 */
59
+ export interface ResolvedPrompts {
60
+ readonly nudge: NudgePrompts;
61
+ readonly rangeTable: RangeTablePrompts;
62
+ readonly tools: ToolPrompts;
63
+ /** 注意:这是【模板】(含 {philosophy}),不是渲染结果。渲染用 renderSystemPrompt。 */
64
+ readonly systemPromptTemplate: string;
65
+ }
66
+ /**
67
+ * 纯替换。两个契约:
68
+ * 1. 未知占位符不可能到达这里(构建期已校验);
69
+ * 2. 已知占位符缺值 = 编程错误 → throw(绝不静默渲染空串)。
70
+ */
71
+ export declare function renderTemplate(template: string, vars: Record<string, string | number>): string;
72
+ /**
73
+ * 深合并 + 校验;引擎构造期调用一次,出错即抛(fail-fast)。
74
+ * 未传入时返回 DEFAULT_RESOLVED,零校验重跑。
75
+ */
76
+ export declare function resolvePrompts(input?: AcpPrompts): ResolvedPrompts;
77
+ /** 渲染 system prompt 模板(注入 kernel 压缩哲学)。 */
78
+ export declare function renderSystemPrompt(prompts: ResolvedPrompts): string;
79
+ /**
80
+ * 默认模板 —— 与 v4 之前的硬编码文案逐字节一致
81
+ * (回归锚点见 tests/prompts.test.ts 的硬编码字面量快照)。
82
+ */
83
+ export declare const DEFAULT_PROMPTS: ResolvedPrompts;
84
+ /** 模块级默认缓存:默认参/兜底直接引用,避免每次调用重跑校验。 */
85
+ export declare const DEFAULT_RESOLVED: ResolvedPrompts;
@@ -4,8 +4,12 @@
4
4
  * instead of being re-sent with every nudge. The nudge itself stays a short,
5
5
  * advisory notice — ACP is model-driven, the model decides whether and when
6
6
  * to compress (never "compress now").
7
+ *
8
+ * The text is DEFAULT_PROMPTS.systemPromptTemplate rendered with the kernel's
9
+ * COMPRESS_PHILOSOPHY; hosts can override the whole section via
10
+ * `config.prompts.systemPrompt` (see docs/configurable-prompts-design.md).
7
11
  * @module billion-context-dsh/system-prompt
8
12
  */
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. Seq refs must be on the current surface: seqs from older nudges or earlier compresses go stale as the surface moves, so a stale span is auto-remapped to its still-live remainder (the result reports the adjusted span), a fully compressed span is reported as already compressed, and invented/other-session 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 right before compressing \u2014 the only seqs that never go stale are the ones you just read.\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.";
13
+ export declare const ACP_SYSTEM_PROMPT: string;
10
14
  /** System-prompt section order: tool guidance lives in 100–199. */
11
15
  export declare const ACP_SYSTEM_PROMPT_ORDER = 150;
package/dist/tools.d.ts CHANGED
@@ -15,11 +15,14 @@ import type { Agent } from '@deepseek-ai/dsh-agent';
15
15
  import type { AcpStateStore } from './state.ts';
16
16
  import { type KernelConfigInput } from './config.ts';
17
17
  import { type AcpWindow } from './window.ts';
18
+ import { type ResolvedPrompts } from './prompts.ts';
18
19
  export interface ToolEnvironment extends KernelConfigInput {
19
20
  readonly kernel: CompressionCore;
20
21
  readonly store: AcpStateStore;
21
22
  /** Resolve the effective context window for an agent (optional: status falls back to modelContextLimit). */
22
23
  readonly windowFor?: (agent: Agent) => Promise<AcpWindow>;
24
+ /** Resolved prompt templates (optional: falls back to DEFAULT_RESOLVED). */
25
+ readonly prompts?: ResolvedPrompts;
23
26
  }
24
27
  /** Build the four ACP model tools bound to one engine. */
25
28
  export declare function makeTools(env: ToolEnvironment): ToolDefinition[];
package/package.json CHANGED
@@ -1,7 +1,19 @@
1
1
  {
2
2
  "name": "billion-context-dsh",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "description": "Active Context Pruning (ACP) for the DeepSeek Harness — model-driven context management as a CompactionEngine backend.",
5
+ "keywords": [
6
+ "deepseek",
7
+ "harness",
8
+ "dsh",
9
+ "dsh-plugin",
10
+ "acp",
11
+ "context-management",
12
+ "context-compression",
13
+ "llm",
14
+ "agent",
15
+ "compaction"
16
+ ],
5
17
  "type": "module",
6
18
  "main": "dist/index.js",
7
19
  "types": "dist/index.d.ts",
@@ -13,11 +25,17 @@
13
25
  },
14
26
  "files": [
15
27
  "dist",
28
+ "cordis.patch.yml",
16
29
  "README.md",
17
30
  "README.en.md",
18
31
  "LICENSE"
19
32
  ],
20
33
  "sideEffects": false,
34
+ "dsh": {
35
+ "bundle": {
36
+ "patch": "./cordis.patch.yml"
37
+ }
38
+ },
21
39
  "license": "MIT",
22
40
  "engines": {
23
41
  "node": ">=20"