From 7c7b02176645d7324e7d44713a1becd89863ded6 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Sun, 25 Oct 2026 18:14:32 +0800 Subject: [PATCH] docs(session): document events, deprecated page and activation order Sync the Session README, implementation notes and follow upgrade guide, then regenerate the API, subsystem, persistence and event-graph catalogs. --- ...sion-history-and-event-transport.i18n.yaml | 4 +- ...-18-session-history-and-event-transport.md | 2 +- ...-session-history-and-event-transport.zh.md | 2 +- ...client-derived-tool-presentation.i18n.yaml | 4 +- ...-08-23-client-derived-tool-presentation.md | 4 +- ...-23-client-derived-tool-presentation.zh.md | 4 +- ...nd-projection-owned-client-state.i18n.yaml | 20 ++-- ...tions-and-projection-owned-client-state.md | 10 +- ...ns-and-projection-owned-client-state.zh.md | 10 +- ...ly-session-migration-preparation.i18n.yaml | 4 +- ...read-only-session-migration-preparation.md | 2 +- ...d-only-session-migration-preparation.zh.md | 2 +- ...sion-history-stream-and-snapshot.i18n.yaml | 28 +++++ ...-21-session-history-stream-and-snapshot.md | 59 ++++++++++ ...-session-history-stream-and-snapshot.zh.md | 59 ++++++++++ docs/config-catalog.md | 6 +- docs/config-catalog.zh.md | 6 +- docs/event-producer-consumer.md | 10 +- docs/event-producer-consumer.zh.md | 10 +- docs/persistence-catalog.i18n.yaml | 8 +- docs/persistence-catalog.md | 4 +- docs/persistence-catalog.zh.md | 4 +- docs/persistence-schema.json | 4 +- docs/subsystems/session.md | 48 +++++++- docs/subsystems/session.zh.md | 48 +++++++- docs/subsystems/typert.md | 8 ++ docs/subsystems/typert.zh.md | 8 ++ .../session-follow-activation/guide.i18n.yaml | 16 +++ .../session-follow-activation/guide.md | 21 ++++ .../session-follow-activation/guide.zh.md | 21 ++++ packages/api/gateway/README.i18n.yaml | 4 +- packages/api/gateway/README.md | 2 + packages/api/gateway/README.zh.md | 2 + .../api/session-controller/README.i18n.yaml | 4 +- packages/api/session-controller/README.md | 4 +- packages/api/session-controller/README.zh.md | 4 +- .../extensions/tool-cordis/src/api-catalog.ts | 104 +++++++++++++++++- scripts/gen-cordis-catalog.ts | 10 ++ scripts/no-unknown-casts.baseline.json | 3 - 39 files changed, 490 insertions(+), 83 deletions(-) create mode 100644 .agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.i18n.yaml create mode 100644 .agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.md create mode 100644 .agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.zh.md create mode 100644 docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.i18n.yaml create mode 100644 docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.md create mode 100644 docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.zh.md diff --git a/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.i18n.yaml index c0e4a6d3e3..716e573874 100644 --- a/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.i18n.yaml @@ -27,8 +27,8 @@ en: d5d0d6a57a4fa581 zh: 265973b157f957d9 /agent-note-session-history-control-state-and-remote-event-transport/decision/session-controller: - en: e408868a60ed4876 - zh: c6c930da77279f81 + en: f432480a52414d56 + zh: 15a3f175b69cdb53 /agent-note-session-history-control-state-and-remote-event-transport/decision/session-controller/activation-policy: en: 03e24cdee8519a92 zh: 82dc02eb26d7d7f4 diff --git a/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.md b/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.md index 45631eaf11..6be3de6fee 100644 --- a/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.md +++ b/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.md @@ -139,7 +139,7 @@ If a page request is canceled with its physical carrier generation, the journal `packages/api/session-controller` provides Host `ctx.sessionController` and the generated `ctx.remote.session` namespace. -It owns Session list, search, create, selectModel, rename, fork, prompt, attachment, updateQueue, cancel, page, follow, and control. The Host-generation model catalog is exposed separately through `session/modelCatalog` because it is not Session-specific. +It owns Session list, search, create, selectModel, rename, fork, prompt, attachment, updateQueue, cancel, `events`, the deprecated `page`, `follow`, `control`, plus `observeEvent`, `projections`, `observeProjections`, `state`, `observeState`, and `wait`. The Host-generation model catalog is exposed separately through `session/modelCatalog` because it is not Session-specific. The package separates agent, commands, control, history, and list controllers internally, but Session identity resolution, activation policy, subagent ownership, and Remote error projection have one public owner. diff --git a/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.zh.md b/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.zh.md index 46cc1d0b7a..454242df88 100644 --- a/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-18-session-history-and-event-transport.zh.md @@ -139,7 +139,7 @@ repair 期间旧 window 保持可读;page 与期间积累的 live entries 拼 `packages/api/session-controller` 提供 Host `ctx.sessionController` 与生成的 `ctx.remote.session` namespace。 -它拥有 Session list、search、create、selectModel、rename、fork、prompt、attachment、updateQueue、cancel、page、follow 与 control。Host generation 的 model catalog 通过独立的 `session/modelCatalog` 公开,因为它不属于特定 Session。 +它拥有 Session list、search、create、selectModel、rename、fork、prompt、attachment、updateQueue、cancel、`events`、已弃用的 `page`、`follow`、`control`,以及 `observeEvent`、`projections`、`observeProjections`、`state`、`observeState` 与 `wait`。Host generation 的 model catalog 通过独立的 `session/modelCatalog` 公开,因为它不属于特定 Session。 包内的 agent、commands、control、history 与 list controller 分开实现,但 Session 身份解析、激活策略、subagent ownership 和 Remote 错误投影只有一个公开 owner。 diff --git a/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.i18n.yaml index e70e858963..86b5f42ac4 100644 --- a/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.i18n.yaml @@ -51,8 +51,8 @@ en: 51f99cfca9c4c808 zh: ce95bab241d306f7 /agent-note-client-derived-presentation-from-raw-session-tool-events/host-design: - en: 16fd2b3e545ede21 - zh: 4d28f52132495441 + en: d5e5d1376dc42558 + zh: c2f302b2a5d1de39 /agent-note-client-derived-presentation-from-raw-session-tool-events/host-design/performance-constraints: en: 102b14e3eb9367ff zh: d391099dbc41db24 diff --git a/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.md b/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.md index 8a0c4ea6fc..8c32436c6a 100644 --- a/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.md +++ b/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.md @@ -195,9 +195,9 @@ The Client narrows `meta` locally at runtime. Renaming `presentationMeta` to mor ## Host Design -After obtaining source events, `SessionHistoryController.page()` performs only pagination and the existing projection-baseline calculation. Attached Sessions use the projection registry snapshot; detached Sessions use its restore path over the inspected log. History does not mount a preset to change the registered projection set. +After obtaining source events, `HistoryController.history()` performs only pagination and requests projections only for a subagent address that needs descriptor validation. Attached Sessions use the projection registry snapshot; detached Sessions use its restore path over the inspected log. History does not mount a preset to change the registered projection set. -`SessionHistoryController.follow()` retains listener-first setup, opening cursors, gap-free replay, live buffering, cancellation, and teardown. It maintains no additional state for tool events. +`WebController.follow()` retains listener-first setup, opening cursors, gap-free replay, live buffering, cancellation, and teardown. It maintains no additional state for tool events. The controller has no `presenterScopeFor()`, `viewFor()`, `backscanArgs()`, `parseToolCall()`, or `jsonView()` path. Page state contains no presenter scope or argument resolver; follow state contains no `openCalls`, `fallbackEvents`, or presentation argument resolver. Each page/follow event is wrapped only as `{event}` while addressing, ownership, cursor, sequence, and projection logic remains intact. diff --git a/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.zh.md b/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.zh.md index 2dd4ad8bc9..6ba3e040bd 100644 --- a/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.zh.md @@ -195,9 +195,9 @@ Client 对 `meta` 做局部运行时收窄。是否把 `presentationMeta` 改名 ## Host 端设计 -`SessionHistoryController.page()` 在取得 source events 后只执行分页与现有 projection baseline 计算。attached Session 使用 projection registry snapshot;detached Session 使用该 registry 对 inspected log 的 restore 路径。history 不通过挂载 preset 改变已注册的 projection 集合。 +`HistoryController.history()` 在取得 source events 后只执行分页,并且只有需要校验 descriptor 的 subagent 地址才请求投影。attached Session 使用 projection registry snapshot;detached Session 使用该 registry 对 inspected log 的 restore 路径。history 不通过挂载 preset 改变已注册的 projection 集合。 -`SessionHistoryController.follow()` 保留 listener-first、opening cursor、gap-free replay、live buffering、取消和 teardown;它不为工具事件维护额外状态。 +`WebController.follow()` 保留 listener-first、opening cursor、gap-free replay、live buffering、取消和 teardown;它不为工具事件维护额外状态。 Controller 不存在 `presenterScopeFor()`、`viewFor()`、`backscanArgs()`、`parseToolCall()` 或 `jsonView()` 路径。page state 不含 presenter scope 或参数 resolver;follow state 不含 `openCalls`、`fallbackEvents` 或 presentation 参数 resolver。每个 page/follow event 只包装成 `{event}`,地址、ownership、cursor、seq 与 projection 逻辑保持完整。 diff --git a/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.i18n.yaml index 0cce40f858..c67dff0722 100644 --- a/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.i18n.yaml @@ -15,17 +15,17 @@ en: 480284ae1a6ce210 zh: d42c72ada9f019f8 /agent-note-session-observations-and-projection-owned-client-state/decision/observation-is-the-point-read-unit: - en: fac92f8547482a49 - zh: 60240c47fbe4611f + en: 283136ae36512767 + zh: e342b446c77ae300 /agent-note-session-observations-and-projection-owned-client-state/decision/source-resolution-and-lifetime: - en: e550ae9892474276 - zh: fb6a2d9e91ebd4d9 + en: bced4b90cb03525d + zh: b0c1ca4bf1064f89 /agent-note-session-observations-and-projection-owned-client-state/decision/projection-execution-boundary: - en: 148de86941b90f41 - zh: c065a8e96e28b9d7 + en: b3b235fa0250868a + zh: 0bb5eedf14cdafee /agent-note-session-observations-and-projection-owned-client-state/decision/read-audiences: - en: f6cd715c8a0dc151 - zh: 3e1897ae49b19eb7 + en: e394e9480340f69c + zh: 7eea994ee9fa380d /agent-note-session-observations-and-projection-owned-client-state/decision/replayable-client-facts-are-projection-owned: en: efded09f0cd30a8e zh: 5e16580a39ff3359 @@ -48,8 +48,8 @@ en: 8d699dfc22ab5c5f zh: 8dcd9fc6bd1594db /agent-note-session-observations-and-projection-owned-client-state/verification: - en: df17217023668428 - zh: 88f7da4deffc6bf9 + en: 29f364d1031b7d85 + zh: 2b193ceb52fb0406 /agent-note-session-observations-and-projection-owned-client-state/alternatives-considered: en: 90574351058d5d8c zh: 6aa514cf47495ed2 diff --git a/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.md b/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.md index dd8c332fd1..530aeb36e1 100644 --- a/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.md +++ b/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.md @@ -46,7 +46,7 @@ flowchart LR `SessionQueryEngine.observeSession(sessionId, options)` returns a disposable `SessionObservation` containing one source kind, header, contiguous event prefix, cursor, optional projection snapshot, and the durable revision for a prepared source. An attached Session wins. Otherwise the reader's own prepared cache — keyed by `stat().revision` and pinned by observation leases — serves the cold Session, sharing one persistence read (`open(id, 'read')` + `read`) across concurrent observations, including an in-flight cold load. -Every owner disposes its observation. `retain()` creates another lease over the same cut, which lets `session.follow` publish a snapshot and then transfer that exact prepared source to background Agent promotion without rereading the log. A live Session that appears during cold resolution wins before publication; a disappeared live source is retried as cold. +Every owner disposes its observation. `retain()` creates another lease over the same cut, which lets `session.follow` transfer that exact prepared source to background Agent promotion before delivering the snapshot, without rereading the log. A live Session that appears during cold resolution wins before publication; a disappeared live source is retried as cold. ### Source resolution and lifetime @@ -56,7 +56,7 @@ Live preference is checked both before and after a cold borrow. The second check Persistence absence maps to Session-not-found only after no attached Session exists. Durable corruption, source-identity conflict, cancellation, and operational persistence failure remain distinct `SessionQueryError` outcomes so API owners can preserve their own public error vocabulary without duplicating source detection. -The observation owns no mutation authority. Its event array is an immutable prefix, and its prepared Session remains unpublished. Promotion is an explicit ownership transfer performed by the Session Controller after it has emitted the opening snapshot; other readers cannot turn an observation into a live Agent. +The observation owns no mutation authority. Its event array is an immutable prefix, and its prepared Session remains unpublished. Promotion is an explicit ownership transfer the Session Controller starts once the opening is computed, before delivering it; other readers cannot turn an observation into a live Agent. Projection work is deliberately `all | none`. `all` computes every registered projection at the observation's event cursor; `none` leaves projection state untouched. There is no per-key preparation state, `projectionKeys` mode, or cached `viewedState`/`viewedValue` layer. A publisher may filter the completed values for an audience, but the underlying observation is never partly projected. @@ -72,7 +72,7 @@ The registry owns fold state; each domain owns its `init`, `apply`, `view`, sche Corpus listing remains a separate lightweight operation. `listSessions()` returns live-preferred headers without materializing every log. Session list first uses live projection state or durable projection-cache rows. Subagent discovery reads parent-catalog projections through exact observations. Session list may take one complete observation for an individually stored artifact within its configured small-log limit when cached metadata cannot establish whether it is blank; a large or unreadable cache miss remains visible with unknown hints. -`session.follow` publishes a required opening snapshot containing header, cursor, the initial event window, and a complete projection baseline. Reconnect replaces the previous generation from another complete snapshot. `session.page` is reserved for older-history reads and gap repair. Observation-only reads never activate an Agent; only an ordinary follow may retain its prepared observation and request promotion after the opening snapshot has been delivered. +`session.follow` publishes a required opening snapshot containing header, cursor, the initial event window, and a complete projection baseline. Reconnect replaces the previous generation from another complete snapshot. `session.page` supports current or fixed-cut history reads, older-history reads, and gap repair. Observation-only reads never activate an Agent; only an activation-enabled ordinary Follow may retain its prepared observation and request promotion once the opening snapshot is computed, before it is delivered. The [snapshot and subscription decision](2026-10-21-session-history-stream-and-snapshot.md) defines the Controller composition and passive subscription semantics. ### Read audiences @@ -82,7 +82,7 @@ Each public operation chooses one query and projection policy. The choice is par |---|---|---|---| | `session.list` | Corpus headers, live state, and cached rows; bounded small-log fallback | Partial hints, or one full small-log observation | Never | | `session.search` | Corpus authorization plus the configured search provider | None for result listing | Never | -| `session.follow` | One exact observation | All, carried in the opening snapshot | Ordinary cold Session only, after snapshot delivery | +| `session.follow` | One exact observation | All, carried in the opening snapshot | Only with `activate: true`, for an ordinary cold Session once the opening is computed, before delivery | | `session.page` | One exact observation | None, except projection-backed subagent authorization | Never | | Fork source | One exact observation | None unless authorization requires it | Never for the source | | Attachment | Direct store read under the [image access rule](2026-10-23-store-scoped-image-reads.md) | None | Never | @@ -172,7 +172,7 @@ These rules apply to new Session-derived Client state even when a direct event s ## Verification -Persistence and SessionQuery tests pin shared cold loading, cancellation, live-source races, retained observations, disposal, and all-or-none projection calculation. Session Controller and Gateway tests pin snapshot-first opening, replacement reconnect, older-page reads, gap repair, list-cache hints, bounded small-log fallback, and promotion after snapshot delivery. +Persistence and SessionQuery tests pin shared cold loading, cancellation, live-source races, retained observations, disposal, and all-or-none projection calculation. Session Controller and Gateway tests pin snapshot-first opening, replacement reconnect, older-page reads, gap repair, list-cache hints, bounded small-log fallback, and promotion once the opening is computed. Client tests pin higher-sequence-wins projection storage, title updates, model catalog and selection readiness, preset roster refresh and Session-specific selection, and subagent loading without transient offline presentation. Subagent tests pin parent-catalog order, recursive traversal, branch diagnostics, cancellation, fork isolation, and no Agent activation during listing. diff --git a/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.zh.md b/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.zh.md index 7434603314..62ac9db852 100644 --- a/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-25-session-observations-and-projection-owned-client-state.zh.md @@ -46,7 +46,7 @@ flowchart LR `SessionQueryEngine.observeSession(sessionId, options)` 返回可 dispose(资源释放)的 `SessionObservation`,其中包含同一份 source kind、header、连续事件前缀、cursor、可选 projection snapshot,以及 prepared source 的持久化 revision。已挂载 Session 优先;否则由读取方自己的 prepared cache——以 `stat().revision` 为键、由 observation lease 固定——提供冷 Session,让并发 observation 共享同一次持久化读取(`open(id, 'read')` + `read`),包括尚未完成的冷加载。 -每个 owner 都会 dispose 自己的 observation。`retain()` 为同一切面创建另一份 lease,使 `session.follow` 能够先发布 snapshot,再把完全相同的 prepared source 转交给后台 Agent promotion,而无需重读日志。冷解析期间出现的 live Session 会在发布前胜出;已经消失的 live source 会按 cold source 重试。 +每个 owner 都会 dispose 自己的 observation。`retain()` 为同一切面创建另一份 lease,使 `session.follow` 能把完全相同的 prepared source 转交给后台 Agent promotion,并在交付 snapshot 前启动它,而无需重读日志。冷解析期间出现的 live Session 会在发布前胜出;已经消失的 live source 会按 cold source 重试。 ### 数据源解析与生命周期 @@ -56,7 +56,7 @@ flowchart LR 只有在不存在已挂载 Session 后,persistence absence 才映射为 Session-not-found。持久数据损坏、source identity 冲突、取消和 persistence 操作失败分别保留不同的 `SessionQueryError`,API owner 因而可以维持自身公开错误词汇,而不用重复数据源判定。 -Observation 不拥有任何 mutation 权限。其事件数组是不可变前缀,prepared Session 保持未发布。Promotion 是 Session Controller 在 opening snapshot 发出后执行的显式 ownership transfer;其他读方不能把 observation 变成 live Agent。 +Observation 不拥有任何 mutation 权限。其事件数组是不可变前缀,prepared Session 保持未发布。Promotion 是 Session Controller 在 opening 计算完成后、交付前启动的显式 ownership transfer;其他读方不能把 observation 变成 live Agent。 Projection 工作明确只有 `all | none` 两种模式。`all` 在 observation 的事件 cursor 上计算所有已注册 projection;`none` 完全不触碰 projection 状态。系统不存在按 key preparation 的状态、`projectionKeys` 模式或额外的 `viewedState`/`viewedValue` cache。发布方可以按 audience 筛选已完成的值,但底层 observation 不会处于只算完部分 projection 的状态。 @@ -72,7 +72,7 @@ Registry 拥有 fold state;各领域拥有自己的 `init`、`apply`、`view` 语料库 list 仍是独立的轻量操作。`listSessions()` 返回 live-preferred header,而不物化每份日志。Session list 先读取 live projection 状态或持久 projection-cache row。Subagent 发现通过精确 observation 读取父目录 projection。当 cache 无法判断 Session 是否为空,且该 Session 拥有的独立产物未超过配置的小日志限制时,Session list 可以执行一次完整 observation;大型或不可读的 cache miss 仍以 hints 未知但 row 可见的方式返回。 -`session.follow` 发布必需的 opening snapshot,其中包含 header、cursor、首个事件窗口和完整 projection baseline。重连使用另一份完整 snapshot 替换上一 generation。`session.page` 仅用于旧历史读取与 gap repair。只读 observation 不激活 Agent;只有普通 follow 可以保留 prepared observation,并在 opening snapshot 已交付后请求 promotion。 +`session.follow` 发布必需的 opening snapshot,包含 header、cursor、初始事件窗口与完整 projection baseline。重连通过另一份完整快照替换之前的 generation。`session.page` 支持当前或固定切点的历史读取、旧历史分页及缺口修复。只读 Observation 不激活 Agent;只有显式启用激活的普通 Follow 可以在开场计算完成后、交付之前 retain prepared observation 并请求提升。[快照与订阅决策](2026-10-21-session-history-stream-and-snapshot.zh.md)定义 Controller 组合和纯订阅语义。 ### 读取 audience @@ -82,7 +82,7 @@ Registry 拥有 fold state;各领域拥有自己的 `init`、`apply`、`view` |---|---|---|---| | `session.list` | Corpus header、live state 和 cached row;有界小日志 fallback | 部分 hints,或一次完整小日志 observation | 从不 | | `session.search` | Corpus 鉴权加已配置 search provider | 结果列表不计算 | 从不 | -| `session.follow` | 一份精确 observation | 全算,并由 opening snapshot 携带 | 仅普通 cold Session,且在 snapshot 交付后 | +| `session.follow` | 一份精确 observation | 全算,并由 opening snapshot 携带 | 仅 `activate: true` 的普通 cold Session,且在开场计算完成后、交付前 | | `session.page` | 一份精确 observation | 不计算,但 projection-backed subagent 鉴权除外 | 从不 | | Fork source | 一份精确 observation | 鉴权不要求时不计算 | source 从不激活 | | Attachment | 按[图片访问规则](2026-10-23-store-scoped-image-reads.zh.md)直接读取存储 | 不计算 | 从不 | @@ -172,7 +172,7 @@ Client 本地交互状态也继续留在本地:loading 和 error 状态、打 ## 验证 -Persistence 与 SessionQuery 测试固定共享冷加载、取消、live-source race、retained observation、dispose 和 all-or-none projection 计算。Session Controller 与 Gateway 测试固定 snapshot-first opening、replacement reconnect、旧分页读取、gap repair、list-cache hints、小日志有界 fallback,以及 snapshot 交付后的 promotion。 +Persistence 与 SessionQuery 测试固定共享冷加载、取消、live-source race、retained observation、dispose 和 all-or-none projection 计算。Session Controller 与 Gateway 测试固定 snapshot-first opening、replacement reconnect、旧分页读取、gap repair、list-cache hints、小日志有界 fallback,以及开场计算完成后的 promotion。 Client 测试固定 higher-sequence-wins projection store、title 更新、model catalog 与 selection readiness、preset roster refresh 与 Session 专属选择,以及不会短暂展示离线状态的 subagent loading。Subagent 测试固定父目录顺序、递归遍历、分支诊断、取消、fork 隔离,以及 listing 期间不激活 Agent。 diff --git a/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.i18n.yaml b/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.i18n.yaml index 93080791e0..bb7d9e396e 100644 --- a/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.i18n.yaml @@ -30,8 +30,8 @@ en: 9d2d50cb76754b74 zh: 9ceed3652475f18d /agent-note-historical-session-reads-prepare-before-write-publication/decision/follow-and-agent-promotion: - en: 692c29db3e7ab07e - zh: 7da0cfdbc80f407d + en: 301b18b0952f4896 + zh: 2e3941c35907d629 /agent-note-historical-session-reads-prepare-before-write-publication/problem-to-solution-mapping: en: e067e187cd4d0a8c zh: b0c79b635a637296 diff --git a/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.md b/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.md index 081044e34d..b0eeb270c0 100644 --- a/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.md +++ b/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.md @@ -102,7 +102,7 @@ No external caller can append before the handle exists. `append`, `flush`, and ` ### Follow and Agent promotion -`session.follow` opens history through the read path, restores the Session and projections, emits the opening snapshot, and then starts Agent promotion. Agent resume uses write open, so it waits for publication before the Agent accepts a new turn. History visibility and write readiness are separate timing points without introducing an unpublished append state. +`session.follow` opens history through the read path, restores the Session and projections, starts Agent promotion from the separately retained Observation, and then delivers the opening snapshot. Agent resume uses write open, so it waits for publication before the Agent accepts a new turn. History visibility and write readiness are separate timing points without introducing an unpublished append state. ## Problem-to-solution mapping diff --git a/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.zh.md b/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.zh.md index 7406e7cf31..2f17de348a 100644 --- a/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.zh.md +++ b/.agents/notes/implemented/architecture/2026-09-05-read-only-session-migration-preparation.zh.md @@ -102,7 +102,7 @@ Handle 返回前,外部 caller 无法 append。因此 `append`、`flush` 与 ` ### Follow 与 Agent promotion -`session.follow` 通过 read path 打开历史、恢复 Session 与 projections、发出 opening snapshot,然后启动 Agent promotion。Agent resume 使用 write open,因此会在 Agent 接收新一轮对话前等待 publication。历史可见与写入就绪成为两个明确时间点,同时不引入 unpublished append state。 +`session.follow` 通过 read path 打开历史、恢复 Session 与 projections,先用单独 retain 的 Observation 启动 Agent promotion,再交付 opening snapshot。Agent resume 使用 write open,因此会在 Agent 接收新一轮对话前等待 publication。历史可见与写入就绪成为两个明确时间点,同时不引入 unpublished append state。 ## 问题与方案对照 diff --git a/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.i18n.yaml b/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.i18n.yaml new file mode 100644 index 0000000000..9ae0452069 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.i18n.yaml @@ -0,0 +1,28 @@ +# Bilingual-pair consistency record for 2026-10-21-session-history-stream-and-snapshot.md (docs/i18n/README.md): per heading +# section, a hash of its English and Chinese blocks outside code blocks and generated regions. +# After editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.md +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation: + en: 0c9a7bc6591feb16 + zh: 3606a2c1caffd36f +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/problem: + en: ac1583e7ae1377f8 + zh: c60bdbda9ee89144 +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/decision: + en: 45c63df5dac389eb + zh: d72a5bcb94de22f1 +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/decision/reads-and-subscriptions: + en: 38df4f3c4fba2cc9 + zh: a34f3376faf26f0c +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/decision/follow-ordering-and-ownership: + en: 352ff87a3e9cd110 + zh: 4ac6366cecfc08a3 +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/decision/state-and-wait: + en: a87c7427582e6b03 + zh: b28d2a73b36eb27f +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/alternatives-considered: + en: c5fb06ab9df9e7ad + zh: b20adf151018111c +/agent-note-session-snapshots-passive-subscriptions-and-web-aggregation/consequences: + en: dc1da262b4911a31 + zh: 2a4e503696fc477b diff --git a/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.md b/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.md new file mode 100644 index 0000000000..b5e1112a18 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.md @@ -0,0 +1,59 @@ +# Agent Note: Session snapshots, passive subscriptions, and Web aggregation + +Status: implemented + +English | [中文](2026-10-21-session-history-stream-and-snapshot.zh.md) + +## Problem + +A point read, an event subscription, and a Web conversation opening have different lifetimes. Combining them inside one history controller makes passive observation perform unnecessary reads and gives each aggregate its own acquisition logic. Reading before subscribing also creates a gap that requires another read to repair. The APIs need independent operations that can compose without losing events or duplicating ownership. + +## Decision + +`SessionController` is the single Session Remote Service. It owns ordinary `HistoryController`, `StateController`, and `WebController` instances, not three additional Cordis Services or Remote namespaces. The implementation separates six operations: history snapshot and observation, projection snapshot and observation, and state snapshot and observation. Follow and Wait compose those capabilities for their callers; the existing `page` entry forwards to the history reader. + +### Reads and subscriptions + +History reads return chronological records, `hasMore`, and an inclusive cursor. An omitted `throughSeq` selects the observed log end; `beforeSeq` selects older records without changing that read cut. Projection reads return exact sequenced values, sequence-free cache hints when migration is required, or null when the Session is absent. Live projection reads avoid persistence metadata access. + +`usingObservation({ sessionId, projection }, signal, callback?)` acquires the existing disposable SessionObservation. A callback borrows it until the callback settles; without a callback the caller owns disposal. Ordinary history, state, and Wait output reads do not request projections. Follow, exact projection reads, and subagent history descriptor validation request them. No read activates an Agent implicitly. + +`observeEvent` and `observeProjections` install listeners without acquiring an Observation. Their initial `ready` confirms subscription, not a snapshot cursor, existence, parent-child validity, or Agent readiness. History establishes continuity from its first received event; projection updates replace individual keys and may share a sequence number. `observeState` instead begins with a complete state read and coalesces later Session and Agent invalidations. + +History, history observation, and Follow accept Address requests; projection and state operations accept Session IDs. All internal readers and listeners use Session IDs. History and Follow validate Address against their opening Observation at the Controller layer, including the existing subagent descriptor rules. Pure history observation does not acquire a read for entity validation. Gateway resource authorization remains independent: the registered Session resolver extracts the target ID from the request before access is decided. + +### Follow ordering and ownership + +Follow installs history and optional assistant listeners first, then acquires one projected Observation. It captures the assistant baseline and binding-local arrival ordinal synchronously, sets both cuts, publishes the opening snapshot, and consumes the shared output queue. History notifications at or before the snapshot cursor and assistant notifications at or before the ordinal are discarded at consumption. Later notifications remain ordered without a second history read, background merge pumps, or a tail repair introduced by the opening itself. + +`session/created` contributes constructor seed events through the same history buffer. The adapter retains the supplied Session and its captured end position, then reads that in-memory prefix when consumed; it does not acquire another Observation. Each binding owns its subscriptions; a shared output queue belongs to Follow rather than to either listener. + +Follow activates only when the caller passes `activate: true`; the Web Client does so explicitly. Background promotion starts once the opening is computed and before it is delivered, and does not promise Agent readiness. Ordinary promotion reuses the existing Agent controller and receives a separately retained Observation. Either Follow releases its opening Observation once the opening is computed, before yielding it; activation continues on the separately retained lease, so the cold entry's reference count drops to that lease alone. Subagent Sessions do not use ordinary promotion. + +### State and Wait + +State contains the event cursor, active and running flags, the complete readable queue or null, and pending-input kinds. It exposes neither a header nor an internal revision. Gateway owns unsettled Remote events; State samples their detached metadata and classifies approval, question, or other input without copying a request registry. + +Wait evaluates complete states, confirms active-Agent quiescence with `whenIdle`, and rejects stale observations using listener-local revisions and Agent/Session identity checks. Session and Agent events wake reads immediately; while waiting, a one-second recheck detects pending input that produces no such event. This avoids adding a Gateway change event, at the cost of polling and bounded sampling delay rather than instantaneous notification. `observeState` does not poll, so pending-only changes need another state invalidation to become visible there. + +Wait returns idle, input-required, or timeout with the last state it accepted and bounded assistant output. Output contains only `assistant/message` records in `(afterSeq, state.cursor]`, newest first, and reports truncation only when another eligible record exists. The caller's cancellation signal controls that output read independently of the expired wait deadline. A wait that accepts no state before its deadline fails instead of inventing a state. + +## Alternatives considered + +**Read history, then subscribe and repair the gap.** Subscription-before-read already captures opening-time increments. A second read adds acquisition and replay obligations without improving that ordering. + +**Give pure subscriptions an Observation or ready cursor.** These values conflate subscription readiness with an independently selected read cut. Callers that need both subscribe and buffer first, then read and discard covered increments. + +**Keep separate Remote Services for the implementation controllers.** The classes divide behavior, not external service identity. One Session Service owns their composition, resource policy, and Remote entry points. + +**Have Gateway interpret pending input or emit Session status.** Gateway only owns Remote event transport and unsettled-event metadata. State owns classification; Wait's periodic sampling avoids adding a transport notification solely for Session waiting. + +**Merge assistant and history with independent asynchronous pumps.** One caller-owned buffer retains cross-source arrival order without extra pump cancellation or queue ownership. Snapshot construction and per-binding buffering retain distinct lifetimes. + +## Consequences + +The standard reads and Web aggregate share one Observation acquisition path, while pure subscriptions remain read-free. The old combined History controller is removed; still-used pagination, validation, and wire helpers remain at their original path. Cancellation, consumer termination, failed opening reads, and Context disposal release subscriptions and owned leases without cancelling Agent execution. + +The [Observation decision](2026-08-25-session-observations-and-projection-owned-client-state.md) remains the authority for exact read cuts and projection derivation. The [history and Remote transport decision](2026-08-18-session-history-and-event-transport.md) retains ownership of Client reconnection and transport lifetimes. This decision refines Session API composition rather than replacing either broader decision. + +The migrated history, cold-read, and transport tests exercise the new classes, including cursor overlap, assistant ordinal cuts, sequence gaps, subagent validation, and teardown. Slow consumers can still retain queued notifications; silent dropping is not a supported recovery strategy. Independent completion-acknowledged activation is not implemented by these reads or by Follow's background activation option. diff --git a/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.zh.md b/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.zh.md new file mode 100644 index 0000000000..773ab039b3 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-21-session-history-stream-and-snapshot.zh.md @@ -0,0 +1,59 @@ +# Agent Note: Session 快照、纯订阅与 Web 聚合 + +Status: implemented + +[English](2026-10-21-session-history-stream-and-snapshot.md) | 中文 + +## Problem + +定点读取、事件订阅和 Web 会话开场具有不同的生命周期。把它们合并在同一个历史控制器中,会使被动观察执行不必要的读取,并让每个聚合各自维护获取数据的逻辑。先读后订阅还会产生需要再次读取来修复的缺口。接口需要相互独立的操作,使组合既不丢事件,也不重复资源所有权。 + +## Decision + +`SessionController` 是唯一的 Session Remote Service。它持有普通的 `HistoryController`、`StateController` 和 `WebController` 实例,而不是额外的三个 Cordis Service 或 Remote namespace。实现分离六个操作:历史快照与观察、投影快照与观察、状态快照与观察。Follow 和 Wait 为调用方组合这些能力;已有的 `page` 入口转发到历史读取器。 + +### 读取与订阅 + +历史读取返回时间正序的记录、`hasMore` 和包含末项的游标。省略 `throughSeq` 时选择观察到的日志末尾;`beforeSeq` 只选择更早的记录,不改变读取点位。投影读取返回精确的有序值、需要迁移时无序号的缓存提示,或在 Session 不存在时返回 null。live 投影读取不访问持久化元信息。 + +`usingObservation({ sessionId, projection }, signal, callback?)` 获取已有的可释放 SessionObservation。有回调时租约借给回调直到其结束;无回调时由调用方释放。普通历史、状态及 Wait 输出读取不请求投影。Follow、精确投影读取和子会话历史 descriptor 校验请求投影。读取不会隐式激活 Agent。 + +`observeEvent` 和 `observeProjections` 安装监听而不获取 Observation。首个 `ready` 确认订阅生效,不代表快照游标、实体存在、父子关系有效或 Agent 就绪。历史从首个收到的事件建立连续性;投影更新替换单个键,多个更新可以共享序号。`observeState` 则从完整状态读取开始,并合并后续 Session 和 Agent 失效通知。 + +历史、历史观察和 Follow 接收 Address 请求;投影和状态操作接收 Session ID。所有内部读取器和监听器都使用 Session ID。History 和 Follow 在 Controller 层以开场 Observation 校验 Address,包括已有的子会话 descriptor 规则。纯历史观察不为实体校验获取读取。Gateway 资源授权与之独立:注册的 Session 解析器在访问判定前从请求提取目标 ID。 + +### Follow 顺序与所有权 + +Follow 先安装历史和可选 assistant 监听,再获取一份带投影的 Observation。它同步捕获 assistant 基线和绑定局部的到达序号,设置两种截断点,发布开场快照,然后消费共享输出队列。消费时丢弃序号不超过快照游标的历史通知,以及到达序号不超过截断点的 assistant 通知。后续通知保持顺序,无需第二次历史读取、后台合并任务,或由开场自身引入的尾部修复。 + +`session/created` 经同一历史缓冲提供构造期种子事件。适配器保留收到的 Session 及捕获的末尾位置,在消费时读取对应内存前缀,不获取另一份 Observation。每个绑定拥有自己的订阅;共享输出队列属于 Follow,而不是任一监听器。 + +只有调用方传入 `activate: true` 时 Follow 才激活;Web Client 显式传入该参数。后台提升在开场计算完成后、交付之前启动,不承诺 Agent 已就绪。普通提升复用已有 Agent controller,并接收单独 retain 的 Observation。两种 Follow 都在开场计算完成后、交付前释放开场 Observation;激活则继续使用单独 retain 的租约,因此冷 entry 的引用计数只剩那一份。子会话不走普通提升。 + +### 状态与 Wait + +State 包含事件游标、active 与 running 标志、完整可读队列或 null,以及待输入种类。它不暴露 header 或内部 revision。Gateway 拥有未结算的 Remote 事件;State 采样独立元数据,将输入分类为 approval、question 或 other,不复制请求注册表。 + +Wait 判断完整状态,通过 `whenIdle` 确认活跃 Agent 已静止,并通过监听器局部 revision 和 Agent/Session 身份检查拒绝过时观察。Session 和 Agent 事件立即唤醒读取;等待期间每秒重查一次,检测没有产生上述事件的待输入请求。这避免新增 Gateway change 事件,代价是轮询和采样延迟,而非即时通知。`observeState` 不轮询,因此仅有 pending 变化时,需要另一项状态失效通知才会显示更新。 + +Wait 返回 idle、input-required 或 timeout,以及最后一次被接受的状态和有界 assistant 输出。输出仅包含 `(afterSeq, state.cursor]` 内从新到旧的 `assistant/message` 记录,只有存在另一条符合条件的记录时才报告截断。输出读取使用调用方的取消信号,不受已过期的等待截止信号控制。截止前没有任何状态通过校验的 wait 会失败,不构造虚假的状态。 + +## Alternatives considered + +**先读历史,再订阅并修复缺口。** 先订阅后读取已经捕获开场期间的增量。第二次读取增加资源获取和重放责任,却不改善这个顺序。 + +**给纯订阅提供 Observation 或 ready 游标。** 这会混淆订阅就绪和独立选取的读取点位。需要两者的调用方先订阅并缓冲,再读取并丢弃已覆盖增量。 + +**为各实现 Controller 保留独立 Remote Service。** 这些类划分行为,而不是外部服务身份。一个 Session Service 拥有其组合、资源策略和 Remote 入口。 + +**让 Gateway 解释待输入状态或发送 Session status。** Gateway 只拥有 Remote 事件传输和未结算事件元数据。State 拥有分类;Wait 定期采样,避免仅为 Session 等待增加传输通知。 + +**用独立异步任务合并 assistant 与历史。** 调用方拥有的单个缓冲保留跨来源到达顺序,不引入额外任务取消或队列所有权。快照构造和各绑定缓冲仍保留不同生命周期。 + +## Consequences + +标准读取和 Web 聚合共享同一 Observation 获取路径,纯订阅不读取数据。旧的合并 History controller 已删除;仍使用的分页、校验和 wire 辅助函数留在原路径。取消、消费者结束、开场读取失败和 Context 释放都会释放订阅及拥有的租约,而不取消 Agent 执行。 + +[Observation 决策](2026-08-25-session-observations-and-projection-owned-client-state.zh.md)仍拥有精确读取点位和投影派生规则。[历史与 Remote 传输决策](2026-08-18-session-history-and-event-transport.zh.md)继续拥有 Client 重连和传输生命周期。本决策细化 Session API 组合,而不取代上述更广泛的决策。 + +迁移后的历史、冷读取和传输测试覆盖新类,包括游标重叠、assistant 到达序号截断、序号缺口、子会话校验和释放。慢消费者仍可能积累队列通知;静默丢弃不是支持的恢复策略。这些读取以及 Follow 的后台激活选项均未实现独立的、确认完成后返回的激活接口。 diff --git a/docs/config-catalog.md b/docs/config-catalog.md index eda51827f8..b29fffaa2d 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -203,7 +203,7 @@ export interface Config { ## `@deepseek-ai/dsh-api-gateway` - `inject`: `typert` · `remoteAccess` -- `source`: [`packages/api/gateway/src/index.ts:156`](../packages/api/gateway/src/index.ts) +- `source`: [`packages/api/gateway/src/index.ts:158`](../packages/api/gateway/src/index.ts) ```ts config-catalog /** Gateway transport configuration. */ @@ -242,8 +242,8 @@ export interface Config { ## `@deepseek-ai/dsh-api-session-controller` -- `inject`: `agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `fs` · `llm` · `remoteAccess` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `workspaceRegistry` -- `source`: [`packages/api/session-controller/src/index.ts:109`](../packages/api/session-controller/src/index.ts) +- `inject`: `agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `fs` · `llm` · `remoteAccess` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `typertGateway` · `workspaceRegistry` +- `source`: [`packages/api/session-controller/src/index.ts:110`](../packages/api/session-controller/src/index.ts) ```ts config-catalog /** Session Controller deployment policy. */ diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index a91d43209c..76e5f4150c 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -205,7 +205,7 @@ export interface Config { ## `@deepseek-ai/dsh-api-gateway` - `inject`: `typert` · `remoteAccess` -- `source`: [`packages/api/gateway/src/index.ts:156`](../packages/api/gateway/src/index.ts) +- `source`: [`packages/api/gateway/src/index.ts:158`](../packages/api/gateway/src/index.ts) ```ts config-catalog /** Gateway transport configuration. */ @@ -244,8 +244,8 @@ export interface Config { ## `@deepseek-ai/dsh-api-session-controller` -- `inject`: `agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `fs` · `llm` · `remoteAccess` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `workspaceRegistry` -- `source`: [`packages/api/session-controller/src/index.ts:109`](../packages/api/session-controller/src/index.ts) +- `inject`: `agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `fs` · `llm` · `remoteAccess` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `typertGateway` · `workspaceRegistry` +- `source`: [`packages/api/session-controller/src/index.ts:110`](../packages/api/session-controller/src/index.ts) ```ts config-catalog /** Session Controller deployment policy. */ diff --git a/docs/event-producer-consumer.md b/docs/event-producer-consumer.md index 9941bcc53b..0bc825c2dd 100644 --- a/docs/event-producer-consumer.md +++ b/docs/event-producer-consumer.md @@ -21,11 +21,11 @@ This matrix shows which packages dispatch each harness-owned event and which pac | `agent/request-error` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:389`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compaction-basic`](../packages/compaction/compaction-basic), [`compaction-image-offload`](../packages/compaction/compaction-image-offload), [`llm-retry`](../packages/llm/llm-retry) | | `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:309`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `agent-team`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), `server`, `session-controller` | | `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:417`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`workspace-changes`](../packages/deliverables/workspace-changes) | -| `api-session/activity` | `emit` | [`packages/api/session-controller/src/types.ts:602`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/added` | `emit` | [`packages/api/session-controller/src/types.ts:582`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/error` | `emit` | [`packages/api/session-controller/src/types.ts:609`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:588`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:595`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/activity` | `emit` | [`packages/api/session-controller/src/types.ts:686`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/added` | `emit` | [`packages/api/session-controller/src/types.ts:666`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/error` | `emit` | [`packages/api/session-controller/src/types.ts:693`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:672`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:679`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | | `app-boot/config-reload` | `emit` | [`packages/boot/app-boot/src/index.ts:53`](../packages/boot/app-boot/src/index.ts) | [`app-boot`](../packages/boot/app-boot) (`emit`) | [`settings`](../packages/settings/settings) | | `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:87`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes`, `server` | | `authorization/settled` | `emit` | [`packages/credentials/authorization/src/index.ts:57`](../packages/credentials/authorization/src/index.ts) | [`authorization`](../packages/credentials/authorization) (`events.dispatch`) | - | diff --git a/docs/event-producer-consumer.zh.md b/docs/event-producer-consumer.zh.md index ef50bc058a..083e84ad7f 100644 --- a/docs/event-producer-consumer.zh.md +++ b/docs/event-producer-consumer.zh.md @@ -23,11 +23,11 @@ | `agent/request-error` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:389`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compaction-basic`](../packages/compaction/compaction-basic), [`compaction-image-offload`](../packages/compaction/compaction-image-offload), [`llm-retry`](../packages/llm/llm-retry) | | `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:309`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `agent-team`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), `server`, `session-controller` | | `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:417`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), [`hooks-codex`](../packages/experimental/hooks-codex), [`workspace-changes`](../packages/deliverables/workspace-changes) | -| `api-session/activity` | `emit` | [`packages/api/session-controller/src/types.ts:602`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/added` | `emit` | [`packages/api/session-controller/src/types.ts:582`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/error` | `emit` | [`packages/api/session-controller/src/types.ts:609`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:588`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | -| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:595`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/activity` | `emit` | [`packages/api/session-controller/src/types.ts:686`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/added` | `emit` | [`packages/api/session-controller/src/types.ts:666`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/error` | `emit` | [`packages/api/session-controller/src/types.ts:693`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:672`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | +| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:679`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` | | `app-boot/config-reload` | `emit` | [`packages/boot/app-boot/src/index.ts:53`](../packages/boot/app-boot/src/index.ts) | [`app-boot`](../packages/boot/app-boot) (`emit`) | [`settings`](../packages/settings/settings) | | `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:87`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes`, `server` | | `authorization/settled` | `emit` | [`packages/credentials/authorization/src/index.ts:57`](../packages/credentials/authorization/src/index.ts) | [`authorization`](../packages/credentials/authorization) (`events.dispatch`) | - | diff --git a/docs/persistence-catalog.i18n.yaml b/docs/persistence-catalog.i18n.yaml index 58ae5924b7..4ec686df63 100644 --- a/docs/persistence-catalog.i18n.yaml +++ b/docs/persistence-catalog.i18n.yaml @@ -1350,8 +1350,8 @@ en: 2786fef560851bb4 zh: 5d787475356b2606 /session-persistence-event-catalog/resolved-persistence-types/string: - en: 1525c04d0ebfc56e - zh: 902d37c1de80bfe7 + en: 1e12d380c4988d40 + zh: 14a781104e00f360 /session-persistence-event-catalog/resolved-persistence-types/string~2: en: 0089620bf4638263 zh: 1922bef1713094bb @@ -1857,8 +1857,8 @@ en: 5a0bbf4c76266ac5 zh: 0b20854f90f9d74d /session-persistence-event-catalog/resolved-persistence-types/kind-user: - en: 1dd9740285c43aff - zh: 093fab99146cac11 + en: e98b716228feb157 + zh: 2bb593ae9cd0ce0d /session-persistence-event-catalog/resolved-persistence-types/kind-user-approval: en: a52d2dfbaf844127 zh: 4c5306ca40f20873 diff --git a/docs/persistence-catalog.md b/docs/persistence-catalog.md index e35438504e..8dbd3621ac 100644 --- a/docs/persistence-catalog.md +++ b/docs/persistence-catalog.md @@ -5600,7 +5600,7 @@ Array of `number`. SHA-256: `4cd48f3e5108bd6ebedf7301c3638839b8b2b9db8dbd493974177fbdeb91a01b` -Sources: [`packages/api/session-controller/src/types.ts:382`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:21`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:21`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:33`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:9`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/webhook/src/brand.ts:12`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:6`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:9`](../packages/experimental/webhook/src/brand.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/jobs/jobs/src/brand.ts:19`](../packages/jobs/jobs/src/brand.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts) +Sources: [`packages/api/session-controller/src/types.ts:386`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:21`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:21`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:33`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:9`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/webhook/src/brand.ts:12`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:6`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:9`](../packages/experimental/webhook/src/brand.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/jobs/jobs/src/brand.ts:19`](../packages/jobs/jobs/src/brand.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts) `string` @@ -7656,7 +7656,7 @@ Sources: [`packages/core/tools/src/index.ts:28`](../packages/core/tools/src/inde SHA-256: `6dacb1584f2bfbe209dc6b6f578d51da6d55595f64d0e63c727c98f359278def` -Sources: [`packages/api/session-controller/src/types.ts:391`](../packages/api/session-controller/src/types.ts) +Sources: [`packages/api/session-controller/src/types.ts:395`](../packages/api/session-controller/src/types.ts) | Property | Presence | Type | |---|---|---| diff --git a/docs/persistence-catalog.zh.md b/docs/persistence-catalog.zh.md index 4c76a104f1..e28c70c102 100644 --- a/docs/persistence-catalog.zh.md +++ b/docs/persistence-catalog.zh.md @@ -5602,7 +5602,7 @@ SHA-256: `5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78` SHA-256: `4cd48f3e5108bd6ebedf7301c3638839b8b2b9db8dbd493974177fbdeb91a01b` -来源:[`packages/api/session-controller/src/types.ts:382`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:21`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:21`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:33`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:9`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/webhook/src/brand.ts:12`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:6`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:9`](../packages/experimental/webhook/src/brand.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/jobs/jobs/src/brand.ts:19`](../packages/jobs/jobs/src/brand.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts) +来源:[`packages/api/session-controller/src/types.ts:386`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:21`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:21`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:33`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:9`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/webhook/src/brand.ts:12`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:6`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:9`](../packages/experimental/webhook/src/brand.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/jobs/jobs/src/brand.ts:19`](../packages/jobs/jobs/src/brand.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts) `string` @@ -7658,7 +7658,7 @@ SHA-256: `8fcb0b44a575e998665c053643d1ab04c82f39253ebd190ac0c975b78e40b543` SHA-256: `6dacb1584f2bfbe209dc6b6f578d51da6d55595f64d0e63c727c98f359278def` -来源:[`packages/api/session-controller/src/types.ts:391`](../packages/api/session-controller/src/types.ts) +来源:[`packages/api/session-controller/src/types.ts:395`](../packages/api/session-controller/src/types.ts) | 属性 | 存在性 | 类型 | |---|---|---| diff --git a/docs/persistence-schema.json b/docs/persistence-schema.json index 141b5bab03..d70bd19123 100644 --- a/docs/persistence-schema.json +++ b/docs/persistence-schema.json @@ -249,7 +249,7 @@ {"digest":"4b259f7f8f0a44ad5e90b70a73553ced1df27012d126921d397ff403b6c86731","names":["packages/llm/llm/src/message.ts#ToolResultMessage"],"sources":["packages/llm/llm/src/message.ts:173"]}, {"digest":"4b7ddaf3710b88ff9b8df66304f5f97bf03688fd19730eedc2e9535203c820ea","names":[],"sources":[]}, {"digest":"4bb451330ff699f36b45539ceb0eb2606ead72084e2c5bb637c36cc80e2252db","names":[],"sources":["packages/core/session/src/types.ts:198"]}, - {"digest":"4cd48f3e5108bd6ebedf7301c3638839b8b2b9db8dbd493974177fbdeb91a01b","names":["packages/api/session-controller/src/types.ts#SessionRequestId","packages/attachment/attachment/src/brand.ts#AttachmentId","packages/compaction/compaction/src/brand.ts#CompactionId","packages/core/session/src/types.ts#SessionId","packages/experimental/agent-team/src/types.ts#TeamId","packages/experimental/agent-team/src/types.ts#TeamMessageId","packages/experimental/agent-team/src/types.ts#TeamTaskId","packages/experimental/webhook/src/brand.ts#WebhookDeliveryId","packages/experimental/webhook/src/brand.ts#WebhookRuleId","packages/experimental/webhook/src/brand.ts#WebhookSourceId","packages/feedback/message-feedback/src/types.ts#MessageFeedbackVersion","packages/goal/goal/src/types.ts#GoalId","packages/interaction/commands/src/brand.ts#CommandId","packages/interaction/user-approval/src/types.ts#ApprovalRequestId","packages/jobs/jobs/src/brand.ts#JobId","packages/llm/llm-retry/src/brand.ts#RetryId","packages/llm/llm/src/brand.ts#MessageId","packages/llm/llm/src/brand.ts#ProviderRequestId","packages/llm/llm/src/brand.ts#ReasoningEffortId","packages/llm/llm/src/brand.ts#ToolCallId","packages/schedule/schedule/src/types.ts#ScheduleId","packages/session/session-title/src/index.ts#SessionTitleProviderId","packages/session/session-title/src/types.ts#SessionTitleProviderId","packages/workflow/workflow/src/types.ts#WorkflowRunId"],"sources":["packages/api/session-controller/src/types.ts:382","packages/attachment/attachment/src/brand.ts:6","packages/compaction/compaction/src/brand.ts:4","packages/core/session/src/types.ts:21","packages/experimental/agent-team/src/types.ts:21","packages/experimental/agent-team/src/types.ts:33","packages/experimental/agent-team/src/types.ts:9","packages/experimental/webhook/src/brand.ts:12","packages/experimental/webhook/src/brand.ts:6","packages/experimental/webhook/src/brand.ts:9","packages/feedback/message-feedback/src/types.ts:14","packages/goal/goal/src/types.ts:17","packages/interaction/commands/src/brand.ts:31","packages/interaction/user-approval/src/types.ts:17","packages/jobs/jobs/src/brand.ts:19","packages/llm/llm-retry/src/brand.ts:4","packages/llm/llm/src/brand.ts:16","packages/llm/llm/src/brand.ts:31","packages/llm/llm/src/brand.ts:43","packages/llm/llm/src/brand.ts:67","packages/schedule/schedule/src/types.ts:14","packages/session/session-title/src/index.ts:42","packages/session/session-title/src/types.ts:17","packages/workflow/workflow/src/types.ts:13"]}, + {"digest":"4cd48f3e5108bd6ebedf7301c3638839b8b2b9db8dbd493974177fbdeb91a01b","names":["packages/api/session-controller/src/types.ts#SessionRequestId","packages/attachment/attachment/src/brand.ts#AttachmentId","packages/compaction/compaction/src/brand.ts#CompactionId","packages/core/session/src/types.ts#SessionId","packages/experimental/agent-team/src/types.ts#TeamId","packages/experimental/agent-team/src/types.ts#TeamMessageId","packages/experimental/agent-team/src/types.ts#TeamTaskId","packages/experimental/webhook/src/brand.ts#WebhookDeliveryId","packages/experimental/webhook/src/brand.ts#WebhookRuleId","packages/experimental/webhook/src/brand.ts#WebhookSourceId","packages/feedback/message-feedback/src/types.ts#MessageFeedbackVersion","packages/goal/goal/src/types.ts#GoalId","packages/interaction/commands/src/brand.ts#CommandId","packages/interaction/user-approval/src/types.ts#ApprovalRequestId","packages/jobs/jobs/src/brand.ts#JobId","packages/llm/llm-retry/src/brand.ts#RetryId","packages/llm/llm/src/brand.ts#MessageId","packages/llm/llm/src/brand.ts#ProviderRequestId","packages/llm/llm/src/brand.ts#ReasoningEffortId","packages/llm/llm/src/brand.ts#ToolCallId","packages/schedule/schedule/src/types.ts#ScheduleId","packages/session/session-title/src/index.ts#SessionTitleProviderId","packages/session/session-title/src/types.ts#SessionTitleProviderId","packages/workflow/workflow/src/types.ts#WorkflowRunId"],"sources":["packages/api/session-controller/src/types.ts:386","packages/attachment/attachment/src/brand.ts:6","packages/compaction/compaction/src/brand.ts:4","packages/core/session/src/types.ts:21","packages/experimental/agent-team/src/types.ts:21","packages/experimental/agent-team/src/types.ts:33","packages/experimental/agent-team/src/types.ts:9","packages/experimental/webhook/src/brand.ts:12","packages/experimental/webhook/src/brand.ts:6","packages/experimental/webhook/src/brand.ts:9","packages/feedback/message-feedback/src/types.ts:14","packages/goal/goal/src/types.ts:17","packages/interaction/commands/src/brand.ts:31","packages/interaction/user-approval/src/types.ts:17","packages/jobs/jobs/src/brand.ts:19","packages/llm/llm-retry/src/brand.ts:4","packages/llm/llm/src/brand.ts:16","packages/llm/llm/src/brand.ts:31","packages/llm/llm/src/brand.ts:43","packages/llm/llm/src/brand.ts:67","packages/schedule/schedule/src/types.ts:14","packages/session/session-title/src/index.ts:42","packages/session/session-title/src/types.ts:17","packages/workflow/workflow/src/types.ts:13"]}, {"digest":"4e011753f8263f436efaabfbb3b4db53a98fc55342c5ded2daf7208b217be159","names":[],"sources":[]}, {"digest":"4e44c9118152f6829634bfd508e47669ab0497caffa380c94b4be91f9390d35d","names":[],"sources":[]}, {"digest":"4e887768586528565381dadbddee6cef555874148089f4579e0b4b1ad096fc9c","names":["packages/llm/llm/src/types.ts#TextBlock"],"sources":["packages/llm/llm/src/types.ts:62","packages/web/web-search-deepseek/src/provider.ts:66"]}, @@ -333,7 +333,7 @@ {"digest":"6ccb6bc423fb3952458abf9c1b1c3284208b7e660344b612cc55da773d61afe4","names":[],"sources":[]}, {"digest":"6cda0d6d3b4336d83998fe580628426df81c2afbab5d768b8813b56d569120e8","names":[],"sources":[]}, {"digest":"6cf082d0fb6034dea61636787ff0ddf43b6e59aad71e644435a479bc9b83ad65","names":[],"sources":[]}, - {"digest":"6dacb1584f2bfbe209dc6b6f578d51da6d55595f64d0e63c727c98f359278def","names":[],"sources":["packages/api/session-controller/src/types.ts:391"]}, + {"digest":"6dacb1584f2bfbe209dc6b6f578d51da6d55595f64d0e63c727c98f359278def","names":[],"sources":["packages/api/session-controller/src/types.ts:395"]}, {"digest":"6e52dd55a1d48954ed5464ec46fe34d9eb65f709baabc9561e7a279910b0c406","names":[],"sources":["packages/preset/agent-preset-registry/src/session.ts:31"]}, {"digest":"6ea608bdc8a7a63d3d23b84c49721325094db88d136482e43a820945295eee3e","names":[],"sources":[]}, {"digest":"6ebcc2dbec9f2dabca9f668ae6d39e877899b180740570f453409db339221df3","names":[],"sources":[]}, diff --git a/docs/subsystems/session.md b/docs/subsystems/session.md index df7aa39899..7cbc91298d 100644 --- a/docs/subsystems/session.md +++ b/docs/subsystems/session.md @@ -960,11 +960,51 @@ workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | /** * Read one cold-safe, message-aligned Session history page. - * @param request - durable address, backward cursor, and page budget. + * @param request - durable address, optional fixed cut, backward cursor, and page budget. * @param signal - cancellation for persistence reads. - * @returns one chronological page. + * @returns one chronological page with its inclusive cursor. */ -@Remote('page') page(request: SessionPageRequest, signal: AbortSignal): Promise +@Remote events(request: SessionPageRequest, signal: AbortSignal): Promise + +/** + * Subscribe to Session events without reading a snapshot. + * @param request - Session address. + * @param signal - subscription cancellation. + * @returns readiness and subsequent events, without a snapshot. + */ +@Remote({ mode: 'stream' }) observeEvent(request: SessionObserveEventRequest, signal: AbortSignal): AsyncIterable + +/** + * Subscribe to sparse Session projection changes. + * @param request - target Session. + * @param signal - subscription cancellation. + * @returns readiness and sparse projection changes. + */ +@Remote({ mode: 'stream' }) observeProjections(request: SessionProjectionsRequest, signal: AbortSignal): AsyncIterable + +/** + * Read passive Session state. + * @param request - target Session. + * @param signal - read cancellation. + * @returns current passive state. + */ +@Remote state(request: SessionStateRequest, signal: AbortSignal): Promise + +/** + * Subscribe to complete Session state replacements. + * @param request - target Session. + * @param signal - subscription cancellation. + * @returns complete passive state replacements. + */ +@Remote({ mode: 'stream' }) observeState(request: SessionStateRequest, signal: AbortSignal): AsyncIterable + +/** + * Wait for Session quiescence or pending input with bounded assistant output. + * @param request - Session, wait bounds and output window. + * @param signal - caller cancellation. + * @returns stopping state and bounded assistant output. + */ +@Remote wait(request: SessionWaitRequest, signal: AbortSignal): Promise /** * Follow one Session log from its opening or resume cursor. @@ -981,7 +1021,7 @@ workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | * @param signal - cancellation for the Session read. * @returns a sequenced baseline, cached hints when migration is deferred, or null when absent. */ -@Remote('projections') async projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise +@Remote('projections') projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise /** * Stream a complete live-control baseline followed by replacement frames. diff --git a/docs/subsystems/session.zh.md b/docs/subsystems/session.zh.md index c2bc413691..1f40042967 100644 --- a/docs/subsystems/session.zh.md +++ b/docs/subsystems/session.zh.md @@ -964,11 +964,51 @@ workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | /** * Read one cold-safe, message-aligned Session history page. - * @param request - durable address, backward cursor, and page budget. + * @param request - durable address, optional fixed cut, backward cursor, and page budget. * @param signal - cancellation for persistence reads. - * @returns one chronological page. + * @returns one chronological page with its inclusive cursor. */ -@Remote('page') page(request: SessionPageRequest, signal: AbortSignal): Promise +@Remote events(request: SessionPageRequest, signal: AbortSignal): Promise + +/** + * Subscribe to Session events without reading a snapshot. + * @param request - Session address. + * @param signal - subscription cancellation. + * @returns readiness and subsequent events, without a snapshot. + */ +@Remote({ mode: 'stream' }) observeEvent(request: SessionObserveEventRequest, signal: AbortSignal): AsyncIterable + +/** + * Subscribe to sparse Session projection changes. + * @param request - target Session. + * @param signal - subscription cancellation. + * @returns readiness and sparse projection changes. + */ +@Remote({ mode: 'stream' }) observeProjections(request: SessionProjectionsRequest, signal: AbortSignal): AsyncIterable + +/** + * Read passive Session state. + * @param request - target Session. + * @param signal - read cancellation. + * @returns current passive state. + */ +@Remote state(request: SessionStateRequest, signal: AbortSignal): Promise + +/** + * Subscribe to complete Session state replacements. + * @param request - target Session. + * @param signal - subscription cancellation. + * @returns complete passive state replacements. + */ +@Remote({ mode: 'stream' }) observeState(request: SessionStateRequest, signal: AbortSignal): AsyncIterable + +/** + * Wait for Session quiescence or pending input with bounded assistant output. + * @param request - Session, wait bounds and output window. + * @param signal - caller cancellation. + * @returns stopping state and bounded assistant output. + */ +@Remote wait(request: SessionWaitRequest, signal: AbortSignal): Promise /** * Follow one Session log from its opening or resume cursor. @@ -985,7 +1025,7 @@ workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | * @param signal - cancellation for the Session read. * @returns a sequenced baseline, cached hints when migration is deferred, or null when absent. */ -@Remote('projections') async projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise +@Remote('projections') projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise /** * Stream a complete live-control baseline followed by replacement frames. diff --git a/docs/subsystems/typert.md b/docs/subsystems/typert.md index 9838c8c82d..1fe31a9918 100644 --- a/docs/subsystems/typert.md +++ b/docs/subsystems/typert.md @@ -444,6 +444,8 @@ interface TypertGateway { * @returns whether an owner stream is open and has not been cancelled. */ hasLiveClient(): boolean + /** @returns detached metadata for all unsettled forwarded events in arrival order. */ + getPendingRemoteEvents(): readonly PendingRemoteEventInfo[] /** * Register the application-selected forwarded-event source. * @param source - stream factory installed by the Remote assembly. @@ -664,6 +666,12 @@ Resolve strict generated definitions or conservative SRC markers against current */ hasLiveClient(): boolean +/** + * Inspect unsettled forwarded events without changing their lifetime. + * @returns detached event names and Agent identities. + */ +getPendingRemoteEvents(): readonly PendingRemoteEventInfo[] + /** * Register the sole application-selected forwarded-event source. * @param source - stream factory installed by the Remote assembly. diff --git a/docs/subsystems/typert.zh.md b/docs/subsystems/typert.zh.md index 2cbdaf4a2c..840825979e 100644 --- a/docs/subsystems/typert.zh.md +++ b/docs/subsystems/typert.zh.md @@ -444,6 +444,8 @@ interface TypertGateway { * @returns whether an owner stream is open and has not been cancelled. */ hasLiveClient(): boolean + /** @returns detached metadata for all unsettled forwarded events in arrival order. */ + getPendingRemoteEvents(): readonly PendingRemoteEventInfo[] /** * Register the application-selected forwarded-event source. * @param source - stream factory installed by the Remote assembly. @@ -664,6 +666,12 @@ Resolve strict generated definitions or conservative SRC markers against current */ hasLiveClient(): boolean +/** + * Inspect unsettled forwarded events without changing their lifetime. + * @returns detached event names and Agent identities. + */ +getPendingRemoteEvents(): readonly PendingRemoteEventInfo[] + /** * Register the sole application-selected forwarded-event source. * @param source - stream factory installed by the Remote assembly. diff --git a/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.i18n.yaml b/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.i18n.yaml new file mode 100644 index 0000000000..8e84c0dcab --- /dev/null +++ b/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.i18n.yaml @@ -0,0 +1,16 @@ +# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading +# section, a hash of its English and Chinese blocks outside code blocks and generated regions. +# After editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.md +/: + en: 789ee06aa8932a32 + zh: d465eb26824f2b4b +/request-activation-when-following-a-session: + en: 25bd54a8216b1c71 + zh: edaa12b04713528a +/request-activation-when-following-a-session/change: + en: d4021672fedcbfb7 + zh: 35d5e76a69301e4a +/request-activation-when-following-a-session/migration: + en: aa22d72ca3f91d38 + zh: ebe991eca4bf74c2 diff --git a/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.md b/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.md new file mode 100644 index 0000000000..cb01f8e90e --- /dev/null +++ b/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.md @@ -0,0 +1,21 @@ +--- +kind: upgrade-guide +description: "Session follow callers must explicitly request background Agent activation." +--- +# Request activation when following a Session + +English | [中文](guide.zh.md) + +## Change + +`session.follow` no longer automatically resumes a cold ordinary Agent when `activate` is omitted. It reads the opening snapshot and follows subsequent events without activation. This affects integrations that used opening a history stream to make an Agent available. The shipped Web Client sends `activate: true` explicitly and retains its opening behavior. + +With `activate: true`, activation starts once the opening snapshot is computed, before it is delivered; that snapshot does not acknowledge Agent readiness. Subagent Sessions still do not use ordinary Agent activation. + +## Migration + +1. Add `activate: true` to `session.follow` requests that must resume a cold ordinary Agent. Keep the existing `address` and history-window fields. +2. For passive viewers, omit `activate` or set it to `false`. +3. Verify that an activation-enabled stream still returns its opening snapshot, then check Agent availability separately. Do not treat receipt of the snapshot as completion of activation. + +See the [Session Controller reference](../../../../packages/api/session-controller/README.md) for history and state observation behavior. diff --git a/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.zh.md b/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.zh.md new file mode 100644 index 0000000000..5df6e523a3 --- /dev/null +++ b/docs/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.zh.md @@ -0,0 +1,21 @@ +--- +kind: upgrade-guide +description: "Session follow 调用方必须显式请求后台 Agent 激活。" +--- +# 跟随 Session 时显式请求激活 + +[English](guide.md) | 中文 + +## 变更 + +`session.follow` 在省略 `activate` 时不再自动恢复冷普通 Agent。它只读取开场快照并跟随后续事件,不进行激活。这会影响通过打开历史流使 Agent 可用的集成。随产品提供的 Web Client 显式发送 `activate: true`,保留原有打开行为。 + +设置 `activate: true` 时,激活在开场快照计算完成后、交付之前开始;该快照不确认 Agent 已就绪。子会话仍不走普通 Agent 激活。 + +## 迁移 + +1. 为需要恢复冷普通 Agent 的 `session.follow` 请求添加 `activate: true`,保留原有 `address` 和历史窗口字段。 +2. 被动查看器可以省略 `activate` 或设为 `false`。 +3. 确认启用激活的流仍返回开场快照,再单独检查 Agent 是否可用。不要把收到快照当作激活完成。 + +历史与状态观察行为见 [Session Controller 参考](../../../../packages/api/session-controller/README.zh.md)。 diff --git a/packages/api/gateway/README.i18n.yaml b/packages/api/gateway/README.i18n.yaml index a9ddbc70b5..eb3352e60d 100644 --- a/packages/api/gateway/README.i18n.yaml +++ b/packages/api/gateway/README.i18n.yaml @@ -15,8 +15,8 @@ en: d9859219cdb0f367 zh: 2a3cfa8cb786e327 /deepseek-ai-dsh-api-gateway/host-service-typertgatewayservice-ctx-key-typertgateway: - en: b35573c6707d00d9 - zh: 619bbba900b0fb8f + en: 6ee072ffebd2eb38 + zh: 6a8723d13f443d51 /deepseek-ai-dsh-api-gateway/client-service-clientremote-ctx-key-remote: en: 0916113cdbe794fb zh: 14893c2cba95bfd6 diff --git a/packages/api/gateway/README.md b/packages/api/gateway/README.md index 6518441122..fea754c891 100644 --- a/packages/api/gateway/README.md +++ b/packages/api/gateway/README.md @@ -34,6 +34,8 @@ Every call names the Peer it speaks for: `InvokeRemoteRequest.peer` and the `pee Resources are read from validated arguments: Typert-compiled codecs drop undeclared object fields, while SRC fallback checks JSON safety without stripping them; lookup and Context identities keep their wire values. For each resource kind, a reader in the method's `@Remote({ resources })` or `@RemoteScope(key, { resources })` options wins; it is called with the method's positional arguments, where lookup positions hold wire identities and the cancellation position holds the call's signal, and is read from the class metadata of the root Service instance. Otherwise every lookup parameter whose provider declares that kind through `resource` contributes its wire identity, an omitted optional one contributing none, and a Context method whose Host Context adapter declares that kind contributes its Context identity, read from the arguments before the Context is resolved. Otherwise the kind's declaration in `typert.resources` supplies either a default field or a synchronous resolver. A field reads a top-level argument of that name or, failing that, the first object argument. A resolver is called once with `{ args, parameters }`: named validated wire values and ordered parameter descriptions containing `name` and `wire`. Both defaults return one identity or `undefined`; arrays are invalid. An explicit reader may return several identities. A resolver or reader that throws, a reader returning an empty list, or an identity, including a Context identity, that is not a non-empty string makes the resolution `invalid`; a call that names no resource touches the `global` resource alone, and a call that names resources touches only those. A forwarded event carries every resource its entry declares, so there a reader returning `undefined` also makes the resolution `invalid`, while an entry without readers touches `global`. +`getPendingRemoteEvents()` returns detached event-name and Agent-ID metadata for currently unsettled forwarded events in arrival order. It neither exposes request bodies nor changes event lifetimes, and it does not provide a change notification. + A cancellation-aware Remote method declares `signal: AbortSignal` as its final Host parameter. The signal is descriptor metadata rather than a wire argument: Connection supplies it to the Gateway, and the Gateway injects it after decoded business parameters. SRC recognizes the reserved final name, while strict generation additionally requires the global `AbortSignal` type. A stream Remote uses `@Remote({ mode: 'stream' })` and returns an `Iterable` or `AsyncIterable`. `ctx.typertGateway.stream()` applies the same endpoint, argument, lookup, and cancellation checks as unary invocation, then returns a cancellation-aware iterable over the business items. The Client opens the Gateway-owned `/api/remote.mux` WebSocket when its plugin activates and keeps it connected while idle. Connection owns the retry schedule; before each retry it asks the mux to cancel any candidate or active socket and make exactly one fresh physical attempt. The Host sends Ping control frames at the configured `websocketHeartbeatIntervalMs` interval (two seconds by default), and the browser answers Pong at the WebSocket protocol layer, so idle network intermediaries see traffic without any Remote stream frame. A Pong, any received frame, or a downlink write that does not complete at once counts as peer activity; with the default `'deflate'`, a frame whose JSON text reaches the compression threshold is deflated asynchronously, so its completion always counts. A socket with no activity across two Ping intervals is terminated, so a congested link that delays the Pong behind data stays connected. With `websocketCompression` at its `'deflate'` default, an upgrade that offers `permessage-deflate` negotiates the extension, and the Host compresses its own outbound frames whose JSON text reaches 1,024 characters; shorter frames stay uncompressed, uplink frames are compressed at the peer's discretion, and `'none'` accepts the same upgrades without the extension. Independently cancellable logical streams share that socket; an in-process Connection carrier provides equivalent streams directly without opening it. diff --git a/packages/api/gateway/README.zh.md b/packages/api/gateway/README.zh.md index 34759301dd..1dad623204 100644 --- a/packages/api/gateway/README.zh.md +++ b/packages/api/gateway/README.zh.md @@ -34,6 +34,8 @@ Connection 可用时,Host 入口会在 Connection 共享的 `/api` FetchHandle 资源从已校验参数中读取:Typert 编译 codec 会移除未声明的对象字段,SRC fallback 只检查 JSON 安全性而不移除字段;lookup 与 Context 身份保持 wire 值。对每个资源种类,方法 `@Remote({ resources })` 或 `@RemoteScope(key, { resources })` options 中的读取函数优先;它以方法的位置参数调用(lookup 位为 wire 身份,取消参数位为调用的 signal),从根 Service 实例的类元数据读取。否则 provider 经 `resource` 声明了该种类的每个 lookup 参数贡献其 wire 身份,省略的可选 lookup 参数不贡献;Host Context adapter 声明了该种类的 Context 方法贡献其 Context 身份,在解析 Context 之前直接从参数读取。再否则使用该种类在 `typert.resources` 中登记的默认字段或同步 resolver。字段规则读取同名顶层参数,没有时读取第一个对象参数的同名字段。resolver 以 `{ args, parameters }` 调用一次:命名的已校验 wire 值,以及包含 `name`、`wire` 的有序参数描述。两种默认规则均返回单个身份或 `undefined`,数组无效。显式读取函数可以返回多个身份。resolver 或读取函数抛错、读取函数返回空列表、或某个身份(含 Context 身份)不是非空字符串时,解析结果为 `invalid`;不指明任何资源的调用只访问 `global` 资源,指明了资源的调用只访问这些资源。转发事件携带其条目声明的每个资源,因此在事件路径上读取函数返回 `undefined` 同样使解析结果为 `invalid`,而没有读取函数的条目访问 `global`。 +`getPendingRemoteEvents()` 按到达顺序返回当前未结算转发事件的独立元数据,仅含事件名和 Agent ID。它不暴露请求正文,不改变事件生命周期,也不提供变化通知。 + 支持取消的 Remote 方法会把 `signal: AbortSignal` 声明为最后一个 Host 参数。signal 是 descriptor 元数据,而不是 wire 参数:Connection 将它提供给 Gateway,Gateway 则在已解码的业务参数之后注入它。SRC 识别这个保留的末位参数名,严格生成还要求它具有全局 `AbortSignal` 类型。 流式 Remote 使用 `@Remote({ mode: 'stream' })` 并返回 `Iterable` 或 `AsyncIterable`。`ctx.typertGateway.stream()` 执行与一元调用相同的 endpoint、参数、lookup 和取消校验,再返回可取消的业务项 iterable。Client 插件激活时打开 Gateway 自有的 `/api/remote.mux` WebSocket,并让它在空闲时保持连接。Connection 拥有重试调度;每次 retry 前,它要求 mux 取消候选或活动 socket,并且只做一次全新的物理连接尝试。Host 按配置的 `websocketHeartbeatIntervalMs` 间隔(默认 2 秒)发送 Ping 控制帧,浏览器在 WebSocket 协议层自动回复 Pong,使空闲网络中间层持续看到流量,而不新增 Remote 流帧。Pong、收到的任意帧,或未一次性完成的下行写入,都视为对端活动;默认 `'deflate'` 下,JSON 文本达到压缩阈值的帧异步 deflate,因此其完成总是计入。连续两个 Ping 间隔没有活动的 socket 会被终止,因此 Pong 被数据阻塞在拥塞链路上时连接仍会保持。`websocketCompression` 保持默认的 `'deflate'` 时,携带 `permessage-deflate` 的升级会协商该扩展,Host 压缩自己发出的、JSON 文本达到 1024 个字符 的帧;更短的帧不压缩,上行帧是否压缩由对端决定,设为 `'none'` 时接受同样的升级但不带该扩展。可独立取消的逻辑流共享这条连接;进程内 Connection 载体直接提供等价的流,不打开该 WebSocket。 diff --git a/packages/api/session-controller/README.i18n.yaml b/packages/api/session-controller/README.i18n.yaml index d6dd4c810c..a9ca9616e5 100644 --- a/packages/api/session-controller/README.i18n.yaml +++ b/packages/api/session-controller/README.i18n.yaml @@ -15,8 +15,8 @@ en: 1fdf707322fb6996 zh: 0204f7e9d4aa3cce /session-controller/use-this-package: - en: 17778cfd84635f2b - zh: 8fa20e050e607ad9 + en: 6bbd371bb1907ad1 + zh: 03a1b13862404c14 /session-controller/client-references: en: 41bdda1ac32df558 zh: aa5d0e325924066b diff --git a/packages/api/session-controller/README.md b/packages/api/session-controller/README.md index deb143b3d9..708479b2b3 100644 --- a/packages/api/session-controller/README.md +++ b/packages/api/session-controller/README.md @@ -35,7 +35,9 @@ The Client journal validates current Session event envelopes before publishing f Each endpoint states its activation policy. List reads only stored headers and projection-cache rows: it never calls per-session stat or opens a cold Session body. A current-format cache identity may supply every list hint; a lifecycle-matching predecessor cache may supply only its version-compatible title as a stale display fact, never as an authoritative fold seed. Search, history pages, log following, skill discovery, and workspace-path opening can inspect persistence without activating an Agent; `canOpenWorkspacePath()` reports native-opening availability without addressing a Session. Cancellation requires live state; queue mutation, model, rename, prompt, and file-reference operations may resolve or resume an ordinary Session. Prompt rejects content with neither non-whitespace text nor an attachment before resolving the Agent or appending Session events; queue edits accept only non-empty text content. Prompt admission consumes opaque receipts from the injected [`fileUploads`](../../client/file-upload/README.md) Host service and resolves every same-Agent receipt before sending the complete ordered content list through `ctx.attachments`. A receipt names a staged file or a staged image, and an image receipt subjects the prompt to the same image-input check as an encoded image. Prompt retries whose `requestId` is already queued or logged return the original acceptance without inserting another message. Create and fork are the only operations that create a new Agent directly. The service applies one preset-aware resume policy and subagent ownership fence to its own methods and to the Typert Agent and Session lookups used by other Remote namespaces. Queue mutation has one narrow exception: a live child whose current projected identity is continuable and comes from its own non-seed suffix accepts the ordinary Edit, Remove, and QueueDock Steer actions across both inbox destinations. One-shot, missing, unknown, corrupt, seed-only, or cold children remain rejected without resume. The skill catalog uses a live Agent's effective working directory and scoped registry when present. Cold listing uses the projected current directory, falling back to the recorded origin and then the configured directory default. It retains the preset standing scope without activating an Agent. The authenticated delivery routes use `workspaceDesktop()` for the serving Host name and file-manager behavior. `openWorkspacePath({ path, action: "reveal" })` delegates file-manager navigation to the native adapter; omitting `action` opens the file-type association, including HTML and SVG. Both operations require the composed filesystem to map the requested Host path to the same canonical process path; unmapped remote paths are refused before a native command runs. `session.projections` normally reads an exact baseline, including current-format cold logs, and returns `kind: sequenced`. Only a read requiring migration returns `kind: migration-required` hints without `asOfSeq`; missing keys remain absent. It returns null for a missing Session. Fork callers may set `allowMigration: false` to receive `session/migration-required` instead of starting source migration; omission retains automatic migration. The Client exposes shared values and explicit-read state through `projectionsBySession`; domains select their own keys. Session-list summaries carry `agentAvailable`, updated through existing summary and status events independently of durable projections. Sequenced reads and live projection frames use the same sequence ordering; cached reads fill hints without replacing sequenced values. -Every Remote endpoint is access-controlled: a Peer whose principal is not the owner reaches an endpoint only when, on every resource the call touches, a binding of that principal kind's policy in [`dsh-api-remote-access`](../remote-access/README.md) grants a role listing the action ([Peer principals Agent Note](../../../.agents/notes/implemented/architecture/2026-10-12-peer-principal-and-remote-access.md)). The controller injects `remoteAccess` and registers a default resolver for the `session` resource kind through `typert.resources`. It reads a named `sessionId` parameter, otherwise the first object argument's `sessionId` or `address`; unrelated string parameters name no Session. An object containing both `sessionId` and `address` is invalid, even when they name the same Session. `session/page` and `session/follow` use this resolver to read `address.sessionId` for an ordinary Session address and `address.childSessionId` for a subagent address; whether access to the parent Session covers its children is the policy's rule. `session/projections` reads the Session resource from `request.sessionId`, so a reconnecting reader reloads only the projections of Sessions it may read. `session/list`, `session/search`, and `session/control` read no resource, so their calls touch the `global` resource and need a `global` role; for a non-owner caller, `session/list` returns only the rows, `session/search` only the hits, and `session/control` only the baseline projections and projection frames, whose Session `ctx.remoteAccess.allows()` admits for the same action, so that action also belongs to a `session` role; owner results are unfiltered. `session/prompt` builds the durable `user-rpc` message source in its Remote method and records `principal` only for a non-owner caller, read through `principalOf(this.ctx.invocation)`; a source without `principal` belongs to the owner. +Every Remote endpoint is access-controlled: a Peer whose principal is not the owner reaches an endpoint only when, on every resource the call touches, a binding of that principal kind's policy in [`dsh-api-remote-access`](../remote-access/README.md) grants a role listing the action ([Peer principals Agent Note](../../../.agents/notes/implemented/architecture/2026-10-12-peer-principal-and-remote-access.md)). The controller injects `remoteAccess` and registers a default resolver for the `session` resource kind through `typert.resources`. It reads a named `sessionId` parameter, otherwise the first object argument's `sessionId` or `address`; unrelated string parameters name no Session. An object containing both `sessionId` and `address` is invalid, even when they name the same Session. `session/events`, the deprecated `session/page`, `session/observeEvent`, and `session/follow` use this resolver to read `address.sessionId` for an ordinary Session address and `address.childSessionId` for a subagent address; whether access to the parent Session covers its children is the policy's rule. `session/projections`, `session/observeProjections`, `session/state`, `session/observeState`, and `session/wait` read the Session resource from `request.sessionId`, so each call and subscription names only the Sessions it may read. `session/list`, `session/search`, and `session/control` read no resource, so their calls touch the `global` resource and need a `global` role; for a non-owner caller, `session/list` returns only the rows, `session/search` only the hits, and `session/control` only the baseline projections and projection frames, whose Session `ctx.remoteAccess.allows()` admits for the same action, so that action also belongs to a `session` role; owner results are unfiltered. `session/prompt` builds the durable `user-rpc` message source in its Remote method and records `principal` only for a non-owner caller, read through `principalOf(this.ctx.invocation)`; a source without `principal` belongs to the owner. + +`events` reads one chronological page from a durable cut and returns its records, `hasMore`, and an inclusive `cursor`; omitting `throughSeq` selects the observed log end, and the compatible `page` method carries the same read with a deprecated entry point. `events`, `observeEvent`, and `follow` take an Address; projection and state operations take a Session ID. Page reads and Follow openings validate the supplied Address. Pure `observeEvent` and `observeProjections` subscriptions neither acquire an Observation nor establish existence: their `ready` frame carries no snapshot cursor. List rows carry `formatStatus` when available, so Clients can identify migration-required Sessions without requesting their projections. diff --git a/packages/api/session-controller/README.zh.md b/packages/api/session-controller/README.zh.md index de28026522..b64f424d4d 100644 --- a/packages/api/session-controller/README.zh.md +++ b/packages/api/session-controller/README.zh.md @@ -35,7 +35,9 @@ Client journal 在发布 follow 快照、live entry 或历史页之前验证当 每个 endpoint 都声明自己的激活策略。列表只读取持久化 header 与 projection cache row,绝不调用逐 Session stat 或打开冷 Session body。当前格式 cache identity 可以提供全部列表 hint;生命周期匹配的 predecessor cache 只能提供版本兼容的 title,作为可能过时的展示事实,绝不能作为权威 fold seed。搜索、历史页、日志跟随、skill 发现和工作区路径打开可以在不激活 Agent 的情况下检查 persistence;`canOpenWorkspacePath()` 无需指定 Session 即可报告原生打开能力。取消要求 live 状态;queue 变更、模型、重命名、prompt 和文件引用操作可以解析或恢复普通 Session。提示词会在解析 Agent 或追加 Session 事件前,拒绝既没有非空白文本也没有附件的 content;queue edit 只接受非空文本 content。prompt 准入从注入的 [`fileUploads`](../../client/file-upload/README.zh.md) Host 服务取得不透明凭证,在把完整有序内容列表交给 `ctx.attachments` 前解析每个属于同一 Agent 的凭证。凭证指向一个暂存文件或一张暂存图片;图片凭证与编码图片一样要经过图片输入检查。`requestId` 已进入 queue 或日志时,prompt 重试直接返回原来的接受结果,不会重复插入消息。只有 create 与 fork 会直接创建新 Agent。该服务把同一套感知 preset 的恢复策略和 subagent ownership fence 同时用于自身方法,以及其他 Remote namespace 使用的 Typert Agent 与 Session lookup。Queue 变更只有一个狭窄例外:当前 projection identity 为 continuable 且来自自身非 seed suffix 的在线 child,可以在两个 inbox 目标上使用普通 Edit、Remove 与 QueueDock Steer action。One-shot、缺失、未知、损坏、仅含 seed identity 或冷 child 继续被拒绝,且不会恢复。skill 目录优先使用已有 live Agent 的有效工作目录与限定范围内的注册表。冷态列表使用投影中的当前目录,依次回退到记录的起始目录与配置的默认目录。它保留 preset 常驻 scope,不会激活 Agent。经过鉴权的文件交付路由通过 `workspaceDesktop()` 获取提供服务的 Host 名称和文件管理器行为。`openWorkspacePath({ path, action: "reveal" })` 将文件管理器导航委托给原生适配器;省略 `action` 时按文件类型关联打开,包括 HTML 和 SVG。两种操作都要求当前文件系统将请求的 Host 路径映射到同一个规范进程路径;无法映射的远端路径会在执行原生命令之前被拒绝。 `session.projections` 正常读取准确基线,包括当前格式的冷日志,返回 `kind: sequenced`。只有需要迁移时才返回不带 `asOfSeq` 的 `kind: migration-required` 提示,缺少的键保持缺席。Session 不存在时返回 null。Fork 调用者可设置 `allowMigration: false`,在源历史需要迁移时收到 `session/migration-required`;省略则保持自动迁移。Client 通过 `projectionsBySession` 暴露共享值和显式读取状态,由领域选择自身的 key。Session 列表摘要携带 `agentAvailable`,通过已有摘要与状态事件更新,与持久化 projection 相互独立。有序读取与实时 projection 帧使用相同的序号排序规则;缓存读取只补充提示,不替换有序值。 -每个 Remote 端点都受访问控制:principal 不是 owner 的 Peer 只有在本次调用访问的每个资源上,该 principal kind 在 [`dsh-api-remote-access`](../remote-access/README.zh.md) 中的 policy 都有某个 binding 授予列出该 action 的 role 时,才能调用该端点([Peer 身份属性 Agent Note](../../../.agents/notes/implemented/architecture/2026-10-12-peer-principal-and-remote-access.zh.md))。控制器注入 `remoteAccess`,并经 `typert.resources` 为 `session` 资源种类登记默认 resolver。它读取具名 `sessionId` 参数,否则读取第一个对象参数的 `sessionId` 或 `address`;无关字符串参数不指明 Session。对象同时包含 `sessionId` 和 `address` 时无效,即使两者指向同一 Session。`session/page` 与 `session/follow` 使用该 resolver:对普通 Session 地址读 `address.sessionId`,对 subagent 地址读 `address.childSessionId`;父会话的访问权是否覆盖其子会话由 policy 决定。`session/projections` 从 `request.sessionId` 读取会话资源,因此重连的读者只会重新读取它可读的会话的 projections。`session/list`、`session/search` 与 `session/control` 不读取资源,其调用访问 `global` 资源,需要 `global` role;对非 owner 调用方,`session/list` 只返回其 Session 被 `ctx.remoteAccess.allows()` 按同一 action 允许的行,`session/search` 只返回这类 Session 的命中,`session/control` 也只返回这类 Session 的 baseline projection 与 projection 帧,因此该 action 也要列在 `session` role 中;owner 的结果不过滤。`session/prompt` 在其 Remote 方法内构造持久的 `user-rpc` 消息 source,且只为非 owner 调用方记录经 `principalOf(this.ctx.invocation)` 读取的 `principal`;不带 `principal` 的 source 属于 owner。 +每个 Remote 端点都受访问控制:principal 不是 owner 的 Peer 只有在本次调用访问的每个资源上,该 principal kind 在 [`dsh-api-remote-access`](../remote-access/README.zh.md) 中的 policy 都有某个 binding 授予列出该 action 的 role 时,才能调用该端点([Peer 身份属性 Agent Note](../../../.agents/notes/implemented/architecture/2026-10-12-peer-principal-and-remote-access.zh.md))。控制器注入 `remoteAccess`,并经 `typert.resources` 为 `session` 资源种类登记默认 resolver。它读取具名 `sessionId` 参数,否则读取第一个对象参数的 `sessionId` 或 `address`;无关字符串参数不指明 Session。对象同时包含 `sessionId` 和 `address` 时无效,即使两者指向同一 Session。`session/events`、已弃用的 `session/page`、`session/observeEvent` 与 `session/follow` 使用该 resolver:对普通 Session 地址读 `address.sessionId`,对 subagent 地址读 `address.childSessionId`;父会话的访问权是否覆盖其子会话由 policy 决定。`session/projections`、`session/observeProjections`、`session/state`、`session/observeState` 与 `session/wait` 从 `request.sessionId` 读取会话资源,因此每次调用与订阅都只点名它可读的会话。`session/list`、`session/search` 与 `session/control` 不读取资源,其调用访问 `global` 资源,需要 `global` role;对非 owner 调用方,`session/list` 只返回其 Session 被 `ctx.remoteAccess.allows()` 按同一 action 允许的行,`session/search` 只返回这类 Session 的命中,`session/control` 也只返回这类 Session 的 baseline projection 与 projection 帧,因此该 action 也要列在 `session` role 中;owner 的结果不过滤。`session/prompt` 在其 Remote 方法内构造持久的 `user-rpc` 消息 source,且只为非 owner 调用方记录经 `principalOf(this.ctx.invocation)` 读取的 `principal`;不带 `principal` 的 source 属于 owner。 + +`events` 从一个持久切点读取一页时间正序的记录,返回记录、`hasMore` 和包含末项的 `cursor`;省略 `throughSeq` 时选取观察到的日志末尾,兼容的 `page` 方法提供同样的读取,但入口已弃用。`events`、`observeEvent` 和 `follow` 接收 Address,投影和状态操作接收 Session ID。分页读取与 Follow 开场会校验传入的 Address。纯 `observeEvent` 和 `observeProjections` 订阅既不获取 Observation,也不确认实体存在:其 `ready` 帧不携带快照游标。 列表行在状态可用时携带 `formatStatus`,Client 无需请求其投影即可识别需要迁移的 Session。 diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index 1c74bdf612..5435897986 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -2361,10 +2361,40 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [ returns: 'acknowledgement that cancellation was requested.', }, { - signature: '@Remote(\'page\') page(request: SessionPageRequest, signal: AbortSignal): Promise', + signature: '@Remote events(request: SessionPageRequest, signal: AbortSignal): Promise', description: 'Read one cold-safe, message-aligned Session history page.', - parameters: [{ name: 'request', description: 'durable address, backward cursor, and page budget.' }, { name: 'signal', description: 'cancellation for persistence reads.' }], - returns: 'one chronological page.', + parameters: [{ name: 'request', description: 'durable address, optional fixed cut, backward cursor, and page budget.' }, { name: 'signal', description: 'cancellation for persistence reads.' }], + returns: 'one chronological page with its inclusive cursor.', + }, + { + signature: '@Remote({ mode: \'stream\' }) observeEvent(request: SessionObserveEventRequest, signal: AbortSignal): AsyncIterable', + description: 'Subscribe to Session events without reading a snapshot.', + parameters: [{ name: 'request', description: 'Session address.' }, { name: 'signal', description: 'subscription cancellation.' }], + returns: 'readiness and subsequent events, without a snapshot.', + }, + { + signature: '@Remote({ mode: \'stream\' }) observeProjections(request: SessionProjectionsRequest, signal: AbortSignal): AsyncIterable', + description: 'Subscribe to sparse Session projection changes.', + parameters: [{ name: 'request', description: 'target Session.' }, { name: 'signal', description: 'subscription cancellation.' }], + returns: 'readiness and sparse projection changes.', + }, + { + signature: '@Remote state(request: SessionStateRequest, signal: AbortSignal): Promise', + description: 'Read passive Session state.', + parameters: [{ name: 'request', description: 'target Session.' }, { name: 'signal', description: 'read cancellation.' }], + returns: 'current passive state.', + }, + { + signature: '@Remote({ mode: \'stream\' }) observeState(request: SessionStateRequest, signal: AbortSignal): AsyncIterable', + description: 'Subscribe to complete Session state replacements.', + parameters: [{ name: 'request', description: 'target Session.' }, { name: 'signal', description: 'subscription cancellation.' }], + returns: 'complete passive state replacements.', + }, + { + signature: '@Remote wait(request: SessionWaitRequest, signal: AbortSignal): Promise', + description: 'Wait for Session quiescence or pending input with bounded assistant output.', + parameters: [{ name: 'request', description: 'Session, wait bounds and output window.' }, { name: 'signal', description: 'caller cancellation.' }], + returns: 'stopping state and bounded assistant output.', }, { signature: '@Remote({ mode: \'stream\' }) follow(request: SessionFollowRequest, signal: AbortSignal): AsyncIterable', @@ -2373,7 +2403,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [ returns: 'a complete opening snapshot followed by gap-free durable event frames and optional cursorless assistant-stream frames.', }, { - signature: '@Remote(\'projections\') async projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise', + signature: '@Remote(\'projections\') projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise', description: 'Read exact projections, returning cached hints only when migration is required.', parameters: [{ name: 'request', description: 'Session whose current values are required.' }, { name: 'signal', description: 'cancellation for the Session read.' }], returns: 'a sequenced baseline, cached hints when migration is deferred, or null when absent.', @@ -3766,6 +3796,12 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [ parameters: [], returns: 'whether an owner stream is open and has not been cancelled.', }, + { + signature: 'getPendingRemoteEvents(): readonly PendingRemoteEventInfo[]', + description: 'Inspect unsettled forwarded events without changing their lifetime.', + parameters: [], + returns: 'detached event names and Agent identities.', + }, { signature: 'registerRemoteEvents( source: TypertRemoteEventSource, host: RemoteEventHostInfo, ): () => Promise', description: 'Register the sole application-selected forwarded-event source.', @@ -6688,6 +6724,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'PendingModule', declaration: 'export interface PendingModule {\n url: string;\n reason: \'host-module\' | \'unmanaged-plugin\' | \'module-comparison\';\n}', }, + { + name: 'PendingRemoteEventInfo', + declaration: 'export interface PendingRemoteEventInfo {\n readonly event: string;\n readonly agentId: RemoteEventAgentId;\n}', + }, { name: 'PermissionCatalog', declaration: 'export interface PermissionCatalog {\n options: PresetOption[];\n defaultOptions: PresetOption[];\n defaultPreset: string;\n}', @@ -7108,6 +7148,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'RemoteErrorDetailsMap', declaration: 'export interface RemoteErrorDetailsMap {\n \'gateway/bad-request\': {\n readonly issues?: readonly object[];\n };\n \'gateway/cancelled\': {};\n \'gateway/internal\': {};\n}', }, + { + name: 'RemoteEventAgentId', + declaration: 'export type RemoteEventAgentId = Branded<\'RemoteEventAgentId\'>;', + }, { name: 'RemoteEventHostInfo', declaration: 'export interface RemoteEventHostInfo {\n readonly home: string;\n}', @@ -7456,6 +7500,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionEventEntry', declaration: 'export interface SessionEventEntry {\n readonly type: \'event\';\n readonly event: SessionWireEvent;\n}', }, + { + name: 'SessionEventFrame', + declaration: 'export type SessionEventFrame = {\n readonly type: \'ready\';\n} | SessionEventEntry;', + }, { name: 'SessionEventMap', declaration: 'export interface SessionEventMap {\n \'turn/start\': {\n turn: number;\n };\n \'turn/end\': {\n turn: number;\n reason: TurnEndReason;\n };\n \'step/start\': {\n turn: number;\n step: number;\n };\n \'step/end\': {\n turn: number;\n step: number;\n };\n \'user/message\': UserMessage;\n \'developer/message\': {\n turn: number;\n step: number;\n message: DeveloperMessage;\n headerSeq?: SessionSeq;\n };\n \'system/message\': {\n turn: number;\n step: number;\n message: SystemMessage;\n };\n \'assistant/message\': {\n turn: number;\n step: number;\n message: AssistantMessage;\n stream: AssistantStreamRecord[];\n usage?: TokenUsage;\n interrupted?: true;\n };\n \'assistant/attempt\': {\n turn: number;\n step: number;\n stream: AssistantStreamRecord[];\n };\n \'tool/call\': {\n turn: number;\n step: number;\n callId: ToolCallId;\n name: string;\n arguments: string;\n };\n \'tool/result\': {\n turn: number;\n step: number;\n message: ToolResultMessage;\n error?: {\n name: string;\n code: string;\n reason?: string;\n };\n meta?: JsonValue;\n };\n \'request/header\': {\n header: EpochHeader;\n reason: RequestHeaderReason;\n startsSeries?: true;\n };\n \'request/context\': RequestContext;\n \'session/end-seed\': {\n /* …truncated — full shape in source */', @@ -7492,6 +7540,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionEventSearchRequest', declaration: 'export interface SessionEventSearchRequest {\n sessionId: SessionId;\n query: string;\n filters?: readonly SessionEventMetadataFilter[];\n limit?: number;\n cursor?: SessionSearchCursor;\n}', }, + { + name: 'SessionEventsPage', + declaration: 'export interface SessionEventsPage extends SessionPage {\n readonly cursor: number;\n}', + }, { name: 'SessionEventSurface', declaration: 'export type SessionEventSurface = \'current\' | \'shadowed\' | \'log-only\';', @@ -7538,7 +7590,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'SessionFollowRequest', - declaration: 'export interface SessionFollowRequest extends Pick {\n readonly address: SessionAddress;\n readonly assistantStream?: true;\n}', + declaration: 'export interface SessionFollowRequest extends Pick {\n readonly address: SessionAddress;\n readonly activate?: boolean;\n readonly assistantStream?: true;\n}', }, { name: 'SessionForkRequest', @@ -7652,6 +7704,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionObservationOptions', declaration: 'export interface SessionObservationOptions {\n readonly signal?: AbortSignal;\n readonly projectionMode?: \'all\' | \'none\';\n}', }, + { + name: 'SessionObserveEventRequest', + declaration: 'export interface SessionObserveEventRequest {\n readonly address: SessionAddress;\n}', + }, { name: 'SessionOpenWorkspacePathRequest', declaration: 'export interface SessionOpenWorkspacePathRequest {\n readonly action?: \'reveal\';\n readonly application?: string;\n readonly path: string;\n}', @@ -7666,7 +7722,11 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'SessionPageRequest', - declaration: 'export interface SessionPageRequest {\n readonly address: SessionAddress;\n readonly throughSeq: number;\n readonly beforeSeq?: number;\n readonly maxMessages?: number;\n readonly turnWindow?: {\n readonly minMessages: number;\n readonly minTurns: number;\n };\n}', + declaration: 'export interface SessionPageRequest {\n readonly address: SessionAddress;\n readonly throughSeq?: number;\n readonly beforeSeq?: number;\n readonly maxMessages?: number;\n readonly turnWindow?: {\n readonly minMessages: number;\n readonly minTurns: number;\n };\n}', + }, + { + name: 'SessionPendingInput', + declaration: 'export type SessionPendingInput = \'approval\' | \'question\' | \'other\';', }, { name: 'SessionPersistenceCreateOptions', @@ -7696,6 +7756,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionProjectionBaseline', declaration: 'export interface SessionProjectionBaseline {\n readonly asOfSeq: number;\n readonly values: SessionProjectionValues;\n}', }, + { + name: 'SessionProjectionChange', + declaration: 'export type SessionProjectionChange = {\n readonly type: \'projection\';\n} & Omit;', + }, + { + name: 'SessionProjectionFrame', + declaration: 'export type SessionProjectionFrame = {\n readonly type: \'ready\';\n} | SessionProjectionChange;', + }, { name: 'SessionProjectionHints', declaration: 'export interface SessionProjectionHints {\n readonly kind: \'cached\' | \'sequenced\';\n readonly asOfSeq: number;\n readonly values: Partial;\n}', @@ -7752,6 +7820,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionPromptValue', declaration: 'export interface SessionPromptValue {\n readonly accepted: true;\n}', }, + { + name: 'SessionQueuedItem', + declaration: 'export interface SessionQueuedItem {\n readonly id: MessageId;\n readonly placement: \'queued\' | \'steering\' | \'context\';\n readonly rpcId?: SessionRequestId;\n readonly content: readonly JsonValue[];\n}', + }, { name: 'SessionRecord', declaration: 'export interface SessionRecord {\n header: SessionHeader;\n live: boolean;\n persisted: boolean;\n formatStatus?: \'current\' | \'migration-required\';\n}', @@ -7844,6 +7916,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionStartSource', declaration: 'export type SessionStartSource = \'startup\' | \'resume\' | \'clear\' | \'compact\';', }, + { + name: 'SessionState', + declaration: 'export interface SessionState {\n readonly cursor: number;\n readonly active: boolean;\n readonly running: boolean;\n readonly queue: readonly SessionQueuedItem[] | null;\n readonly pendingInput: readonly SessionPendingInput[];\n}', + }, + { + name: 'SessionStateRequest', + declaration: 'export interface SessionStateRequest {\n readonly sessionId: SessionId;\n}', + }, { name: 'SessionStorageMetadata', declaration: 'export interface SessionStorageMetadata {\n readonly meta: SessionHeader;\n readonly inheritedEventCount: SessionLogOffset;\n}', @@ -7924,6 +8004,18 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionUpdateQueueValue', declaration: 'export interface SessionUpdateQueueValue {\n readonly accepted: true;\n}', }, + { + name: 'SessionWaitOutput', + declaration: 'export interface SessionWaitOutput {\n readonly records: readonly SessionHistoryRecord[];\n readonly truncated: boolean;\n}', + }, + { + name: 'SessionWaitRequest', + declaration: 'export interface SessionWaitRequest extends SessionStateRequest {\n readonly timeoutMs?: number;\n readonly afterSeq?: number;\n readonly maxMessages?: number;\n}', + }, + { + name: 'SessionWaitValue', + declaration: 'export interface SessionWaitValue {\n readonly reason: \'idle\' | \'input-required\' | \'timeout\';\n readonly state: SessionState;\n readonly output: SessionWaitOutput;\n}', + }, { name: 'SessionWireEvent', declaration: 'export interface SessionWireEvent {\n readonly type: string;\n readonly seq: number;\n readonly time: number;\n readonly data: JsonValue;\n readonly ignorable?: true;\n readonly sourceEventSeqs?: JsonValue;\n readonly surfaceOp?: JsonValue;\n}', diff --git a/scripts/gen-cordis-catalog.ts b/scripts/gen-cordis-catalog.ts index 9a0ecfcc1b..73a4123579 100644 --- a/scripts/gen-cordis-catalog.ts +++ b/scripts/gen-cordis-catalog.ts @@ -451,6 +451,16 @@ export const LINK_MAP: Readonly> = { SessionModelsRequest: 'session.md', SessionPage: 'session.md', SessionPageRequest: 'session.md', + SessionEventsPage: 'session.md', + SessionEventFrame: 'session.md', + SessionObserveEventRequest: 'session.md', + SessionProjectionFrame: 'session.md', + SessionProjectionChange: 'session.md', + SessionState: 'session.md', + SessionStateRequest: 'session.md', + SessionWaitRequest: 'session.md', + SessionWaitValue: 'session.md', + PendingRemoteEventInfo: 'typert.md', SessionPromptRequest: 'session.md', SessionPromptValue: 'session.md', SessionRenameRequest: 'session.md', diff --git a/scripts/no-unknown-casts.baseline.json b/scripts/no-unknown-casts.baseline.json index 13c3115328..bef0f27ca0 100644 --- a/scripts/no-unknown-casts.baseline.json +++ b/scripts/no-unknown-casts.baseline.json @@ -555,9 +555,6 @@ "e01c2c40d53d557b621628de47a0a6677e11b4f151fbefd865c97be99a7b6c48": 1, "e69e0ec4368790661e1f7cae5c2059f757c213f0ebb0bd40ec23af982bc73d20": 1 }, - "packages/client/ui-plan/tests/plan-resource.client.spec.ts": { - "fa53d5cd55d87b522c83a98968e3a2bf933b1cc1b84d2f009e79d6c702099786": 1 - }, "packages/client/ui-primitives/tests/highlight-viewport.client.spec.tsx": { "6061de0a1e01547eb1abf9d4e1b5fa79fda112fa35dda980775491123413dcce": 1 },