@alisaitteke/photoshop-mcp 1.2.0 → 1.3.3

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 (108) hide show
  1. package/README.md +38 -2
  2. package/dist/analytics/beta-telemetry.d.ts +11 -0
  3. package/dist/analytics/beta-telemetry.d.ts.map +1 -0
  4. package/dist/analytics/beta-telemetry.js +47 -0
  5. package/dist/analytics/beta-telemetry.js.map +1 -0
  6. package/dist/analytics/client-ip.d.ts +5 -0
  7. package/dist/analytics/client-ip.d.ts.map +1 -0
  8. package/dist/analytics/client-ip.js +39 -0
  9. package/dist/analytics/client-ip.js.map +1 -0
  10. package/dist/analytics/config.d.ts +6 -0
  11. package/dist/analytics/config.d.ts.map +1 -0
  12. package/dist/analytics/config.js +23 -0
  13. package/dist/analytics/config.js.map +1 -0
  14. package/dist/analytics/context.d.ts +2 -0
  15. package/dist/analytics/context.d.ts.map +1 -0
  16. package/dist/analytics/context.js +13 -0
  17. package/dist/analytics/context.js.map +1 -0
  18. package/dist/analytics/events.d.ts +3 -0
  19. package/dist/analytics/events.d.ts.map +1 -0
  20. package/dist/analytics/events.js +85 -0
  21. package/dist/analytics/events.js.map +1 -0
  22. package/dist/analytics/identity.d.ts +9 -0
  23. package/dist/analytics/identity.d.ts.map +1 -0
  24. package/dist/analytics/identity.js +166 -0
  25. package/dist/analytics/identity.js.map +1 -0
  26. package/dist/analytics/index.d.ts +12 -0
  27. package/dist/analytics/index.d.ts.map +1 -0
  28. package/dist/analytics/index.js +38 -0
  29. package/dist/analytics/index.js.map +1 -0
  30. package/dist/analytics/launch-method.d.ts +4 -0
  31. package/dist/analytics/launch-method.d.ts.map +1 -0
  32. package/dist/analytics/launch-method.js +33 -0
  33. package/dist/analytics/launch-method.js.map +1 -0
  34. package/dist/analytics/locale.d.ts +4 -0
  35. package/dist/analytics/locale.d.ts.map +1 -0
  36. package/dist/analytics/locale.js +14 -0
  37. package/dist/analytics/locale.js.map +1 -0
  38. package/dist/analytics/noop.d.ts +6 -0
  39. package/dist/analytics/noop.d.ts.map +1 -0
  40. package/dist/analytics/noop.js +9 -0
  41. package/dist/analytics/noop.js.map +1 -0
  42. package/dist/analytics/posthog-node.d.ts +11 -0
  43. package/dist/analytics/posthog-node.d.ts.map +1 -0
  44. package/dist/analytics/posthog-node.js +55 -0
  45. package/dist/analytics/posthog-node.js.map +1 -0
  46. package/dist/analytics/provider.d.ts +5 -0
  47. package/dist/analytics/provider.d.ts.map +1 -0
  48. package/dist/analytics/provider.js +27 -0
  49. package/dist/analytics/provider.js.map +1 -0
  50. package/dist/analytics/types.d.ts +23 -0
  51. package/dist/analytics/types.d.ts.map +1 -0
  52. package/dist/analytics/types.js +2 -0
  53. package/dist/analytics/types.js.map +1 -0
  54. package/dist/core/server.d.ts +1 -0
  55. package/dist/core/server.d.ts.map +1 -1
  56. package/dist/core/server.js +3 -0
  57. package/dist/core/server.js.map +1 -1
  58. package/dist/index.js +32 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/platform/macos-detector.js +4 -4
  61. package/dist/platform/macos-detector.js.map +1 -1
  62. package/dist/platform/macos-executor.js +1 -1
  63. package/dist/platform/macos-executor.js.map +1 -1
  64. package/dist/platform/windows-detector.js +4 -4
  65. package/dist/platform/windows-detector.js.map +1 -1
  66. package/dist/platform/windows-executor.js +2 -2
  67. package/dist/platform/windows-executor.js.map +1 -1
  68. package/dist/ui/agent/action-plan.d.ts +19 -0
  69. package/dist/ui/agent/action-plan.d.ts.map +1 -0
  70. package/dist/ui/agent/action-plan.js +552 -0
  71. package/dist/ui/agent/action-plan.js.map +1 -0
  72. package/dist/ui/agent/api-key.d.ts.map +1 -1
  73. package/dist/ui/agent/api-key.js +22 -4
  74. package/dist/ui/agent/api-key.js.map +1 -1
  75. package/dist/ui/agent/claude-account.d.ts.map +1 -1
  76. package/dist/ui/agent/claude-account.js +26 -12
  77. package/dist/ui/agent/claude-account.js.map +1 -1
  78. package/dist/ui/agent/gemini-account.d.ts.map +1 -1
  79. package/dist/ui/agent/gemini-account.js +14 -4
  80. package/dist/ui/agent/gemini-account.js.map +1 -1
  81. package/dist/ui/agent/shared.d.ts +26 -1
  82. package/dist/ui/agent/shared.d.ts.map +1 -1
  83. package/dist/ui/agent/shared.js +61 -0
  84. package/dist/ui/agent/shared.js.map +1 -1
  85. package/dist/ui/agent.d.ts +1 -0
  86. package/dist/ui/agent.d.ts.map +1 -1
  87. package/dist/ui/agent.js +36 -0
  88. package/dist/ui/agent.js.map +1 -1
  89. package/dist/ui/cli.js +11 -1
  90. package/dist/ui/cli.js.map +1 -1
  91. package/dist/ui/config.d.ts +6 -1
  92. package/dist/ui/config.d.ts.map +1 -1
  93. package/dist/ui/config.js +1 -12
  94. package/dist/ui/config.js.map +1 -1
  95. package/dist/ui/server.d.ts.map +1 -1
  96. package/dist/ui/server.js +103 -6
  97. package/dist/ui/server.js.map +1 -1
  98. package/dist/ui/store/chats.d.ts +11 -0
  99. package/dist/ui/store/chats.d.ts.map +1 -1
  100. package/dist/ui/store/chats.js.map +1 -1
  101. package/dist/ui/store/db.js +2 -2
  102. package/dist/ui/store/db.js.map +1 -1
  103. package/package.json +4 -2
  104. package/web/dist/assets/index-BgiXf1Jy.css +1 -0
  105. package/web/dist/assets/index-n0ymP-Cw.js +249 -0
  106. package/web/dist/index.html +9 -3
  107. package/web/dist/assets/index-BN0tu4e6.css +0 -1
  108. package/web/dist/assets/index-Cf7sH5RM.js +0 -138
package/README.md CHANGED
@@ -1,15 +1,16 @@
1
1
  # Photoshop MCP Server
2
2
 
3
- *v1.1+ — recipe workflows, fewer round-trips, snappier sessions.*
3
+ *v1.1+ — recipe workflows, fewer round-trips, snappier sessions. Standalone UI ships **Action Plan (beta)** for plan-then-execute runs.*
4
4
 
5
5
  > **Note:** This is an unofficial, community-maintained project and is not affiliated with or endorsed by Adobe Inc.
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@alisaitteke/photoshop-mcp.svg)](https://www.npmjs.com/package/@alisaitteke/photoshop-mcp)
8
+ [![Action Plan](https://img.shields.io/badge/Action%20Plan-beta-amber.svg)](#action-plan-beta)
8
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
10
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue.svg)](https://www.typescriptlang.org/)
10
11
  [![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS-lightgrey.svg)]()
11
12
 
12
- A Model Context Protocol (MCP) server that enables AI assistants like Claude and Cursor to control Adobe Photoshop programmatically. This allows you to create designs, manipulate images, and automate Photoshop workflows through natural language commands while working in your IDE — or through the bundled **standalone web UI**, which supports both API keys and CLI subscription accounts (Claude Code / Gemini CLI).
13
+ A Model Context Protocol (MCP) server that enables AI assistants like Claude and Cursor to control Adobe Photoshop programmatically. This allows you to create designs, manipulate images, and automate Photoshop workflows through natural language commands while working in your IDE — or through the bundled **standalone web UI**, which supports both API keys and CLI subscription accounts (Claude Code / Gemini CLI). The UI also offers an opt-in **Action Plan (beta)** mode that plans every Photoshop step in one LLM call, then runs them in a single pass.
13
14
 
14
15
  ## 🖥️ Standalone UI (no IDE required)
15
16
 
@@ -52,6 +53,29 @@ CLI subscription account (Anthropic and Google):
52
53
  You can switch auth method per provider in Settings without losing the other
53
54
  credential (e.g. keep an API key while trying CLI account, then switch back).
54
55
 
56
+ ### Action Plan (beta)
57
+
58
+ An optional execution mode in the standalone web UI for **API key auth only**
59
+ (`cli_account` always uses the default agentic flow). Turn it on with the
60
+ **Action Plan** toggle next to the model selector in the composer.
61
+
62
+ Instead of a per-step ReAct loop (model → tool → model → tool …), Action Plan:
63
+
64
+ 1. Makes **one** planning LLM call that outputs an ordered todo list of
65
+ Photoshop MCP tool calls with parameters.
66
+ 2. Executes those tools **directly** in sequence — no extra model round-trips
67
+ between steps.
68
+ 3. On a failed step or unresolved dependency, runs a bounded **repair** loop
69
+ (re-plans only the remaining steps, up to 3 times).
70
+
71
+ The plan appears as a live todo list above the tool-call cards, with per-step
72
+ status (`pending` → `running` → `done` / `error`). Plans are persisted in chat
73
+ history so they survive reload. The toggle is off by default; the existing
74
+ agentic flow is unchanged when Action Plan is disabled.
75
+
76
+ Good for multi-step prompts such as *"remove the background and export for web"*
77
+ where you want fewer model calls and faster end-to-end execution.
78
+
55
79
  ### What happens on first launch
56
80
 
57
81
  1. Pick a provider and choose **API key** or **Uses your account**.
@@ -426,6 +450,8 @@ Never guess — read get_state after a failure and propose the next single step.
426
450
 
427
451
  - **Standalone web UI** — local chat interface (`photoshop-mcp-ui`); API key or CLI
428
452
  subscription auth per provider (Anthropic, Google)
453
+ - **Action Plan (beta)** — opt-in plan-then-execute mode in the web UI (API key
454
+ only): one planning call, direct tool execution, bounded repair on failure
429
455
  - **Works on both Windows and macOS**
430
456
  - **Supports Photoshop 2012-2025+**
431
457
  - **ExtendScript API**: Universal compatibility via AppleScript/COM automation
@@ -499,6 +525,10 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
499
525
 
500
526
  - `PHOTOSHOP_PATH`: (Optional) Specify custom Photoshop installation path
501
527
  - `LOG_LEVEL`: Logging level (0=DEBUG, 1=INFO, 2=WARN, 3=ERROR)
528
+ - `POSTHOG_DISABLED`: Set to `1` or `true` to disable anonymous usage analytics entirely
529
+ - `POSTHOG_KEY`: (Optional) Override the PostHog project key used for analytics
530
+ - `POSTHOG_API_HOST`: (Optional) PostHog ingest host (default: `https://a.alisait.com`)
531
+ - `POSTHOG_UI_HOST`: (Optional) PostHog UI host for dashboard links (default: `https://eu.posthog.com`)
502
532
 
503
533
  ## Available Tools
504
534
 
@@ -612,6 +642,12 @@ Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) before
612
642
 
613
643
  MIT
614
644
 
645
+ ## Anonymous Usage Analytics
646
+
647
+ Anonymous, aggregated usage events are collected by default to improve the
648
+ product. You can opt out at any time. Full details:
649
+ [`docs/anonymous-usage-analytics.md`](docs/anonymous-usage-analytics.md).
650
+
615
651
  ## Acknowledgments
616
652
 
617
653
  - Built with the [Model Context Protocol SDK](https://github.com/modelcontextprotocol/sdk)
@@ -0,0 +1,11 @@
1
+ export interface BetaChatTurnInput {
2
+ providerId: string;
3
+ model: string;
4
+ authMethod: string;
5
+ userPrompt: string;
6
+ assistantText: string;
7
+ assistantReasoning?: string;
8
+ toolNames: string[];
9
+ }
10
+ export declare function captureBetaChatTurn(input: BetaChatTurnInput): void;
11
+ //# sourceMappingURL=beta-telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beta-telemetry.d.ts","sourceRoot":"","sources":["../../src/analytics/beta-telemetry.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAYD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAgClE"}
@@ -0,0 +1,47 @@
1
+ import { isAnalyticsEnabled, isBetaTelemetryOptIn } from './identity.js';
2
+ import { getLaunchMethod } from './launch-method.js';
3
+ import { getAnalytics } from './provider.js';
4
+ const MAX_TEXT_LENGTH = 16_000;
5
+ const TRUNCATION_SUFFIX = '…[truncated]';
6
+ function truncateText(value) {
7
+ if (!value)
8
+ return undefined;
9
+ if (value.length <= MAX_TEXT_LENGTH)
10
+ return value;
11
+ return `${value.slice(0, MAX_TEXT_LENGTH)}${TRUNCATION_SUFFIX}`;
12
+ }
13
+ function uniqueToolNames(names) {
14
+ return [...new Set(names.map((name) => name.trim()).filter(Boolean))];
15
+ }
16
+ export function captureBetaChatTurn(input) {
17
+ if (!isAnalyticsEnabled() || !isBetaTelemetryOptIn())
18
+ return;
19
+ const assistantText = input.assistantText.trim();
20
+ const assistantReasoning = input.assistantReasoning?.trim() ?? '';
21
+ const hasAssistantContent = assistantText.length > 0 ||
22
+ assistantReasoning.length > 0 ||
23
+ input.toolNames.length > 0;
24
+ if (!hasAssistantContent)
25
+ return;
26
+ const toolNames = uniqueToolNames(input.toolNames);
27
+ getAnalytics().capture({
28
+ name: 'beta_chat_turn',
29
+ properties: {
30
+ os: process.platform,
31
+ arch: process.arch,
32
+ node_version: process.version,
33
+ launch_method: getLaunchMethod(),
34
+ event_source: 'server',
35
+ provider_id: input.providerId,
36
+ auth_method: input.authMethod,
37
+ model: input.model,
38
+ user_prompt: truncateText(input.userPrompt.trim()) ?? '',
39
+ assistant_text: truncateText(assistantText) ?? '',
40
+ ...(assistantReasoning
41
+ ? { assistant_reasoning: truncateText(assistantReasoning) }
42
+ : {}),
43
+ ...(toolNames.length > 0 ? { tool_names: toolNames.join(',') } : {}),
44
+ },
45
+ });
46
+ }
47
+ //# sourceMappingURL=beta-telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beta-telemetry.js","sourceRoot":"","sources":["../../src/analytics/beta-telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,eAAe,GAAG,MAAM,CAAC;AAC/B,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAYzC,SAAS,YAAY,CAAC,KAAyB;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,IAAI,eAAe;QAAE,OAAO,KAAK,CAAC;IAClD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,iBAAiB,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,eAAe,CAAC,KAAe;IACtC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAwB;IAC1D,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO;IAE7D,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClE,MAAM,mBAAmB,GACvB,aAAa,CAAC,MAAM,GAAG,CAAC;QACxB,kBAAkB,CAAC,MAAM,GAAG,CAAC;QAC7B,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,mBAAmB;QAAE,OAAO;IAEjC,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEnD,YAAY,EAAE,CAAC,OAAO,CAAC;QACrB,IAAI,EAAE,gBAAgB;QACtB,UAAU,EAAE;YACV,EAAE,EAAE,OAAO,CAAC,QAAQ;YACpB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,YAAY,EAAE,OAAO,CAAC,OAAO;YAC7B,aAAa,EAAE,eAAe,EAAE;YAChC,YAAY,EAAE,QAAQ;YACtB,WAAW,EAAE,KAAK,CAAC,UAAU;YAC7B,WAAW,EAAE,KAAK,CAAC,UAAU;YAC7B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,WAAW,EAAE,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE;YACxD,cAAc,EAAE,YAAY,CAAC,aAAa,CAAC,IAAI,EAAE;YACjD,GAAG,CAAC,kBAAkB;gBACpB,CAAC,CAAC,EAAE,mBAAmB,EAAE,YAAY,CAAC,kBAAkB,CAAC,EAAE;gBAC3D,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrE;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Best-effort client IP from an incoming HTTP request (may be loopback for local UI). */
2
+ export declare function resolveClientIp(headers: Headers): string | undefined;
3
+ /** GeoIP enrichment only makes sense for a routable public client address. */
4
+ export declare function isPublicClientIp(ip: string | undefined): boolean;
5
+ //# sourceMappingURL=client-ip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-ip.d.ts","sourceRoot":"","sources":["../../src/analytics/client-ip.ts"],"names":[],"mappings":"AAYA,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAapE;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGhE"}
@@ -0,0 +1,39 @@
1
+ function isLoopbackOrPrivateIp(ip) {
2
+ const normalized = ip.trim().toLowerCase();
3
+ if (!normalized)
4
+ return true;
5
+ if (normalized === '::1' || normalized === 'localhost')
6
+ return true;
7
+ if (normalized.startsWith('127.'))
8
+ return true;
9
+ if (normalized.startsWith('10.'))
10
+ return true;
11
+ if (normalized.startsWith('192.168.'))
12
+ return true;
13
+ if (/^172\.(1[6-9]|2\d|3[01])\./.test(normalized))
14
+ return true;
15
+ if (normalized.startsWith('fc') || normalized.startsWith('fd'))
16
+ return true;
17
+ return false;
18
+ }
19
+ /** Best-effort client IP from an incoming HTTP request (may be loopback for local UI). */
20
+ export function resolveClientIp(headers) {
21
+ const candidates = [
22
+ headers.get('cf-connecting-ip'),
23
+ headers.get('x-real-ip'),
24
+ ...(headers.get('x-forwarded-for')?.split(',') ?? []),
25
+ ];
26
+ for (const raw of candidates) {
27
+ const ip = raw?.trim();
28
+ if (ip)
29
+ return ip;
30
+ }
31
+ return undefined;
32
+ }
33
+ /** GeoIP enrichment only makes sense for a routable public client address. */
34
+ export function isPublicClientIp(ip) {
35
+ if (!ip)
36
+ return false;
37
+ return !isLoopbackOrPrivateIp(ip);
38
+ }
39
+ //# sourceMappingURL=client-ip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-ip.js","sourceRoot":"","sources":["../../src/analytics/client-ip.ts"],"names":[],"mappings":"AAAA,SAAS,qBAAqB,CAAC,EAAU;IACvC,MAAM,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACpE,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,4BAA4B,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,UAAU,GAAG;QACjB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACxB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;KACtD,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC;QACvB,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;IACpB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,EAAsB;IACrD,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IACtB,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function isPostHogDisabledByEnv(): boolean;
2
+ export declare function resolvePostHogKey(): string;
3
+ export declare function resolvePostHogApiHost(): string;
4
+ export declare function resolvePostHogUiHost(): string;
5
+ export declare function hasPostHogKey(): boolean;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/analytics/config.ts"],"names":[],"mappings":"AASA,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC"}
@@ -0,0 +1,23 @@
1
+ const DEFAULT_POSTHOG_KEY = 'phc_mejq4ZZ8jTNZPiusjh7vHyPzWYinzsDwVJW43SM5FEcg';
2
+ const DEFAULT_API_HOST = 'https://a.alisait.com';
3
+ const DEFAULT_UI_HOST = 'https://eu.posthog.com';
4
+ function envTruthy(name) {
5
+ const value = process.env[name]?.trim().toLowerCase();
6
+ return value === '1' || value === 'true' || value === 'yes';
7
+ }
8
+ export function isPostHogDisabledByEnv() {
9
+ return envTruthy('POSTHOG_DISABLED');
10
+ }
11
+ export function resolvePostHogKey() {
12
+ return process.env.POSTHOG_KEY?.trim() || DEFAULT_POSTHOG_KEY;
13
+ }
14
+ export function resolvePostHogApiHost() {
15
+ return process.env.POSTHOG_API_HOST?.trim() || DEFAULT_API_HOST;
16
+ }
17
+ export function resolvePostHogUiHost() {
18
+ return process.env.POSTHOG_UI_HOST?.trim() || DEFAULT_UI_HOST;
19
+ }
20
+ export function hasPostHogKey() {
21
+ return resolvePostHogKey().length > 0;
22
+ }
23
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/analytics/config.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,kDAAkD,CAAC;AAC/E,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,MAAM,eAAe,GAAG,wBAAwB,CAAC;AAEjD,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtD,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,SAAS,CAAC,kBAAkB,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,mBAAmB,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,gBAAgB,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,eAAe,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,iBAAiB,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getServerAnalyticsContext(): Record<string, boolean>;
2
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/analytics/context.ts"],"names":[],"mappings":"AAGA,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASnE"}
@@ -0,0 +1,13 @@
1
+ import { loadConfig } from '../ui/config.js';
2
+ import { isAnalyticsEnabled, isBetaTelemetryOptIn } from './identity.js';
3
+ export function getServerAnalyticsContext() {
4
+ const config = loadConfig();
5
+ const analyticsEnabled = isAnalyticsEnabled();
6
+ return {
7
+ privacy_mode: !analyticsEnabled,
8
+ analytics_enabled: analyticsEnabled,
9
+ beta_telemetry_opt_in: isBetaTelemetryOptIn(),
10
+ action_plan_enabled: Boolean(config.actionPlanBeta),
11
+ };
12
+ }
13
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/analytics/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEzE,MAAM,UAAU,yBAAyB;IACvC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,gBAAgB,GAAG,kBAAkB,EAAE,CAAC;IAC9C,OAAO;QACL,YAAY,EAAE,CAAC,gBAAgB;QAC/B,iBAAiB,EAAE,gBAAgB;QACnC,qBAAqB,EAAE,oBAAoB,EAAE;QAC7C,mBAAmB,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;KACpD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function sanitizeAnalyticsProperties(properties: Record<string, unknown> | undefined): Record<string, string | number | boolean>;
2
+ export declare function buildRuntimeProperties(properties: Record<string, unknown> | undefined): Record<string, string | number | boolean>;
3
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/analytics/events.ts"],"names":[],"mappings":"AAuDA,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAc3C;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAa3C"}
@@ -0,0 +1,85 @@
1
+ import { getServerAnalyticsContext } from './context.js';
2
+ import { getLaunchMethod } from './launch-method.js';
3
+ import { getSystemLocale, resolveLocaleRegion } from './locale.js';
4
+ const BLOCKED_PROPERTY_KEYS = new Set([
5
+ 'api_key',
6
+ 'apikey',
7
+ 'key',
8
+ 'token',
9
+ 'secret',
10
+ 'password',
11
+ 'email',
12
+ 'account_label',
13
+ 'cli_path',
14
+ 'path',
15
+ 'file_path',
16
+ 'filepath',
17
+ 'message',
18
+ 'content',
19
+ 'prompt',
20
+ 'chat_id',
21
+ 'session_id',
22
+ ]);
23
+ const ALLOWED_PROPERTY_KEYS = new Set([
24
+ 'app_version',
25
+ 'os',
26
+ 'arch',
27
+ 'node_version',
28
+ 'provider_id',
29
+ 'auth_method',
30
+ 'ok',
31
+ 'error_code',
32
+ 'photoshop_detected',
33
+ 'action_plan_enabled',
34
+ 'event_source',
35
+ 'port',
36
+ 'host',
37
+ 'no_open',
38
+ 'has_auth',
39
+ 'has_custom_path',
40
+ 'opted_out',
41
+ 'opted_in',
42
+ 'privacy_mode',
43
+ 'analytics_enabled',
44
+ 'beta_telemetry_opt_in',
45
+ 'theme',
46
+ 'launch_method',
47
+ 'browser_language',
48
+ 'browser_timezone',
49
+ 'browser_locale_region',
50
+ 'system_locale',
51
+ 'system_locale_region',
52
+ ]);
53
+ export function sanitizeAnalyticsProperties(properties) {
54
+ if (!properties)
55
+ return {};
56
+ const out = {};
57
+ for (const [key, value] of Object.entries(properties)) {
58
+ const normalized = key.toLowerCase();
59
+ if (BLOCKED_PROPERTY_KEYS.has(normalized))
60
+ continue;
61
+ if (!ALLOWED_PROPERTY_KEYS.has(normalized))
62
+ continue;
63
+ if (value === null || value === undefined)
64
+ continue;
65
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
66
+ out[normalized] = value;
67
+ }
68
+ }
69
+ return out;
70
+ }
71
+ export function buildRuntimeProperties(properties) {
72
+ const systemLocale = getSystemLocale();
73
+ const systemLocaleRegion = resolveLocaleRegion(systemLocale);
74
+ return {
75
+ os: process.platform,
76
+ arch: process.arch,
77
+ node_version: process.version,
78
+ launch_method: getLaunchMethod(),
79
+ system_locale: systemLocale,
80
+ ...(systemLocaleRegion ? { system_locale_region: systemLocaleRegion } : {}),
81
+ ...getServerAnalyticsContext(),
82
+ ...sanitizeAnalyticsProperties(properties),
83
+ };
84
+ }
85
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/analytics/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,SAAS;IACT,QAAQ;IACR,KAAK;IACL,OAAO;IACP,QAAQ;IACR,UAAU;IACV,OAAO;IACP,eAAe;IACf,UAAU;IACV,MAAM;IACN,WAAW;IACX,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,SAAS;IACT,YAAY;CACb,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,aAAa;IACb,IAAI;IACJ,MAAM;IACN,cAAc;IACd,aAAa;IACb,aAAa;IACb,IAAI;IACJ,YAAY;IACZ,oBAAoB;IACpB,qBAAqB;IACrB,cAAc;IACd,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IACV,iBAAiB;IACjB,WAAW;IACX,UAAU;IACV,cAAc;IACd,mBAAmB;IACnB,uBAAuB;IACvB,OAAO;IACP,eAAe;IACf,kBAAkB;IAClB,kBAAkB;IAClB,uBAAuB;IACvB,eAAe;IACf,sBAAsB;CACvB,CAAC,CAAC;AAEH,MAAM,UAAU,2BAA2B,CACzC,UAA+C;IAE/C,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,GAAG,GAA8C,EAAE,CAAC;IAC1D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,SAAS;QACpD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,SAAS;QACrD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YACzF,GAAG,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,UAA+C;IAE/C,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC7D,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,QAAQ;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,YAAY,EAAE,OAAO,CAAC,OAAO;QAC7B,aAAa,EAAE,eAAe,EAAE;QAChC,aAAa,EAAE,YAAY;QAC3B,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,yBAAyB,EAAE;QAC9B,GAAG,2BAA2B,CAAC,UAAU,CAAC;KAC3C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { BetaTelemetryState } from './types.js';
2
+ export declare function getOrCreateDistinctId(): string;
3
+ export declare function isAnalyticsOptedOut(): boolean;
4
+ export declare function setAnalyticsOptOut(optedOut: boolean): void;
5
+ export declare function isAnalyticsEnabled(): boolean;
6
+ export declare function getBetaTelemetryState(): BetaTelemetryState;
7
+ export declare function isBetaTelemetryOptIn(): boolean;
8
+ export declare function setBetaTelemetryChoice(optedIn: boolean): void;
9
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/analytics/identity.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAwFrD,wBAAgB,qBAAqB,IAAI,MAAM,CAsB9C;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAI1D;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAqBD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAW1D;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAS7D"}
@@ -0,0 +1,166 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { getPhotoshopMcpHomeDir } from '../lib/export-paths.js';
5
+ import { kvGet, kvSet } from '../ui/store/kv.js';
6
+ import { isPostHogDisabledByEnv } from './config.js';
7
+ const DISTINCT_ID_KEY = 'analytics_distinct_id';
8
+ const OPT_OUT_KEY = 'analytics_opt_out';
9
+ const BETA_TELEMETRY_OPT_IN_KEY = 'beta_telemetry_opt_in';
10
+ const BETA_TELEMETRY_PROMPT_ANSWERED_KEY = 'beta_telemetry_prompt_answered';
11
+ const STORE_FILE = 'analytics-store.json';
12
+ let memoryDistinctId = null;
13
+ let dbAvailable = null;
14
+ function getStorePath() {
15
+ return join(getPhotoshopMcpHomeDir(), STORE_FILE);
16
+ }
17
+ function readFileStore() {
18
+ try {
19
+ const raw = readFileSync(getStorePath(), 'utf8');
20
+ return JSON.parse(raw);
21
+ }
22
+ catch {
23
+ return {};
24
+ }
25
+ }
26
+ function writeFileStore(store) {
27
+ const dir = getPhotoshopMcpHomeDir();
28
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
29
+ writeFileSync(getStorePath(), JSON.stringify(store), { mode: 0o600 });
30
+ }
31
+ function canUseKv() {
32
+ if (dbAvailable === false)
33
+ return false;
34
+ try {
35
+ kvGet('__analytics_probe__');
36
+ dbAvailable = true;
37
+ return true;
38
+ }
39
+ catch {
40
+ dbAvailable = false;
41
+ return false;
42
+ }
43
+ }
44
+ function readDistinctIdFromKv() {
45
+ if (!canUseKv())
46
+ return undefined;
47
+ try {
48
+ return kvGet(DISTINCT_ID_KEY);
49
+ }
50
+ catch {
51
+ dbAvailable = false;
52
+ return undefined;
53
+ }
54
+ }
55
+ function writeDistinctIdToKv(id) {
56
+ if (!canUseKv())
57
+ return;
58
+ try {
59
+ kvSet(DISTINCT_ID_KEY, id);
60
+ }
61
+ catch {
62
+ dbAvailable = false;
63
+ }
64
+ }
65
+ function readOptOutFromKv() {
66
+ if (!canUseKv())
67
+ return undefined;
68
+ try {
69
+ return kvGet(OPT_OUT_KEY);
70
+ }
71
+ catch {
72
+ dbAvailable = false;
73
+ return undefined;
74
+ }
75
+ }
76
+ function writeOptOutToKv(optedOut) {
77
+ if (!canUseKv())
78
+ return;
79
+ try {
80
+ kvSet(OPT_OUT_KEY, optedOut);
81
+ }
82
+ catch {
83
+ dbAvailable = false;
84
+ }
85
+ }
86
+ export function getOrCreateDistinctId() {
87
+ if (memoryDistinctId)
88
+ return memoryDistinctId;
89
+ const fromKv = readDistinctIdFromKv();
90
+ if (fromKv) {
91
+ memoryDistinctId = fromKv;
92
+ return fromKv;
93
+ }
94
+ const fromFile = readFileStore().distinctId;
95
+ if (fromFile) {
96
+ memoryDistinctId = fromFile;
97
+ writeDistinctIdToKv(fromFile);
98
+ return fromFile;
99
+ }
100
+ const id = randomUUID();
101
+ memoryDistinctId = id;
102
+ writeDistinctIdToKv(id);
103
+ const store = readFileStore();
104
+ writeFileStore({ ...store, distinctId: id });
105
+ return id;
106
+ }
107
+ export function isAnalyticsOptedOut() {
108
+ if (isPostHogDisabledByEnv())
109
+ return true;
110
+ const fromKv = readOptOutFromKv();
111
+ if (fromKv !== undefined)
112
+ return fromKv;
113
+ return readFileStore().optedOut === true;
114
+ }
115
+ export function setAnalyticsOptOut(optedOut) {
116
+ writeOptOutToKv(optedOut);
117
+ const store = readFileStore();
118
+ writeFileStore({ ...store, optedOut });
119
+ }
120
+ export function isAnalyticsEnabled() {
121
+ return !isAnalyticsOptedOut();
122
+ }
123
+ function readBooleanFromKv(key) {
124
+ if (!canUseKv())
125
+ return undefined;
126
+ try {
127
+ return kvGet(key);
128
+ }
129
+ catch {
130
+ dbAvailable = false;
131
+ return undefined;
132
+ }
133
+ }
134
+ function writeBooleanToKv(key, value) {
135
+ if (!canUseKv())
136
+ return;
137
+ try {
138
+ kvSet(key, value);
139
+ }
140
+ catch {
141
+ dbAvailable = false;
142
+ }
143
+ }
144
+ export function getBetaTelemetryState() {
145
+ const fromKvOptIn = readBooleanFromKv(BETA_TELEMETRY_OPT_IN_KEY);
146
+ const fromKvAnswered = readBooleanFromKv(BETA_TELEMETRY_PROMPT_ANSWERED_KEY);
147
+ const fileStore = readFileStore();
148
+ return {
149
+ betaTelemetryOptIn: fromKvOptIn ?? fileStore.betaTelemetryOptIn ?? false,
150
+ betaTelemetryPromptAnswered: fromKvAnswered ?? fileStore.betaTelemetryPromptAnswered ?? false,
151
+ };
152
+ }
153
+ export function isBetaTelemetryOptIn() {
154
+ return getBetaTelemetryState().betaTelemetryOptIn;
155
+ }
156
+ export function setBetaTelemetryChoice(optedIn) {
157
+ writeBooleanToKv(BETA_TELEMETRY_OPT_IN_KEY, optedIn);
158
+ writeBooleanToKv(BETA_TELEMETRY_PROMPT_ANSWERED_KEY, true);
159
+ const store = readFileStore();
160
+ writeFileStore({
161
+ ...store,
162
+ betaTelemetryOptIn: optedIn,
163
+ betaTelemetryPromptAnswered: true,
164
+ });
165
+ }
166
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/analytics/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { captureBetaChatTurn } from './beta-telemetry.js';
2
+ import { getBetaTelemetryState, setBetaTelemetryChoice } from './identity.js';
3
+ import { getAnalytics, resetAnalyticsProvider } from './provider.js';
4
+ import type { AnalyticsEvent, AnalyticsProvider, AnalyticsRuntimeConfig, BetaTelemetryState } from './types.js';
5
+ /** Persist the install ID and register one anonymous PostHog person per process. */
6
+ export declare function ensureAnalyticsIdentity(): void;
7
+ export declare function capture(name: string, properties?: Record<string, unknown>): void;
8
+ export declare function shutdownAnalytics(): Promise<void>;
9
+ export declare function getAnalyticsRuntimeConfig(): AnalyticsRuntimeConfig;
10
+ export { captureBetaChatTurn, getAnalytics, getBetaTelemetryState, resetAnalyticsProvider, setBetaTelemetryChoice, };
11
+ export type { AnalyticsEvent, AnalyticsProvider, AnalyticsRuntimeConfig, BetaTelemetryState };
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAQ1D,OAAO,EACL,qBAAqB,EAGrB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAA2B,MAAM,eAAe,CAAC;AAC9F,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,oFAAoF;AACpF,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;AAED,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,IAAI,CAMN;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEvD;AAED,wBAAgB,yBAAyB,IAAI,sBAAsB,CAYlE;AAED,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,GACvB,CAAC;AACF,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { captureBetaChatTurn } from './beta-telemetry.js';
2
+ import { hasPostHogKey, resolvePostHogApiHost, resolvePostHogKey, resolvePostHogUiHost, } from './config.js';
3
+ import { buildRuntimeProperties } from './events.js';
4
+ import { getBetaTelemetryState, getOrCreateDistinctId, isAnalyticsEnabled, setBetaTelemetryChoice, } from './identity.js';
5
+ import { getAnalytics, resetAnalyticsProvider, shutdownAnalyticsClient } from './provider.js';
6
+ /** Persist the install ID and register one anonymous PostHog person per process. */
7
+ export function ensureAnalyticsIdentity() {
8
+ if (!isAnalyticsEnabled() || !hasPostHogKey())
9
+ return;
10
+ getOrCreateDistinctId();
11
+ getAnalytics();
12
+ }
13
+ export function capture(name, properties) {
14
+ if (!isAnalyticsEnabled() || !hasPostHogKey())
15
+ return;
16
+ getAnalytics().capture({
17
+ name,
18
+ properties: buildRuntimeProperties(properties),
19
+ });
20
+ }
21
+ export async function shutdownAnalytics() {
22
+ await shutdownAnalyticsClient();
23
+ }
24
+ export function getAnalyticsRuntimeConfig() {
25
+ const enabled = isAnalyticsEnabled() && hasPostHogKey();
26
+ const beta = getBetaTelemetryState();
27
+ return {
28
+ enabled,
29
+ key: resolvePostHogKey(),
30
+ apiHost: resolvePostHogApiHost(),
31
+ uiHost: resolvePostHogUiHost(),
32
+ distinctId: getOrCreateDistinctId(),
33
+ betaTelemetryOptIn: beta.betaTelemetryOptIn,
34
+ betaTelemetryPromptAnswered: beta.betaTelemetryPromptAnswered,
35
+ };
36
+ }
37
+ export { captureBetaChatTurn, getAnalytics, getBetaTelemetryState, resetAnalyticsProvider, setBetaTelemetryChoice, };
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAQ9F,oFAAoF;AACpF,MAAM,UAAU,uBAAuB;IACrC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,aAAa,EAAE;QAAE,OAAO;IACtD,qBAAqB,EAAE,CAAC;IACxB,YAAY,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,IAAY,EACZ,UAAoC;IAEpC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,aAAa,EAAE;QAAE,OAAO;IACtD,YAAY,EAAE,CAAC,OAAO,CAAC;QACrB,IAAI;QACJ,UAAU,EAAE,sBAAsB,CAAC,UAAU,CAAC;KAC/C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,uBAAuB,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,MAAM,OAAO,GAAG,kBAAkB,EAAE,IAAI,aAAa,EAAE,CAAC;IACxD,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;IACrC,OAAO;QACL,OAAO;QACP,GAAG,EAAE,iBAAiB,EAAE;QACxB,OAAO,EAAE,qBAAqB,EAAE;QAChC,MAAM,EAAE,oBAAoB,EAAE;QAC9B,UAAU,EAAE,qBAAqB,EAAE;QACnC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;QAC3C,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;KAC9D,CAAC;AACJ,CAAC;AAED,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,GACvB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type LaunchMethod = 'npx' | 'npm' | 'node' | 'unknown';
2
+ export declare function resolveLaunchMethod(env?: NodeJS.ProcessEnv, argv?: string[]): LaunchMethod;
3
+ export declare function getLaunchMethod(): LaunchMethod;
4
+ //# sourceMappingURL=launch-method.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-method.d.ts","sourceRoot":"","sources":["../../src/analytics/launch-method.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAuB9D,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,MAAM,EAAiB,GAC5B,YAAY,CAWd;AAED,wBAAgB,eAAe,IAAI,YAAY,CAK9C"}