Merge remote-tracking branch 'origin/master' into codex/fix-compact-agents-reinjection

# Conflicts:
#	.agents/notes/implemented/feature/2026-06-24-workspace-context.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-24-workspace-context.md
#	.agents/notes/implemented/feature/2026-06-24-workspace-context.zh.md
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	docs/cordis-catalog/events.md
#	docs/core-data-structures/system-prompt.i18n.yaml
#	docs/event-producer-consumer.md
#	examples/acp-agent/tests/snapshots/workspace-context/session.jsonl
#	packages/context/workspace-context/README.i18n.yaml
#	packages/context/workspace-context/README.md
#	packages/context/workspace-context/README.zh.md
#	packages/context/workspace-context/src/index.ts
#	packages/context/workspace-context/tests/workspace-context.spec.ts
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/src/agent.ts
#	packages/core/agent/README.i18n.yaml
#	packages/core/agent/README.md
#	packages/core/agent/README.zh.md
#	packages/core/agent/tests/agent.spec.ts
#	packages/core/system-prompt/README.i18n.yaml
This commit is contained in:
fz
2026-08-06 10:16:16 +08:00
825 changed files with 18415 additions and 15130 deletions

View File

@@ -6,9 +6,7 @@
## 概览
每个 harness 都是 [Cordis](cordis-primer.md) 上下文各包package贡献服务、类型化事件和可释放的注册项。
`packages/core/` 汇集默认的 agent智能体流程各项功能仍以插件形式存在。
每个 harness 都是 [Cordis](cordis-primer.md) 上下文各包package贡献服务、类型化事件和可释放的注册项。`packages/core/` 汇集默认流程;各项功能仍以插件形式存在。
### 默认服务
@@ -16,9 +14,9 @@
|---|---|---|
| — | [`dsh-scope`](../packages/core/scope/README.md) | 作用域上下文注册项与共享层存储(库) |
| `ctx.sessions` | `dsh-session` | 内存中的事件溯源会话 |
| `ctx.systemPrompt` | `dsh-system-prompt` | 有序的稳定系统提示词片段、缓存安全的动态上下文、工具 schema 和变量 |
| `ctx.systemPrompt` | `dsh-system-prompt` | 有序的提示词片段、工具 schema 和变量 |
| `ctx.tools` | `dsh-tools` | 工具注册表和[执行流水线](tool-execution-pipeline.md) |
| `ctx.agents` | `dsh-agent` | 活跃 agent、委托创建、`agent/*` 事件、进程内发起方作用域 |
| `ctx.agents` | `dsh-agent` | 活跃 agent(智能体)、委托创建、`agent/*` 事件、进程内发起方作用域 |
| `ctx.agentLoop` | `dsh-agent-loop` | 实体 `Agent` 驱动器 |
### 功能服务
@@ -38,7 +36,7 @@
| `ctx.skills` | [`skill/`](../packages/skill/README.md) | skill技能提供方注册表和渐进式披露 |
| `ctx.web` | [`web/`](../packages/web/README.md) | 搜索与抓取提供方注册表 |
| `ctx.compact``ctx.toolResultPrune` | [`compact/`](../packages/compact/README.md)/[`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune/README.md) | 摘要压缩compaction和可选的无模型结果裁剪 |
| `ctx.subagents` | [`subagent/`](../packages/subagent/README.md) | 具名委托提供方和由 Activation 支撑的继续执行 |
| `ctx.subagents` | [`subagent/`](../packages/subagent/README.md) | 具名委托提供方 |
| `ctx.planMode` | [`plan/`](../packages/plan/README.md) | 落日志的 plan 协作状态 |
| `ctx.tasks` | [`tasks/`](../packages/tasks/README.md) | 后台任务注册表和通用 `task_*` 控制 |
| `ctx.workflows` | [`workflow/`](../packages/workflow/README.md) | 脚本驱动的多 agent 编排 |
@@ -59,8 +57,8 @@
### 事件域
- **会话事件**是通过 `session/event` 发出的持久日志事实。
- **Agent 事件**携带活跃 `Agent`,用于状态、提示词准入、请求塑形、验证和续跑。
- **功能事件**让所属服务边界无需导入循环即可附加策略和适配器。
- **Agent 事件**携带活跃 `Agent`,用于 inbox、步骤、状态、请求、验证和续跑。
- **功能事件**无需导入循环即可附加策略和适配器。
### 拦截语义
@@ -68,68 +66,71 @@ waterfall瀑布式事件是环绕中间件监听器通过 `next()` 委
## 默认循环生命周期
**会话**仅追加。普通**轮次**认领一个排队的 `send()` 项;注入不会认领。轮次在模型或插件停止时结束;一个**步骤**一次模型请求及其工具调用组成。只有私有设置和恢复状态准备完毕后,系统才会发布 agent 与会话。[下文时序](agent-lifecycle.md)中的引号标记持久事件。
**会话**采用仅追加方式。一个**轮次**领取一条已排队的后续消息,等待前一轮次的检查点,并可与其共用 `running` 区间([决策](../.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.md));注入不领取输入。一个**步骤**包含一次模型请求及其工具。[时序](agent-lifecycle.md)中的引号标记持久事件。
创建时若未提供 id流程会生成 `<config-id>-session-<uuid>``sessionId` 用于恢复或创建会话,而 `resumeSessionId` 要求已有历史。恢复流程在发布前还原沿袭关系和委托深度;初始化失败会发出 `agent-loop/config-start-failed`
### 轮次流程
```text
choose declarative identity and fresh/resume path
-> prepare private session + agent.ctx -> await unpublished setup -> invoke optional synchronous setup commit
-> prepare private session + agent.ctx -> await unpublished setup
-> enter session + agent -> session/created -> agent/created
-> enable driving -> agent/session-start(source) -> start driver
forever:
wait for queued occurrence
claim (edit/remove end) -> emit agent/status(running) if starting an interval
open the next-step acceptance window
-> agent/prompt-submit
blocked or failed prompt -> close the window without opening a turn
append a context-only caller batch immediately
keep steering and context staged beside it pending for a later admitted turn
allowed prompt:
'turn/start'
append prompt + additional contexts as separate 'user/message' events
STEP loop:
agent/step
assemble system prompt and tools
materialize changed runtime context as sourced 'user/message'
drain injected context and provisional steering (steering bypasses prompt-submit)
snapshot the derived messages (the reconstruction boundary)
waking inbox insertion starts the driver before send returns
-> emit agent/status(running) if starting an interval
-> 'turn/start'
claim next-step input plus one next-turn message
-> emit agent/inbox/claimed({ message, turn }) for each claimed message
-> agent/pre-step(messages, { turn, step, signal })
reject, empty input, cancellation, or listener failure
-> the claimed batch stays removed; close the no-step turn; stop the driver
enter -> step loop:
'step/start'
admit the drained steering receipts
append the returned batch as separate 'user/message' events
assemble ordered prompt and tool schemas -> snapshot derived messages
agent/request (config only) -> prepare adapter defaults/provenance + context capacity under turn signal -> log request/header (+ request/context on route change) -> llm/stream (frozen, registration-bound)
'assistant/chunk'
'assistant/message'
schedule tool calls by ctx.tools.executionMode:
exclusive -> barrier
parallel -> rolling pool, <= maxParallelToolCalls; reclassify-at-start; scheduler failure -> stop starts, drain dispatches
start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
parallel -> rolling pool, <= maxParallelToolCalls; reclassify at start
start -> 'tool/call' -> tools/pre-execute -> concurrent tools/execute
model-order result -> ordered tools/post-execute -> 'tool/result'
drain accepted tool context after all results; keep steering provisional
'step/end'
continue for tools or steering unless a result concluded the turn and rejects pending steering
otherwise agent/turn-stopping -> drain context -> continue only for steering
close the next-step acceptance window
'turn/end' -> agent/settled
tools owe another request or next-step inbox is nonempty
-> claim -> agent/pre-step -> append entered batch -> continue
otherwise agent/turn-stopping -> re-check the next-step inbox
'turn/end'
start the next waking queued message, or emit agent/status(idle)
idle inject:
append 'user/message'
do not open a turn or run the model
queue non-waking next-step context
leave it pending until followup or steer wakes the driver
```
每个步骤都会组装提示词、工具、运行时上下文、适配器设置和模型历史,随后记录其重建边界。之后,工具调用通过共享执行流水线运行。`inject()` 添加上下文但不打开空闲轮次;`steer()` 针对下一步骤的准入窗口;排队输入仍是普通轮次的来源。精确事件顺序由生成的 [agent 生命周期](agent-lifecycle.md)定义队列、steering、重试与取消机制由 [agent-loop README](../packages/core/agent-loop/README.md)定义
每个步骤都会组装有序的提示词片段、工具 schema 和变量;未知引用会使该轮次失败。`dsh-system-prompt` 负责身份和角色设定;循环提供 `provider``model``cwd`[提示词归属](../.agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md)
`inject()` 将不会唤醒驱动器的上下文排入 `next-step`;空闲驱动器会让它保持待处理,直至 `followup()``steer()` 唤醒。工具执行后的 `additionalContexts` 使用同一个 inbox。`agent/pre-step` 接收独占的已领取批次,以及即将使用的轮次、步骤和信号。拒绝则不进入步骤;进入则提供在 `step/start` 后追加的完整批次。空的工具续跑仍会经过 waterfall其最终值一次性结算所有改写。
裁剪先于摘要;溢出重试必须取得持久进展。`agent/request-error` 可以授权使用冻结提示词进行同步骤重试;取消优先。适配器的 `retryPolicy` 使 normal mode 保持有界always mode 则在专门恢复后重试([压缩](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md)、[重试基础](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md)、[提供方策略](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md))。精确事件顺序由生成的 [agent 生命周期](agent-lifecycle.md)定义队列、steering、重试与取消机制由 [agent-loop README](../packages/core/agent-loop/README.md)定义。
### 失败边界
适配器故障会先关闭步骤,再由 `agent/request-error` 授权从持久历史恢复。其他故障使用 `agent/error`;取消和资源释放优先于恢复。失败的模型尝试不会提交 assistant 消息或工具副作用。轮次关闭由一个 [TurnEndReason](core-data-structures/session.md#why-a-turn-ended-turnendreasonmap)表示;准确的重试契约由 [LLM 流式输出](core-data-structures/llm-streaming.md)定义
适配器选择、分发与迭代失败会成为 error 或 aborted 类型的终止 `finish` 分片。`agent/request-error` 接收请求坐标、标准化 `LlmFailure`、可用的重试策略和信号middleware 与消费方错误仍在恢复之外。失败分片既不提交消息,也不提交工具调用
其他故障使用 `agent/error`;取消和资源释放优先于恢复。在提交请求头之前,轮次信号会取消功能准备;尚未分派的工具会得到合成的 `tool/call`/`ABORTED_BEFORE_DISPATCH` 对。实际生效的 `cancel(cause)` 会在清空队列和中止前报告原因;空闲调用不发事件。持久化层以 `aborted` 区分取消,以 `disposed` 区分会等待完全停稳的拆卸([决策](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md))。
轮次和步骤事件均位于轮次边界内loop 只会在轮次内从进入步骤的批次追加 `user/message`。轮次会在首次领取与 pre-step 之前打开,因此拒绝、空输入、取消或失败会关闭一个不包含任何步骤事件的持久轮次。独立的 `compact/* { turn: null }` 事件不占用轮次,其锁定时刻标记可以与 inbox splice 交错。重新加载会为中断的轮次合成结束事件;`session/end-seed` 区分陈旧的压缩遗留项与活跃锁。关闭后仅由 `agent/error` 报告故障。每个轮次有一个 [TurnEndReason](core-data-structures/session.md#why-a-turn-ended-turnendreasonmap)。
### Agent 句柄
`ctx.agents` 管理 agent并返回 `AgentHandle { agent, dispose() }`。插件通过 [agent 接口](../packages/core/agent/README.md#agent-interface-typests)提交排队工作、steering 或注入上下文;取消、空闲状态和拆卸也都由同一个句柄封装
`ctx.agents` 拥有 agent 并返回 `AgentHandle { agent, dispose() }`。插件使用 `send()`,或使用其 `followup()``steer()``inject()` 预设。`cancel()``whenIdle()` 控制生命周期,需等待完成的资源释放则负责拆卸。后续消息的 `MessageId` 跟踪持久 inbox 的插入、领取与丢弃通知,而不标识提示词输出或轮次结束;只有完整活动区间的所有方才能将其概括为一次运行结果([决策](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md)
### Agent 作用域
每个 agent 都拥有作用域化的 `agent.ctx`;共享存储会将其工具、提示词和命令叠加到全局贡献之上,作用域监听器过滤分派。设置过程在发布前完成组合,清理过程会撤销贡献。详细生命周期由 [agent 作用域决策](../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md)定义
每个 agent 都拥有作用域化的 `agent.ctx`;共享存储会将其工具、提示词和命令条目叠加到全局条目之上,同时保留各领域视图([决策](../.agents/notes/implemented/architecture/2026-07-12-scoped-layers-store.md))。作用域监听器过滤分派;贡献都会在撤销时等待清理完成。`CreateAgentOptions.setup(agentCtx)` 在发布前完成组合。类型化解析器从合并后的 `Events``scopeTarget` 推导载体检查([语义门禁](../.agents/notes/implemented/process/2026-07-14-typescript-program-backed-semantic-gates.md))。详情见 [agent 作用域](../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md)和 [subagent 组合](../.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.md)。`AgentLoop``ctx.agents.withInitiator()` 内运行;私有编排会派生 `agent.session`但轮次、步骤、信号、cwd 和权限仍保持显式([决策](../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md)
## 状态
@@ -137,11 +138,11 @@ idle inject:
会话日志是权威依据。`deriveMessages()` 投影出模型历史;原始 `assistant/chunk` 事件保证回放和 UI 保真。fork、恢复、transcript文本记录渲染、遥测和持久化均派生自该事件流。
**模型可见 ⟺ 已记录**:在 `step/start` 之前,循环会将完整的当前运行时上下文快照作为一条带来源的 `user/message` 追加,随后对派生消息制作快照。这些消息与折叠后的 `request/header` 可以重建每个请求。该 header 会标记适配器默认值,使后续提议丢弃这些值并重新解析路由,同时不丢失显式设置。`dsh-agent-loop/invariant` 通过 `ctx.invariants` 断言这一点[可重建性](../.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.md))。
**模型可见 ⟺ 已记录**:在 `step/start` 进入的消息加上折叠后的 `request/header` 可以重建每个请求。该 header 会标记适配器默认值,使后续提议丢弃这些值并重新解析路由,同时不丢失显式设置。`request/context` 会在路由变化时另行记录与注册项绑定的提供方、模型及容量元数据;它不参与请求重建或 header 相等性判断。`dsh-agent-loop/invariant` 通过 `ctx.invariants` 断言可重建性[可重建性](../.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.md))。
持久性由插件负责。后端会尽快排空同步的 `session/event` 通知。`session/flush` 屏障位于每次请求与顶层工具分发之前,并在 `turn/end` 之后、处理另一个已排队轮次或观察到空闲状态之前执行。`SessionPersistence` 直接存储 `SessionEvent`,并将元数据存入 `SessionHeader`JSONL 默认采用带校验和的 ZstandardSQLite 遵循同一契约([决策](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md))。
持久性由插件负责。后端会尽快排空同步的 `session/event` 通知。`session/flush` 位于请求与顶层工具分发之前,并在 `turn/end` 之后、另一个轮次或空闲状态之前执行。`SessionPersistence` 存储事件和 header 元数据JSONL 默认采用带校验和的 ZstandardSQLite 遵循同一契约([决策](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md))。
在轮次之间,事件所有方通过 `Session` 追加纯日志事件,仅为持久性而刷写。`session/title` 需要尽快持久化与生命周期排空;手动压缩会在释放轮次接纳预留前 flush 其标记对。标题工作绝不延迟响应;最新标题按后写覆盖并携带来源信息。标题记录是可继承的 fork 边界([决策](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md))。
在轮次之间,事件所有方通过 `Session` 追加纯日志事件,仅为持久性而刷写。`session/title` 需要尽快持久化与生命周期排空;手动压缩会在操作完成前 flush 其标记对。标题工作绝不延迟响应;最新标题按后写覆盖并携带来源信息。标题记录是可继承的 fork 边界([决策](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md))。
### 模型内容
@@ -157,7 +158,7 @@ idle inject:
例外情况包括 LLM大语言模型合并接口和消费方、文件系统整合策略、web 使用注册表、skill 和 subagent 使用具名提供方。subagent 可以通过 spawn 创建全新实例、fork 一个已完成轮次的前缀,或使用 ACPAgent Client Protocol子 agent[subagent.md](core-data-structures/subagent.md))。
`dsh-workspace-context` 在第一次 `agent/step` 注入基线,在请求创建快照前于 loop 面向模型请求的 `system-prompt/assemble` 期间恢复因压缩而被遮蔽的基线,并通过 `tools/post-execute` 追加 `ctx.fs` 发现的变更;仅检查组装保持只读。其[决策](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md)记录隔离方式`dsh-paths` 负责共享路径。
`dsh-workspace-context` 在第一次 `agent/pre-step` 组合基线并将它折入最终进入的批次、紧随已领取的直接提示词之后使其与直接提示词一同抵达第一次请求reject 则将它留在 next-step inbox。当压缩从可见表层移除该基线时下一次进入步骤的 pre-step 会组合当前基线,并在同一请求中携带它。工具执行后投影的文件系统变更也会折入下一次进入步骤的 pre-step而不会另外创建稍后的纯上下文步骤[决策](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md)`dsh-paths` 负责共享路径。
### 组合包与应用
@@ -178,7 +179,7 @@ idle inject:
| 添加文件系统访问或策略 | 实现 `ctx.fs` 提供方,或监听 `fs/*` 策略事件 |
| 限制生成的进程 | 使用 `ctx.sandbox` 后端;消费方在生成前包装 argv |
| 拦截请求、工具或轮次 | 使用相应的 `agent/*``tools/*` 事件;`agent/turn-stopping` 是停止边界 |
| 添加模型可见上下文 | 调用 `agent.inject()`追加带来源的 `user/message`,但不创建轮次 |
| 添加模型可见上下文 | 调用 `agent.inject()`带来源的上下文排入下一次获准请求 |
| 添加 UI 或编辑器集成 | 驱动 `ctx.agents` 并从 `session/event` 渲染 |
| 添加持久会话状态 | 扩展 `SessionEventMap`;从日志渲染和回放 |
| 添加异步会话标题生成 | 注册唯一的 `ctx.sessionTitle` 提供方 |
@@ -186,4 +187,4 @@ idle inject:
| fork 活跃会话 | 调用 `ctx.sessions.fork(source, boundary?, childSessionId?)` |
| 将注册项限定到单个 agent | 使用其 `agent.ctx`(参见 Agent 作用域) |
[扩展实操手册cookbook](cookbook/extension-cookbook.md)提供插件骨架;指南涵盖[](cookbook/adding-a-package.md)、[工具](cookbook/adding-a-tool.md)、[LLM 适配器](cookbook/adding-an-llm-adapter.md)和 [vendored 包](cookbook/adding-a-vendored-package.md)。
[扩展实操手册cookbook](cookbook/extension-cookbook.md)提供插件骨架和功能到服务边界的映射;指南涵盖[](cookbook/adding-a-package.md)、[工具](cookbook/adding-a-tool.md)、[LLM 适配器](cookbook/adding-an-llm-adapter.md)和 [vendored 包](cookbook/adding-a-vendored-package.md)。