fix: suppress runtime context in minimal profiles

This commit is contained in:
Yichen Jiang
2026-08-12 23:28:15 +08:00
parent c4e24071d6
commit ece8645080
41 changed files with 400 additions and 233 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/examples/agent-spine-demo/README.md
README.md: 789715e53038f610d1e2db79cf56f9aabd681fac
README.zh.md: 7a861297d76d18d5e55539334ca8e7ee5ffef640
README.md: d45a128e786da18d2e2a41c1e4c048270a9c5cc7
README.zh.md: ae9c523b53a13eae89a670b9177ed996b4fbb928

View File

@@ -55,11 +55,11 @@ This applies the [Service Definition / Service provider / Consumer separation](.
```ts
import type { Config } from '@deepseek-ai/dsh-agent-spine-demo'
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, persona?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, tasks?, toolTasks?, goals?, invariants? }
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, includeRuntimeContext?, persona?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, tasks?, toolTasks?, goals?, invariants? }
// workspaceContext requires { maxBytes } or false; the other owner schemas supply defaults.
```
The bundle forwards each field to the child that owns it. App packages supply any pre-created agents: headless and JSON-RPC compositions create `main`, while the ACP app creates agents on demand at `session/new`. Prompt, tool, title, skill, workspace-context, invariant, goal, and task settings retain the schemas and defaults documented by their owning packages; `tasks.maxConcurrentTasksPerOwner` configures the local provider independently of the model-facing `toolTasks` controls. `pickSpineConfig()` copies only fields owned by this bundle, and conflicting `dshHome` values fail during composition.
The bundle forwards each field to the child that owns it. App packages supply any pre-created agents: headless and JSON-RPC compositions create `main`, while the ACP app creates agents on demand at `session/new`. `includeRuntimeContext: false` is forwarded to `dsh-system-prompt` and suppresses all dynamic context snapshots for fresh sessions without disabling their policy services. Prompt, tool, title, skill, workspace-context, invariant, goal, and task settings retain the schemas and defaults documented by their owning packages; `tasks.maxConcurrentTasksPerOwner` configures the local provider independently of the model-facing `toolTasks` controls. `pickSpineConfig()` copies only fields owned by this bundle, and conflicting `dshHome` values fail during composition.
For example, `{ invariants: { enabled: true, package_allowlist: ['^@deepseek-ai/dsh-'], package_blocklist: ['agent-loop$'] } }` keeps the package-owned companions mounted but suppresses the blocked owner. Blocklist matches override allowlist matches; see [`dsh-invariants`](../../support/invariants/README.md) for regex and lifecycle rules.

View File

@@ -55,11 +55,11 @@
```ts
import type { Config } from '@deepseek-ai/dsh-agent-spine-demo'
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, persona?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, tasks?, toolTasks?, goals?, invariants? }
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, includeRuntimeContext?, persona?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, tasks?, toolTasks?, goals?, invariants? }
// workspaceContext requires { maxBytes } or false; the other owner schemas supply defaults.
```
组合包将每个字段转发给拥有它的子节点。应用包提供预创建的 agent无头和 JSON-RPC 组合会创建 `main`ACP 应用则在 `session/new` 按需创建 agent。提示词、工具、标题、skill、工作区上下文、不变式、目标和任务设置沿用其所属包记录的 schema 与默认值;`tasks.maxConcurrentTasksPerOwner` 配置本地 Service provider并与面向模型的 `toolTasks` 控制工具相互独立。`pickSpineConfig()` 只复制该组合包拥有的字段,`dshHome` 值冲突会在组合时失败。
组合包将每个字段转发给拥有它的子节点。应用包提供预创建的 agent无头和 JSON-RPC 组合会创建 `main`ACP 应用则在 `session/new` 按需创建 agent。`includeRuntimeContext: false` 会转发给 `dsh-system-prompt`,为新建会话抑制所有动态上下文快照,但不禁用其策略服务。提示词、工具、标题、skill、工作区上下文、不变式、目标和任务设置沿用其所属包记录的 schema 与默认值;`tasks.maxConcurrentTasksPerOwner` 配置本地 Service provider并与面向模型的 `toolTasks` 控制工具相互独立。`pickSpineConfig()` 只复制该组合包拥有的字段,`dshHome` 值冲突会在组合时失败。
例如,`{ invariants: { enabled: true, package_allowlist: ['^@deepseek-ai/dsh-'], package_blocklist: ['agent-loop$'] } }` 会让包拥有的配套插件保持挂载但抑制被阻止的拥有者。Blocklist 匹配优先于 allowlist 匹配;正则表达式与生命周期规则见 [`dsh-invariants`](../../support/invariants/README.md)。

View File

@@ -69,9 +69,10 @@ export interface GoalConfig {
/**
* Bundle config: each field forwarded verbatim to the child that owns it —
* `agents` to the agent loop (an app that pre-creates no agents, like the ACP
* bridge, simply omits it), `includeHarnessIdentity`, `persona`, and `toolOrder`
* to the system-prompt plugin (the fixed opener, deployment persona, and explicit
* model-facing tool order), the `tools` object to the tool registry (its presentation `mode`),
* bridge, simply omits it), `includeHarnessIdentity`, `includeRuntimeContext`,
* `persona`, and `toolOrder` to the system-prompt plugin (the fixed opener,
* dynamic-context policy, deployment persona, and explicit model-facing tool
* order), the `tools` object to the tool registry (its presentation `mode`),
* `dshHome` to bash environment and local skill discovery, `sessionTitle` to
* the fallback title service, `skills` to the
* skill registry/local provider/tool consumer, `workspaceContext` to the
@@ -95,6 +96,8 @@ export interface Config {
maxParallelToolCalls?: AgentLoopConfig['maxParallelToolCalls']
/** Whether the system prompt includes the fixed Harness identity (default true). */
includeHarnessIdentity?: SystemPromptConfig['includeHarnessIdentity']
/** Whether model history includes dynamic runtime-context snapshots (default true). */
includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext']
/** The deployment persona (see dsh-system-prompt's `Config`). */
persona?: SystemPromptConfig['persona']
/** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */
@@ -180,6 +183,7 @@ export function pickSpineConfig(config: Omit<Config, 'agents'>): Omit<Config, 'a
return {
...config.maxParallelToolCalls !== undefined ? { maxParallelToolCalls: config.maxParallelToolCalls } : {},
...config.includeHarnessIdentity !== undefined ? { includeHarnessIdentity: config.includeHarnessIdentity } : {},
...config.includeRuntimeContext !== undefined ? { includeRuntimeContext: config.includeRuntimeContext } : {},
...config.persona !== undefined ? { persona: config.persona } : {},
...config.toolOrder !== undefined ? { toolOrder: config.toolOrder } : {},
...config.tools !== undefined ? { tools: config.tools } : {},
@@ -220,6 +224,7 @@ export function apply(ctx: Context, config: Config): void {
// Owner schemas resolve defaults; forward toolOrder only when explicitly set.
ctx.plugin(SystemPrompt, {
includeHarnessIdentity: config.includeHarnessIdentity ?? true,
includeRuntimeContext: config.includeRuntimeContext ?? true,
persona: config.persona ?? '',
...config.toolOrder !== undefined ? { toolOrder: config.toolOrder } : {},
})

View File

@@ -712,6 +712,7 @@ describe('dsh-agent-spine-demo bundle', () => {
it('can omit the bundled bash tool and Harness identity for a compatibility deployment', async () => {
const ctx = await mount({
includeHarnessIdentity: false,
includeRuntimeContext: false,
persona: 'You are a helpful software engineer assistant.',
workspaceContext: false,
skills: { enabled: false },
@@ -720,6 +721,8 @@ describe('dsh-agent-spine-demo bundle', () => {
}, true)
expect(ctx.tools.schemas()).toEqual([])
ctx.systemPrompt.context({ name: 'policy', order: 0, text: 'hidden policy' })
expect((await ctx.systemPrompt.assemble()).contexts).toEqual([])
expect(renderPrompt(await ctx.systemPrompt.assemble()))
.toBe('You are a helpful software engineer assistant.')
@@ -729,7 +732,9 @@ describe('dsh-agent-spine-demo bundle', () => {
it('picks shared spine config without leaking entry-point fields', () => {
const appConfig = {
model: 'entrypoint-only',
maxParallelToolCalls: 3,
includeHarnessIdentity: false,
includeRuntimeContext: false,
persona: 'You are merged.',
toolOrder: ['zulu'],
tools: { mode: 'native' as const },
@@ -741,10 +746,13 @@ describe('dsh-agent-spine-demo bundle', () => {
tasks: { maxConcurrentTasksPerOwner: 4 },
toolTasks: false as const,
invariants: { enabled: false },
goals: false as const,
}
expect(agentCore.pickSpineConfig(appConfig)).toEqual({
maxParallelToolCalls: appConfig.maxParallelToolCalls,
includeHarnessIdentity: appConfig.includeHarnessIdentity,
includeRuntimeContext: appConfig.includeRuntimeContext,
persona: appConfig.persona,
toolOrder: appConfig.toolOrder,
tools: appConfig.tools,
@@ -756,6 +764,7 @@ describe('dsh-agent-spine-demo bundle', () => {
tasks: appConfig.tasks,
toolTasks: appConfig.toolTasks,
invariants: appConfig.invariants,
goals: appConfig.goals,
})
expect(agentCore.pickSpineConfig({ workspaceContext: false })).toEqual({ workspaceContext: false })
})