@threadplane/telemetry 0.0.52 → 0.0.54

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/README.md CHANGED
@@ -28,12 +28,12 @@ Transparent, opt-out anonymous usage telemetry for the Threadplane framework. Is
28
28
 
29
29
  | Event | What is sent |
30
30
  |-------|-------------|
31
- | `ngaf:postinstall` | Package name, package version, Node version, OS, CPU architecture, package manager name/version, workspace/global install flags when npm exposes them, sample weight. Per-process anonymous id. No project path, no raw environment variables, no dependency tree, no installer IP address. |
32
- | `ngaf:runtime_instance_created` | Which transport, which model provider (string), Angular peer version. No API keys, no endpoint hostnames, no user data. |
33
- | `ngaf:runtime_request_created` | Transport, request type, provider, model. No prompts, thread IDs, assistant IDs, endpoint URLs, or headers. |
34
- | `ngaf:stream_started` | Provider, model name. No prompts, no message content. |
35
- | `ngaf:stream_ended` | Provider, model name, duration. No prompts, no completions, no message content. |
36
- | `ngaf:stream_errored` | Provider, model name, error class. No prompts, no completions, no message content. |
31
+ | `tplane:postinstall` | Package name, package version, Node version, OS, CPU architecture, package manager name/version, workspace/global install flags when npm exposes them, sample weight. Per-process anonymous id. No project path, no raw environment variables, no dependency tree, no installer IP address. |
32
+ | `tplane:runtime_instance_created` | Which transport, which model provider (string), Angular peer version. No API keys, no endpoint hostnames, no user data. |
33
+ | `tplane:runtime_request_created` | Transport, request type, provider, model. No prompts, thread IDs, assistant IDs, endpoint URLs, or headers. |
34
+ | `tplane:stream_started` | Provider, model name. No prompts, no message content. |
35
+ | `tplane:stream_ended` | Provider, model name, duration. No prompts, no completions, no message content. |
36
+ | `tplane:stream_errored` | Provider, model name, error class. No prompts, no completions, no message content. |
37
37
 
38
38
  ### Browser events (opt-in, off by default)
39
39
 
@@ -41,10 +41,10 @@ Nothing fires unless `provideThreadplaneTelemetry({ enabled: true, ... })` is ca
41
41
 
42
42
  | Event | What is sent |
43
43
  |-------|-------------|
44
- | `ngaf:browser_provided` | Telemetry initialized; surface name, sample weight. Anonymous, no user data. |
45
- | `ngaf:browser_chat_init` | Chat component initialized; surface name, sample weight. Anonymous, no message content. |
44
+ | `tplane:browser_provided` | Telemetry initialized; surface name, sample weight. Anonymous, no user data. |
45
+ | `tplane:browser_chat_init` | Chat component initialized; surface name, sample weight. Anonymous, no message content. |
46
46
 
47
- Browser-side runtime lifecycle events (`ngaf:runtime_instance_created`, `ngaf:runtime_request_created`, `ngaf:stream_started`, `ngaf:stream_ended`, `ngaf:stream_errored`) may also be sent when the app captures them explicitly. Same payload constraints as Node.
47
+ Browser-side runtime lifecycle events (`tplane:runtime_instance_created`, `tplane:runtime_request_created`, `tplane:stream_started`, `tplane:stream_ended`, `tplane:stream_errored`) may also be sent when the app captures them explicitly. Same payload constraints as Node.
48
48
 
49
49
  ### Never collected — by anyone, at any time
50
50
 
@@ -73,7 +73,7 @@ Node telemetry is on by default. Any one of the following turns it off entirely.
73
73
 
74
74
  | Variable | Value | Notes |
75
75
  |----------|-------|-------|
76
- | `NGAF_TELEMETRY_DISABLED` | `1` or `true` | Package-level kill-switch |
76
+ | `TPLANE_TELEMETRY_DISABLED` | `1` or `true` | Package-level kill-switch |
77
77
  | `DO_NOT_TRACK` | `1` or `true` | Cross-vendor standard; `npm_config_do_not_track` and `NPM_CONFIG_DO_NOT_TRACK` are also respected |
78
78
 
79
79
  ### CI auto-disable
@@ -98,7 +98,7 @@ disableTelemetry();
98
98
  Default sample rate is **1.0** (100%). Reduce it via:
99
99
 
100
100
  ```bash
101
- NGAF_TELEMETRY_SAMPLE_RATE=0.1 # sample 10% of events
101
+ TPLANE_TELEMETRY_SAMPLE_RATE=0.1 # sample 10% of events
102
102
  ```
103
103
 
104
104
  Every event carries a `sample_weight` property so de-sampling at query time works correctly.
@@ -108,10 +108,10 @@ Every event carries a `sample_weight` property so de-sampling at query time work
108
108
  Redirect all Node telemetry to your own endpoint:
109
109
 
110
110
  ```bash
111
- NGAF_TELEMETRY_INGEST_URL=https://telemetry.acme-internal.example.com/api/ingest
111
+ TPLANE_TELEMETRY_INGEST_URL=https://telemetry.acme-internal.example.com/api/ingest
112
112
  ```
113
113
 
114
- The default ingest (when unset) is a thin proxy at `https://threadplane.ai/api/ingest` that accepts the `@threadplane/telemetry` JSON payload, forwards `ngaf:*` events to the project PostHog instance, and does not forward installer IP addresses. Source lives in `apps/website/src/app/api/ingest/`.
114
+ The default ingest (when unset) is a thin proxy at `https://threadplane.ai/api/ingest` that accepts the `@threadplane/telemetry` JSON payload, forwards `tplane:*` events to the project PostHog instance, and does not forward installer IP addresses. Source lives in `apps/website/src/app/api/ingest/`.
115
115
 
116
116
  ## Usage
117
117
 
@@ -175,7 +175,7 @@ import {
175
175
  } from '@threadplane/telemetry';
176
176
  ```
177
177
 
178
- `getDisableReason()` returns `'DO_NOT_TRACK' | 'NGAF_TELEMETRY_DISABLED' | 'CI' | null`.
178
+ `getDisableReason()` returns `'DO_NOT_TRACK' | 'TPLANE_TELEMETRY_DISABLED' | 'CI' | null`.
179
179
 
180
180
  ## Reliability and transparency
181
181
 
@@ -184,10 +184,10 @@ import {
184
184
  Inspect payloads locally without sending them:
185
185
 
186
186
  ```bash
187
- DEBUG=ngaf:telemetry npm install
187
+ DEBUG=tplane:telemetry npm install
188
188
  ```
189
189
 
190
- `ngaf:telemetry` is the debug namespace — it is not an event name and is never sent to the ingest endpoint.
190
+ `tplane:telemetry` is the debug namespace — it is not an event name and is never sent to the ingest endpoint.
191
191
 
192
192
  ### Anonymous id strategy
193
193
 
package/browser/README.md CHANGED
@@ -28,12 +28,12 @@ Transparent, opt-out anonymous usage telemetry for the Threadplane framework. Is
28
28
 
29
29
  | Event | What is sent |
30
30
  |-------|-------------|
31
- | `ngaf:postinstall` | Package name, package version, Node version, OS, CPU architecture, package manager name/version, workspace/global install flags when npm exposes them, sample weight. Per-process anonymous id. No project path, no raw environment variables, no dependency tree, no installer IP address. |
32
- | `ngaf:runtime_instance_created` | Which transport, which model provider (string), Angular peer version. No API keys, no endpoint hostnames, no user data. |
33
- | `ngaf:runtime_request_created` | Transport, request type, provider, model. No prompts, thread IDs, assistant IDs, endpoint URLs, or headers. |
34
- | `ngaf:stream_started` | Provider, model name. No prompts, no message content. |
35
- | `ngaf:stream_ended` | Provider, model name, duration. No prompts, no completions, no message content. |
36
- | `ngaf:stream_errored` | Provider, model name, error class. No prompts, no completions, no message content. |
31
+ | `tplane:postinstall` | Package name, package version, Node version, OS, CPU architecture, package manager name/version, workspace/global install flags when npm exposes them, sample weight. Per-process anonymous id. No project path, no raw environment variables, no dependency tree, no installer IP address. |
32
+ | `tplane:runtime_instance_created` | Which transport, which model provider (string), Angular peer version. No API keys, no endpoint hostnames, no user data. |
33
+ | `tplane:runtime_request_created` | Transport, request type, provider, model. No prompts, thread IDs, assistant IDs, endpoint URLs, or headers. |
34
+ | `tplane:stream_started` | Provider, model name. No prompts, no message content. |
35
+ | `tplane:stream_ended` | Provider, model name, duration. No prompts, no completions, no message content. |
36
+ | `tplane:stream_errored` | Provider, model name, error class. No prompts, no completions, no message content. |
37
37
 
38
38
  ### Browser events (opt-in, off by default)
39
39
 
@@ -41,10 +41,10 @@ Nothing fires unless `provideThreadplaneTelemetry({ enabled: true, ... })` is ca
41
41
 
42
42
  | Event | What is sent |
43
43
  |-------|-------------|
44
- | `ngaf:browser_provided` | Telemetry initialized; surface name, sample weight. Anonymous, no user data. |
45
- | `ngaf:browser_chat_init` | Chat component initialized; surface name, sample weight. Anonymous, no message content. |
44
+ | `tplane:browser_provided` | Telemetry initialized; surface name, sample weight. Anonymous, no user data. |
45
+ | `tplane:browser_chat_init` | Chat component initialized; surface name, sample weight. Anonymous, no message content. |
46
46
 
47
- Browser-side runtime lifecycle events (`ngaf:runtime_instance_created`, `ngaf:runtime_request_created`, `ngaf:stream_started`, `ngaf:stream_ended`, `ngaf:stream_errored`) may also be sent when the app captures them explicitly. Same payload constraints as Node.
47
+ Browser-side runtime lifecycle events (`tplane:runtime_instance_created`, `tplane:runtime_request_created`, `tplane:stream_started`, `tplane:stream_ended`, `tplane:stream_errored`) may also be sent when the app captures them explicitly. Same payload constraints as Node.
48
48
 
49
49
  ### Never collected — by anyone, at any time
50
50
 
@@ -73,7 +73,7 @@ Node telemetry is on by default. Any one of the following turns it off entirely.
73
73
 
74
74
  | Variable | Value | Notes |
75
75
  |----------|-------|-------|
76
- | `NGAF_TELEMETRY_DISABLED` | `1` or `true` | Package-level kill-switch |
76
+ | `TPLANE_TELEMETRY_DISABLED` | `1` or `true` | Package-level kill-switch |
77
77
  | `DO_NOT_TRACK` | `1` or `true` | Cross-vendor standard; `npm_config_do_not_track` and `NPM_CONFIG_DO_NOT_TRACK` are also respected |
78
78
 
79
79
  ### CI auto-disable
@@ -98,7 +98,7 @@ disableTelemetry();
98
98
  Default sample rate is **1.0** (100%). Reduce it via:
99
99
 
100
100
  ```bash
101
- NGAF_TELEMETRY_SAMPLE_RATE=0.1 # sample 10% of events
101
+ TPLANE_TELEMETRY_SAMPLE_RATE=0.1 # sample 10% of events
102
102
  ```
103
103
 
104
104
  Every event carries a `sample_weight` property so de-sampling at query time works correctly.
@@ -108,10 +108,10 @@ Every event carries a `sample_weight` property so de-sampling at query time work
108
108
  Redirect all Node telemetry to your own endpoint:
109
109
 
110
110
  ```bash
111
- NGAF_TELEMETRY_INGEST_URL=https://telemetry.acme-internal.example.com/api/ingest
111
+ TPLANE_TELEMETRY_INGEST_URL=https://telemetry.acme-internal.example.com/api/ingest
112
112
  ```
113
113
 
114
- The default ingest (when unset) is a thin proxy at `https://threadplane.ai/api/ingest` that accepts the `@threadplane/telemetry` JSON payload, forwards `ngaf:*` events to the project PostHog instance, and does not forward installer IP addresses. Source lives in `apps/website/src/app/api/ingest/`.
114
+ The default ingest (when unset) is a thin proxy at `https://threadplane.ai/api/ingest` that accepts the `@threadplane/telemetry` JSON payload, forwards `tplane:*` events to the project PostHog instance, and does not forward installer IP addresses. Source lives in `apps/website/src/app/api/ingest/`.
115
115
 
116
116
  ## Usage
117
117
 
@@ -175,7 +175,7 @@ import {
175
175
  } from '@threadplane/telemetry';
176
176
  ```
177
177
 
178
- `getDisableReason()` returns `'DO_NOT_TRACK' | 'NGAF_TELEMETRY_DISABLED' | 'CI' | null`.
178
+ `getDisableReason()` returns `'DO_NOT_TRACK' | 'TPLANE_TELEMETRY_DISABLED' | 'CI' | null`.
179
179
 
180
180
  ## Reliability and transparency
181
181
 
@@ -184,10 +184,10 @@ import {
184
184
  Inspect payloads locally without sending them:
185
185
 
186
186
  ```bash
187
- DEBUG=ngaf:telemetry npm install
187
+ DEBUG=tplane:telemetry npm install
188
188
  ```
189
189
 
190
- `ngaf:telemetry` is the debug namespace — it is not an event name and is never sent to the ingest endpoint.
190
+ `tplane:telemetry` is the debug namespace — it is not an event name and is never sent to the ingest endpoint.
191
191
 
192
192
  ### Anonymous id strategy
193
193
 
@@ -59,20 +59,20 @@ class ThreadplaneTelemetryService {
59
59
  }
60
60
  }
61
61
  captureRuntimeInstanceCreated(input) {
62
- return this.capture('ngaf:runtime_instance_created', { ...input });
62
+ return this.capture('tplane:runtime_instance_created', { ...input });
63
63
  }
64
64
  captureRuntimeRequestCreated(input) {
65
- return this.capture('ngaf:runtime_request_created', { ...input });
65
+ return this.capture('tplane:runtime_request_created', { ...input });
66
66
  }
67
67
  captureStreamStarted(input) {
68
- return this.capture('ngaf:stream_started', { ...input });
68
+ return this.capture('tplane:stream_started', { ...input });
69
69
  }
70
70
  captureStreamEnded(input) {
71
- return this.capture('ngaf:stream_ended', { ...input });
71
+ return this.capture('tplane:stream_ended', { ...input });
72
72
  }
73
73
  captureStreamErrored(input) {
74
74
  const { error, ...rest } = input;
75
- return this.capture('ngaf:stream_errored', {
75
+ return this.capture('tplane:stream_errored', {
76
76
  ...rest,
77
77
  errorClass: errorClass(error),
78
78
  });
@@ -1 +1 @@
1
- {"version":3,"file":"threadplane-telemetry.mjs","sources":["../../../../../libs/telemetry/src/browser/tokens.ts","../../../../../libs/telemetry/src/browser/service.ts","../../../../../libs/telemetry/src/browser/provide.ts","../../../../../libs/telemetry/src/browser/properties.ts","../../../../../libs/telemetry/src/browser/threadplane-telemetry.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport type ThreadplaneTelemetryEvent =\n | 'ngaf:browser_provided'\n | 'ngaf:browser_chat_init'\n | 'ngaf:runtime_instance_created'\n | 'ngaf:runtime_request_created'\n | 'ngaf:stream_started'\n | 'ngaf:stream_ended'\n | 'ngaf:stream_errored';\n\nexport interface ThreadplaneTelemetryEventPayload {\n event: ThreadplaneTelemetryEvent;\n properties?: Record<string, unknown>;\n}\n\nexport type ThreadplaneTelemetrySink = (payload: ThreadplaneTelemetryEventPayload) => void | Promise<void>;\n\nexport interface ThreadplaneTelemetryConfig {\n enabled: boolean;\n /**\n * Preferred app-owned delivery hook. Use this when the consuming app wants\n * to forward events through its own analytics boundary.\n */\n sink?: ThreadplaneTelemetrySink;\n /**\n * Preferred app-owned ingest URL. The browser service POSTs neutral event\n * payloads here; the endpoint decides where they ultimately go.\n */\n endpoint?: string;\n /** @deprecated Prefer sink or endpoint so public app code is vendor-neutral. */\n posthogKey?: string;\n /** @deprecated Prefer sink or endpoint so public app code is vendor-neutral. */\n posthogHost?: string;\n sampleRate?: number;\n}\n\nexport const THREADPLANE_TELEMETRY_CONFIG = new InjectionToken<ThreadplaneTelemetryConfig | null>(\n 'THREADPLANE_TELEMETRY_CONFIG',\n);\n","import { Injectable, inject } from '@angular/core';\nimport {\n THREADPLANE_TELEMETRY_CONFIG,\n type ThreadplaneTelemetryConfig,\n type ThreadplaneTelemetryEvent,\n} from './tokens';\n\n// Inlined from shared/events.ts: ng-packagr enforces rootDir at the entry-file\n// level (src/browser/), so the browser entry cannot import from ../shared/.\n// Keep this type in sync with shared/events.ts.\nexport type ThreadplaneBrowserEvent = ThreadplaneTelemetryEvent;\n\nexport interface ThreadplaneBrowserRuntimeTelemetry {\n transport: string;\n surface?: string;\n provider?: string;\n model?: string;\n}\n\nexport interface ThreadplaneBrowserStreamTelemetry extends ThreadplaneBrowserRuntimeTelemetry {\n durationMs?: number;\n}\n\nexport interface ThreadplaneBrowserStreamErrorTelemetry extends ThreadplaneBrowserStreamTelemetry {\n error?: unknown;\n}\n\nfunction normalizeSampleRate(sampleRate: number | undefined): number {\n if (sampleRate === undefined) return 1;\n if (!Number.isFinite(sampleRate)) return 1;\n if (sampleRate <= 0) return 0;\n if (sampleRate >= 1) return 1;\n return sampleRate;\n}\n\nfunction errorClass(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n if (error && typeof error === 'object' && 'name' in error && typeof error.name === 'string') {\n return error.name;\n }\n return 'UnknownError';\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ThreadplaneTelemetryService {\n private config: ThreadplaneTelemetryConfig | null = inject(THREADPLANE_TELEMETRY_CONFIG, { optional: true });\n private postHogPromise: Promise<typeof import('posthog-js')['default'] | null> | null = null;\n private distinctId: string | null = null;\n\n async capture(event: ThreadplaneTelemetryEvent, properties?: Record<string, unknown>): Promise<void> {\n if (!this.config?.enabled) return;\n const sampleRate = normalizeSampleRate(this.config.sampleRate);\n if (sampleRate === 0) return;\n if (sampleRate < 1 && Math.random() >= sampleRate) return;\n\n const enrichedProperties = {\n ...(properties ?? {}),\n sample_weight: properties?.['sample_weight'] ?? 1 / sampleRate,\n };\n\n try {\n if (this.config.sink) {\n await this.config.sink({ event, properties: enrichedProperties });\n return;\n }\n if (this.config.endpoint) {\n await this.captureEndpoint(event, enrichedProperties);\n return;\n }\n if (!this.config.posthogKey) return;\n const ph = await this.loadPostHog();\n if (!ph) return;\n ph.capture(event, enrichedProperties);\n } catch {\n // silent fail\n }\n }\n\n captureRuntimeInstanceCreated(input: ThreadplaneBrowserRuntimeTelemetry): Promise<void> {\n return this.capture('ngaf:runtime_instance_created', { ...input });\n }\n\n captureRuntimeRequestCreated(input: ThreadplaneBrowserRuntimeTelemetry & { requestType: string }): Promise<void> {\n return this.capture('ngaf:runtime_request_created', { ...input });\n }\n\n captureStreamStarted(input: ThreadplaneBrowserStreamTelemetry): Promise<void> {\n return this.capture('ngaf:stream_started', { ...input });\n }\n\n captureStreamEnded(input: ThreadplaneBrowserStreamTelemetry): Promise<void> {\n return this.capture('ngaf:stream_ended', { ...input });\n }\n\n captureStreamErrored(input: ThreadplaneBrowserStreamErrorTelemetry): Promise<void> {\n const { error, ...rest } = input;\n return this.capture('ngaf:stream_errored', {\n ...rest,\n errorClass: errorClass(error),\n });\n }\n\n private async captureEndpoint(event: ThreadplaneTelemetryEvent, properties: Record<string, unknown>): Promise<void> {\n if (typeof fetch !== 'function' || !this.config?.endpoint) return;\n await fetch(this.config.endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n keepalive: true,\n body: JSON.stringify({\n event,\n distinctId: this.getDistinctId(),\n properties,\n }),\n });\n }\n\n private getDistinctId(): string {\n if (!this.distinctId) {\n const cryptoApi = globalThis.crypto as Crypto | undefined;\n const value = typeof cryptoApi?.randomUUID === 'function'\n ? cryptoApi.randomUUID()\n : Math.random().toString(36).slice(2, 12);\n this.distinctId = `browser:${value}`;\n }\n return this.distinctId;\n }\n\n private loadPostHog(): Promise<typeof import('posthog-js')['default'] | null> {\n if (!this.postHogPromise) {\n this.postHogPromise = import('posthog-js').then((mod) => {\n if (!this.config?.posthogKey) return null;\n mod.default.init(this.config.posthogKey, {\n api_host: this.config.posthogHost ?? 'https://us.i.posthog.com',\n });\n return mod.default;\n }).catch(() => null);\n }\n return this.postHogPromise;\n }\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { THREADPLANE_TELEMETRY_CONFIG, type ThreadplaneTelemetryConfig } from './tokens';\nimport { ThreadplaneTelemetryService } from './service';\n\nexport function provideThreadplaneTelemetry(config: ThreadplaneTelemetryConfig): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: THREADPLANE_TELEMETRY_CONFIG, useValue: config },\n ThreadplaneTelemetryService,\n ]);\n}\n","// SPDX-License-Identifier: MIT\n// Note: kept self-contained (no `../shared` import) so ng-packagr can compile\n// this entry point in isolation. The trim+truncate hardening is duplicated\n// from shared/properties.ts on purpose — it's a few lines, and the alternative\n// is a secondary ng-packagr entry point for shared, which is heavier.\nfunction toSafeString(value: unknown, maxLength: number): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n return trimmed.slice(0, maxLength);\n}\n\nexport type CaptureConfig = {\n token?: string;\n captureLocal?: boolean;\n host?: string;\n};\n\nexport function isLocalAnalyticsHost(host: unknown): boolean {\n const value = toSafeString(host, 300)?.toLowerCase();\n if (!value) return false;\n\n // IPv6 literal `::1` or `[::1]:port` — don't naively split on `:`.\n if (value === '::1' || value.startsWith('[::1]')) return true;\n\n const hostname = value.split(':')[0];\n return hostname === 'localhost' || hostname === '127.0.0.1';\n}\n\nexport function shouldCaptureAnalytics({ token, captureLocal = false, host }: CaptureConfig): boolean {\n if (!toSafeString(token, 500)) return false;\n if (isLocalAnalyticsHost(host) && !captureLocal) return false;\n return true;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"threadplane-telemetry.mjs","sources":["../../../../../libs/telemetry/src/browser/tokens.ts","../../../../../libs/telemetry/src/browser/service.ts","../../../../../libs/telemetry/src/browser/provide.ts","../../../../../libs/telemetry/src/browser/properties.ts","../../../../../libs/telemetry/src/browser/threadplane-telemetry.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport type ThreadplaneTelemetryEvent =\n | 'tplane:browser_provided'\n | 'tplane:browser_chat_init'\n | 'tplane:runtime_instance_created'\n | 'tplane:runtime_request_created'\n | 'tplane:stream_started'\n | 'tplane:stream_ended'\n | 'tplane:stream_errored';\n\nexport interface ThreadplaneTelemetryEventPayload {\n event: ThreadplaneTelemetryEvent;\n properties?: Record<string, unknown>;\n}\n\nexport type ThreadplaneTelemetrySink = (payload: ThreadplaneTelemetryEventPayload) => void | Promise<void>;\n\nexport interface ThreadplaneTelemetryConfig {\n enabled: boolean;\n /**\n * Preferred app-owned delivery hook. Use this when the consuming app wants\n * to forward events through its own analytics boundary.\n */\n sink?: ThreadplaneTelemetrySink;\n /**\n * Preferred app-owned ingest URL. The browser service POSTs neutral event\n * payloads here; the endpoint decides where they ultimately go.\n */\n endpoint?: string;\n /** @deprecated Prefer sink or endpoint so public app code is vendor-neutral. */\n posthogKey?: string;\n /** @deprecated Prefer sink or endpoint so public app code is vendor-neutral. */\n posthogHost?: string;\n sampleRate?: number;\n}\n\nexport const THREADPLANE_TELEMETRY_CONFIG = new InjectionToken<ThreadplaneTelemetryConfig | null>(\n 'THREADPLANE_TELEMETRY_CONFIG',\n);\n","import { Injectable, inject } from '@angular/core';\nimport {\n THREADPLANE_TELEMETRY_CONFIG,\n type ThreadplaneTelemetryConfig,\n type ThreadplaneTelemetryEvent,\n} from './tokens';\n\n// Inlined from shared/events.ts: ng-packagr enforces rootDir at the entry-file\n// level (src/browser/), so the browser entry cannot import from ../shared/.\n// Keep this type in sync with shared/events.ts.\nexport type ThreadplaneBrowserEvent = ThreadplaneTelemetryEvent;\n\nexport interface ThreadplaneBrowserRuntimeTelemetry {\n transport: string;\n surface?: string;\n provider?: string;\n model?: string;\n}\n\nexport interface ThreadplaneBrowserStreamTelemetry extends ThreadplaneBrowserRuntimeTelemetry {\n durationMs?: number;\n}\n\nexport interface ThreadplaneBrowserStreamErrorTelemetry extends ThreadplaneBrowserStreamTelemetry {\n error?: unknown;\n}\n\nfunction normalizeSampleRate(sampleRate: number | undefined): number {\n if (sampleRate === undefined) return 1;\n if (!Number.isFinite(sampleRate)) return 1;\n if (sampleRate <= 0) return 0;\n if (sampleRate >= 1) return 1;\n return sampleRate;\n}\n\nfunction errorClass(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n if (error && typeof error === 'object' && 'name' in error && typeof error.name === 'string') {\n return error.name;\n }\n return 'UnknownError';\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ThreadplaneTelemetryService {\n private config: ThreadplaneTelemetryConfig | null = inject(THREADPLANE_TELEMETRY_CONFIG, { optional: true });\n private postHogPromise: Promise<typeof import('posthog-js')['default'] | null> | null = null;\n private distinctId: string | null = null;\n\n async capture(event: ThreadplaneTelemetryEvent, properties?: Record<string, unknown>): Promise<void> {\n if (!this.config?.enabled) return;\n const sampleRate = normalizeSampleRate(this.config.sampleRate);\n if (sampleRate === 0) return;\n if (sampleRate < 1 && Math.random() >= sampleRate) return;\n\n const enrichedProperties = {\n ...(properties ?? {}),\n sample_weight: properties?.['sample_weight'] ?? 1 / sampleRate,\n };\n\n try {\n if (this.config.sink) {\n await this.config.sink({ event, properties: enrichedProperties });\n return;\n }\n if (this.config.endpoint) {\n await this.captureEndpoint(event, enrichedProperties);\n return;\n }\n if (!this.config.posthogKey) return;\n const ph = await this.loadPostHog();\n if (!ph) return;\n ph.capture(event, enrichedProperties);\n } catch {\n // silent fail\n }\n }\n\n captureRuntimeInstanceCreated(input: ThreadplaneBrowserRuntimeTelemetry): Promise<void> {\n return this.capture('tplane:runtime_instance_created', { ...input });\n }\n\n captureRuntimeRequestCreated(input: ThreadplaneBrowserRuntimeTelemetry & { requestType: string }): Promise<void> {\n return this.capture('tplane:runtime_request_created', { ...input });\n }\n\n captureStreamStarted(input: ThreadplaneBrowserStreamTelemetry): Promise<void> {\n return this.capture('tplane:stream_started', { ...input });\n }\n\n captureStreamEnded(input: ThreadplaneBrowserStreamTelemetry): Promise<void> {\n return this.capture('tplane:stream_ended', { ...input });\n }\n\n captureStreamErrored(input: ThreadplaneBrowserStreamErrorTelemetry): Promise<void> {\n const { error, ...rest } = input;\n return this.capture('tplane:stream_errored', {\n ...rest,\n errorClass: errorClass(error),\n });\n }\n\n private async captureEndpoint(event: ThreadplaneTelemetryEvent, properties: Record<string, unknown>): Promise<void> {\n if (typeof fetch !== 'function' || !this.config?.endpoint) return;\n await fetch(this.config.endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n keepalive: true,\n body: JSON.stringify({\n event,\n distinctId: this.getDistinctId(),\n properties,\n }),\n });\n }\n\n private getDistinctId(): string {\n if (!this.distinctId) {\n const cryptoApi = globalThis.crypto as Crypto | undefined;\n const value = typeof cryptoApi?.randomUUID === 'function'\n ? cryptoApi.randomUUID()\n : Math.random().toString(36).slice(2, 12);\n this.distinctId = `browser:${value}`;\n }\n return this.distinctId;\n }\n\n private loadPostHog(): Promise<typeof import('posthog-js')['default'] | null> {\n if (!this.postHogPromise) {\n this.postHogPromise = import('posthog-js').then((mod) => {\n if (!this.config?.posthogKey) return null;\n mod.default.init(this.config.posthogKey, {\n api_host: this.config.posthogHost ?? 'https://us.i.posthog.com',\n });\n return mod.default;\n }).catch(() => null);\n }\n return this.postHogPromise;\n }\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { THREADPLANE_TELEMETRY_CONFIG, type ThreadplaneTelemetryConfig } from './tokens';\nimport { ThreadplaneTelemetryService } from './service';\n\nexport function provideThreadplaneTelemetry(config: ThreadplaneTelemetryConfig): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: THREADPLANE_TELEMETRY_CONFIG, useValue: config },\n ThreadplaneTelemetryService,\n ]);\n}\n","// SPDX-License-Identifier: MIT\n// Note: kept self-contained (no `../shared` import) so ng-packagr can compile\n// this entry point in isolation. The trim+truncate hardening is duplicated\n// from shared/properties.ts on purpose — it's a few lines, and the alternative\n// is a secondary ng-packagr entry point for shared, which is heavier.\nfunction toSafeString(value: unknown, maxLength: number): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n return trimmed.slice(0, maxLength);\n}\n\nexport type CaptureConfig = {\n token?: string;\n captureLocal?: boolean;\n host?: string;\n};\n\nexport function isLocalAnalyticsHost(host: unknown): boolean {\n const value = toSafeString(host, 300)?.toLowerCase();\n if (!value) return false;\n\n // IPv6 literal `::1` or `[::1]:port` — don't naively split on `:`.\n if (value === '::1' || value.startsWith('[::1]')) return true;\n\n const hostname = value.split(':')[0];\n return hostname === 'localhost' || hostname === '127.0.0.1';\n}\n\nexport function shouldCaptureAnalytics({ token, captureLocal = false, host }: CaptureConfig): boolean {\n if (!toSafeString(token, 500)) return false;\n if (isLocalAnalyticsHost(host) && !captureLocal) return false;\n return true;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, EnvironmentProviders } from '@angular/core';
3
3
 
4
- type ThreadplaneTelemetryEvent = 'ngaf:browser_provided' | 'ngaf:browser_chat_init' | 'ngaf:runtime_instance_created' | 'ngaf:runtime_request_created' | 'ngaf:stream_started' | 'ngaf:stream_ended' | 'ngaf:stream_errored';
4
+ type ThreadplaneTelemetryEvent = 'tplane:browser_provided' | 'tplane:browser_chat_init' | 'tplane:runtime_instance_created' | 'tplane:runtime_request_created' | 'tplane:stream_started' | 'tplane:stream_ended' | 'tplane:stream_errored';
5
5
  interface ThreadplaneTelemetryEventPayload {
6
6
  event: ThreadplaneTelemetryEvent;
7
7
  properties?: Record<string, unknown>;
package/node/adapter.js CHANGED
@@ -9,22 +9,22 @@ export async function captureRuntimeInstanceCreated(input) {
9
9
  await safe(async () => {
10
10
  const { apiKey, ...rest } = input;
11
11
  void apiKey;
12
- await captureEvent('ngaf:runtime_instance_created', { ...rest });
12
+ await captureEvent('tplane:runtime_instance_created', { ...rest });
13
13
  });
14
14
  }
15
15
  export async function captureRuntimeRequestCreated(input) {
16
- await safe(() => captureEvent('ngaf:runtime_request_created', { ...input }));
16
+ await safe(() => captureEvent('tplane:runtime_request_created', { ...input }));
17
17
  }
18
18
  export async function captureStreamStarted(input) {
19
- await safe(() => captureEvent('ngaf:stream_started', { ...input }));
19
+ await safe(() => captureEvent('tplane:stream_started', { ...input }));
20
20
  }
21
21
  export async function captureStreamEnded(input) {
22
- await safe(() => captureEvent('ngaf:stream_ended', { ...input }));
22
+ await safe(() => captureEvent('tplane:stream_ended', { ...input }));
23
23
  }
24
24
  export async function captureStreamErrored(input) {
25
25
  await safe(async () => {
26
26
  const { error, ...rest } = input;
27
27
  const errorClass = error instanceof Error ? error.constructor.name : 'Unknown';
28
- await captureEvent('ngaf:stream_errored', { ...rest, errorClass });
28
+ await captureEvent('tplane:stream_errored', { ...rest, errorClass });
29
29
  });
30
30
  }
package/node/client.js CHANGED
@@ -8,7 +8,7 @@ const REQUEST_TIMEOUT_MS = 3_000;
8
8
  // server-side with the private PostHog token.
9
9
  const PUBLIC_INGEST_KEY = 'phc_public_cacheplane_telemetry';
10
10
  function getSampleRate(env = process.env) {
11
- const parsed = Number(env.NGAF_TELEMETRY_SAMPLE_RATE ?? '1');
11
+ const parsed = Number(env.TPLANE_TELEMETRY_SAMPLE_RATE ?? '1');
12
12
  if (!Number.isFinite(parsed))
13
13
  return 1;
14
14
  return Math.max(0, Math.min(1, parsed));
@@ -94,7 +94,7 @@ export async function captureEvent(event, properties = {}) {
94
94
  if (!shouldSample(rate, anonId))
95
95
  return { sent: false, reason: 'sampled' };
96
96
  try {
97
- await postJson(process.env.NGAF_TELEMETRY_INGEST_URL ?? DEFAULT_INGEST, {
97
+ await postJson(process.env.TPLANE_TELEMETRY_INGEST_URL ?? DEFAULT_INGEST, {
98
98
  key: PUBLIC_INGEST_KEY,
99
99
  distinctId: anonId,
100
100
  event,
@@ -110,7 +110,7 @@ export async function captureEvent(event, properties = {}) {
110
110
  }
111
111
  }
112
112
  export async function capturePostinstall(input) {
113
- return captureEvent('ngaf:postinstall', createPostinstallProperties(input));
113
+ return captureEvent('tplane:postinstall', createPostinstallProperties(input));
114
114
  }
115
115
  // @internal — tests only
116
116
  export function _resetClientForTesting() {
@@ -11,7 +11,7 @@ function truthy(value) {
11
11
  function debugEnabled(env) {
12
12
  return (env.DEBUG ?? '')
13
13
  .split(/[\s,]+/)
14
- .some((part) => part === '*' || part === 'ngaf:*' || part === 'ngaf:telemetry');
14
+ .some((part) => part === '*' || part === 'tplane:*' || part === 'tplane:telemetry');
15
15
  }
16
16
  function isGlobalInstall(env) {
17
17
  return truthy(env.npm_config_global) || env.npm_config_location === 'global';
@@ -43,7 +43,7 @@ function readLifecyclePackageJson(env, cwd) {
43
43
  }
44
44
  export async function capturePostinstallScript(deps) {
45
45
  // Single opt-out gate. DO_NOT_TRACK, npm_config_do_not_track,
46
- // NGAF_TELEMETRY_DISABLED, and CI envs all return early: no event, no notice.
46
+ // TPLANE_TELEMETRY_DISABLED, and CI envs all return early: no event, no notice.
47
47
  if (isTelemetryDisabled(deps.env))
48
48
  return;
49
49
  const cwd = deps.cwd?.() ?? process.cwd();
@@ -60,13 +60,13 @@ export async function capturePostinstallScript(deps) {
60
60
  const result = await capturePostinstall({ pkg: pkg.name, version: pkg.version });
61
61
  if (debugEnabled(deps.env)) {
62
62
  deps.write(`@threadplane/telemetry payload: ${JSON.stringify({
63
- event: 'ngaf:postinstall',
63
+ event: 'tplane:postinstall',
64
64
  properties: createPostinstallProperties({ pkg: pkg.name, version: pkg.version }, deps.env),
65
65
  })}\n`);
66
66
  }
67
67
  if (result.sent) {
68
68
  deps.write(`@threadplane/telemetry: install telemetry sent (${pkg.name}@${pkg.version}). ` +
69
- `Disable: DO_NOT_TRACK=1 or NGAF_TELEMETRY_DISABLED=1. ` +
69
+ `Disable: DO_NOT_TRACK=1 or TPLANE_TELEMETRY_DISABLED=1. ` +
70
70
  `See https://github.com/cacheplane/angular-agent-framework/blob/main/libs/telemetry/README.md\n`);
71
71
  }
72
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadplane/telemetry",
3
- "version": "0.0.52",
3
+ "version": "0.0.54",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/shared/env.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- type DisableReason = 'DO_NOT_TRACK' | 'NGAF_TELEMETRY_DISABLED' | 'CI' | null;
1
+ type DisableReason = 'DO_NOT_TRACK' | 'TPLANE_TELEMETRY_DISABLED' | 'CI' | null;
2
2
  export declare function getDisableReason(env?: NodeJS.ProcessEnv): DisableReason;
3
3
  export declare function isTelemetryDisabled(env?: NodeJS.ProcessEnv): boolean;
4
4
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../../libs/telemetry/src/shared/env.ts"],"names":[],"mappings":"AAMA,KAAK,aAAa,GAAG,cAAc,GAAG,yBAAyB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9E,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,CAepF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEjF"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../../libs/telemetry/src/shared/env.ts"],"names":[],"mappings":"AAMA,KAAK,aAAa,GAAG,cAAc,GAAG,2BAA2B,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhF,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,CAepF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEjF"}
package/shared/env.js CHANGED
@@ -6,8 +6,8 @@ export function getDisableReason(env = process.env) {
6
6
  if (truthy(env.DO_NOT_TRACK) || truthy(env.npm_config_do_not_track) || truthy(env.NPM_CONFIG_DO_NOT_TRACK)) {
7
7
  return 'DO_NOT_TRACK';
8
8
  }
9
- if (truthy(env.NGAF_TELEMETRY_DISABLED))
10
- return 'NGAF_TELEMETRY_DISABLED';
9
+ if (truthy(env.TPLANE_TELEMETRY_DISABLED))
10
+ return 'TPLANE_TELEMETRY_DISABLED';
11
11
  if (truthy(env.CI) ||
12
12
  truthy(env.GITHUB_ACTIONS) ||
13
13
  truthy(env.CONTINUOUS_INTEGRATION) ||
@@ -1,4 +1,4 @@
1
- export type ThreadplaneNodeEvent = 'ngaf:postinstall' | 'ngaf:runtime_instance_created' | 'ngaf:runtime_request_created' | 'ngaf:stream_started' | 'ngaf:stream_ended' | 'ngaf:stream_errored';
2
- export type ThreadplaneBrowserEvent = 'ngaf:browser_provided' | 'ngaf:browser_chat_init';
1
+ export type ThreadplaneNodeEvent = 'tplane:postinstall' | 'tplane:runtime_instance_created' | 'tplane:runtime_request_created' | 'tplane:stream_started' | 'tplane:stream_ended' | 'tplane:stream_errored';
2
+ export type ThreadplaneBrowserEvent = 'tplane:browser_provided' | 'tplane:browser_chat_init';
3
3
  export type ThreadplaneEvent = ThreadplaneNodeEvent | ThreadplaneBrowserEvent;
4
4
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../../libs/telemetry/src/shared/events.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B,kBAAkB,GAClB,+BAA+B,GAC/B,8BAA8B,GAC9B,qBAAqB,GACrB,mBAAmB,GACnB,qBAAqB,CAAC;AAE1B,MAAM,MAAM,uBAAuB,GAC/B,uBAAuB,GACvB,wBAAwB,CAAC;AAE7B,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,uBAAuB,CAAC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../../libs/telemetry/src/shared/events.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B,oBAAoB,GACpB,iCAAiC,GACjC,gCAAgC,GAChC,uBAAuB,GACvB,qBAAqB,GACrB,uBAAuB,CAAC;AAE5B,MAAM,MAAM,uBAAuB,GAC/B,yBAAyB,GACzB,0BAA0B,CAAC;AAE/B,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,uBAAuB,CAAC"}