Merge remote-tracking branch 'origin/master' into worktree/fix-minimal-preset-prompt

This commit is contained in:
Yichen Jiang
2026-08-10 21:06:25 +08:00
49 changed files with 909 additions and 92 deletions
+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/module-graph.md
module-graph.md: a81c8fa85eb85d5ec31bfff286fceff511880715
module-graph.zh.md: b1ec05f45d1dac545e020f6438f2e2b4d197ebdf
module-graph.md: b596cb564943e321ff42cd59855bd7dc10981319
module-graph.zh.md: b64f30c2df1eedb1a1fa106b79710558b765fdde
+2 -1
View File
@@ -825,6 +825,7 @@ flowchart TD
pkg_command_compact --> pkg_compact
pkg_command_compact --> pkg_invariants
pkg_subagent --> pkg_agent
pkg_subagent --> pkg_agent_presets
pkg_subagent --> pkg_brand
pkg_subagent --> pkg_invariants
pkg_subagent --> pkg_llm
@@ -1390,7 +1391,7 @@ flowchart TD
| [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`tools`](../packages/core/tools) |
| [`tool-skill`](../packages/skill/tool-skill) | `skill` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
| [`command-compact`](../packages/compact/command-compact) | `compact` | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants) |
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`agent-presets`](../packages/preset/agent-presets), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`tool-web`](../packages/web/tool-web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`web`](../packages/web/web) |
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
| [`tool-todo`](../packages/todo/tool-todo) | `todo` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`tools`](../packages/core/tools) |
+2 -1
View File
@@ -827,6 +827,7 @@ flowchart TD
pkg_command_compact --> pkg_compact
pkg_command_compact --> pkg_invariants
pkg_subagent --> pkg_agent
pkg_subagent --> pkg_agent_presets
pkg_subagent --> pkg_brand
pkg_subagent --> pkg_invariants
pkg_subagent --> pkg_llm
@@ -1392,7 +1393,7 @@ flowchart TD
| [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`tools`](../packages/core/tools) |
| [`tool-skill`](../packages/skill/tool-skill) | `skill` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
| [`command-compact`](../packages/compact/command-compact) | `compact` | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants) |
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`agent-presets`](../packages/preset/agent-presets), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
| [`tool-web`](../packages/web/tool-web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`web`](../packages/web/web) |
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
| [`tool-todo`](../packages/todo/tool-todo) | `todo` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`tools`](../packages/core/tools) |
+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/subsystems/core.md
core.md: 75f55fe5b1837576ba79564b9aee7e289f5f16f4
core.zh.md: 7cd55b41c8f1358a89c6f35a4d3f733ccd8550ee
core.md: ad00c4da7d77b0e1ab4728173b202ebc17fb56a0
core.zh.md: 9c606023c85369643e7148f829526b1f75ea3631
+39
View File
@@ -419,6 +419,45 @@ async resolve(id?: string): Promise<AgentPreset>
*/
async mount(agentCtx: Context, id?: string): Promise<AgentPreset>
/**
* Join one agent to the SAME standing composition another already runs on.
*
* This is how a child agent inherits its parent's capabilities. It is a bind,
* not a mount: the parent's generation is already composed, so the child gets
* that exact instance — the same plugin objects, the same tool registrations,
* the same prompt sections. Re-resolving the parent's preset by id instead
* would re-read the roster, and a composition file edited since the parent
* started would hand the child a DIFFERENT generation than the one its
* parent's history was produced under (and a preset deleted since would fail
* the child outright while its parent keeps running).
*
* Synchronous, and with no composition failure mode of its own — it reads no
* roster, mounts nothing, and touches no file — which is what lets a child
* creation window use it: the two in-process subagent drivers compose their
* children inside a synchronous `setup`. It still rejects a caller error, as
* the `@throws` below record.
*
* A parent that joined no preset — a rosterless deployment — yields no join
* and no error: there, the model-facing rows sit in the host composition and
* the child already sees them through the global layer.
* @param agentCtx - the joining agent's scope context.
* @param parentCtx - the scope context of the agent whose composition to join.
* @returns the preset id joined, or undefined when the parent joined none.
* @throws when `agentCtx` carries no scope, or has already joined a preset.
*/
composeFrom(agentCtx: Context, parentCtx: Context): string | undefined
/**
* The preset one live agent runs on.
*
* Read from the live scope chain rather than from the session, so it answers
* for an agent whose session has not recorded a preset yet — a child agent
* whose durable header is being built from its parent's composition.
* @param agentCtx - the agent's scope context.
* @returns the preset id, or undefined when the agent joined none.
*/
composedPreset(agentCtx: Context): string | undefined
/**
* Read one preset's composition text.
* @param id - the preset id.
+39
View File
@@ -427,6 +427,45 @@ async resolve(id?: string): Promise<AgentPreset>
*/
async mount(agentCtx: Context, id?: string): Promise<AgentPreset>
/**
* Join one agent to the SAME standing composition another already runs on.
*
* This is how a child agent inherits its parent's capabilities. It is a bind,
* not a mount: the parent's generation is already composed, so the child gets
* that exact instance — the same plugin objects, the same tool registrations,
* the same prompt sections. Re-resolving the parent's preset by id instead
* would re-read the roster, and a composition file edited since the parent
* started would hand the child a DIFFERENT generation than the one its
* parent's history was produced under (and a preset deleted since would fail
* the child outright while its parent keeps running).
*
* Synchronous, and with no composition failure mode of its own — it reads no
* roster, mounts nothing, and touches no file — which is what lets a child
* creation window use it: the two in-process subagent drivers compose their
* children inside a synchronous `setup`. It still rejects a caller error, as
* the `@throws` below record.
*
* A parent that joined no preset — a rosterless deployment — yields no join
* and no error: there, the model-facing rows sit in the host composition and
* the child already sees them through the global layer.
* @param agentCtx - the joining agent's scope context.
* @param parentCtx - the scope context of the agent whose composition to join.
* @returns the preset id joined, or undefined when the parent joined none.
* @throws when `agentCtx` carries no scope, or has already joined a preset.
*/
composeFrom(agentCtx: Context, parentCtx: Context): string | undefined
/**
* The preset one live agent runs on.
*
* Read from the live scope chain rather than from the session, so it answers
* for an agent whose session has not recorded a preset yet — a child agent
* whose durable header is being built from its parent's composition.
* @param agentCtx - the agent's scope context.
* @returns the preset id, or undefined when the agent joined none.
*/
composedPreset(agentCtx: Context): string | undefined
/**
* Read one preset's composition text.
* @param id - the preset id.
+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/subsystems/tools.md
tools.md: f8d86704a2237219530c8c23b46a68383458e1cf
tools.zh.md: 87269e5532b0cdfb0a38501d7b98c9986665df1d
tools.md: 6ff2d967c5631d096dd78236ffd0383ddb2b0493
tools.zh.md: 82ade5d8d4117387138296cf54fbc8e88ad335e7
+8 -7
View File
@@ -150,19 +150,20 @@ type InferArgs<S> = InferProperties<S, []>
Registration is a trusted same-process contract. The registry borrows the typed definition as readonly input, requires `output`, validates its raw schema, and checks semantic requirements such as a positive finite `timeoutMs`; `schemas()` constructs the model-facing projection when building a request, so execution and presentation share one resolved definition without leaking callbacks onto the wire.
## `ToolRestriction` — one scope's live global filter
## `ToolRestriction` — one scope's live filter over what it inherits
`ToolRestriction` applies only to the live deployment-global tool layer. The registry compiles readonly names into private sets, intersects multiple restrictions, then overlays scope-local tools. A deny-only filter admits later unlisted globals, while an allow-list excludes them.
`ToolRestriction` applies to the tools a scope inherits: the deployment-global layer plus every ancestor scope on its chain. The registry compiles readonly names into private sets, intersects multiple restrictions, then overlays the scope's OWN registrations, which stay exempt so a delegated child keeps the tools it answers through. A deny-only filter admits later unlisted inherited tools, while an allow-list excludes them.
```ts type-equiv
/**
* Per-scope filter over global tools. Restrictions intersect and do not affect
* scoped registrations or the reserved Code Mode transport.
* Per-scope filter over the tools a scope INHERITS — the global layer and
* every ancestor layer on its chain. Restrictions intersect, and do not affect
* the scope's own registrations or the reserved Code Mode transport.
*/
interface ToolRestriction {
/** Global tool names that stay visible; everything else is removed. */
/** Inherited tool names that stay visible; every other inherited one is removed. */
readonly allow?: readonly string[]
/** Global tool names removed from visibility. */
/** Inherited tool names removed from visibility. */
readonly deny?: readonly string[]
}
```
@@ -565,7 +566,7 @@ async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
Types: [ScopeKey](scope.md)
Source: [`packages/core/tools/src/index.ts:760`](../../packages/core/tools/src/index.ts)
Source: [`packages/core/tools/src/index.ts:761`](../../packages/core/tools/src/index.ts)
<a id="tools-events"></a>
+8 -7
View File
@@ -150,19 +150,20 @@ type InferArgs<S> = InferProperties<S, []>
注册是一项受信任的同进程约定。注册表以 readonly 输入借用已类型化定义,要求它声明 `output`,校验其原始 schema,并检查 `timeoutMs` 必须为正有限值等语义要求;`schemas()` 在构建请求时生成面向模型的投影,使执行和展示共享同一份已解析定义,而不会将回调泄漏到协议上。
## `ToolRestriction` — 单个作用域的实时全局过滤器
## `ToolRestriction` — 单个作用域对其继承内容的实时过滤器
`ToolRestriction` 作用于实时的部署全局工具层。注册表将 readonly 名称编译为私有集合,对多个限制取交集,再叠加作用域本地工具。仅 deny 的过滤器允许后续未列出的全局工具通过,而 allow 列表则排除它们。
`ToolRestriction` 作用于该作用域继承来的工具:部署全局层,加上其链上的每个祖先作用域。注册表将 readonly 名称编译为私有集合,对多个限制取交集,再叠加作用域**自身**的注册——后者不受约束,因此被委派的子 agent 会保留其回报所依赖的工具。仅 deny 的过滤器允许后续未列出的继承工具通过,而 allow 列表则排除它们。
```ts type-equiv
/**
* Per-scope filter over global tools. Restrictions intersect and do not affect
* scoped registrations or the reserved Code Mode transport.
* Per-scope filter over the tools a scope INHERITS — the global layer and
* every ancestor layer on its chain. Restrictions intersect, and do not affect
* the scope's own registrations or the reserved Code Mode transport.
*/
interface ToolRestriction {
/** Global tool names that stay visible; everything else is removed. */
/** Inherited tool names that stay visible; every other inherited one is removed. */
readonly allow?: readonly string[]
/** Global tool names removed from visibility. */
/** Inherited tool names removed from visibility. */
readonly deny?: readonly string[]
}
```
@@ -565,7 +566,7 @@ async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
Types: [ScopeKey](scope.md)
Source: [`packages/core/tools/src/index.ts:760`](../../packages/core/tools/src/index.ts)
Source: [`packages/core/tools/src/index.ts:761`](../../packages/core/tools/src/index.ts)
<a id="tools-events"></a>