OTel uploads explicit feedback for all users by default

This commit is contained in:
Tianyi Cui
2026-09-05 23:21:23 +08:00
parent 02a029e679
commit 9ffe85a512
65 changed files with 1162 additions and 381 deletions
+2 -2
View File
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/config-catalog.md
config-catalog.md: 28fc6e327a14f6f2f41330f01becbcddf50eeb20
config-catalog.zh.md: 49aad4a46eecb39001ec0b3d5c880fdcd74614d3
config-catalog.md: 72d7423f308a60454eaab62a288f3617fb5b91ae
config-catalog.zh.md: d3025a25bd808fe493ea0ae8ed93c8611ece944e
+2 -3
View File
@@ -1977,7 +1977,7 @@ Requires: `sessions`
* and shutdown deadline at plugin load; `DISABLED` reads neither.
*/
export interface Config {
/** Sharing policy; defaults to local-only `DISABLED` behavior. */
/** Defaults to `FEEDBACK_ONLY`: capture session history only when feedback is explicitly submitted. */
mode?: SessionTelemetryMode
/**
* Passed verbatim to the SDK's OTLP/HTTP log exporter — the complete
@@ -2000,7 +2000,6 @@ export interface Config {
/** Session-sharing policy selected by {@link Config.mode}. */
export enum SessionTelemetryMode {
FULL = 'FULL',
FEEDBACK_ONLY = 'FEEDBACK_ONLY',
DISABLED = 'DISABLED',
}
@@ -2008,7 +2007,7 @@ export enum SessionTelemetryMode {
Depends on: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`)
Source: [`packages/session/session-telemetry-otel/src/index.ts:91`](../packages/session/session-telemetry-otel/src/index.ts)
Source: [`packages/session/session-telemetry-otel/src/index.ts:100`](../packages/session/session-telemetry-otel/src/index.ts)
<a id="deepseek-aidsh-session-title"></a>
+2 -3
View File
@@ -1979,7 +1979,7 @@ export interface Config {
* and shutdown deadline at plugin load; `DISABLED` reads neither.
*/
export interface Config {
/** Sharing policy; defaults to local-only `DISABLED` behavior. */
/** Defaults to `FEEDBACK_ONLY`: capture session history only when feedback is explicitly submitted. */
mode?: SessionTelemetryMode
/**
* Passed verbatim to the SDK's OTLP/HTTP log exporter — the complete
@@ -2002,7 +2002,6 @@ export interface Config {
/** Session-sharing policy selected by {@link Config.mode}. */
export enum SessionTelemetryMode {
FULL = 'FULL',
FEEDBACK_ONLY = 'FEEDBACK_ONLY',
DISABLED = 'DISABLED',
}
@@ -2010,7 +2009,7 @@ export enum SessionTelemetryMode {
依赖:`BatchLogRecordProcessorOptions``@opentelemetry/sdk-logs`)· `OTLPExporterNodeConfigBase``@opentelemetry/otlp-exporter-base`
来源:[`packages/session/session-telemetry-otel/src/index.ts:91`](../packages/session/session-telemetry-otel/src/index.ts)
来源:[`packages/session/session-telemetry-otel/src/index.ts:100`](../packages/session/session-telemetry-otel/src/index.ts)
<a id="deepseek-aidsh-session-title"></a>
+2 -2
View File
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/event-producer-consumer.md
event-producer-consumer.md: 0c9bccc5c6524ef165a1ac661fd2ab936e23731d
event-producer-consumer.zh.md: 432cb55ecb5e3755ae513baad80aecfeb5695dc2
event-producer-consumer.md: da072c8d2c12aa768bc1c357e6dea37821116d66
event-producer-consumer.zh.md: af0a2a63c5dfeb391b2e82d2b6e972d69a9e8864
+1
View File
@@ -39,6 +39,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| `credentials/record-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:102`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization) |
| `credentials/reference-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:90`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`credentials`](../packages/credentials/credentials), `remotes` |
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace), `workspace-controller` |
| `feedback/committed` | `parallel` | [`packages/feedback/message-feedback/src/index.ts:57`](../packages/feedback/message-feedback/src/index.ts) | [`message-feedback`](../packages/feedback/message-feedback) (`parallel`) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) |
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:66`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-observation-policy`](../packages/fs/fs-observation-policy) |
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:76`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`emit`) | [`fs-observation-policy`](../packages/fs/fs-observation-policy), [`skill-filesystem`](../packages/skill/skill-filesystem) |
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:58`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-observation-policy`](../packages/fs/fs-observation-policy) |
+2 -1
View File
@@ -31,7 +31,7 @@
| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:579`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:85`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes` |
| `authorization/settled` | `emit` | [`packages/credentials/authorization/src/index.ts:57`](../packages/credentials/authorization/src/index.ts) | [`authorization`](../packages/credentials/authorization) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization) |
| `commands/change` | `emit` | [`packages/interaction/commands/src/types.ts:81`](../packages/interaction/commands/src/types.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `remotes` |
| `commands/change` | `emit` | [`packages/interaction/commands/src/types.ts:87`](../packages/interaction/commands/src/types.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `remotes` |
| `cordis/dynamic-package` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:380`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
| `cordis/dynamic-retract` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:386`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
| `cordis/inspect-query` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:392`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
@@ -41,6 +41,7 @@
| `credentials/record-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:102`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization) |
| `credentials/reference-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:90`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`credentials`](../packages/credentials/credentials), `remotes` |
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace), `workspace-controller` |
| `feedback/committed` | `parallel` | [`packages/feedback/message-feedback/src/index.ts:57`](../packages/feedback/message-feedback/src/index.ts) | [`message-feedback`](../packages/feedback/message-feedback) (`parallel`) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) |
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:66`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-observation-policy`](../packages/fs/fs-observation-policy) |
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:76`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`emit`) | [`fs-observation-policy`](../packages/fs/fs-observation-policy), [`skill-filesystem`](../packages/skill/skill-filesystem) |
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:58`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-observation-policy`](../packages/fs/fs-observation-policy) |
+2 -2
View File
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/module-graph.md
module-graph.md: 8128e19e32a0afdf3061c26879cc34d43d736ef5
module-graph.zh.md: 63a056c2a1b5c41a3d3fc7b3d4ab2813334354a4
module-graph.md: acf01f4cf7c8bb4c7356332832c92623265904f0
module-graph.zh.md: 78dfc42cfffb1c1515197a9132fcca70d56b15e6
+2 -1
View File
@@ -837,6 +837,7 @@ flowchart TD
pkg_session_telemetry_otel --> pkg_anonymous_user_id
pkg_session_telemetry_otel --> pkg_command_feedback
pkg_session_telemetry_otel --> pkg_llm
pkg_session_telemetry_otel --> pkg_message_feedback
pkg_session_telemetry_otel --> pkg_session
pkg_session_telemetry_otel --> pkg_session_telemetry
pkg_session_title_all_prompts_llm --> pkg_llm
@@ -1362,7 +1363,7 @@ flowchart TD
| [`agent-presets`](../packages/preset/agent-presets) | `preset` | [`agent`](../packages/core/agent), [`atomic-write`](../packages/util/atomic-write), [`home-paths`](../packages/util/home-paths), [`invariants`](../packages/runtime-diagnostics/invariants), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol) |
| [`schedule`](../packages/schedule/schedule) | `schedule` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`tools`](../packages/core/tools) |
| [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy) | `session` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`tools`](../packages/core/tools) |
| [`session-telemetry-otel`](../packages/session/session-telemetry-otel) | `session` | [`anonymous-user-id`](../packages/identity/anonymous-user-id), [`command-feedback`](../packages/feedback/command-feedback), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-telemetry`](../packages/session/session-telemetry) |
| [`session-telemetry-otel`](../packages/session/session-telemetry-otel) | `session` | [`anonymous-user-id`](../packages/identity/anonymous-user-id), [`command-feedback`](../packages/feedback/command-feedback), [`llm`](../packages/llm/llm), [`message-feedback`](../packages/feedback/message-feedback), [`session`](../packages/core/session), [`session-telemetry`](../packages/session/session-telemetry) |
| [`session-title-all-prompts-llm`](../packages/session/session-title-all-prompts-llm) | `session` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`session-title-llm`](../packages/session/session-title-llm) |
| [`session-title-first-prompt-llm`](../packages/session/session-title-first-prompt-llm) | `session` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`session-title-llm`](../packages/session/session-title-llm) |
| [`shell-env`](../packages/shell/shell-env) | `shell` | [`home-paths`](../packages/util/home-paths), [`shell`](../packages/shell/shell), [`tools`](../packages/core/tools) |
+2 -1
View File
@@ -839,6 +839,7 @@ flowchart TD
pkg_session_telemetry_otel --> pkg_anonymous_user_id
pkg_session_telemetry_otel --> pkg_command_feedback
pkg_session_telemetry_otel --> pkg_llm
pkg_session_telemetry_otel --> pkg_message_feedback
pkg_session_telemetry_otel --> pkg_session
pkg_session_telemetry_otel --> pkg_session_telemetry
pkg_session_title_all_prompts_llm --> pkg_llm
@@ -1364,7 +1365,7 @@ flowchart TD
| [`agent-presets`](../packages/preset/agent-presets) | `preset` | [`agent`](../packages/core/agent), [`atomic-write`](../packages/util/atomic-write), [`home-paths`](../packages/util/home-paths), [`invariants`](../packages/runtime-diagnostics/invariants), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol) |
| [`schedule`](../packages/schedule/schedule) | `schedule` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`tools`](../packages/core/tools) |
| [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy) | `session` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`tools`](../packages/core/tools) |
| [`session-telemetry-otel`](../packages/session/session-telemetry-otel) | `session` | [`anonymous-user-id`](../packages/identity/anonymous-user-id), [`command-feedback`](../packages/feedback/command-feedback), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-telemetry`](../packages/session/session-telemetry) |
| [`session-telemetry-otel`](../packages/session/session-telemetry-otel) | `session` | [`anonymous-user-id`](../packages/identity/anonymous-user-id), [`command-feedback`](../packages/feedback/command-feedback), [`llm`](../packages/llm/llm), [`message-feedback`](../packages/feedback/message-feedback), [`session`](../packages/core/session), [`session-telemetry`](../packages/session/session-telemetry) |
| [`session-title-all-prompts-llm`](../packages/session/session-title-all-prompts-llm) | `session` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`session-title-llm`](../packages/session/session-title-llm) |
| [`session-title-first-prompt-llm`](../packages/session/session-title-first-prompt-llm) | `session` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`session-title-llm`](../packages/session/session-title-llm) |
| [`shell-env`](../packages/shell/shell-env) | `shell` | [`home-paths`](../packages/util/home-paths), [`shell`](../packages/shell/shell), [`tools`](../packages/core/tools) |
+2 -2
View File
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/feedback.md
feedback.md: e1f2d05435cb5e0fe09c315d4123c4621e4c7c68
feedback.zh.md: 9ce5b44995302687a39a655bf019f623e8c8c7e7
feedback.md: c538fac50b0c75e43f761a3b58b385840b83e4ef
feedback.zh.md: 4a77f9c0396f3635755c301a80ccaefe398d5ad6
+27 -1
View File
@@ -221,7 +221,7 @@ Successful message-feedback mutations await canonical persistence: live operatio
Plugin disposal closes operation admission and drains accepted per-Session queue work.
When explicitly enabled, [`session-log-deepseek`](../../packages/session/session-log-deepseek/README.md) carries feedback as part of the ordinary `dsh_session_log` suffix on subsequent eligible DeepSeek requests. Recording feedback does not trigger a request or a separate `dsh_feedback` upload. The command acknowledgement confirms recording and identifies the Session and anonymous user; it reports neither telemetry policy nor delivery.
When explicitly enabled, [`session-log-deepseek`](../../packages/session/session-log-deepseek/README.md) carries feedback as part of the ordinary `dsh_session_log` suffix on subsequent eligible DeepSeek requests. Recording feedback does not trigger an LLM request or a separate `dsh_feedback` upload. For non-DeepSeek routes, the [OTel backend](../../packages/session/session-telemetry-otel/README.md) can release the canonical prefix through recorded feedback. The command acknowledgement confirms recording and identifies the Session and anonymous user; it reports neither telemetry policy nor delivery.
## Web surface
@@ -280,5 +280,31 @@ Session-log service; cold operations never construct a Session or Agent.
@Remote('delete') delete(request: MessageFeedbackDeleteRequest): Promise<MessageFeedbackDeleteResult>
```
Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
<a id="feedback-events"></a>
### `feedback/*` events
<a id="feedbackcommitted--parallel"></a>
#### `feedback/committed` — parallel
Observe a durable cold feedback mutation without publishing a live Session. Observers run before write ownership is released and must not await another message-feedback operation for this Session. The payload is borrowed read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
```ts cordis-catalog
/**
* Observe a durable cold feedback mutation without publishing a live Session.
* Observers run before write ownership is released and must not await
* another message-feedback operation for this Session. The payload is borrowed
* read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
* @param inspection - committed canonical prefix, including the feedback as its last event.
* @mode parallel
*/
'feedback/committed'(inspection: SessionInspection): void
```
Types: [SessionInspection](persistence.md)
Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
<!-- END GENERATED cordis-surface -->
+27 -1
View File
@@ -221,7 +221,7 @@ fork 种子可以包含父 Session 的反馈事件,但 payload 保留父级 `s
插件释放会关闭操作接纳,并排空已进入各 Session 队列的工作。
显式启用后,[`session-log-deepseek`](../../packages/session/session-log-deepseek/README.zh.md) 会在后续符合条件的 DeepSeek 请求中,把反馈作为普通 `dsh_session_log` 后缀的一部分传送。记录反馈不会触发请求,也不会单独上传 `dsh_feedback`。命令确认文本确认记录并标识 Session 与匿名用户,不报告遥测策略或投递结果。
显式启用后,[`session-log-deepseek`](../../packages/session/session-log-deepseek/README.zh.md) 会在后续符合条件的 DeepSeek 请求中,把反馈作为普通 `dsh_session_log` 后缀的一部分传送。记录反馈不会触发 LLM 请求,也不会单独上传 `dsh_feedback`。对于非 DeepSeek 路由,[OTel 后端](../../packages/session/session-telemetry-otel/README.zh.md)可以将权威日志前缀释放至已记录的反馈。命令确认文本确认记录并标识 Session 与匿名用户,不报告遥测策略或投递结果。
## Web 界面
@@ -280,5 +280,31 @@ Session-log service; cold operations never construct a Session or Agent.
@Remote('delete') delete(request: MessageFeedbackDeleteRequest): Promise<MessageFeedbackDeleteResult>
```
Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
<a id="feedback-events"></a>
### `feedback/*` events
<a id="feedbackcommitted--parallel"></a>
#### `feedback/committed` — parallel
Observe a durable cold feedback mutation without publishing a live Session. Observers run before write ownership is released and must not await another message-feedback operation for this Session. The payload is borrowed read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
```ts cordis-catalog
/**
* Observe a durable cold feedback mutation without publishing a live Session.
* Observers run before write ownership is released and must not await
* another message-feedback operation for this Session. The payload is borrowed
* read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
* @param inspection - committed canonical prefix, including the feedback as its last event.
* @mode parallel
*/
'feedback/committed'(inspection: SessionInspection): void
```
Types: [SessionInspection](persistence.zh.md)
Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
<!-- END GENERATED cordis-surface -->
+2 -2
View File
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/session-telemetry.md
session-telemetry.md: 83224cf03005909f9b3d600a950c2d6402ca3b2a
session-telemetry.zh.md: a093590819d62839fb69a0e50b2d11f495171ec8
session-telemetry.md: f452dc6fa9064689664bcaed08205d30def822e6
session-telemetry.zh.md: 59c817cca945e3f972e30104104f44fb15006aa5
+22 -6
View File
@@ -55,22 +55,38 @@ interface SessionTelemetryRecord {
}
```
Every canonical [session event](session.md), including each `assistant/message` or `assistant/attempt` with its complete compact stream and every plugin-merged type the seam never heard of, passes through whole as one ordered ledger record. Process-local `agent/assistant-stream` frames do not enter this durable feed. A new Session object replays its complete log from seq 0, including constructor seed history; re-adopting the same object resumes after its handoff cursor. Delivery is best-effort: the cursor marks handed-off, not delivered, and records can be lost (crash, reload window) or duplicated (new-object replay, SDK retries), so receivers dedupe ledger records on `(session.id, session.format_version, event.seq)`; ops records deliberately omit that identity — they are signals to alert on, not entries to sum, and tolerate duplicates instead.
Every canonical [session event](session.md), including each `assistant/message` or `assistant/attempt` with its complete compact stream and every plugin-merged type the seam never heard of, passes through whole as one ordered ledger record. Process-local `agent/assistant-stream` frames do not enter this durable feed. A new Session object starts at its lifecycle boundary unless the backend selects `includeHistory`; re-adopting the same object resumes after its handoff cursor. Delivery is best-effort: the cursor marks handed-off, not delivered, and records can be lost (crash, reload window) or duplicated (new-object replay, SDK retries), so receivers dedupe ledger records on `(session.id, session.format_version, event.seq)`; ops records deliberately omit that identity — they are signals to alert on, not entries to sum, and tolerate duplicates instead.
## The sharing disclosure
The seam's acknowledgement contract (owned by the [Service Definition README's sharing-disclosure section](../../packages/session/session-telemetry/README.md#the-sharing-disclosure)): every backend discloses its deployment-selected sharing policy through the required abstract `sharing` member on `ctx.sessionTelemetry`, and consumers render "not configured" only when no telemetry service is mounted. The disclosure states the current policy, never delivery or retention — handoff is the non-blocking enqueue, and batching, retry, and loss policy stay the reporting SDK's.
Every backend exposes its deployment-selected mode through the required abstract `sharing` member on `ctx.sessionTelemetry` ([Service Definition README](../../packages/session/session-telemetry/README.md#the-sharing-disclosure)). This is neither a per-Session admission decision nor a delivery receipt. The `/feedback` acknowledgement does not consult it.
```ts type-equiv
/**
* Deployment-selected session-sharing policy disclosed by a mounted
* {@link SessionTelemetryBackend} backend to human-facing acknowledgement surfaces (the
* `/feedback` command's confirmation text). The Service Definition owns the
* vocabulary so consumers and backends do not depend on a specific provider.
* Deployment-selected session-sharing mode, not confirmation of SDK delivery.
*/
type SessionTelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
```
## Capture policy
```ts type-equiv
/** Whether capture follows live events or reads the canonical log only when requested. */
type SessionTelemetryCapture = 'live' | 'on-demand'
```
```ts type-equiv
/** Backend-selected capture mode and history policy. */
interface SessionTelemetryCaptureOptions {
/** Follow live events, or wait for explicit capture; defaults to live. */
capture?: SessionTelemetryCapture
/** Include stored history before this lifecycle; defaults to false. */
includeHistory?: boolean
}
```
`includeHistory` permits stored and inherited records but does not itself authorize capture. The [OTel backend](../../packages/session/session-telemetry-otel/README.md) uses on-demand capture and requires new own explicit feedback; it releases only the complete prefix through that feedback, for every provider.
## The backend contract
```ts type-equiv
+22 -6
View File
@@ -55,22 +55,38 @@ interface SessionTelemetryRecord {
}
```
每条权威[会话事件](session.zh.md)都会完整透传为一条有序 ledger 记录,包括每个携带完整紧凑 stream 的 `assistant/message` 或 `assistant/attempt`,以及该 seam 从未听说过、由插件合并进来的类型。进程本地 `agent/assistant-stream` frame 不进入该持久 feed。新 Session 对象会从 seq 0 回放完整日志,包括构造 seed 历史;重新收养同一对象时会从 handoff 游标之后继续。投递是尽力而为的:游标标记的是「已交接」而非「已送达」,记录可能丢失(崩溃、重载窗口)也可能重复(新对象回放、SDK 重试),因此接收端对 ledger 记录基于 `(session.id, session.format_version, event.seq)` 去重;ops 记录刻意省略这类标识——它们是用于告警的信号,而非用于累加的条目,重复被容忍而非被去重。
每条权威[会话事件](session.zh.md)都会完整透传为一条有序 ledger 记录,包括每个携带完整紧凑 stream 的 `assistant/message` 或 `assistant/attempt`,以及该 seam 从未听说过、由插件合并进来的类型。进程本地 `agent/assistant-stream` frame 不进入该持久 feed。新 Session 对象从其生命周期边界开始,除非后端选择 `includeHistory`;重新收养同一对象时会从 handoff 游标之后继续。投递是尽力而为的:游标标记的是「已交接」而非「已送达」,记录可能丢失(崩溃、重载窗口)也可能重复(新对象回放、SDK 重试),因此接收端对 ledger 记录基于 `(session.id, session.format_version, event.seq)` 去重;ops 记录刻意省略这类标识——它们是用于告警的信号,而非用于累加的条目,重复被容忍而非被去重。
## 共享披露
该 seam 的确认契约(归属 [Service Definition README 的共享披露段](../../packages/session/session-telemetry/README.zh.md#the-sharing-disclosure):每个后端都通过 `ctx.sessionTelemetry` 上必需的抽象 `sharing` 成员披露其部署级共享策略,消费方只有在未挂载任何遥测服务时才渲染「未配置」。披露只陈述当前策略,绝不承诺投递或留存——交接是非阻塞入队,批处理、重试与丢失策略仍归上报 SDK
每个后端都通过 `ctx.sessionTelemetry` 上必需的抽象 `sharing` 成员暴露其部署级模式([Service Definition README](../../packages/session/session-telemetry/README.zh.md#the-sharing-disclosure)。它既不是逐 Session 的接纳决定,也不是投递回执。`/feedback` 确认文本不查询它
```ts type-equiv
/**
* Deployment-selected session-sharing policy disclosed by a mounted
* {@link SessionTelemetryBackend} backend to human-facing acknowledgement surfaces (the
* `/feedback` command's confirmation text). The Service Definition owns the
* vocabulary so consumers and backends do not depend on a specific provider.
* Deployment-selected session-sharing mode, not confirmation of SDK delivery.
*/
type SessionTelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
```
## 捕获策略
```ts type-equiv
/** Whether capture follows live events or reads the canonical log only when requested. */
type SessionTelemetryCapture = 'live' | 'on-demand'
```
```ts type-equiv
/** Backend-selected capture mode and history policy. */
interface SessionTelemetryCaptureOptions {
/** Follow live events, or wait for explicit capture; defaults to live. */
capture?: SessionTelemetryCapture
/** Include stored history before this lifecycle; defaults to false. */
includeHistory?: boolean
}
```
`includeHistory` 允许捕获存储与继承的记录,但本身不授权捕获。[OTel 后端](../../packages/session/session-telemetry-otel/README.zh.md)使用按需捕获,并要求新的自身显式反馈;它只释放截至该反馈的完整前缀,适用于所有提供方。
## 后端约定
```ts type-equiv