Add @deepseek-ai/dsh-telemetry, a launcher-side (non-plugin) library for the ConsentResolver (parses cordis.yml consent + DO_NOT_TRACK/CI), buildTelemetryPayload (redacted cordis.yml + package.json full content, never .env), getOrCreateAnonymousId (random UUID in a per-machine global config file), and TelemetryReporter (fire-and-forget, never blocks or crashes the command). Endpoint is a fixed .invalid placeholder pending the real endpoint. Launcher dispatch wiring and the helper feature-catalog entry are intentionally out of scope. Registers the package in tsconfig references, the module graph, and the README model-experience audit map. Per-file 100% coverage.
@deepseek-ai/dsh-telemetry
Launcher-side telemetry primitives for the dsh-sdk toolchain. This is a plain library the launcher imports around each command; it is not a Cordis plugin, because build and first-init create never boot Cordis. Wiring the reporter into the launcher command dispatch and adding the telemetry consent feature to the dsh-helper catalog live in their owning packages, not here.
| Export | Role |
|---|---|
SecretRedactor |
Conservative safety backstop: replaces secret-shaped values (secret-like keys, known token shapes, PEM blocks, URL credentials, high-entropy opaque tokens) with a placeholder in both parsed values (redactValue) and raw text (redactText). Never drops a field or line. |
ConsentResolver |
Parses (never boots) a project cordis.yml and reads the telemetry entry's enabled/disabled state as consent; DO_NOT_TRACK/CI env force a hard opt-out. |
buildTelemetryPayload |
Assembles {command, durationMs, success, cordisYmlContent, packageJsonContent}, running the redactor over the full cordis.yml and package.json text. Never reads .env. |
getOrCreateAnonymousId |
Random UUID persisted in a per-user GLOBAL config file (never in the project, never derived from git). |
TelemetryReporter |
Fire-and-forget send: report() never blocks or throws; delivery resolves on every path; flush() optionally drains in-flight sends within a cap. |
Consent is carried by the telemetry entry in cordis.yml, so disabling telemetry is disabling that entry. When cordis.yml does not yet exist (first create) consent defaults to allowed; when it exists without a telemetry entry consent defaults to denied — both are configurable on ConsentResolver.
The collection endpoint is a fixed constant (DSH_TELEMETRY_ENDPOINT); its .invalid placeholder must be replaced with the real endpoint before release.
Model Experience
None, as the reporter sends developer-cycle telemetry from the launcher and never reaches a model request.
Known Limitations and Deferred Work
- Placeholder endpoint —
DSH_TELEMETRY_ENDPOINTpoints at.invaliduntil the real endpoint is set. - Redaction is heuristic — a conservative backstop, not a guarantee; secrets belong in
.env, which is never read or reported.