* feat(release): publish package source, declaration maps, and documentation Every release member publishes its TypeScript source and the declaration maps that resolve into it, and @deepseek-ai/dsh publishes the repository Markdown documentation staged from docs/ at prepack time. The ./src/* export most members already declared now resolves for an installed consumer, and a consumer editor follows a declaration to the implementation. Bundled JavaScript maps stay unpublished; the vendored family and the Desktop runtime file policy are unchanged. Rationale: .agents/notes/implemented/process/2026-10-08-published-source-and-docs.md * feat(release): publish JavaScript maps and compress bundles Every emitted JavaScript map ships beside the bundle it describes, and the workspace build and the client preset compress bundles without mangling identifiers. The documentation payload now mirrors the website publication manifest and is removed again by `postpack`; Desktop and the Python executable exclude the published source, documentation, and maps; `clean` removes a staged copy. Typert's publication contract gains the Remote declaration map. * fix(release): keep node bundles readable for the worker image The browser worker image lowers `yield*` only as a whole statement and rewrites `for await` loops by their source layout, so compressed node-side entries either fail that lowering or lower to unparseable code. Only the browser bundles keep compression, which removes about a third of their text. The bundle-purity assertion now matches the module-loader call regardless of the quote style compression picks, and the release-pack fixture exercises the installed package's new documentation requirement. * feat(release): publish the whole documentation tree `@deepseek-ai/dsh` copies `docs/` in full instead of the website's page set: the maintainer documents, the generated migration records, the translation guidelines, and the `*.i18n.yaml` consistency records ship with the installed package, so the documentation's own links resolve without a checkout. * feat(release): publish the upgrade guides with the documentation The staged documentation keeps the website's page set and adds every `docs/upgrade-guide/` document, which is what an installed reader consults when a released change breaks something. The rest of the maintainer tree stays out. * test(release): expect source and maps in master's new payload cases * feat(release): keep installed docs and source readable in Desktop Desktop keeps the published src/ and docs/ trees inside app.asar, and every model shell call receives DSH_INSTALL_DIR and DSH_NODE_EXECUTABLE so an agent can read them through Electron's Node mode. Staging also generates docs/upgrade-guide/README.md, an index of the upgrade guides grouped by the release they upgrade from. Minified client bundles print string literals with backticks: the worker image packer now recognizes those chunk requests, client license banners are prepended after minification so their text survives, and the affected artifact tests accept either quote. * test(desktop): read archived docs through the Windows PowerShell form Regenerate the config catalog for the shifted shell-env source line. * test(desktop): wait for the GUI-subsystem Electron process from PowerShell * build(release): publish source and maps from the message-quotes package * build(release): publish source and maps from packages new on master * build(release): publish source and maps from the tool-office package
description, kind
| description | kind |
|---|---|
| Session-telemetry capture seam for deployments and backend authors choosing a reporting backend, mounting redaction rules, or implementing the backend contract. | package-library |
@deepseek-ai/dsh-session-telemetry
English | 中文
Summary
Session telemetry lets deployments send ordered copies of session activity for reporting while preserving the canonical session log. Deployments choose one reporting backend and can redact each outbound copy before delivery; without redaction rules, captured data leaves the process unchanged. The handoff is non-blocking, so reporting does not delay session processing. Delivery is best effort, and queued records may be lost if the process crashes.
Table of Contents
- Use this package
- Understand the implementation
- Further Exploration
- Model Experience
- Known Limitations and Deferred Work
- Dev Note
Use this package
As a deployment, choose a backend, mount it, and add redaction rules when records must not leave the process as captured. As a backend author, implement the three-member contract and compose the coordinator with a capture mode.
Choosing and mounting a backend
Load exactly one backend plugin; it registers ctx.sessionTelemetry with the capture coordinator and its delivery pipeline. A duplicate load throws. The required sharing member reports the deployment mode, not per-session admission or delivery. A consumer may report "not configured" only when no telemetry service is mounted. The /feedback command confirms recording without reading this policy.
The backend contract
A backend implements three members: emit(record) must be a non-blocking enqueue because it runs synchronously on the session-event path; optional flush() is a fire-and-forget hint after a turn ends, which most backends omit in favor of their SDK's own batching schedule; shutdown() drains queued records and resolves when the SDK stops, and disposal awaits it. A backend that implements flush() must order concurrent flushes with the final shutdown() drain.
What gets captured
Capture runs in one of two modes. live capture follows session events as they are appended, replays already-live sessions at mount time, and records lifecycle markers; on-demand capture reads the canonical session log only when the backend requests a prefix through captureSession(session, throughSeq?). Coordinator options select whether stored history is included. Every canonical session event maps to one ledger record in order. An assistant/message or assistant/attempt record carries its complete embedded compact stream, including failed and retried output. Each ledger record also carries session.id, session.format_version, the numeric event identity, optional header facts, and a pre-mapped severity (error for tool/result.isError, turn/end error reasons, and agent-error; info otherwise).
Ledger records carry sourceEvent with the owning Session id and a copied event envelope excluding data. The redaction waterfall receives body as the only payload copy. Backends can reconstruct a complete exported event from the envelope and redacted body without bypassing redaction.
The sharing disclosure
Every backend discloses its deployment mode through sharing: full, feedback-only, or disabled. A backend may additionally restrict eligible Sessions. This property is not a delivery receipt; handoff is a non-blocking enqueue, and batching, retry, and loss policy belong to the backend SDK.
Redacting records
Every outbound record passes the sessionTelemetry/record waterfall after the coordinator copies its canonical event. This package ships no rules: with no listener mounted, records reach the backend exactly as captured, so exported data is as clean as the rules a deployment mounts. Listeners stack by transforming next()'s return value; a throwing listener withholds that one record fail-closed. Redaction applies to the outbound copy only — the canonical session log is never rewritten.
Understand the implementation
Implementation internals — click to expand
This section explains the capture design; the observable behavior is fully covered in Use this package.
Design concept
The capture package owns complete event capture, redaction, and handoff cursors. Redaction rules must preserve sourceEvent for OTel upload; returning a fresh record without it withholds the event with a diagnostic. Its cloned envelope excludes data, which is carried only in body. The OTel backend owns byte/count scheduling and uses SDK transport/retries. The historical revival Agent Note records capture and redaction rationale.
Source map
| File | Role |
|---|---|
src/index.ts |
Service Definition: SessionTelemetryBackend/SessionTelemetrySink contract, record vocabulary, session-telemetry/record waterfall declaration |
src/coordinator.ts |
Capture: live listeners, lifecycle-local on-demand replay, redaction, handoff cursor, containment |
Capture flow
Live capture registers Session events, flush hints, shutdown markers, and agent/error observers through the composing fiber’s effects. On-demand capture registers only the disposal effect and reads the requested canonical-log prefix under its history policy. Synchronous handlers contain failures so they cannot affect the agent loop or other listeners.
The handoff cursor
A module-scope WeakMap<Session, seq> records the highest sequence handed off, not delivered. Re-adopting the same object resumes after that cursor. Capture starts at firstLifecycleSeq: a new fork includes its child-owned marker and closers, while a restored Session excludes its stored prefix, including prior child turns; explicit includeHistory: true starts an unhanded object at seq 0, including restored or fork history. The backend owns capture authorization. Stored history does not itself authorize capture; the OTel backend waits for new explicit feedback. Receivers deduplicate repeated records by (session.id, session.format_version, event.seq).
Further Exploration
Read these pages when the seam contract is not enough. They move from the shipped backend to the subsystem reference and the decision evidence.
- OpenTelemetry telemetry backend — the shipped backend deployments load, with mode and exporter configuration.
- Session telemetry subsystem — the capability split and type declarations.
- historical Session telemetry revival decision — rationale, trade-offs, and rejected alternatives.
- Session package map — adjacent persistence, projection, title, and telemetry packages.
Model Experience
None, as the seam observes the session stream and hands redacted copies outward; it registers nothing model-facing.
KV Cache effect
None; the package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
These limits define the delivery and data-protection guarantees a deployment gets. They are current package constraints.
- Best-effort delivery — the cursor marks handed-off, not delivered; a session torn down inside a reload window cannot be re-adopted, and whatever sits in a backend queue at crash time is lost. A durable outbox (spool, per-sink cursors, at-least-once) is deferred until a deployment states a crash-loss requirement.
- No built-in redaction rules — with no
sessionTelemetry/recordlistener mounted, records leave the process exactly as captured, including any credentials embedded in file contents or command output; a deployment exporting to a shared collector owns its rule set. - On-demand redaction uses current state — uncaptured events exist only in the canonical session log; a later
captureSession()deep-copies and redacts their current values with the policy mounted at that time, and there is no capture-time telemetry snapshot or durable pre-capture spool.
Dev Note
Working context for maintainers — click to expand
None.