retrace-sdk 0.16.8 → 0.16.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.js CHANGED
@@ -63,7 +63,7 @@ export function configure(opts) {
63
63
  if (config.enabled) {
64
64
  void import("./interceptors/install.js").then((m) => m.ensureInterceptorsInstalled()).catch(() => { });
65
65
  }
66
- void import("./telemetry.js").then((m) => m.track("configure")).catch(() => { });
66
+ void import("./telemetry.js").then((m) => m.track("sdk_init", { has_api_key: !!config.apiKey, enabled: config.enabled })).catch(() => { });
67
67
  return config;
68
68
  }
69
69
  export function requireApiKey() {
package/dist/recorder.js CHANGED
@@ -184,6 +184,13 @@ export class TraceRecorder {
184
184
  // lossy / capture_complete:false). Only a naturally-drained run produces a clean terminal.
185
185
  ...(opts?.terminatedEarly ? { terminated_early: true } : {}),
186
186
  });
187
+ // Anonymous usage analytics (fire-and-forget; never throws): record success/failure + which
188
+ // provider families ran. No PII, no user content.
189
+ try {
190
+ const dict = this.builder.toDict();
191
+ void import("./telemetry.js").then((m) => m.trackRecord(String(data.status), dict.spans ?? [], dict.metadata ?? {})).catch(() => { });
192
+ }
193
+ catch { /* never affect the user's program */ }
187
194
  // Restore the enclosing trace's fallback (e.g. the ambient init() recorder) instead of nulling.
188
195
  setActiveRecorderFallback(this.prevFallback, this.prevFallbackSink);
189
196
  this.prevFallback = null;
@@ -221,6 +228,7 @@ export class TraceRecorder {
221
228
  if (span.ended_at) {
222
229
  this.transport.send("span_ended", {
223
230
  id: span.id,
231
+ trace_id: span.trace_id,
224
232
  ended_at: span.ended_at,
225
233
  output: span.output,
226
234
  output_tokens: span.output_tokens,
@@ -263,6 +271,7 @@ export class TraceRecorder {
263
271
  this.builder.addSpan(span);
264
272
  this.transport.send("span_ended", {
265
273
  id: span.id,
274
+ trace_id: span.trace_id,
266
275
  ended_at: span.ended_at,
267
276
  output: span.output,
268
277
  output_tokens: span.output_tokens,
package/dist/resume.d.ts CHANGED
@@ -17,6 +17,9 @@ export interface ResumeCommand {
17
17
  forkPointIndex?: number;
18
18
  modifiedInput: unknown;
19
19
  originalArgs?: unknown[];
20
+ /** Server replay-lease generation token; echoed back on the result trace so the server can reject
21
+ * a superseded (stale) generation and release the correct lease. */
22
+ executionId?: string;
20
23
  }
21
24
  export declare function registerResumable(name: string, fn: (...args: unknown[]) => unknown): void;
22
25
  export declare function getResumable(name: string): ((...args: unknown[]) => unknown) | undefined;
package/dist/resume.js CHANGED
@@ -29,6 +29,7 @@ export async function handleResume(command) {
29
29
  _fork_id: command.forkId,
30
30
  _fork_of: command.traceId,
31
31
  _fork_point: command.forkPointSpanId,
32
+ _fork_execution_id: command.executionId,
32
33
  _cascade_replay: true,
33
34
  },
34
35
  forkPointSpanId: command.forkPointSpanId,
@@ -63,5 +64,6 @@ export function parseResumeMessage(msg) {
63
64
  forkPointIndex: msg.data.forkPointIndex,
64
65
  modifiedInput: msg.data.modifiedInput,
65
66
  originalArgs: msg.data.originalArgs,
67
+ executionId: msg.data.executionId,
66
68
  };
67
69
  }
@@ -1 +1,8 @@
1
+ /** Coarse provider family from a model name (analytics only — never the key or content). */
2
+ export declare function providerOf(model?: string | null): string;
1
3
  export declare function track(event: string, fields?: Record<string, string | number | boolean>): void;
4
+ /** Emit record_success / record_failure with anonymous, aggregate-only fields (span count, provider
5
+ * families used, whether the run was resumable / a cascade replay). Never throws. */
6
+ export declare function trackRecord(status: string, spans: Array<{
7
+ model?: string | null;
8
+ }>, metadata?: Record<string, unknown>): void;
package/dist/telemetry.js CHANGED
@@ -1,26 +1,35 @@
1
1
  /**
2
- * Anonymous, opt-out diagnostic telemetry.
2
+ * Anonymous, always-on diagnostic telemetry.
3
3
  *
4
4
  * Sends NO user code, API keys, prompts, responses, or personal information — only the SDK version,
5
- * the runtime/OS family, an anonymous per-process id, and event/error *categories* to the Retrace
6
- * API's internal log ingest (forwarded to the centralized logging platform under
7
- * service="sdk-typescript"). Fire-and-forget; never blocks, never throws.
5
+ * the runtime/OS family, an anonymous per-process id, and event/error *categories*. Events are POSTed
6
+ * to the Retrace API's internal ingest, which forwards them to PostHog (and the logging platform)
7
+ * under service="sdk-typescript" so the SDK NEVER holds any analytics key (SDK → Retrace API →
8
+ * PostHog).
8
9
  *
9
- * Disable entirely with RETRACE_TELEMETRY=0 (also accepts false/no/off).
10
+ * Fire-and-forget: never blocks the user's program, never throws. Anonymous by construction (no PII,
11
+ * random per-process id) and intentionally NOT user-disableable.
10
12
  */
11
13
  import os from "node:os";
12
14
  import { getConfig } from "./config.js";
13
15
  // Per-process random id — anonymous, not linked to any account, user, or machine identity.
14
16
  const ANON_ID = Math.random().toString(16).slice(2, 18);
15
- const DISABLED = new Set(["0", "false", "no", "off"]);
16
17
  // Keep in sync with package.json version.
17
- const SDK_VERSION = "0.16.5";
18
- function enabled() {
19
- return !DISABLED.has((process.env.RETRACE_TELEMETRY ?? "1").trim().toLowerCase());
18
+ const SDK_VERSION = "0.16.9";
19
+ /** Coarse provider family from a model name (analytics only — never the key or content). */
20
+ export function providerOf(model) {
21
+ const m = (model || "").toLowerCase();
22
+ if (!m)
23
+ return "";
24
+ if (m.startsWith("gemini") || m.includes("google"))
25
+ return "google";
26
+ if (/^(gpt|o1|o3|o4|chatgpt|text-embedding|davinci)/.test(m))
27
+ return "openai";
28
+ if (m.includes("claude"))
29
+ return "anthropic";
30
+ return "other";
20
31
  }
21
32
  export function track(event, fields = {}) {
22
- if (!enabled())
23
- return;
24
33
  try {
25
34
  const base = (getConfig().baseUrl || "https://api.retraceai.tech").replace(/\/$/, "");
26
35
  const body = JSON.stringify({
@@ -49,3 +58,19 @@ export function track(event, fields = {}) {
49
58
  /* telemetry must never affect the user's program */
50
59
  }
51
60
  }
61
+ /** Emit record_success / record_failure with anonymous, aggregate-only fields (span count, provider
62
+ * families used, whether the run was resumable / a cascade replay). Never throws. */
63
+ export function trackRecord(status, spans, metadata = {}) {
64
+ try {
65
+ const provs = Array.from(new Set(spans.map((s) => providerOf(s.model)).filter(Boolean)));
66
+ track(status === "completed" ? "record_success" : "record_failure", {
67
+ spans: spans.length,
68
+ providers: provs.join(",") || "none",
69
+ resumable: !!metadata._resumable,
70
+ cascade: !!metadata._cascade_replay,
71
+ });
72
+ }
73
+ catch {
74
+ /* never throw */
75
+ }
76
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "retrace-sdk",
3
- "version": "0.16.8",
3
+ "version": "0.16.10",
4
4
  "description": "The execution replay engine for AI agents. Record, replay, fork, and share agent executions.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -77,11 +77,11 @@
77
77
  }
78
78
  },
79
79
  "devDependencies": {
80
- "@anthropic-ai/sdk": "^0.105.0",
81
- "@google/genai": "^2.9.0",
80
+ "@anthropic-ai/sdk": "^0.111.0",
81
+ "@google/genai": "^2.11.0",
82
82
  "@types/node": "24.13.2",
83
83
  "@types/ws": "8.18.1",
84
- "openai": "^6.44.0",
84
+ "openai": "^6.46.0",
85
85
  "typescript": "6.0.3"
86
86
  }
87
87
  }