Resolve compaction policy per routed model

This commit is contained in:
Yichen Jiang
2026-07-20 15:34:00 +08:00
parent b877ede82d
commit cfa180c127
54 changed files with 1210 additions and 319 deletions

View File

@@ -9,6 +9,11 @@
config:
apiKey: !!js process.env.DEEPSEEK_API_KEY
baseURL: !!js process.env.DEEPSEEK_BASE_URL
models:
- id: deepseek-v4-flash
contextWindow: 256000
- id: deepseek-v4-pro
contextWindow: 256000
# The default composition confines bash to the workspace and asks before a
# wider retry. Snapshots use danger-full-access; DSH_PERMISSION_MODE overrides
@@ -48,20 +53,17 @@
Verify your work by running the code or tests. Keep answers brief and factual.
# Replay-aware request pressure with one service-wide context window.
# Replay-aware request pressure; the routed adapter supplies model capacity.
- id: token-meter
name: '@deepseek-ai/dsh-token-meter'
config:
# FIXME: Resolve compaction config per model; this capacity assumes a 256k context window.
contextWindow: 256000
# Summarize an older range after measured pressure or a canonical provider overflow.
# Service-wide policy provides pressure, retention, and one overflow-retry default.
# Ratios scale against the routed model's context window.
- id: compact-basic
name: '@deepseek-ai/dsh-compact-basic'
config:
thresholdRatio: 0.8
retainTokens: 20480
retainRatio: 0.08
maxTokens: 8192
compactionRetries: 1

View File

@@ -21,6 +21,8 @@ flowchart LR
bundle_agent_core --> spine_sessions["ctx.sessions"]
bundle_agent_core --> spine_tools["ctx.tools + tool-bash"]
bundle_agent_core --> spine_loop["ctx.agents + ctx.agentLoop"]
plugin_headless_token_meter["token-meter<br/>@deepseek-ai/dsh-token-meter"]
cfg --> plugin_headless_token_meter
plugin_headless_compact_basic["compact-basic<br/>@deepseek-ai/dsh-compact-basic"]
cfg --> plugin_headless_compact_basic
plugin_headless_subagent["subagent<br/>@deepseek-ai/dsh-subagent"]
@@ -52,6 +54,7 @@ flowchart LR
| `llm-deepseek` | `@deepseek-ai/dsh-llm-deepseek` |
| `bash` | `@deepseek-ai/dsh-bash-local` |
| `cli-agent` | `@deepseek-ai/dsh-cli-demo` |
| `token-meter` | `@deepseek-ai/dsh-token-meter` |
| `compact-basic` | `@deepseek-ai/dsh-compact-basic` |
| `subagent` | `@deepseek-ai/dsh-subagent` |
| `subagent-spawn` | `@deepseek-ai/dsh-subagent-spawn` |

View File

@@ -11,7 +11,9 @@
baseURL: !!js process.env.DEEPSEEK_BASE_URL
models:
- id: deepseek-v4-pro
contextWindow: 128000
- id: deepseek-v4-flash
contextWindow: 128000
- id: bash
name: '@deepseek-ai/dsh-bash-local'
@@ -34,13 +36,14 @@
factual.
# Summarize an older range when derived history approaches the context window.
- id: token-meter
name: '@deepseek-ai/dsh-token-meter'
- id: compact-basic
name: '@deepseek-ai/dsh-compact-basic'
config:
contextWindow: 128000
thresholdRatio: 0.8
retainTokens: 20480
summarizationModel: ''
retainRatio: 0.16
maxTokens: 8192
compactionRetries: 1

View File

@@ -63,12 +63,13 @@
- id: tool-fs
name: '@deepseek-ai/dsh-tool-fs'
- id: token-meter
name: '@deepseek-ai/dsh-token-meter'
- id: compact-basic
name: '@deepseek-ai/dsh-compact-basic'
config:
contextWindow: 128000
thresholdRatio: 0.8
retainTokens: 20480
summarizationModel: ''
retainRatio: 0.16
maxTokens: 8192
compactionRetries: 1

View File

@@ -47,12 +47,12 @@
Verify your work by running the code or tests. Keep answers brief and
factual.
# Replay-aware request pressure with one service-wide context window.
# Replay-aware request pressure; the routed adapter supplies model capacity.
- id: token-meter
name: '@deepseek-ai/dsh-token-meter'
# Summarize an older range after measured pressure or a canonical provider overflow.
# Service-wide policy provides pressure, retention, and one overflow-retry default.
# Ratios scale against the routed model's context window.
- id: compact-basic
name: '@deepseek-ai/dsh-compact-basic'

View File

@@ -33,9 +33,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('compaction: a long session compa
// Reasoning tokens require a larger generation cap than the retained checkpoint.
ctx = await codingHarness(workdir, {
persona: SYSTEM_PROMPT,
tokenMeter: {
contextWindow: 2000,
},
modelContextWindow: 2000,
compact: {
thresholdRatio: 0.5,
retainTokens: 400,

View File

@@ -8,7 +8,6 @@ import * as ToolBash from '@deepseek-ai/dsh-tool-bash'
import * as ToolTodo from '@deepseek-ai/dsh-tool-todo'
import * as LlmDeepSeek from '@deepseek-ai/dsh-llm-deepseek'
import TokenMeterService from '@deepseek-ai/dsh-token-meter'
import type { TokenMeterConfig } from '@deepseek-ai/dsh-token-meter'
import SessionPersistenceJsonl from '@deepseek-ai/dsh-session-persistence-jsonl'
import { BasicCompactService } from '@deepseek-ai/dsh-compact-basic'
import type { BasicCompactConfig } from '@deepseek-ai/dsh-compact-basic'
@@ -45,8 +44,8 @@ export interface CodingHarnessOptions {
* compaction plugin (the default suites run without it).
*/
compact?: BasicCompactConfig
/** Optional token-meter capacity loaded before compact-basic. */
tokenMeter?: TokenMeterConfig
/** Test-only context capacity advertised for `deepseek-v4-flash`. */
modelContextWindow?: number
}
export async function codingHarness(workdir: string, options: CodingHarnessOptions = {}): Promise<Context> {
@@ -55,14 +54,15 @@ export async function codingHarness(workdir: string, options: CodingHarnessOptio
systemPrompt: { persona: options.persona ?? '' },
})
await ctx.plugin(AgentLoop, { agents: [] })
await ctx.plugin(LlmDeepSeek)
await ctx.plugin(LlmDeepSeek, options.modelContextWindow === undefined ? {} : {
models: [{ id: 'deepseek-v4-flash', contextWindow: options.modelContextWindow }],
})
await ctx.plugin(LocalBashExecutor, { cwd: workdir, timeoutMs: 30_000 })
await ctx.plugin(ToolBash)
await ctx.plugin(ToolTodo)
// Compaction is opt-in: only the compaction e2e loads the reusable meter and
// backend, with a lower context window so a short real session crosses the threshold.
// Compaction is opt-in: only the compaction e2e loads the reusable meter and backend.
if (options.compact !== undefined) {
await ctx.plugin(TokenMeterService, options.tokenMeter)
await ctx.plugin(TokenMeterService)
await ctx.plugin(BasicCompactService, options.compact)
}
// Durable JSONL persistence is opt-in: only the resume e2e needs it, and the