refactor(prompt): remove unused complete-persona config

This commit is contained in:
Tianyi Cui
2026-08-25 12:21:50 +08:00
parent d35459e3c1
commit 43f0f07f9b
16 changed files with 24 additions and 61 deletions
@@ -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 .agents/notes/implemented/architecture/2026-08-24-standalone-sdk-minimal-profile.md
2026-08-24-standalone-sdk-minimal-profile.md: 692bf9763f4ad710ff5cc819a7480b2f3e8d9b5f
2026-08-24-standalone-sdk-minimal-profile.zh.md: f39baad1b4429b73f13d601716dadd8376c71bfb
2026-08-24-standalone-sdk-minimal-profile.md: 9cdc92248326f115cb77444531cee420507ff871
2026-08-24-standalone-sdk-minimal-profile.zh.md: a4fa2b3d4c0941447e84347f4999c15951ad76be
@@ -44,7 +44,7 @@ The bundle test pins the exact row and dependency roster. Profile-template and c
## Alternatives considered
**Keep the minimal mode as an overlay on `sdk`.** Rejected because filtering model-visible tools does not remove base services, prompt contributors, persistence choices, or later runtime behavior. It also makes the minimal application depend on controls in shared SDK server and system-prompt interfaces.
**Keep the minimal mode as an overlay on `sdk`.** Rejected because filtering model-visible tools does not remove base services, prompt contributors, persistence choices, or later runtime behavior. It also required root-tool filtering in the shared SDK server and a complete-persona shortcut in the system-prompt config; neither shared interface carries those composition controls.
**Restore a Python `cordis` argument or environment-selected complete config.** Rejected because it recreates a Python-owned application composition and bypasses profile plugin management and launcher lifecycle.
@@ -44,7 +44,7 @@ Python 运行时继续打包 `dsh-web-app` 与前端产物。`dsh web` 会从已
## 考虑过的替代方案
**继续把极简模式作为 `sdk` 上的 overlay。** 否决:筛选面向模型的工具不会移除 base 服务、提示词贡献方、持久化选择或后续运行时行为,还会让极简应用依赖共享 SDK server 与系统提示词接口中的控制项。
**继续把极简模式作为 `sdk` 上的 overlay。** 否决:筛选面向模型的工具不会移除 base 服务、提示词贡献方、持久化选择或后续运行时行为。该方案还要求共享 SDK server 提供根工具筛选,并要求 system-prompt 配置提供 complete-persona 快捷项;这两个共享接口均不再携带这些组合控制项。
**恢复 Python `cordis` 参数或由环境选择的完整配置。** 否决:这会重新创建 Python 自有应用组合,并绕过 profile 插件管理与 launcher 生命周期。
+2 -2
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 docs/config-catalog.md
config-catalog.md: 54cf64bdf6ff5c8ee51b6ecedaf218267778d19f
config-catalog.zh.md: e887edf989d279435ae04beb40172341f5125b1e
config-catalog.md: d4069d17ef269461ca4b76e10b9e7ccdbf3fce21
config-catalog.zh.md: 1931358d2a9ca54905e4ccadb76b7b770935405f
+3 -7
View File
@@ -166,9 +166,9 @@ Source: [`packages/preset/agent-presets/src/preset.ts:52`](../packages/preset/ag
* 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`, `includeRuntimeContext`,
* `persona`, `personaComplete`, and `toolOrder` to the system-prompt plugin
* (the fixed opener, dynamic-context policy, deployment persona completeness,
* and explicit model-facing tool order), the `tools` object to the tool
* `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
@@ -197,8 +197,6 @@ export interface Config {
includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext']
/** The deployment persona (see dsh-system-prompt's `Config`). */
persona?: SystemPromptConfig['persona']
/** Whether the deployment persona is the complete system prompt. */
personaComplete?: SystemPromptConfig['personaComplete']
/** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */
toolOrder?: SystemPromptConfig['toolOrder']
/** The tool registry's config — its presentation `mode` (see dsh-tools' `Config`). */
@@ -2450,8 +2448,6 @@ export interface Config {
* `deployment:persona` shadows it; `{{variable}}` references are strict.
*/
persona?: string
/** Treat the deployment persona as the complete system prompt (default false). */
personaComplete?: boolean
/**
* Model-facing tool names in order, with {@link TOOL_ORDER_REST} exactly once.
* Invalid fields fail at load and unknown names fail at assembly; known names
+3 -7
View File
@@ -168,9 +168,9 @@ export type PresetTrust = 'system' | 'user'
* 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`, `includeRuntimeContext`,
* `persona`, `personaComplete`, and `toolOrder` to the system-prompt plugin
* (the fixed opener, dynamic-context policy, deployment persona completeness,
* and explicit model-facing tool order), the `tools` object to the tool
* `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
@@ -199,8 +199,6 @@ export interface Config {
includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext']
/** The deployment persona (see dsh-system-prompt's `Config`). */
persona?: SystemPromptConfig['persona']
/** Whether the deployment persona is the complete system prompt. */
personaComplete?: SystemPromptConfig['personaComplete']
/** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */
toolOrder?: SystemPromptConfig['toolOrder']
/** The tool registry's config — its presentation `mode` (see dsh-tools' `Config`). */
@@ -2452,8 +2450,6 @@ export interface Config {
* `deployment:persona` shadows it; `{{variable}}` references are strict.
*/
persona?: string
/** Treat the deployment persona as the complete system prompt (default false). */
personaComplete?: boolean
/**
* Model-facing tool names in order, with {@link TOOL_ORDER_REST} exactly once.
* Invalid fields fail at load and unknown names fail at assembly; known names
+2 -2
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/core/system-prompt/README.md
README.md: a52aa3e4c2782993fed5a525cc827aba4e3eaeb0
README.zh.md: cf0ba43aa2f2f47ea61ef13c74fbf182fbd9f2ee
README.md: d750a507e628e7609af542227e4528d4d4934ce8
README.zh.md: ec5b32d742b96c8044a3707c35f15e30ba642b4f
-1
View File
@@ -11,7 +11,6 @@ System prompt assembly registry. Plugins contribute ordered sections, tool schem
| `includeHarnessIdentity` | `true` | Include the fixed `You are an AI agent powered by DeepSeek Harness.` order-100 opener. Set false only when a compatibility deployment owns the complete system prompt. |
| `includeRuntimeContext` | `true` | Include ordered dynamic contexts in assembly. When false, context providers are not evaluated and contexts added by `system-prompt/assemble` listeners are discarded after the waterfall; other services and their enforcement remain active. |
| `persona` | `''` | The global deployment-persona default: the ONE config-authored prompt fragment, rendered as the order-0 `deployment:persona` section unless an agent-scoped contribution shadows it. A template — complete `{{…}}` groups are interpreted strictly against the registered variables (the shipped loop registers `{{model}}`/`{{cwd}}`), with no escape syntax for literal braces yet. Empty ⇒ the section is dropped at render. |
| `personaComplete` | `false` | Treat `persona` as the complete system prompt after assembly. Other sections remain registered but are omitted from model requests; tool schemas and variables remain available. |
| `toolOrder` | — | Explicit model-facing tool order, as a list of `ToolSchema.name`s with one `'<unlisted-tools>'` rest entry (`TOOL_ORDER_REST`): listed tools take their listed position, unlisted tools land at the rest entry in lexicographic name order. Absent ⇒ plain lexicographic name order. Applied to the collected tools BEFORE the `system-prompt/assemble` waterfall — like the sections' `order` sort, it canonicalizes what the registry contributed (registration order is a plugin-load artifact), and a waterfall listener that mutates the list owns the determinism of what it emits. Misconfiguration fails loud: a list without exactly one rest entry, or with duplicates, throws at load; a listed name with no registered tool rejects every `assemble()`; a tool provider returning the reserved rest-entry name also rejects. Under the shipped loop the turn fails before any model request. Why a central list and not per-plugin weights: [Explicit model-facing tool order](../../../.agents/notes/implemented/feature/2026-07-06-explicit-tool-order.md). |
## Service: `SystemPrompt` (ctx key: `systemPrompt`)
-1
View File
@@ -11,7 +11,6 @@
| `includeHarnessIdentity` | `true` | 是否包含顺序为 −100 的固定开场白 `You are an AI agent powered by DeepSeek Harness.`。仅当兼容性部署拥有完整系统提示词时设为 false。 |
| `includeRuntimeContext` | `true` | 是否在组装中包含有序动态上下文。设为 false 时不会求值上下文提供方,并会在 waterfall 后丢弃 `system-prompt/assemble` 监听器添加的上下文;其他服务及其强制机制仍然生效。 |
| `persona` | `''` | 全局部署 persona 默认值:唯一由配置提供的提示词片段,渲染为顺序为 0 的 `deployment:persona` 段,除非 agent 作用域的贡献将其遮蔽。它是模板,完整的 `{{…}}` 组会严格按已注册变量解释(随附循环注册 `{{model}}`/`{{cwd}}`),目前没有表达字面量花括号的转义语法。为空 ⇒ 渲染时删除该段。 |
| `personaComplete` | `false` | 在组装后将 `persona` 作为完整系统提示词。其他段仍保持注册,但不会进入模型请求;工具 schema 与变量仍然可用。 |
| `toolOrder` | 无 | 显式指定面向模型的工具顺序。该列表由 `ToolSchema.name` 组成,并且必须恰好包含一个 `'<unlisted-tools>'` 其余项标记(`TOOL_ORDER_REST`):已列工具按列表位置排列,未列工具则按名称字典序插入该标记所在的位置。缺席 ⇒ 直接按名称字典序排列。该顺序会在 `system-prompt/assemble` waterfall(瀑布式事件)之前应用于已收集的工具。与段的 `order` 排序一样,它会规范化注册表贡献的内容;注册顺序只是插件加载时序的产物。修改列表的 waterfall 监听器对其输出的确定性负责。配置错误会明确失败:列表没有恰好一个其余项或存在重复项,会在加载时抛出;已列名称没有对应已注册工具,会使每次 `assemble()` 被拒绝;工具提供方返回保留的其余项名称也会被拒绝。在随附循环下,轮次会在任何模型请求前失败。为何采用中心列表而非每插件权重,见[显式面向模型工具顺序](../../../.agents/notes/implemented/feature/2026-07-06-explicit-tool-order.zh.md)。 |
## 服务:`SystemPrompt`ctx 键:`systemPrompt`
-4
View File
@@ -193,8 +193,6 @@ export interface Config {
* `deployment:persona` shadows it; `{{variable}}` references are strict.
*/
persona?: string
/** Treat the deployment persona as the complete system prompt (default false). */
personaComplete?: boolean
/**
* Model-facing tool names in order, with {@link TOOL_ORDER_REST} exactly once.
* Invalid fields fail at load and unknown names fail at assembly; known names
@@ -342,7 +340,6 @@ export class SystemPrompt extends Service {
includeHarnessIdentity: z.boolean().default(true),
includeRuntimeContext: z.boolean().default(true),
persona: z.string().default(''),
personaComplete: z.boolean().default(false),
// Preserve omission because an explicit empty order lacks the rest marker.
toolOrder: z.array(z.string()).default(undefined as unknown as string[]),
})
@@ -369,7 +366,6 @@ export class SystemPrompt extends Service {
order: PERSONA_ORDER,
// The fallback narrows the optional input type; the schema already defaults it.
text: config.persona ?? '',
complete: config.personaComplete ?? false,
})
if (!(config.includeRuntimeContext ?? true)) this.suppressRuntimeContext()
}
@@ -49,21 +49,6 @@ describe('SystemPrompt', () => {
expect(renderPrompt(assembly)).toBe('You are a helpful software engineer assistant.')
})
it('can make the deployment persona the complete system prompt', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt, {
persona: 'You are a focused SDK agent.',
personaComplete: true,
})
ctx.systemPrompt.section({ name: 'tool:future', order: 100, text: 'Future tool guidance.' })
const assembly = await ctx.systemPrompt.assemble()
expect(assembly.sections).toEqual([
{ name: 'deployment:persona', text: 'You are a focused SDK agent.' },
])
expect(renderPrompt(assembly)).toBe('You are a focused SDK agent.')
})
it('can suppress runtime context without evaluating providers or accepting waterfall additions', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt, { includeRuntimeContext: false })
@@ -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: 28e1496a8c941f6524ec4b4dfbfad52d17df5d71
README.zh.md: c2838bb4cf78d6ac863bac2eba4d2e4df335fa55
README.md: ef82aa4b413be41049dbbd247deee4f1969cdb48
README.zh.md: 7701da0d965736efd905a3331401752119b160d9
+2 -2
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?, includeRuntimeContext?, persona?, personaComplete?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, jobs?, toolJobs?, goals?, invariants? }
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, includeRuntimeContext?, persona?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, jobs?, toolJobs?, 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`. `includeRuntimeContext: false` suppresses all dynamic context snapshots for fresh sessions without disabling their policy services; `personaComplete: true` makes the deployment persona the sole system-prompt section. Prompt, tool, title, skill, agent-instructions, invariant, goal, and task settings retain the schemas and defaults documented by their owning packages; `jobs.maxConcurrentJobsPerOwner` configures the local provider independently of the model-facing `toolJobs` 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` suppresses all dynamic context snapshots for fresh sessions without disabling their policy services. Prompt, tool, title, skill, agent-instructions, invariant, goal, and task settings retain the schemas and defaults documented by their owning packages; `jobs.maxConcurrentJobsPerOwner` configures the local provider independently of the model-facing `toolJobs` 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`](../../runtime-diagnostics/invariants/README.md) for regex and lifecycle rules.
@@ -55,11 +55,11 @@
```ts
import type { Config } from '@deepseek-ai/dsh-agent-spine-demo'
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, includeRuntimeContext?, persona?, personaComplete?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, jobs?, toolJobs?, goals?, invariants? }
// { agents?, maxParallelToolCalls?, includeHarnessIdentity?, includeRuntimeContext?, persona?, toolOrder?, tools?, dshHome?, sessionTitle?, skills?, workspaceContext, toolBash?, jobs?, toolJobs?, goals?, invariants? }
// workspaceContext requires { maxBytes } or false; the other owner schemas supply defaults.
```
组合包将每个字段转发给拥有它的子节点。应用包提供预创建的 agent:无头和 JSON-RPC 组合会创建 `main`ACP 应用则在 `session/new` 按需创建 agent。`includeRuntimeContext: false` 会为新建会话抑制所有动态上下文快照,但不禁用其策略服务`personaComplete: true` 会让部署 persona 成为唯一系统提示词段。提示词、工具、标题、skill、工作区上下文、不变式、目标和任务设置沿用其所属包记录的 schema 与默认值;`jobs.maxConcurrentJobsPerOwner` 配置本地 Service Provider,并与面向模型的 `toolJobs` 控制工具相互独立。`pickSpineConfig()` 只复制该组合包拥有的字段,`dshHome` 值冲突会在组合时失败。
组合包将每个字段转发给拥有它的子节点。应用包提供预创建的 agent:无头和 JSON-RPC 组合会创建 `main`ACP 应用则在 `session/new` 按需创建 agent。`includeRuntimeContext: false` 会为新建会话抑制所有动态上下文快照,但不禁用其策略服务。提示词、工具、标题、skill、工作区上下文、不变式、目标和任务设置沿用其所属包记录的 schema 与默认值;`jobs.maxConcurrentJobsPerOwner` 配置本地 Service Provider,并与面向模型的 `toolJobs` 控制工具相互独立。`pickSpineConfig()` 只复制该组合包拥有的字段,`dshHome` 值冲突会在组合时失败。
例如,`{ invariants: { enabled: true, package_allowlist: ['^@deepseek-ai/dsh-'], package_blocklist: ['agent-loop$'] } }` 会让包拥有的配套插件保持挂载,但抑制被阻止的拥有者。Blocklist 匹配优先于 allowlist 匹配;正则表达式与生命周期规则见 [`dsh-invariants`](../../runtime-diagnostics/invariants/README.zh.md)。
@@ -70,9 +70,9 @@ 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`, `includeRuntimeContext`,
* `persona`, `personaComplete`, and `toolOrder` to the system-prompt plugin
* (the fixed opener, dynamic-context policy, deployment persona completeness,
* and explicit model-facing tool order), the `tools` object to the tool
* `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
@@ -101,8 +101,6 @@ export interface Config {
includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext']
/** The deployment persona (see dsh-system-prompt's `Config`). */
persona?: SystemPromptConfig['persona']
/** Whether the deployment persona is the complete system prompt. */
personaComplete?: SystemPromptConfig['personaComplete']
/** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */
toolOrder?: SystemPromptConfig['toolOrder']
/** The tool registry's config — its presentation `mode` (see dsh-tools' `Config`). */
@@ -188,7 +186,6 @@ export function pickSpineConfig(config: Omit<Config, 'agents'>): Omit<Config, 'a
...config.includeHarnessIdentity !== undefined ? { includeHarnessIdentity: config.includeHarnessIdentity } : {},
...config.includeRuntimeContext !== undefined ? { includeRuntimeContext: config.includeRuntimeContext } : {},
...config.persona !== undefined ? { persona: config.persona } : {},
...config.personaComplete !== undefined ? { personaComplete: config.personaComplete } : {},
...config.toolOrder !== undefined ? { toolOrder: config.toolOrder } : {},
...config.tools !== undefined ? { tools: config.tools } : {},
...config.dshHome !== undefined ? { dshHome: config.dshHome } : {},
@@ -230,7 +227,6 @@ export function apply(ctx: Context, config: Config): void {
includeHarnessIdentity: config.includeHarnessIdentity ?? true,
includeRuntimeContext: config.includeRuntimeContext ?? true,
persona: config.persona ?? '',
personaComplete: config.personaComplete ?? false,
...config.toolOrder !== undefined ? { toolOrder: config.toolOrder } : {},
})
ctx.plugin(ToolRuntime, config.tools ?? {})
@@ -709,12 +709,11 @@ describe('dsh-agent-spine-demo bundle', () => {
await ctx.fiber.dispose()
})
it('can omit the bundled bash tool and Harness identity for a compatibility deployment', async () => {
it('can omit the bundled bash tool, Harness identity, and runtime context', async () => {
const ctx = await mount({
includeHarnessIdentity: false,
includeRuntimeContext: false,
persona: 'You are a helpful software engineer assistant.',
personaComplete: true,
workspaceContext: false,
skills: { enabled: false },
toolBash: false,
@@ -724,7 +723,6 @@ describe('dsh-agent-spine-demo bundle', () => {
expect(ctx.tools.schemas()).toEqual([])
ctx.systemPrompt.context({ name: 'policy', order: 0, text: 'hidden policy' })
expect((await ctx.systemPrompt.assemble()).contexts).toEqual([])
ctx.systemPrompt.section({ name: 'hidden', order: 100, text: 'hidden guidance' })
expect(renderPrompt(await ctx.systemPrompt.assemble()))
.toBe('You are a helpful software engineer assistant.')
@@ -738,7 +736,6 @@ describe('dsh-agent-spine-demo bundle', () => {
includeHarnessIdentity: false,
includeRuntimeContext: false,
persona: 'You are merged.',
personaComplete: true,
toolOrder: ['zulu'],
tools: { mode: 'native' as const },
dshHome: '/tmp/dsh-home',
@@ -757,7 +754,6 @@ describe('dsh-agent-spine-demo bundle', () => {
includeHarnessIdentity: appConfig.includeHarnessIdentity,
includeRuntimeContext: appConfig.includeRuntimeContext,
persona: appConfig.persona,
personaComplete: appConfig.personaComplete,
toolOrder: appConfig.toolOrder,
tools: appConfig.tools,
dshHome: appConfig.dshHome,