@muggleai/telemetry 0.2.0

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.
Files changed (83) hide show
  1. package/PRIVACY.md +52 -0
  2. package/README.md +86 -0
  3. package/dist/client.d.ts +8 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +96 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/constants/disclosure.d.ts +2 -0
  8. package/dist/constants/disclosure.d.ts.map +1 -0
  9. package/dist/constants/disclosure.js +2 -0
  10. package/dist/constants/disclosure.js.map +1 -0
  11. package/dist/constants/env.d.ts +4 -0
  12. package/dist/constants/env.d.ts.map +1 -0
  13. package/dist/constants/env.js +4 -0
  14. package/dist/constants/env.js.map +1 -0
  15. package/dist/constants/manifest.d.ts +3 -0
  16. package/dist/constants/manifest.d.ts.map +1 -0
  17. package/dist/constants/manifest.js +8 -0
  18. package/dist/constants/manifest.js.map +1 -0
  19. package/dist/constants/paths.d.ts +6 -0
  20. package/dist/constants/paths.d.ts.map +1 -0
  21. package/dist/constants/paths.js +6 -0
  22. package/dist/constants/paths.js.map +1 -0
  23. package/dist/data-dir.d.ts +3 -0
  24. package/dist/data-dir.d.ts.map +1 -0
  25. package/dist/data-dir.js +13 -0
  26. package/dist/data-dir.js.map +1 -0
  27. package/dist/disclosure.d.ts +5 -0
  28. package/dist/disclosure.d.ts.map +1 -0
  29. package/dist/disclosure.js +18 -0
  30. package/dist/disclosure.js.map +1 -0
  31. package/dist/emit.d.ts +3 -0
  32. package/dist/emit.d.ts.map +1 -0
  33. package/dist/emit.js +21 -0
  34. package/dist/emit.js.map +1 -0
  35. package/dist/index.d.ts +10 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +8 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/install-id.d.ts +3 -0
  40. package/dist/install-id.d.ts.map +1 -0
  41. package/dist/install-id.js +50 -0
  42. package/dist/install-id.js.map +1 -0
  43. package/dist/opt-out.d.ts +3 -0
  44. package/dist/opt-out.d.ts.map +1 -0
  45. package/dist/opt-out.js +16 -0
  46. package/dist/opt-out.js.map +1 -0
  47. package/dist/preferences.d.ts +7 -0
  48. package/dist/preferences.d.ts.map +1 -0
  49. package/dist/preferences.js +39 -0
  50. package/dist/preferences.js.map +1 -0
  51. package/dist/release-manifest.d.ts +7 -0
  52. package/dist/release-manifest.d.ts.map +1 -0
  53. package/dist/release-manifest.js +56 -0
  54. package/dist/release-manifest.js.map +1 -0
  55. package/dist/types/client.d.ts +15 -0
  56. package/dist/types/client.d.ts.map +1 -0
  57. package/dist/types/client.js +2 -0
  58. package/dist/types/client.js.map +1 -0
  59. package/dist/types/events.d.ts +59 -0
  60. package/dist/types/events.d.ts.map +1 -0
  61. package/dist/types/events.js +4 -0
  62. package/dist/types/events.js.map +1 -0
  63. package/dist/types/install-id.d.ts +4 -0
  64. package/dist/types/install-id.d.ts.map +1 -0
  65. package/dist/types/install-id.js +2 -0
  66. package/dist/types/install-id.js.map +1 -0
  67. package/dist/types/preferences.d.ts +6 -0
  68. package/dist/types/preferences.d.ts.map +1 -0
  69. package/dist/types/preferences.js +2 -0
  70. package/dist/types/preferences.js.map +1 -0
  71. package/dist/types/release-manifest.d.ts +8 -0
  72. package/dist/types/release-manifest.d.ts.map +1 -0
  73. package/dist/types/release-manifest.js +2 -0
  74. package/dist/types/release-manifest.js.map +1 -0
  75. package/dist/types/user-id.d.ts +4 -0
  76. package/dist/types/user-id.d.ts.map +1 -0
  77. package/dist/types/user-id.js +2 -0
  78. package/dist/types/user-id.js.map +1 -0
  79. package/dist/user-id.d.ts +2 -0
  80. package/dist/user-id.d.ts.map +1 -0
  81. package/dist/user-id.js +23 -0
  82. package/dist/user-id.js.map +1 -0
  83. package/package.json +49 -0
package/PRIVACY.md ADDED
@@ -0,0 +1,52 @@
1
+ # Privacy
2
+
3
+ Muggle Test client-side telemetry attaches the following fields to every event sent to Azure Application Insights.
4
+
5
+ ## Common properties (every event)
6
+
7
+ | Field | Source | Purpose |
8
+ |---|---|---|
9
+ | `source` | constant `'client'` | Distinguishes from server-auto-collected request spans |
10
+ | `serviceName` | one of `muggle-mcp`, `muggle-electron`, `muggle-skill` | Which surface emitted the event |
11
+ | `surface` | one of `mcp-local`, `mcp-remote`, `skill`, `electron` | Process surface |
12
+ | `release` | release manifest | Product version |
13
+ | `buildId` | release manifest | CI build identifier |
14
+ | `commitSha` | release manifest | Git commit hash |
15
+ | `buildTime` | release manifest | Build timestamp |
16
+ | `installId` | `~/.muggle-ai/install-id.json` | Opaque per-machine UUID, generated on first run, stable across upgrades, lost on uninstall |
17
+ | `userId` | `~/.muggle-ai/oauth-session.json` (when signed in) | Opaque Auth0 subject identifier, **not** the user's email |
18
+ | `nodeVersion` | `process.version` | Node.js version |
19
+ | `platform` | `process.platform` | OS family (`win32`, `darwin`, `linux`) |
20
+
21
+ ## Network-level fields attached by Azure (not by this package)
22
+
23
+ - **Source IP**: Azure App Insights records the originating IP on every event (default SDK behavior). Used for geographic aggregation and abuse detection. We do not strip it.
24
+
25
+ ## What we do NOT collect
26
+
27
+ - Personal email address
28
+ - OS username
29
+ - Hostname / machine name
30
+ - Absolute file paths
31
+ - File contents (test scripts, source code, configuration)
32
+ - Browser session contents
33
+
34
+ ## How to disable
35
+
36
+ Either:
37
+
38
+ ```bash
39
+ echo '{"telemetryEnabled": false}' > ~/.muggle-ai/preferences.json
40
+ ```
41
+
42
+ Or set:
43
+
44
+ ```bash
45
+ export MUGGLE_TELEMETRY_DISABLED=1
46
+ ```
47
+
48
+ When disabled, no network requests are made, no events are queued, and no disk cache is written.
49
+
50
+ ## Data retention
51
+
52
+ Application Insights resources are owned by Multiplex AI. Retention follows the Azure resource's configured retention policy (default 90 days unless otherwise documented).
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @muggleai/telemetry
2
+
3
+ Shared client-side telemetry for Muggle Test. Used by:
4
+
5
+ - **MCP** (`muggle-ai-works/packages/mcps`)
6
+ - **Electron app** (`muggle-ai-teaching-service/packages/electron-app`)
7
+ - **Skills** (`muggle-ai-works` skill bundle) — calls into MCP, which calls this package
8
+
9
+ Sends `customEvents` to Azure Application Insights with consistent identity (`installId`, `userId`, `release`, `buildId`, `commitSha`) and a `source: 'client'` tag so dashboards can separate client-emitted events from server-auto-collected request spans.
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { initTelemetry, track } from "@muggleai/telemetry";
15
+
16
+ initTelemetry({ serviceName: "muggle-mcp", surface: "mcp-local" });
17
+
18
+ track({
19
+ name: "mcp.tool.invoked",
20
+ props: {
21
+ toolName: "muggle-local-execute-replay",
22
+ toolSurface: "local",
23
+ correlationId: "abc-123",
24
+ },
25
+ });
26
+ ```
27
+
28
+ ## Connection string
29
+
30
+ Read in this order:
31
+
32
+ 1. Explicit `initTelemetry({ connectionString })` argument
33
+ 2. `APPLICATIONINSIGHTS_CONNECTION_STRING` env var
34
+ 3. `VITE_APPLICATIONINSIGHTS_CONNECTION_STRING` env var (Electron-style)
35
+
36
+ When none is set, `initTelemetry()` becomes a no-op — `track()` calls are silently dropped. This keeps the package safe to import in dev environments.
37
+
38
+ ## Opt-out
39
+
40
+ ```ts
41
+ import { isTelemetryEnabled, setTelemetryEnabled } from "@muggleai/telemetry";
42
+
43
+ if (!isTelemetryEnabled()) { /* nothing will be sent */ }
44
+ setTelemetryEnabled(false); // persists to ~/.muggle-ai/preferences.json
45
+ ```
46
+
47
+ Or set the env var `MUGGLE_TELEMETRY_DISABLED=1`.
48
+
49
+ ## Disclosure
50
+
51
+ ```ts
52
+ import { getDisclosureCopy, hasShownDisclosure, markDisclosureShown } from "@muggleai/telemetry";
53
+
54
+ if (!hasShownDisclosure()) {
55
+ console.log(getDisclosureCopy());
56
+ markDisclosureShown();
57
+ }
58
+ ```
59
+
60
+ ## Privacy
61
+
62
+ See [PRIVACY.md](./PRIVACY.md) for the complete list of fields collected.
63
+
64
+ ## Design
65
+
66
+ See `muggle-ai-brain/architecture/2026-05-05-mcp-skill-telemetry-design.md` (private repo).
67
+
68
+ ## Development
69
+
70
+ ```bash
71
+ npm install
72
+ npm test # vitest
73
+ npm run typecheck
74
+ npm run build # tsc → dist/
75
+ ```
76
+
77
+ ## Releasing
78
+
79
+ Tag and push:
80
+
81
+ ```bash
82
+ git tag v0.2.0
83
+ git push --tags
84
+ ```
85
+
86
+ The `publish.yml` workflow verifies (typecheck + tests + build) then publishes to public npm via OIDC trusted publishing. No `NPM_TOKEN` secret required — auth is configured on npmjs.com under the package's Trusted Publisher settings.
@@ -0,0 +1,8 @@
1
+ import type { TelemetryClient } from "applicationinsights";
2
+ import type { InitOptions } from "./types/client.js";
3
+ export type { InitOptions } from "./types/client.js";
4
+ export declare function initTelemetry(options: InitOptions): void;
5
+ export declare function getClient(): TelemetryClient | null;
6
+ export declare function isInitialized(): boolean;
7
+ export declare function resetClientForTests(): void;
8
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAM3D,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGlE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmCrD,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAwDxD;AAED,wBAAgB,SAAS,IAAI,eAAe,GAAG,IAAI,CAElD;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
package/dist/client.js ADDED
@@ -0,0 +1,96 @@
1
+ // AppInsights client setup. One process = one client.
2
+ // Common props attached on every event so server-side queries can filter by
3
+ // `source: 'client'`, `serviceName`, `surface`, `installId`, etc.
4
+ import * as AppInsights from "applicationinsights";
5
+ import { ENV_CONNECTION_STRING, ENV_VITE_CONNECTION_STRING } from "./constants/env.js";
6
+ import { getInstallId } from "./install-id.js";
7
+ import { readReleaseManifest } from "./release-manifest.js";
8
+ import { readUserId } from "./user-id.js";
9
+ let state = null;
10
+ function resolveConnectionString(explicit) {
11
+ if (explicit && explicit.length > 0)
12
+ return explicit;
13
+ return (process.env[ENV_CONNECTION_STRING] ??
14
+ process.env[ENV_VITE_CONNECTION_STRING] ??
15
+ undefined);
16
+ }
17
+ function buildCommonProperties(serviceName, surface) {
18
+ const manifest = readReleaseManifest();
19
+ const props = {
20
+ source: "client",
21
+ serviceName,
22
+ surface,
23
+ release: manifest.release,
24
+ buildId: manifest.buildId,
25
+ commitSha: manifest.commitSha,
26
+ buildTime: manifest.buildTime,
27
+ installId: getInstallId(),
28
+ nodeVersion: process.version,
29
+ platform: process.platform,
30
+ };
31
+ const userId = readUserId();
32
+ if (userId !== undefined)
33
+ props.userId = userId;
34
+ return props;
35
+ }
36
+ export function initTelemetry(options) {
37
+ if (state !== null && state.initialized)
38
+ return;
39
+ const connectionString = resolveConnectionString(options.connectionString);
40
+ if (!connectionString) {
41
+ state = {
42
+ client: null,
43
+ serviceName: options.serviceName,
44
+ surface: options.surface,
45
+ initialized: true,
46
+ };
47
+ return;
48
+ }
49
+ try {
50
+ AppInsights.setup(connectionString)
51
+ .setUseDiskRetryCaching(true)
52
+ .setDistributedTracingMode(AppInsights.DistributedTracingModes.AI_AND_W3C)
53
+ .setAutoCollectRequests(false)
54
+ .setAutoCollectPerformance(false, false)
55
+ .setAutoCollectExceptions(true)
56
+ .setAutoCollectDependencies(false)
57
+ .setAutoCollectConsole(false)
58
+ .setSendLiveMetrics(false);
59
+ const client = AppInsights.defaultClient;
60
+ const manifest = readReleaseManifest();
61
+ client.context.tags[client.context.keys.cloudRole] = options.serviceName;
62
+ client.context.tags[client.context.keys.applicationVersion] = manifest.release;
63
+ client.commonProperties = {
64
+ ...client.commonProperties,
65
+ ...buildCommonProperties(options.serviceName, options.surface),
66
+ };
67
+ AppInsights.start();
68
+ state = {
69
+ client,
70
+ serviceName: options.serviceName,
71
+ surface: options.surface,
72
+ initialized: true,
73
+ };
74
+ }
75
+ catch (err) {
76
+ console.warn("[muggle-telemetry] init failed; events will be dropped", {
77
+ error: err.message,
78
+ });
79
+ state = {
80
+ client: null,
81
+ serviceName: options.serviceName,
82
+ surface: options.surface,
83
+ initialized: true,
84
+ };
85
+ }
86
+ }
87
+ export function getClient() {
88
+ return state?.client ?? null;
89
+ }
90
+ export function isInitialized() {
91
+ return state?.initialized === true;
92
+ }
93
+ export function resetClientForTests() {
94
+ state = null;
95
+ }
96
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const DISCLOSURE_COPY = "Muggle Test collects anonymous usage telemetry \u2014 which features you use, how long they take, and whether they succeed \u2014 to help us improve the product. We attach an opaque install ID, your account ID (when signed in), and your IP. We do not collect file contents, OS username, hostname, or file paths. To opt out, set telemetryEnabled to false in ~/.muggle-ai/preferences.json or run `muggle preferences set telemetryEnabled false`.";
2
+ //# sourceMappingURL=disclosure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["../../src/constants/disclosure.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,+bAAub,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const DISCLOSURE_COPY = `Muggle Test collects anonymous usage telemetry — which features you use, how long they take, and whether they succeed — to help us improve the product. We attach an opaque install ID, your account ID (when signed in), and your IP. We do not collect file contents, OS username, hostname, or file paths. To opt out, set telemetryEnabled to false in ~/.muggle-ai/preferences.json or run \`muggle preferences set telemetryEnabled false\`.`;
2
+ //# sourceMappingURL=disclosure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure.js","sourceRoot":"","sources":["../../src/constants/disclosure.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,obAAob,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const ENV_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING";
2
+ export declare const ENV_VITE_CONNECTION_STRING = "VITE_APPLICATIONINSIGHTS_CONNECTION_STRING";
3
+ export declare const ENV_TELEMETRY_DISABLED = "MUGGLE_TELEMETRY_DISABLED";
4
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/constants/env.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,0CAA0C,CAAC;AAE7E,eAAO,MAAM,0BAA0B,+CAA+C,CAAC;AAEvF,eAAO,MAAM,sBAAsB,8BAA8B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const ENV_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING";
2
+ export const ENV_VITE_CONNECTION_STRING = "VITE_APPLICATIONINSIGHTS_CONNECTION_STRING";
3
+ export const ENV_TELEMETRY_DISABLED = "MUGGLE_TELEMETRY_DISABLED";
4
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/constants/env.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,uCAAuC,CAAC;AAE7E,MAAM,CAAC,MAAM,0BAA0B,GAAG,4CAA4C,CAAC;AAEvF,MAAM,CAAC,MAAM,sBAAsB,GAAG,2BAA2B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ReleaseManifest } from "../types/release-manifest.js";
2
+ export declare const DEV_MANIFEST: ReleaseManifest;
3
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/constants/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,eAAO,MAAM,YAAY,EAAE,eAM1B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export const DEV_MANIFEST = {
2
+ release: "dev",
3
+ buildId: "dev",
4
+ commitSha: "dev",
5
+ buildTime: "1970-01-01T00:00:00Z",
6
+ serviceName: "muggle-ai-telemetry",
7
+ };
8
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/constants/manifest.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAoB;IAC3C,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,sBAAsB;IACjC,WAAW,EAAE,qBAAqB;CACnC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const DATA_DIR_NAME = ".muggle-ai";
2
+ export declare const INSTALL_ID_FILENAME = "install-id.json";
3
+ export declare const PREFS_FILENAME = "preferences.json";
4
+ export declare const OAUTH_SESSION_FILENAME = "oauth-session.json";
5
+ export declare const RELEASE_MANIFEST_FILENAME = "release-manifest.json";
6
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/constants/paths.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,eAAe,CAAC;AAE1C,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,eAAO,MAAM,cAAc,qBAAqB,CAAC;AAEjD,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAE3D,eAAO,MAAM,yBAAyB,0BAA0B,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const DATA_DIR_NAME = ".muggle-ai";
2
+ export const INSTALL_ID_FILENAME = "install-id.json";
3
+ export const PREFS_FILENAME = "preferences.json";
4
+ export const OAUTH_SESSION_FILENAME = "oauth-session.json";
5
+ export const RELEASE_MANIFEST_FILENAME = "release-manifest.json";
6
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/constants/paths.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAErD,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAEjD,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAE3D,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function getDataDir(): string;
2
+ export declare function setDataDirForTests(dir: string | undefined): void;
3
+ //# sourceMappingURL=data-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-dir.d.ts","sourceRoot":"","sources":["../src/data-dir.ts"],"names":[],"mappings":"AAOA,wBAAgB,UAAU,IAAI,MAAM,CAGnC;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEhE"}
@@ -0,0 +1,13 @@
1
+ import * as os from "node:os";
2
+ import * as path from "node:path";
3
+ import { DATA_DIR_NAME } from "./constants/paths.js";
4
+ let dataDirOverride;
5
+ export function getDataDir() {
6
+ if (dataDirOverride !== undefined)
7
+ return dataDirOverride;
8
+ return path.join(os.homedir(), DATA_DIR_NAME);
9
+ }
10
+ export function setDataDirForTests(dir) {
11
+ dataDirOverride = dir;
12
+ }
13
+ //# sourceMappingURL=data-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-dir.js","sourceRoot":"","sources":["../src/data-dir.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,IAAI,eAAmC,CAAC;AAExC,MAAM,UAAU,UAAU;IACxB,IAAI,eAAe,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAuB;IACxD,eAAe,GAAG,GAAG,CAAC;AACxB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { DISCLOSURE_COPY } from "./constants/disclosure.js";
2
+ export declare function getDisclosureCopy(): string;
3
+ export declare function hasShownDisclosure(): boolean;
4
+ export declare function markDisclosureShown(now?: Date): void;
5
+ //# sourceMappingURL=disclosure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["../src/disclosure.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAI5C;AAED,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,IAAiB,GAAG,IAAI,CAEhE"}
@@ -0,0 +1,18 @@
1
+ // First-run telemetry disclosure. Stored in preferences.json so MCP, skills,
2
+ // and Electron all share the same "shown" flag.
3
+ import { DISCLOSURE_COPY } from "./constants/disclosure.js";
4
+ import { preferencesFileExists, readPreferences, updatePreference } from "./preferences.js";
5
+ export { DISCLOSURE_COPY } from "./constants/disclosure.js";
6
+ export function getDisclosureCopy() {
7
+ return DISCLOSURE_COPY;
8
+ }
9
+ export function hasShownDisclosure() {
10
+ if (!preferencesFileExists())
11
+ return false;
12
+ const prefs = readPreferences();
13
+ return typeof prefs.disclosureShownAt === "string" && prefs.disclosureShownAt.length > 0;
14
+ }
15
+ export function markDisclosureShown(now = new Date()) {
16
+ updatePreference("disclosureShownAt", now.toISOString());
17
+ }
18
+ //# sourceMappingURL=disclosure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure.js","sourceRoot":"","sources":["../src/disclosure.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gDAAgD;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE5F,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,UAAU,iBAAiB;IAC/B,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,qBAAqB,EAAE;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,OAAO,OAAO,KAAK,CAAC,iBAAiB,KAAK,QAAQ,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAY,IAAI,IAAI,EAAE;IACxD,gBAAgB,CAAC,mBAAmB,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3D,CAAC"}
package/dist/emit.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { TelemetryEvent } from "./types/events.js";
2
+ export declare function track(event: TelemetryEvent): void;
3
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,wBAAgB,KAAK,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAYjD"}
package/dist/emit.js ADDED
@@ -0,0 +1,21 @@
1
+ // Public emit surface. Opt-out is checked at every track() call so flipping
2
+ // the preference takes effect immediately without restart.
3
+ import { getClient } from "./client.js";
4
+ import { isTelemetryEnabled } from "./opt-out.js";
5
+ export function track(event) {
6
+ if (!isTelemetryEnabled())
7
+ return;
8
+ const client = getClient();
9
+ if (!client)
10
+ return;
11
+ try {
12
+ client.trackEvent({
13
+ name: event.name,
14
+ properties: event.props,
15
+ });
16
+ }
17
+ catch {
18
+ // Telemetry must never crash the host process.
19
+ }
20
+ }
21
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,2DAA2D;AAE3D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,MAAM,UAAU,KAAK,CAAC,KAAqB;IACzC,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO;IAClC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,IAAI,CAAC;QACH,MAAM,CAAC,UAAU,CAAC;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,KAAK,CAAC,KAAgC;SACnD,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { initTelemetry, isInitialized, resetClientForTests } from "./client.js";
2
+ export type { InitOptions } from "./types/client.js";
3
+ export { track } from "./emit.js";
4
+ export { isTelemetryEnabled, setTelemetryEnabled } from "./opt-out.js";
5
+ export { DISCLOSURE_COPY, getDisclosureCopy, hasShownDisclosure, markDisclosureShown, } from "./disclosure.js";
6
+ export { getInstallId } from "./install-id.js";
7
+ export { DEV_MANIFEST, readReleaseManifest } from "./release-manifest.js";
8
+ export type { ReleaseManifest } from "./types/release-manifest.js";
9
+ export type { EventName, McpToolCompleted, McpToolInvoked, Outcome, ServiceName, SkillCompleted, SkillInvoked, Surface, SystemDisclosureShown, SystemOptOutChanged, SystemStartup, TelemetryEvent, ToolSurface, Trigger, } from "./types/events.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAChF,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,WAAW,EACX,cAAc,EACd,YAAY,EACZ,OAAO,EACP,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,WAAW,EACX,OAAO,GACR,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // Public surface of @muggleai/telemetry.
2
+ export { initTelemetry, isInitialized, resetClientForTests } from "./client.js";
3
+ export { track } from "./emit.js";
4
+ export { isTelemetryEnabled, setTelemetryEnabled } from "./opt-out.js";
5
+ export { DISCLOSURE_COPY, getDisclosureCopy, hasShownDisclosure, markDisclosureShown, } from "./disclosure.js";
6
+ export { getInstallId } from "./install-id.js";
7
+ export { DEV_MANIFEST, readReleaseManifest } from "./release-manifest.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGhF,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function getInstallId(): string;
2
+ export declare function resetInstallIdCacheForTests(): void;
3
+ //# sourceMappingURL=install-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-id.d.ts","sourceRoot":"","sources":["../src/install-id.ts"],"names":[],"mappings":"AAiCA,wBAAgB,YAAY,IAAI,MAAM,CAuBrC;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
@@ -0,0 +1,50 @@
1
+ // Stable opaque per-machine install identifier. Persisted at ~/.muggle-ai/install-id.json.
2
+ import { randomUUID } from "node:crypto";
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { INSTALL_ID_FILENAME } from "./constants/paths.js";
6
+ import { getDataDir } from "./data-dir.js";
7
+ let cachedInstallId;
8
+ function installIdFilePath() {
9
+ return join(getDataDir(), INSTALL_ID_FILENAME);
10
+ }
11
+ function generateAndPersist(filePath) {
12
+ const installId = randomUUID();
13
+ const contents = { installId };
14
+ mkdirSync(dirname(filePath), { recursive: true });
15
+ writeFileSync(filePath, JSON.stringify(contents, null, 2) + "\n", "utf8");
16
+ return installId;
17
+ }
18
+ function isValid(value) {
19
+ return (typeof value === "object" &&
20
+ value !== null &&
21
+ typeof value.installId === "string" &&
22
+ value.installId.length > 0);
23
+ }
24
+ export function getInstallId() {
25
+ if (cachedInstallId !== undefined)
26
+ return cachedInstallId;
27
+ const filePath = installIdFilePath();
28
+ if (!existsSync(filePath)) {
29
+ cachedInstallId = generateAndPersist(filePath);
30
+ return cachedInstallId;
31
+ }
32
+ try {
33
+ const raw = readFileSync(filePath, "utf8");
34
+ const parsed = JSON.parse(raw);
35
+ if (isValid(parsed)) {
36
+ cachedInstallId = parsed.installId;
37
+ return cachedInstallId;
38
+ }
39
+ cachedInstallId = generateAndPersist(filePath);
40
+ return cachedInstallId;
41
+ }
42
+ catch {
43
+ cachedInstallId = generateAndPersist(filePath);
44
+ return cachedInstallId;
45
+ }
46
+ }
47
+ export function resetInstallIdCacheForTests() {
48
+ cachedInstallId = undefined;
49
+ }
50
+ //# sourceMappingURL=install-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-id.js","sourceRoot":"","sources":["../src/install-id.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,IAAI,eAAmC,CAAC;AAExC,SAAS,iBAAiB;IACxB,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,mBAAmB,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAkB,EAAE,SAAS,EAAE,CAAC;IAC9C,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAQ,KAAiC,CAAC,SAAS,KAAK,QAAQ;QAC/D,KAA+B,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CACtD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,eAAe,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IAE1D,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IAErC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,eAAe,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpB,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,eAAe,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,eAAe,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,eAAe,GAAG,SAAS,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function isTelemetryEnabled(): boolean;
2
+ export declare function setTelemetryEnabled(enabled: boolean): void;
3
+ //# sourceMappingURL=opt-out.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opt-out.d.ts","sourceRoot":"","sources":["../src/opt-out.ts"],"names":[],"mappings":"AAMA,wBAAgB,kBAAkB,IAAI,OAAO,CAK5C;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE1D"}
@@ -0,0 +1,16 @@
1
+ // Resolves whether telemetry is enabled.
2
+ // Order: env override > preferences.json > default true.
3
+ import { ENV_TELEMETRY_DISABLED } from "./constants/env.js";
4
+ import { readPreferences, updatePreference } from "./preferences.js";
5
+ export function isTelemetryEnabled() {
6
+ if (process.env[ENV_TELEMETRY_DISABLED] === "1")
7
+ return false;
8
+ const prefs = readPreferences();
9
+ if (prefs.telemetryEnabled === false)
10
+ return false;
11
+ return true;
12
+ }
13
+ export function setTelemetryEnabled(enabled) {
14
+ updatePreference("telemetryEnabled", enabled);
15
+ }
16
+ //# sourceMappingURL=opt-out.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opt-out.js","sourceRoot":"","sources":["../src/opt-out.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,yDAAyD;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAErE,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,KAAK,CAAC,gBAAgB,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,gBAAgB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Preferences } from "./types/preferences.js";
2
+ export type { Preferences } from "./types/preferences.js";
3
+ export declare function readPreferences(): Preferences;
4
+ export declare function writePreferences(prefs: Preferences): void;
5
+ export declare function updatePreference<K extends keyof Preferences>(key: K, value: Preferences[K]): void;
6
+ export declare function preferencesFileExists(): boolean;
7
+ //# sourceMappingURL=preferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../src/preferences.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAM1D,wBAAgB,eAAe,IAAI,WAAW,CAa7C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAIzD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,WAAW,EAC1D,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GACpB,IAAI,CAIN;AAED,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C"}
@@ -0,0 +1,39 @@
1
+ // Reads and writes ~/.muggle-ai/preferences.json. Used by both opt-out and
2
+ // disclosure to persist user state.
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { PREFS_FILENAME } from "./constants/paths.js";
6
+ import { getDataDir } from "./data-dir.js";
7
+ function prefsFilePath() {
8
+ return join(getDataDir(), PREFS_FILENAME);
9
+ }
10
+ export function readPreferences() {
11
+ const filePath = prefsFilePath();
12
+ if (!existsSync(filePath))
13
+ return {};
14
+ try {
15
+ const raw = readFileSync(filePath, "utf8");
16
+ const parsed = JSON.parse(raw);
17
+ if (typeof parsed === "object" && parsed !== null) {
18
+ return parsed;
19
+ }
20
+ return {};
21
+ }
22
+ catch {
23
+ return {};
24
+ }
25
+ }
26
+ export function writePreferences(prefs) {
27
+ const filePath = prefsFilePath();
28
+ mkdirSync(dirname(filePath), { recursive: true });
29
+ writeFileSync(filePath, JSON.stringify(prefs, null, 2) + "\n", "utf8");
30
+ }
31
+ export function updatePreference(key, value) {
32
+ const prefs = readPreferences();
33
+ prefs[key] = value;
34
+ writePreferences(prefs);
35
+ }
36
+ export function preferencesFileExists() {
37
+ return existsSync(prefsFilePath());
38
+ }
39
+ //# sourceMappingURL=preferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.js","sourceRoot":"","sources":["../src/preferences.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,oCAAoC;AAEpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,SAAS,aAAa;IACpB,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClD,OAAO,MAAqB,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,GAAM,EACN,KAAqB;IAErB,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ReleaseManifest } from "./types/release-manifest.js";
2
+ export { DEV_MANIFEST } from "./constants/manifest.js";
3
+ export type { ReleaseManifest } from "./types/release-manifest.js";
4
+ export declare function readReleaseManifest(): ReleaseManifest;
5
+ export declare function setManifestPathForTests(path: string | undefined): void;
6
+ export declare function resetReleaseManifestCacheForTests(): void;
7
+ //# sourceMappingURL=release-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-manifest.d.ts","sourceRoot":"","sources":["../src/release-manifest.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAyBnE,wBAAgB,mBAAmB,IAAI,eAAe,CAkBrD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtE;AAED,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
@@ -0,0 +1,56 @@
1
+ // Build-time-generated manifest co-located with the built JS as a sibling
2
+ // `release-manifest.json`. Falls back to DEV_MANIFEST when absent.
3
+ import { readFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { DEV_MANIFEST } from "./constants/manifest.js";
7
+ import { RELEASE_MANIFEST_FILENAME } from "./constants/paths.js";
8
+ export { DEV_MANIFEST } from "./constants/manifest.js";
9
+ const MANIFEST_PATH = (() => {
10
+ try {
11
+ return join(dirname(fileURLToPath(import.meta.url)), RELEASE_MANIFEST_FILENAME);
12
+ }
13
+ catch {
14
+ return RELEASE_MANIFEST_FILENAME;
15
+ }
16
+ })();
17
+ let cachedManifest;
18
+ let manifestPathOverride;
19
+ function isValid(value) {
20
+ if (typeof value !== "object" || value === null)
21
+ return false;
22
+ const m = value;
23
+ return (typeof m.release === "string" &&
24
+ typeof m.buildId === "string" &&
25
+ typeof m.commitSha === "string" &&
26
+ typeof m.buildTime === "string" &&
27
+ typeof m.serviceName === "string");
28
+ }
29
+ export function readReleaseManifest() {
30
+ if (cachedManifest !== undefined)
31
+ return cachedManifest;
32
+ const path = manifestPathOverride ?? MANIFEST_PATH;
33
+ try {
34
+ const raw = readFileSync(path, "utf8");
35
+ const parsed = JSON.parse(raw);
36
+ cachedManifest = isValid(parsed) ? parsed : DEV_MANIFEST;
37
+ return cachedManifest;
38
+ }
39
+ catch (err) {
40
+ const code = err.code;
41
+ if (code !== "ENOENT") {
42
+ console.warn("release-manifest: unexpected read error, using DEV fallback", {
43
+ error: err.message,
44
+ });
45
+ }
46
+ cachedManifest = DEV_MANIFEST;
47
+ return cachedManifest;
48
+ }
49
+ }
50
+ export function setManifestPathForTests(path) {
51
+ manifestPathOverride = path;
52
+ }
53
+ export function resetReleaseManifestCacheForTests() {
54
+ cachedManifest = undefined;
55
+ }
56
+ //# sourceMappingURL=release-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-manifest.js","sourceRoot":"","sources":["../src/release-manifest.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,mEAAmE;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGvD,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,yBAAyB,CAAC,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,yBAAyB,CAAC;IACnC,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAEL,IAAI,cAA2C,CAAC;AAChD,IAAI,oBAAwC,CAAC;AAE7C,SAAS,OAAO,CAAC,KAAc;IAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;QAC7B,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;QAC7B,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;QAC/B,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;QAC/B,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,IAAI,cAAc,KAAK,SAAS;QAAE,OAAO,cAAc,CAAC;IACxD,MAAM,IAAI,GAAG,oBAAoB,IAAI,aAAa,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;QACzD,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE;gBAC1E,KAAK,EAAG,GAAa,CAAC,OAAO;aAC9B,CAAC,CAAC;QACL,CAAC;QACD,cAAc,GAAG,YAAY,CAAC;QAC9B,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAwB;IAC9D,oBAAoB,GAAG,IAAI,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,iCAAiC;IAC/C,cAAc,GAAG,SAAS,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { TelemetryClient } from "applicationinsights";
2
+ import type { ServiceName, Surface } from "./events.js";
3
+ export interface InitOptions {
4
+ serviceName: ServiceName;
5
+ surface: Surface;
6
+ /** Override connection string. Falls back to env vars when omitted. */
7
+ connectionString?: string;
8
+ }
9
+ export interface ClientState {
10
+ client: TelemetryClient | null;
11
+ serviceName: ServiceName;
12
+ surface: Surface;
13
+ initialized: boolean;
14
+ }
15
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/types/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/types/client.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ export type Trigger = "user-slash" | "claude-proactive" | "nested-skill";
2
+ export type Outcome = "success" | "error" | "cancelled";
3
+ export type ToolSurface = "local" | "remote";
4
+ export type Surface = "mcp-local" | "mcp-remote" | "skill" | "electron";
5
+ export type ServiceName = "muggle-mcp" | "muggle-electron" | "muggle-skill";
6
+ export type SkillInvoked = {
7
+ name: "skill.invoked";
8
+ props: {
9
+ skillName: string;
10
+ trigger: Trigger;
11
+ };
12
+ };
13
+ export type SkillCompleted = {
14
+ name: "skill.completed";
15
+ props: {
16
+ skillName: string;
17
+ durationMs: number;
18
+ outcome: Outcome;
19
+ };
20
+ };
21
+ export type McpToolInvoked = {
22
+ name: "mcp.tool.invoked";
23
+ props: {
24
+ toolName: string;
25
+ toolSurface: ToolSurface;
26
+ correlationId: string;
27
+ };
28
+ };
29
+ export type McpToolCompleted = {
30
+ name: "mcp.tool.completed";
31
+ props: {
32
+ toolName: string;
33
+ toolSurface: ToolSurface;
34
+ correlationId: string;
35
+ durationMs: number;
36
+ outcome: Outcome;
37
+ errorCode?: string;
38
+ };
39
+ };
40
+ export type SystemStartup = {
41
+ name: "system.startup";
42
+ props: {
43
+ serviceName: ServiceName;
44
+ };
45
+ };
46
+ export type SystemOptOutChanged = {
47
+ name: "system.opt_out_changed";
48
+ props: {
49
+ from: boolean;
50
+ to: boolean;
51
+ };
52
+ };
53
+ export type SystemDisclosureShown = {
54
+ name: "system.disclosure_shown";
55
+ props: Record<string, never>;
56
+ };
57
+ export type TelemetryEvent = SkillInvoked | SkillCompleted | McpToolInvoked | McpToolCompleted | SystemStartup | SystemOptOutChanged | SystemDisclosureShown;
58
+ export type EventName = TelemetryEvent["name"];
59
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,kBAAkB,GAAG,cAAc,CAAC;AAEzE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7C,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,GAAG,UAAU,CAAC;AAExE,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAE5E,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,WAAW,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,WAAW,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE;QACL,WAAW,EAAE,WAAW,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,KAAK,EAAE;QACL,IAAI,EAAE,OAAO,CAAC;QACd,EAAE,EAAE,OAAO,CAAC;KACb,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,yBAAyB,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,mBAAmB,GACnB,qBAAqB,CAAC;AAE1B,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ // Telemetry event schema. Discriminated union; each event has a stable
2
+ // `name` and typed `props`. Adding a new event = add a member here.
3
+ export {};
4
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,oEAAoE"}
@@ -0,0 +1,4 @@
1
+ export interface InstallIdFile {
2
+ installId: string;
3
+ }
4
+ //# sourceMappingURL=install-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-id.d.ts","sourceRoot":"","sources":["../../src/types/install-id.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=install-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-id.js","sourceRoot":"","sources":["../../src/types/install-id.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export interface Preferences {
2
+ telemetryEnabled?: boolean;
3
+ disclosureShownAt?: string;
4
+ [key: string]: unknown;
5
+ }
6
+ //# sourceMappingURL=preferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../src/types/preferences.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=preferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.js","sourceRoot":"","sources":["../../src/types/preferences.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export interface ReleaseManifest {
2
+ release: string;
3
+ buildId: string;
4
+ commitSha: string;
5
+ buildTime: string;
6
+ serviceName: string;
7
+ }
8
+ //# sourceMappingURL=release-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-manifest.d.ts","sourceRoot":"","sources":["../../src/types/release-manifest.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=release-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-manifest.js","sourceRoot":"","sources":["../../src/types/release-manifest.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export interface AuthSessionFile {
2
+ userId?: unknown;
3
+ }
4
+ //# sourceMappingURL=user-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-id.d.ts","sourceRoot":"","sources":["../../src/types/user-id.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=user-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-id.js","sourceRoot":"","sources":["../../src/types/user-id.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function readUserId(): string | undefined;
2
+ //# sourceMappingURL=user-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-id.d.ts","sourceRoot":"","sources":["../src/user-id.ts"],"names":[],"mappings":"AAUA,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAa/C"}
@@ -0,0 +1,23 @@
1
+ // Best-effort read of the opaque userId from the auth session file. Returns
2
+ // undefined when the user is not signed in. Never throws.
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { OAUTH_SESSION_FILENAME } from "./constants/paths.js";
6
+ import { getDataDir } from "./data-dir.js";
7
+ export function readUserId() {
8
+ const filePath = join(getDataDir(), OAUTH_SESSION_FILENAME);
9
+ if (!existsSync(filePath))
10
+ return undefined;
11
+ try {
12
+ const raw = readFileSync(filePath, "utf8");
13
+ const parsed = JSON.parse(raw);
14
+ if (typeof parsed.userId === "string" && parsed.userId.length > 0) {
15
+ return parsed.userId;
16
+ }
17
+ return undefined;
18
+ }
19
+ catch {
20
+ return undefined;
21
+ }
22
+ }
23
+ //# sourceMappingURL=user-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-id.js","sourceRoot":"","sources":["../src/user-id.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0DAA0D;AAE1D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,UAAU,UAAU;IACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;QAClD,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@muggleai/telemetry",
3
+ "version": "0.2.0",
4
+ "description": "Shared client-side telemetry for Muggle Test (MCP, skills, Electron).",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "PRIVACY.md"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public",
22
+ "registry": "https://registry.npmjs.org"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+ssh://git@github.com/multiplex-ai/muggle-ai-telemetry.git"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc -p tsconfig.build.json",
30
+ "test": "vitest run",
31
+ "test:watch": "vitest",
32
+ "typecheck": "tsc --noEmit",
33
+ "clean": "rimraf dist",
34
+ "prepublishOnly": "npm run clean && npm run build"
35
+ },
36
+ "dependencies": {
37
+ "applicationinsights": "^3.14.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.11.0",
41
+ "nock": "^14.0.0",
42
+ "rimraf": "^6.0.1",
43
+ "typescript": "^5.4.0",
44
+ "vitest": "^1.6.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=20"
48
+ }
49
+ }