@posthog/wizard 2.16.1 → 2.18.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/dist/{add-mcp-server-to-clients-BS6Rjcwh.js → add-mcp-server-to-clients-DnPwZl1P.js} +38 -5
  2. package/dist/add-mcp-server-to-clients-DnPwZl1P.js.map +1 -0
  3. package/dist/{agent-interface-B4eUlMso.js → agent-interface-C2VEF-BD.js} +110 -54
  4. package/dist/agent-interface-C2VEF-BD.js.map +1 -0
  5. package/dist/{agent-runner-BxqiKVEf.js → agent-runner-Dw8cjZoN.js} +11 -8
  6. package/dist/{agent-runner-BxqiKVEf.js.map → agent-runner-Dw8cjZoN.js.map} +1 -1
  7. package/dist/{analytics-DUuUurR3.js → analytics-C-zcTO6g.js} +26 -4
  8. package/dist/analytics-C-zcTO6g.js.map +1 -0
  9. package/dist/{api-CGJ1iGps.js → api-B3MWP3vm.js} +14 -4
  10. package/dist/{api-CGJ1iGps.js.map → api-B3MWP3vm.js.map} +1 -1
  11. package/dist/bin.js +238 -82
  12. package/dist/bin.js.map +1 -1
  13. package/dist/{ci-install-DD7WMmIF.js → ci-install-DLuSmSq6.js} +4 -4
  14. package/dist/{ci-install-DD7WMmIF.js.map → ci-install-DLuSmSq6.js.map} +1 -1
  15. package/dist/{debug-Cd0hPlZy.js → debug--gQGudnY.js} +1 -1
  16. package/dist/{debug-ubpO6102.js → debug-BorYMfpE.js} +2 -2
  17. package/dist/{debug-ubpO6102.js.map → debug-BorYMfpE.js.map} +1 -1
  18. package/dist/{defaults-zrYmZ2ID.js → defaults-DA3-9dHT.js} +1 -1
  19. package/dist/{defaults-zrYmZ2ID.js.map → defaults-DA3-9dHT.js.map} +1 -1
  20. package/dist/{env-api-key-DEl3LJBv.js → env-api-key-MlzJYAvt.js} +1 -1
  21. package/dist/{env-api-key-DEl3LJBv.js.map → env-api-key-MlzJYAvt.js.map} +1 -1
  22. package/dist/{environment-BAaC5THg.js → environment-DIOtLqTQ.js} +3 -3
  23. package/dist/{environment-BAaC5THg.js.map → environment-DIOtLqTQ.js.map} +1 -1
  24. package/dist/{file-utils-DPmgn9Vm.js → file-utils-VAXoyXVA.js} +1 -1
  25. package/dist/{file-utils-DPmgn9Vm.js.map → file-utils-VAXoyXVA.js.map} +1 -1
  26. package/dist/{interactive-BaMAq88Q.js → interactive-DjGjlvY3.js} +2 -2
  27. package/dist/{interactive-BaMAq88Q.js.map → interactive-DjGjlvY3.js.map} +1 -1
  28. package/dist/{mcp-prompt-streaming-clGsVw8q.js → mcp-prompt-streaming-Dm47tmiy.js} +62 -12
  29. package/dist/mcp-prompt-streaming-Dm47tmiy.js.map +1 -0
  30. package/dist/{non-interactive-l2AKE3jD.js → non-interactive-C2f3Gwva.js} +2 -2
  31. package/dist/{non-interactive-l2AKE3jD.js.map → non-interactive-C2f3Gwva.js.map} +1 -1
  32. package/dist/{package-json-Cynjr9k4.js → package-json-DCuoye-H.js} +8 -2
  33. package/dist/{package-json-Cynjr9k4.js.map → package-json-DCuoye-H.js.map} +1 -1
  34. package/dist/{package-manager-BqsJK3ej.js → package-manager-Bl2KOUFK.js} +2 -2
  35. package/dist/{package-manager-BqsJK3ej.js.map → package-manager-Bl2KOUFK.js.map} +1 -1
  36. package/dist/{playground-DlE5RNfE.js → playground-ZLG68cvx.js} +21 -10
  37. package/dist/playground-ZLG68cvx.js.map +1 -0
  38. package/dist/{posthog-DWL8uOcl.js → posthog-Cr37rnla.js} +1 -1
  39. package/dist/{posthog-DWL8uOcl.js.map → posthog-Cr37rnla.js.map} +1 -1
  40. package/dist/{posthog-integration-Bf_vtWI9.js → posthog-integration-B_DLodqr.js} +282 -14
  41. package/dist/posthog-integration-B_DLodqr.js.map +1 -0
  42. package/dist/{provisioning-D_hAuxUN.js → provisioning-Bk4E6VYn.js} +9 -4
  43. package/dist/{provisioning-D_hAuxUN.js.map → provisioning-Bk4E6VYn.js.map} +1 -1
  44. package/dist/{registry-DKgYqROt.js → registry-DMM3UmZD.js} +5 -5
  45. package/dist/{registry-DKgYqROt.js.map → registry-DMM3UmZD.js.map} +1 -1
  46. package/dist/{setup-utils-D-uTycLX.js → setup-utils-Df9ezAjZ.js} +86 -38
  47. package/dist/setup-utils-Df9ezAjZ.js.map +1 -0
  48. package/dist/{slides-CL1mv_Kq.js → slides-DwvXZ8iS.js} +1583 -322
  49. package/dist/slides-DwvXZ8iS.js.map +1 -0
  50. package/dist/{start-tui-DXrv6cof.js → start-tui-P9aMwBzt.js} +28 -18
  51. package/dist/start-tui-P9aMwBzt.js.map +1 -0
  52. package/dist/{steps-CgScwqso.js → steps-RCRZbLjZ.js} +6 -6
  53. package/dist/{steps-CgScwqso.js.map → steps-RCRZbLjZ.js.map} +1 -1
  54. package/dist/{task-stream-CF6QMVMv.js → task-stream-CZRj6auI.js} +3 -3
  55. package/dist/{task-stream-CF6QMVMv.js.map → task-stream-CZRj6auI.js.map} +1 -1
  56. package/dist/{telemetry-v6O12Bep.js → telemetry-CMbVbpaY.js} +2 -2
  57. package/dist/{telemetry-v6O12Bep.js.map → telemetry-CMbVbpaY.js.map} +1 -1
  58. package/dist/urls-BzG_Jtw9.js +35 -0
  59. package/dist/urls-BzG_Jtw9.js.map +1 -0
  60. package/dist/{wizard-abort-BGoBKgvC.js → wizard-abort-Dl8WJQgJ.js} +1 -1
  61. package/dist/{wizard-abort-iTaJ8wC8.js → wizard-abort-QuKm_B5z.js} +3 -3
  62. package/dist/{wizard-abort-iTaJ8wC8.js.map → wizard-abort-QuKm_B5z.js.map} +1 -1
  63. package/dist/{wizard-session-gsn8Z3bZ.js → wizard-session-d27JGRGi.js} +1 -1
  64. package/dist/{wizard-session-gsn8Z3bZ.js.map → wizard-session-d27JGRGi.js.map} +1 -1
  65. package/dist/{wizard-session-7tMjgOvP.js → wizard-session-y304gEEI.js} +1 -1
  66. package/package.json +1 -1
  67. package/dist/TextBlock-CdeZog_6.js +0 -275
  68. package/dist/TextBlock-CdeZog_6.js.map +0 -1
  69. package/dist/add-mcp-server-to-clients-BS6Rjcwh.js.map +0 -1
  70. package/dist/agent-interface-B4eUlMso.js.map +0 -1
  71. package/dist/analytics-DUuUurR3.js.map +0 -1
  72. package/dist/api-B8OR0N1V.js +0 -2
  73. package/dist/mcp-prompt-streaming-clGsVw8q.js.map +0 -1
  74. package/dist/package-json-CumwmZpv.js +0 -2
  75. package/dist/playground-DlE5RNfE.js.map +0 -1
  76. package/dist/posthog-integration-Bf_vtWI9.js.map +0 -1
  77. package/dist/provisioning-BlBnlcFd.js +0 -2
  78. package/dist/setup-utils-BHZEdkNZ.js +0 -2
  79. package/dist/setup-utils-D-uTycLX.js.map +0 -1
  80. package/dist/skill-CnOQAZXp.js +0 -29
  81. package/dist/skill-CnOQAZXp.js.map +0 -1
  82. package/dist/slides-CL1mv_Kq.js.map +0 -1
  83. package/dist/start-tui-DXrv6cof.js.map +0 -1
@@ -1,4 +1,6 @@
1
- import { W as WIZARD_USER_AGENT, X as runtimeEnv, s as logToFile } from "./debug-ubpO6102.js";
1
+ import { W as WIZARD_USER_AGENT, X as runtimeEnv, s as logToFile } from "./debug-BorYMfpE.js";
2
+ import { i as getLlmGatewayUrlFromHost } from "./urls-BzG_Jtw9.js";
3
+ import { n as buildAgentEnv } from "./agent-interface-C2VEF-BD.js";
2
4
  //#region src/lib/agent/mcp-prompt-streaming.ts
3
5
  let _sdkModule = null;
4
6
  async function loadSdk() {
@@ -90,7 +92,13 @@ function messageToChunks(message) {
90
92
  }
91
93
  }
92
94
  }
93
- if (message?.type === "result") chunks.push({ kind: "done" });
95
+ if (message?.type === "result") {
96
+ const sessionId = message.session_id;
97
+ chunks.push({
98
+ kind: "done",
99
+ sessionId
100
+ });
101
+ }
94
102
  return chunks;
95
103
  }
96
104
  /**
@@ -108,31 +116,52 @@ function buildTerminalFitPrompt() {
108
116
  const cols = process.stdout.columns ?? 120;
109
117
  const rows = process.stdout.rows ?? 24;
110
118
  const messageBudget = Math.max(8, rows - 10);
111
- const tableRowBudget = Math.min(8, Math.max(3, rows - 14));
112
119
  return [
113
120
  `You are responding inside a CLI window that is exactly ${cols} columns wide and ${rows} rows tall. The user CAN'T SCROLL — your entire reply must fit on screen.`,
114
121
  ``,
115
122
  `LAYOUT PRINCIPLE: tall content is the enemy, wide content is your friend. You have ${cols} columns of horizontal space; use them. Spread data across columns instead of stacking it down rows.`,
116
123
  ``,
117
- `Hard limits:`,
118
- `- Aim for 3-6 lines of prose. Maximum ${messageBudget} lines total.`,
119
- `- Tables: max ${tableRowBudget} rows. Prefer MULTI-COLUMN tables (5-8 columns) over narrow tables with many rows. A two-column table with a long list of rows is exactly what to AVOID — that's the tall layout. If you have many key/value pairs, transpose them: keys as column headers across the top, values as a single wide row underneath.`,
120
- `- Lists: if there are 6+ short items, format them inline (comma-separated) or in 2-3 columns, not as a vertical bullet list.`,
124
+ `Tables:`,
125
+ `- Max 5 body rows. The prompts the user picks already constrain results to 5 or fewer — honor that and do not pad with extra rows.`,
126
+ `- If a tool result returns more than 5 items, show the top 5 and mention the rest count inline (e.g. "...and 12 more").`,
127
+ `- Prefer transposing wide-but-short data (items across columns, metrics down rows) when labels are short.`,
128
+ `- A two-column table with many rows is the tall layout to AVOID.`,
129
+ ``,
130
+ `Other limits:`,
131
+ `- Aim for 3-5 lines of prose. Maximum ${messageBudget} lines total.`,
132
+ `- DO NOT announce what you are about to do. Skip preamble like "I'll query…", "Let me check…", "Now I'll…", "I'm going to…". Go straight to running tools and then the answer.`,
133
+ `- Lists: if there are 6+ short items, format them inline (comma-separated), not as a vertical bullet list.`,
121
134
  `- For tool results, summarize the 1-3 numbers that matter. Do NOT echo raw JSON or the full payload.`,
122
135
  `- Code blocks: no language tag, no leading blank lines.`,
123
136
  `- No closing pleasantries ("let me know if…", "feel free to…"). Stop when the answer is delivered.`,
124
137
  `- No section headers unless the response actually has multiple sections.`,
125
- `- The last paragraph should always be one line that says "Now go use our MCP to build something!"`
138
+ ``,
139
+ `Naming saved artifacts:`,
140
+ `- Every dashboard, insight, notebook, or annotation you create MUST include "(wizard MCP tutorial)" at the end of its title or name field. Examples: "Weekly signups (wizard MCP tutorial)", "Top errors this week (wizard MCP tutorial)", "Onboarding analysis (wizard MCP tutorial)".`,
141
+ `- This applies on both create AND rename calls. If the user asks you to rename a saved artifact, preserve the "(wizard MCP tutorial)" suffix unless they explicitly ask you to drop it.`,
142
+ `- Reason: lets the user find / clean up everything this tutorial created from one search in PostHog. Don't skip it — it's the only signal they'll have that an artifact came from the wizard.`,
143
+ ``,
144
+ `Tone & framing:`,
145
+ `- This is a tutorial demoing PostHog (the product the user just installed). You are showing it off, not auditing it. Stay constructive and neutral about PostHog throughout.`,
146
+ `- Don't editorialize about PostHog's reliability, performance, or cost. Describe what the data shows; treat anomalies as the user's data, not a platform issue.`,
147
+ `- If a tool call fails or returns nothing, say "the query didn't return data — try a different angle" or similar. Do NOT speculate about outages, gateway issues, MCP problems, or service health.`,
148
+ `- Avoid value-laden phrases like "worth investigating", "concerning", "red flag", "problematic", "suspicious", "alarming" when describing the user's metrics. Stick to what the numbers show; the user draws conclusions.`
126
149
  ].join("\n");
127
150
  }
128
151
  async function* runMcpPromptViaSdk(args) {
129
- const { prompt, credentials, signal } = args;
152
+ const { prompt, credentials, signal, resumeSessionId } = args;
153
+ const gatewayUrl = getLlmGatewayUrlFromHost(credentials.host);
154
+ process.env.ANTHROPIC_BASE_URL = gatewayUrl;
155
+ process.env.ANTHROPIC_AUTH_TOKEN = credentials.accessToken;
156
+ process.env.CLAUDE_CODE_OAUTH_TOKEN = credentials.accessToken;
157
+ process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = "true";
158
+ logToFile(`[runMcpPromptViaSdk] gatewayUrl=${gatewayUrl} tokenPrefix=${credentials.accessToken ? credentials.accessToken.slice(0, 4) + "***" : "(missing)"}`);
130
159
  const { query } = await loadSdk();
131
160
  const abortController = new AbortController();
132
161
  if (signal.aborted) abortController.abort();
133
162
  else signal.addEventListener("abort", () => abortController.abort(), { once: true });
134
163
  const mcpUrl = resolveMcpUrl(credentials.host);
135
- logToFile(`[runMcpPromptViaSdk] mcpUrl=${mcpUrl} model=${MODEL}`);
164
+ logToFile(`[runMcpPromptViaSdk] mcpUrl=${mcpUrl} model=${MODEL} resume=${resumeSessionId ?? "(none)"}`);
136
165
  const createPromptStream = async function* () {
137
166
  yield {
138
167
  type: "user",
@@ -160,6 +189,20 @@ async function* runMcpPromptViaSdk(args) {
160
189
  cwd: process.cwd(),
161
190
  permissionMode: "acceptEdits",
162
191
  maxTurns: MAX_TURNS,
192
+ betas: ["context-1m-2025-08-07"],
193
+ settingSources: ["project"],
194
+ ...resumeSessionId ? { resume: resumeSessionId } : {},
195
+ canUseTool: (toolName, input) => {
196
+ if (toolName.startsWith("mcp__posthog-wizard__")) return Promise.resolve({
197
+ behavior: "allow",
198
+ updatedInput: input ?? {}
199
+ });
200
+ logToFile(`[runMcpPromptViaSdk] denying non-MCP tool: ${toolName}`);
201
+ return Promise.resolve({
202
+ behavior: "deny",
203
+ message: `${toolName} is not available in the MCP tutorial — only PostHog MCP tools are permitted.`
204
+ });
205
+ },
163
206
  systemPrompt: {
164
207
  type: "preset",
165
208
  preset: "claude_code",
@@ -173,7 +216,14 @@ async function* runMcpPromptViaSdk(args) {
173
216
  "User-Agent": WIZARD_USER_AGENT
174
217
  }
175
218
  } },
176
- allowedTools: ["mcp__posthog-wizard__*"]
219
+ allowedTools: ["mcp__posthog-wizard__*"],
220
+ env: {
221
+ ...process.env,
222
+ ANTHROPIC_API_KEY: void 0,
223
+ ENABLE_TOOL_SEARCH: "auto:0",
224
+ MCP_CONNECTION_NONBLOCKING: "0",
225
+ ANTHROPIC_CUSTOM_HEADERS: buildAgentEnv({}, {})
226
+ }
177
227
  }
178
228
  });
179
229
  for await (const message of response) {
@@ -197,4 +247,4 @@ async function* runMcpPromptViaSdk(args) {
197
247
  //#endregion
198
248
  export { runMcpPromptViaSdk };
199
249
 
200
- //# sourceMappingURL=mcp-prompt-streaming-clGsVw8q.js.map
250
+ //# sourceMappingURL=mcp-prompt-streaming-Dm47tmiy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-prompt-streaming-Dm47tmiy.js","names":[],"sources":["../src/lib/agent/mcp-prompt-streaming.ts"],"sourcesContent":["/**\n * Streaming prompt runner for the McpSuggestedPromptsScreen.\n *\n * Calls the Claude Agent SDK's `query()` directly with just the PostHog\n * MCP server configured — no skills, no sandbox, no settings sources,\n * no wizard-tools. This is the lightweight cousin of `runAgent` in\n * `agent-interface.ts`: same SDK, much narrower surface, suitable for\n * \"user asked a question, show the answer\" interactions.\n *\n * The function is an async generator that yields `AgentChunk`s extracted\n * from the SDK's message stream. Callers (the screen) consume them via\n * `for await (...)` and render as they arrive.\n */\n\nimport type { AgentChunk } from '@ui/tui/services/mcp-suggested-prompts-services';\nimport type { Credentials } from '@lib/wizard-session';\nimport { WIZARD_USER_AGENT } from '@lib/constants';\nimport { getLlmGatewayUrlFromHost } from '@utils/urls';\nimport { runtimeEnv } from '@env';\nimport { logToFile } from '@utils/debug';\nimport { buildAgentEnv } from '@lib/agent/agent-interface';\n\n// Cached SDK module — first call pays the dynamic-import cost; later\n// calls reuse the same module.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _sdkModule: any | null = null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadSdk(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\nconst MODEL = 'claude-sonnet-4-6';\n\n// Bounded turn count so a single prompt can't loop forever on the\n// user's nickel. 20 gives the agent room for non-trivial multi-step\n// chains (multi-tool reads → reason → write → verify → summarize) while\n// still capping runaway loops. Worth tuning down once we see real\n// telemetry on average turn counts per prompt.\nconst MAX_TURNS = 30;\n\nfunction resolveMcpUrl(host: string): string {\n const override = runtimeEnv('MCP_URL');\n if (override) return override;\n // Parse the actual hostname rather than substring-matching the raw\n // input. `host.includes('eu.posthog.com')` would let arbitrary URLs\n // like `https://evil.eu.posthog.com.attacker.com` or\n // `https://useu.posthog.commerce` route to the EU MCP endpoint\n // (CodeQL: incomplete-url-substring-sanitization). Parsing into a\n // hostname and checking exact match / trusted subdomain blocks both.\n const hostname = parseHostname(host);\n const isEu =\n hostname === 'eu.posthog.com' || hostname.endsWith('.eu.posthog.com');\n return isEu\n ? 'https://mcp-eu.posthog.com/mcp'\n : 'https://mcp.posthog.com/mcp';\n}\n\n/**\n * Normalize a host string into a hostname suitable for trust checks.\n * Accepts either a full URL (`https://us.posthog.com`) or a bare host\n * (`us.posthog.com`). Returns the hostname lowercased, or the trimmed\n * input lowercased if parsing fails (defensive fallback so a malformed\n * value still resolves to the safer-default US endpoint).\n */\nfunction parseHostname(raw: string): string {\n const trimmed = raw.trim().toLowerCase();\n try {\n const withScheme = trimmed.includes('://') ? trimmed : `https://${trimmed}`;\n return new URL(withScheme).hostname.toLowerCase();\n } catch {\n return trimmed;\n }\n}\n\n/**\n * Extract a short, single-line summary from an arbitrary value. Used\n * for tool-call args and tool-result bodies so the screen has something\n * compact to render.\n */\nfunction summarize(value: unknown, maxLen = 120): string {\n if (value == null) return '';\n let text: string;\n if (typeof value === 'string') text = value;\n else {\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n }\n text = text.replace(/\\s+/g, ' ').trim();\n if (text.length > maxLen) text = text.slice(0, maxLen - 1) + '…';\n return text;\n}\n\n/**\n * Convert one SDK message into zero or more AgentChunks. Mirrors the\n * subset of message shapes the wizard's main runAgent middleware\n * handles, but narrowed to just the kinds the screen needs to render.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction messageToChunks(message: any): AgentChunk[] {\n const chunks: AgentChunk[] = [];\n\n if (message?.type === 'assistant') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'text') {\n const text = (block as { text?: string }).text ?? '';\n if (text) chunks.push({ kind: 'text', text });\n } else if (type === 'tool_use') {\n const name = (block as { name?: string }).name ?? 'tool';\n const input = (block as { input?: unknown }).input;\n chunks.push({\n kind: 'tool-call',\n toolName: name,\n detail: summarize(input),\n });\n }\n }\n }\n }\n\n if (message?.type === 'user') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'tool_result') {\n const detail = summarize((block as { content?: unknown }).content);\n chunks.push({ kind: 'tool-result', toolName: 'tool', detail });\n }\n }\n }\n }\n\n if (message?.type === 'result') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const sessionId = (message as { session_id?: string }).session_id;\n chunks.push({ kind: 'done', sessionId });\n }\n\n return chunks;\n}\n\n/**\n * Build a system-prompt append that nudges the agent to fit its response\n * inside the current terminal window. We can't actually constrain Claude\n * — this is a soft cap that the model usually honors. The screen also\n * applies a hard truncation cap as a fallback for non-compliant runs.\n *\n * Core principle nudged at the model: TALL CONTENT IS BAD, WIDE CONTENT\n * IS GOOD. Default terminal is 120 columns × 24 rows — that's a lot of\n * horizontal space, not much vertical. Spread data across columns, never\n * stack it down rows when a horizontal layout would work.\n */\nfunction buildTerminalFitPrompt(): string {\n const cols = process.stdout.columns ?? 120;\n const rows = process.stdout.rows ?? 24;\n // Reserve rows for wizard chrome (title, status, hint, margins).\n const messageBudget = Math.max(8, rows - 10);\n\n return [\n `You are responding inside a CLI window that is exactly ${cols} columns wide and ${rows} rows tall. The user CAN'T SCROLL — your entire reply must fit on screen.`,\n ``,\n `LAYOUT PRINCIPLE: tall content is the enemy, wide content is your friend. You have ${cols} columns of horizontal space; use them. Spread data across columns instead of stacking it down rows.`,\n ``,\n `Tables:`,\n `- Max 5 body rows. The prompts the user picks already constrain results to 5 or fewer — honor that and do not pad with extra rows.`,\n `- If a tool result returns more than 5 items, show the top 5 and mention the rest count inline (e.g. \"...and 12 more\").`,\n `- Prefer transposing wide-but-short data (items across columns, metrics down rows) when labels are short.`,\n `- A two-column table with many rows is the tall layout to AVOID.`,\n ``,\n `Other limits:`,\n `- Aim for 3-5 lines of prose. Maximum ${messageBudget} lines total.`,\n `- DO NOT announce what you are about to do. Skip preamble like \"I'll query…\", \"Let me check…\", \"Now I'll…\", \"I'm going to…\". Go straight to running tools and then the answer.`,\n `- Lists: if there are 6+ short items, format them inline (comma-separated), not as a vertical bullet list.`,\n `- For tool results, summarize the 1-3 numbers that matter. Do NOT echo raw JSON or the full payload.`,\n `- Code blocks: no language tag, no leading blank lines.`,\n `- No closing pleasantries (\"let me know if…\", \"feel free to…\"). Stop when the answer is delivered.`,\n `- No section headers unless the response actually has multiple sections.`,\n ``,\n `Naming saved artifacts:`,\n `- Every dashboard, insight, notebook, or annotation you create MUST include \"(wizard MCP tutorial)\" at the end of its title or name field. Examples: \"Weekly signups (wizard MCP tutorial)\", \"Top errors this week (wizard MCP tutorial)\", \"Onboarding analysis (wizard MCP tutorial)\".`,\n `- This applies on both create AND rename calls. If the user asks you to rename a saved artifact, preserve the \"(wizard MCP tutorial)\" suffix unless they explicitly ask you to drop it.`,\n `- Reason: lets the user find / clean up everything this tutorial created from one search in PostHog. Don't skip it — it's the only signal they'll have that an artifact came from the wizard.`,\n ``,\n `Tone & framing:`,\n `- This is a tutorial demoing PostHog (the product the user just installed). You are showing it off, not auditing it. Stay constructive and neutral about PostHog throughout.`,\n `- Don't editorialize about PostHog's reliability, performance, or cost. Describe what the data shows; treat anomalies as the user's data, not a platform issue.`,\n `- If a tool call fails or returns nothing, say \"the query didn't return data — try a different angle\" or similar. Do NOT speculate about outages, gateway issues, MCP problems, or service health.`,\n `- Avoid value-laden phrases like \"worth investigating\", \"concerning\", \"red flag\", \"problematic\", \"suspicious\", \"alarming\" when describing the user's metrics. Stick to what the numbers show; the user draws conclusions.`,\n ].join('\\n');\n}\n\nexport async function* runMcpPromptViaSdk(args: {\n prompt: string;\n credentials: Credentials;\n signal: AbortSignal;\n /** When set, the SDK loads the named session's prior turns as\n * context so the follow-up prompt can reference what the agent\n * already showed. */\n resumeSessionId?: string;\n}): AsyncIterable<AgentChunk> {\n const { prompt, credentials, signal, resumeSessionId } = args;\n\n // Route the SDK's LLM calls through the PostHog LLM gateway, authed\n // with the user's OAuth access token. Set BEFORE loading the SDK in\n // case any in-process code reads env at module init (cached base\n // URLs, OAuth setup, etc.) — same reason `initializeAgent` does this\n // before its query() call. Without these the SDK tries to\n // authenticate directly against Anthropic and 401s with \"Invalid\n // authentication credentials\".\n const gatewayUrl = getLlmGatewayUrlFromHost(credentials.host);\n process.env.ANTHROPIC_BASE_URL = gatewayUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = credentials.accessToken;\n process.env.CLAUDE_CODE_OAUTH_TOKEN = credentials.accessToken;\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n logToFile(\n `[runMcpPromptViaSdk] gatewayUrl=${gatewayUrl} tokenPrefix=${\n credentials.accessToken\n ? credentials.accessToken.slice(0, 4) + '***'\n : '(missing)'\n }`,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { query } = await loadSdk();\n\n // Bridge external AbortSignal → SDK AbortController.\n const abortController = new AbortController();\n if (signal.aborted) abortController.abort();\n else\n signal.addEventListener('abort', () => abortController.abort(), {\n once: true,\n });\n\n const mcpUrl = resolveMcpUrl(credentials.host);\n logToFile(\n `[runMcpPromptViaSdk] mcpUrl=${mcpUrl} model=${MODEL} resume=${\n resumeSessionId ?? '(none)'\n }`,\n );\n\n // The SDK expects an async generator for the prompt that stays open\n // until the result is received. For a single-turn prompt we yield one\n // user message and then await an abort (which fires when streaming\n // completes or the caller cancels).\n const createPromptStream = async function* () {\n yield {\n type: 'user' as const,\n session_id: '',\n message: { role: 'user' as const, content: prompt },\n parent_tool_use_id: null,\n };\n // Hold the stream open until abort. The SDK closes its end when it\n // sees a `result` message; we close ours via the abortController in\n // the finally block below.\n await new Promise<void>((resolve) => {\n if (abortController.signal.aborted) {\n resolve();\n return;\n }\n abortController.signal.addEventListener('abort', () => resolve(), {\n once: true,\n });\n });\n };\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const response = query({\n prompt: createPromptStream(),\n options: {\n abortController,\n model: MODEL,\n cwd: process.cwd(),\n permissionMode: 'acceptEdits',\n maxTurns: MAX_TURNS,\n // Match agent-interface.ts — the 1M context beta is what keeps\n // resumed follow-up sessions from truncating after a few turns.\n betas: ['context-1m-2025-08-07'],\n // Only load project-level skills/settings. Without this the SDK\n // defaults to ['user', 'project'] and a user's\n // `~/.claude/settings.json` (apiKeyHelper / env block) can\n // override the OAuth routing we set above.\n settingSources: ['project'],\n // When set, the SDK replays the named session's turns into the\n // new query so the follow-up prompt has full conversation\n // context. Omit on the first prompt for a fresh session.\n ...(resumeSessionId ? { resume: resumeSessionId } : {}),\n // Without `canUseTool` the SDK falls back to \"ask the user\" on\n // every MCP tool call — `permissionMode: 'acceptEdits'` only\n // relaxes Edit/Write, not MCP. Our Ink TUI has no surface to\n // answer that prompt, so the agent would stall mid-stream\n // saying things like \"needs your approval to create dashboard\".\n // The tutorial's whole point is demoing the MCP tools against\n // the user's project, so we auto-allow everything that matches\n // the prefix and deny anything else (defense in depth — the\n // `allowedTools` filter above already enforces this).\n canUseTool: (toolName: string, input: unknown) => {\n if (toolName.startsWith('mcp__posthog-wizard__')) {\n return Promise.resolve({\n behavior: 'allow' as const,\n updatedInput: (input ?? {}) as Record<string, unknown>,\n });\n }\n logToFile(`[runMcpPromptViaSdk] denying non-MCP tool: ${toolName}`);\n return Promise.resolve({\n behavior: 'deny' as const,\n message: `${toolName} is not available in the MCP tutorial — only PostHog MCP tools are permitted.`,\n });\n },\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: buildTerminalFitPrompt(),\n },\n mcpServers: {\n 'posthog-wizard': {\n type: 'http',\n url: mcpUrl,\n headers: {\n Authorization: `Bearer ${credentials.accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n },\n },\n // Only let the agent use MCP tools — no shell, no file I/O,\n // no Read/Edit/Write. This is a chat-with-MCP run, not a\n // wizard skill execution.\n allowedTools: ['mcp__posthog-wizard__*'],\n env: {\n ...process.env,\n // Without this the SDK picks up a user's personal\n // ANTHROPIC_API_KEY from their shell and silently bypasses\n // the PostHog LLM gateway — defeats quota tracking and the\n // OAuth flow even though our other env vars are correct.\n ANTHROPIC_API_KEY: undefined,\n // Defer MCP tool schemas to avoid bloating the system prompt.\n // posthog-wizard exposes many query tools with large schemas;\n // without deferral these consume ~113k tokens upfront, which\n // matters especially when follow-ups resume sessions.\n ENABLE_TOOL_SEARCH: 'auto:0',\n // SDK 0.3.142+ connects MCP servers in the background by\n // default; without this the agent may try to call tools\n // before posthog-wizard is connected on turn 1.\n MCP_CONNECTION_NONBLOCKING: '0',\n // Same Bedrock-fallback + telemetry-friendly headers as the\n // main runner. No wizard metadata or flags for the tutorial\n // — runs are distinguished downstream via posthog.capture\n // calls (program_id + event names), not SDK headers.\n ANTHROPIC_CUSTOM_HEADERS: buildAgentEnv({}, {}),\n },\n },\n });\n\n for await (const message of response as AsyncIterable<unknown>) {\n if (signal.aborted) return;\n for (const chunk of messageToChunks(message)) {\n yield chunk;\n if (chunk.kind === 'done') return;\n }\n }\n } catch (err) {\n const text = err instanceof Error ? err.message : String(err);\n logToFile(`[runMcpPromptViaSdk] error: ${text}`);\n yield { kind: 'error', text };\n } finally {\n // Closes the prompt stream so `query()` shuts down cleanly even if\n // we never saw a 'result' message.\n abortController.abort();\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { p as getUI } from "./debug-ubpO6102.js";
1
+ import { p as getUI } from "./debug-BorYMfpE.js";
2
2
  //#region src/commands/basic-integration/non-interactive.ts
3
3
  /** Print the "needs a TTY" error and exit. Used when no `--ci` flag and no TTY. */
4
4
  function failNonInteractive() {
@@ -9,4 +9,4 @@ function failNonInteractive() {
9
9
  //#endregion
10
10
  export { failNonInteractive };
11
11
 
12
- //# sourceMappingURL=non-interactive-l2AKE3jD.js.map
12
+ //# sourceMappingURL=non-interactive-C2f3Gwva.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"non-interactive-l2AKE3jD.js","names":[],"sources":["../src/commands/basic-integration/non-interactive.ts"],"sourcesContent":["import { getUI } from '@ui';\n\n/** Print the \"needs a TTY\" error and exit. Used when no `--ci` flag and no TTY. */\nexport function failNonInteractive(): void {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'This installer requires an interactive terminal (TTY) to run.\\n' +\n 'It appears you are running in a non-interactive environment.\\n' +\n 'Please run the wizard in an interactive terminal.\\n\\n' +\n 'For CI/CD environments, use --ci mode:\\n' +\n ' npx @posthog/wizard --ci --region us --api-key phx_xxx',\n );\n process.exit(1);\n}\n"],"mappings":";;;AAGA,SAAgB,qBAA2B;AACzC,QAAO,CAAC,MAAM,iBAAiB;AAC/B,QAAO,CAAC,IAAI,MACV,qRAKD;AACD,SAAQ,KAAK,EAAE"}
1
+ {"version":3,"file":"non-interactive-C2f3Gwva.js","names":[],"sources":["../src/commands/basic-integration/non-interactive.ts"],"sourcesContent":["import { getUI } from '@ui';\n\n/** Print the \"needs a TTY\" error and exit. Used when no `--ci` flag and no TTY. */\nexport function failNonInteractive(): void {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'This installer requires an interactive terminal (TTY) to run.\\n' +\n 'It appears you are running in a non-interactive environment.\\n' +\n 'Please run the wizard in an interactive terminal.\\n\\n' +\n 'For CI/CD environments, use --ci mode:\\n' +\n ' npx @posthog/wizard --ci --region us --api-key phx_xxx',\n );\n process.exit(1);\n}\n"],"mappings":";;;AAGA,SAAgB,qBAA2B;AACzC,QAAO,CAAC,MAAM,iBAAiB;AAC/B,QAAO,CAAC,IAAI,MACV,qRAKD;AACD,SAAQ,KAAK,EAAE"}
@@ -1,6 +1,12 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
1
2
  import { readFileSync } from "fs";
2
3
  import path from "path";
3
4
  //#region src/utils/package-json.ts
5
+ var package_json_exports = /* @__PURE__ */ __exportAll({
6
+ getDeclaredVersion: () => getDeclaredVersion,
7
+ getInstalledPackageVersion: () => getInstalledPackageVersion,
8
+ hasDeclaredDependency: () => hasDeclaredDependency
9
+ });
4
10
  /**
5
11
  * Returns the raw version spec for `packageName` as written in
6
12
  * `package.json` (range, pinned version, workspace ref, URL, etc.).
@@ -30,6 +36,6 @@ function getInstalledPackageVersion(packageName, installDir) {
30
36
  }
31
37
  }
32
38
  //#endregion
33
- export { getInstalledPackageVersion as n, hasDeclaredDependency as r, getDeclaredVersion as t };
39
+ export { package_json_exports as i, getInstalledPackageVersion as n, hasDeclaredDependency as r, getDeclaredVersion as t };
34
40
 
35
- //# sourceMappingURL=package-json-Cynjr9k4.js.map
41
+ //# sourceMappingURL=package-json-DCuoye-H.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"package-json-Cynjr9k4.js","names":[],"sources":["../src/utils/package-json.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport path from 'path';\n\nexport type PackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string | undefined>;\n version?: string;\n overrides?: Record<string, string>;\n resolutions?: Record<string, string>;\n pnpm?: {\n overrides?: Record<string, string>;\n };\n};\n\ntype InstalledPackage = {\n name: string;\n version: string;\n};\n\n/**\n * Returns the raw version spec for `packageName` as written in\n * `package.json` (range, pinned version, workspace ref, URL, etc.).\n * `dependencies` wins over `devDependencies`. An empty-string value in\n * either slot falls through, matching the previous behaviour.\n */\nexport function getDeclaredVersion(\n packageName: string,\n packageJson: PackageJson,\n): string | undefined {\n const fromDeps = packageJson?.dependencies?.[packageName];\n if (fromDeps) return fromDeps;\n const fromDevDeps = packageJson?.devDependencies?.[packageName];\n if (fromDevDeps) return fromDevDeps;\n return undefined;\n}\n\nexport function hasDeclaredDependency(\n packageName: string,\n packageJson: PackageJson,\n): boolean {\n return getDeclaredVersion(packageName, packageJson) !== undefined;\n}\n\nexport function findDeclaredPackage(\n packageNamesList: string[],\n packageJson: PackageJson,\n): InstalledPackage | undefined {\n for (const name of packageNamesList) {\n const version = getDeclaredVersion(name, packageJson);\n if (version) {\n return { name, version };\n }\n }\n return undefined;\n}\n\n/**\n * Returns the resolved version from `node_modules/<pkg>/package.json`,\n * not the range declared in the project's `package.json`. Use this when\n * you need to know what npm actually installed.\n */\nexport function getInstalledPackageVersion(\n packageName: string,\n installDir: string,\n): string | undefined {\n try {\n const manifestPath = path.join(\n installDir,\n 'node_modules',\n packageName,\n 'package.json',\n );\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as {\n version?: string;\n };\n return manifest.version;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;AA0BA,SAAgB,mBACd,aACA,aACoB;CACpB,MAAM,WAAW,aAAa,eAAe;AAC7C,KAAI,SAAU,QAAO;CACrB,MAAM,cAAc,aAAa,kBAAkB;AACnD,KAAI,YAAa,QAAO;;AAI1B,SAAgB,sBACd,aACA,aACS;AACT,QAAO,mBAAmB,aAAa,YAAY,KAAK,KAAA;;;;;;;AAqB1D,SAAgB,2BACd,aACA,YACoB;AACpB,KAAI;EACF,MAAM,eAAe,KAAK,KACxB,YACA,gBACA,aACA,eACD;AAID,SAHiB,KAAK,MAAM,aAAa,cAAc,QAAQ,CAAC,CAGhD;SACV;AACN"}
1
+ {"version":3,"file":"package-json-DCuoye-H.js","names":[],"sources":["../src/utils/package-json.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport path from 'path';\n\nexport type PackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string | undefined>;\n version?: string;\n overrides?: Record<string, string>;\n resolutions?: Record<string, string>;\n pnpm?: {\n overrides?: Record<string, string>;\n };\n};\n\ntype InstalledPackage = {\n name: string;\n version: string;\n};\n\n/**\n * Returns the raw version spec for `packageName` as written in\n * `package.json` (range, pinned version, workspace ref, URL, etc.).\n * `dependencies` wins over `devDependencies`. An empty-string value in\n * either slot falls through, matching the previous behaviour.\n */\nexport function getDeclaredVersion(\n packageName: string,\n packageJson: PackageJson,\n): string | undefined {\n const fromDeps = packageJson?.dependencies?.[packageName];\n if (fromDeps) return fromDeps;\n const fromDevDeps = packageJson?.devDependencies?.[packageName];\n if (fromDevDeps) return fromDevDeps;\n return undefined;\n}\n\nexport function hasDeclaredDependency(\n packageName: string,\n packageJson: PackageJson,\n): boolean {\n return getDeclaredVersion(packageName, packageJson) !== undefined;\n}\n\nexport function findDeclaredPackage(\n packageNamesList: string[],\n packageJson: PackageJson,\n): InstalledPackage | undefined {\n for (const name of packageNamesList) {\n const version = getDeclaredVersion(name, packageJson);\n if (version) {\n return { name, version };\n }\n }\n return undefined;\n}\n\n/**\n * Returns the resolved version from `node_modules/<pkg>/package.json`,\n * not the range declared in the project's `package.json`. Use this when\n * you need to know what npm actually installed.\n */\nexport function getInstalledPackageVersion(\n packageName: string,\n installDir: string,\n): string | undefined {\n try {\n const manifestPath = path.join(\n installDir,\n 'node_modules',\n packageName,\n 'package.json',\n );\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as {\n version?: string;\n };\n return manifest.version;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,mBACd,aACA,aACoB;CACpB,MAAM,WAAW,aAAa,eAAe;AAC7C,KAAI,SAAU,QAAO;CACrB,MAAM,cAAc,aAAa,kBAAkB;AACnD,KAAI,YAAa,QAAO;;AAI1B,SAAgB,sBACd,aACA,aACS;AACT,QAAO,mBAAmB,aAAa,YAAY,KAAK,KAAA;;;;;;;AAqB1D,SAAgB,2BACd,aACA,YACoB;AACpB,KAAI;EACF,MAAM,eAAe,KAAK,KACxB,YACA,gBACA,aACA,eACD;AAID,SAHiB,KAAK,MAAM,aAAa,cAAc,QAAQ,CAAC,CAGhD;SACV;AACN"}
@@ -1,4 +1,4 @@
1
- import { p as detectAllPackageManagers } from "./setup-utils-D-uTycLX.js";
1
+ import { s as detectAllPackageManagers } from "./setup-utils-Df9ezAjZ.js";
2
2
  import { execSync } from "node:child_process";
3
3
  //#region src/frameworks/python/utils.ts
4
4
  /**
@@ -219,4 +219,4 @@ function gradlePackageManager() {
219
219
  //#endregion
220
220
  export { gradlePackageManager as a, getPackageManagerName as c, detectPythonPackageManagers as i, getPythonVersion as l, composerPackageManager as n, swiftPackageManager as o, detectNodePackageManagers as r, detectPackageManager as s, bundlerPackageManager as t, getPythonVersionBucket as u };
221
221
 
222
- //# sourceMappingURL=package-manager-BqsJK3ej.js.map
222
+ //# sourceMappingURL=package-manager-Bl2KOUFK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager-BqsJK3ej.js","names":["detectPythonPM"],"sources":["../src/frameworks/python/utils.ts","../src/lib/detection/package-manager.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport enum PythonPackageManager {\n UV = 'uv',\n POETRY = 'poetry',\n PDM = 'pdm',\n HATCH = 'hatch',\n RYE = 'rye',\n PIPENV = 'pipenv',\n CONDA = 'conda',\n PIP = 'pip',\n UNKNOWN = 'unknown',\n}\n\n/**\n * Get the installed Python version\n */\nexport function getPythonVersion(\n options: WizardRunOptions,\n): string | undefined {\n try {\n const version = execSync('python --version || python3 --version', {\n cwd: options.installDir,\n encoding: 'utf-8',\n })\n .trim()\n .replace('Python ', '');\n return version;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Bucket Python version for analytics (e.g., \"3.11.x\" -> \"3.11\")\n */\nexport function getPythonVersionBucket(version: string): string {\n const match = version.match(/^(\\d+\\.\\d+)/);\n return match ? match[1] : version;\n}\n\n/**\n * Detect which package manager the project uses\n */\nexport async function detectPackageManager(\n options: WizardRunOptions,\n): Promise<PythonPackageManager> {\n const { installDir } = options;\n const fs = await import('node:fs');\n const path = await import('node:path');\n\n // Check for uv (uv.lock)\n if (fs.existsSync(path.join(installDir, 'uv.lock'))) {\n return PythonPackageManager.UV;\n }\n\n // Check pyproject.toml for various tools\n if (fs.existsSync(path.join(installDir, 'pyproject.toml'))) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, 'pyproject.toml'),\n 'utf-8',\n );\n\n // Check for Poetry\n if (content.includes('[tool.poetry]')) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM\n if (content.includes('[tool.pdm]')) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Hatch\n if (content.includes('[tool.hatch]')) {\n return PythonPackageManager.HATCH;\n }\n\n // Check for Rye\n if (content.includes('[tool.rye]')) {\n return PythonPackageManager.RYE;\n }\n } catch {\n // Continue checking\n }\n }\n\n // Check for Poetry lock file\n if (fs.existsSync(path.join(installDir, 'poetry.lock'))) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM lock file\n if (fs.existsSync(path.join(installDir, 'pdm.lock'))) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Pipenv (Pipfile or Pipfile.lock)\n if (\n fs.existsSync(path.join(installDir, 'Pipfile')) ||\n fs.existsSync(path.join(installDir, 'Pipfile.lock'))\n ) {\n return PythonPackageManager.PIPENV;\n }\n\n // Check for Conda (environment.yml or environment.yaml)\n if (\n fs.existsSync(path.join(installDir, 'environment.yml')) ||\n fs.existsSync(path.join(installDir, 'environment.yaml'))\n ) {\n return PythonPackageManager.CONDA;\n }\n\n // Check for pip (requirements.txt, setup.py, setup.cfg, or pyproject.toml)\n if (\n fs.existsSync(path.join(installDir, 'requirements.txt')) ||\n fs.existsSync(path.join(installDir, 'setup.py')) ||\n fs.existsSync(path.join(installDir, 'setup.cfg')) ||\n fs.existsSync(path.join(installDir, 'pyproject.toml'))\n ) {\n return PythonPackageManager.PIP;\n }\n\n // Check for requirements directory\n try {\n const requirementsDir = path.join(installDir, 'requirements');\n if (\n fs.existsSync(requirementsDir) &&\n fs.statSync(requirementsDir).isDirectory()\n ) {\n const files = fs.readdirSync(requirementsDir);\n if (files.some((f) => f.endsWith('.txt'))) {\n return PythonPackageManager.PIP;\n }\n }\n } catch {\n // Continue\n }\n\n return PythonPackageManager.UNKNOWN;\n}\n\n/**\n * Get package manager display name\n */\nexport function getPackageManagerName(\n packageManager: PythonPackageManager,\n): string {\n switch (packageManager) {\n case PythonPackageManager.UV:\n return 'uv';\n case PythonPackageManager.POETRY:\n return 'Poetry';\n case PythonPackageManager.PDM:\n return 'PDM';\n case PythonPackageManager.HATCH:\n return 'Hatch';\n case PythonPackageManager.RYE:\n return 'Rye';\n case PythonPackageManager.PIPENV:\n return 'Pipenv';\n case PythonPackageManager.CONDA:\n return 'Conda';\n case PythonPackageManager.PIP:\n return 'pip';\n case PythonPackageManager.UNKNOWN:\n return 'unknown';\n }\n}\n","/**\n * Cross-ecosystem package manager detection.\n *\n * Provides a common interface (PackageManagerDetector) that each FrameworkConfig\n * implements, plus shared helpers for Node.js, Python, PHP, and Swift ecosystems.\n * The MCP tool in wizard-tools.ts delegates to whatever detector the\n * current framework supplies.\n */\n\nimport {\n detectAllPackageManagers,\n type PackageManager,\n} from '@utils/package-manager';\nimport {\n detectPackageManager as detectPythonPM,\n PythonPackageManager,\n} from '@frameworks/python/utils';\n\n// ---------------------------------------------------------------------------\n// Common types\n// ---------------------------------------------------------------------------\n\n/** Structured package manager info the agent can act on */\nexport interface DetectedPackageManager {\n name: string;\n label: string;\n installCommand: string;\n runCommand?: string;\n}\n\n/** Result returned by every detector */\nexport interface PackageManagerInfo {\n detected: DetectedPackageManager[];\n primary: DetectedPackageManager | null;\n recommendation: string;\n}\n\n/** Signature each framework implements */\nexport type PackageManagerDetector = (\n installDir: string,\n) => Promise<PackageManagerInfo>;\n\n// ---------------------------------------------------------------------------\n// Node.js helper\n// ---------------------------------------------------------------------------\n\nfunction serializeNodePM(pm: PackageManager): DetectedPackageManager {\n return {\n name: pm.name,\n label: pm.label,\n installCommand: pm.installCommand,\n runCommand: pm.runScriptCommand,\n };\n}\n\n/**\n * Detect Node.js package managers via lockfiles.\n * Wraps the existing detectAllPackageManagers() from utils/package-manager.ts.\n */\nexport function detectNodePackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const detected = detectAllPackageManagers({ installDir }).map(\n serializeNodePM,\n );\n\n if (detected.length === 0) {\n return Promise.resolve({\n detected: [],\n primary: null,\n recommendation: 'No lockfile found. Default to npm (npm add, npm run).',\n });\n }\n\n const primary = detected[0];\n return Promise.resolve({\n detected,\n primary,\n recommendation:\n detected.length === 1\n ? `Use ${primary.label} (${primary.installCommand}).`\n : `Multiple package managers detected. Prefer ${primary.label} (${primary.installCommand}).`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Python helper\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PM_INFO: Record<PythonPackageManager, DetectedPackageManager> = {\n [PythonPackageManager.UV]: {\n name: 'uv',\n label: 'uv',\n installCommand: 'uv add',\n runCommand: 'uv run',\n },\n [PythonPackageManager.POETRY]: {\n name: 'poetry',\n label: 'Poetry',\n installCommand: 'poetry add',\n runCommand: 'poetry run',\n },\n [PythonPackageManager.PDM]: {\n name: 'pdm',\n label: 'PDM',\n installCommand: 'pdm add',\n runCommand: 'pdm run',\n },\n [PythonPackageManager.HATCH]: {\n name: 'hatch',\n label: 'Hatch',\n installCommand: 'hatch add',\n runCommand: 'hatch run',\n },\n [PythonPackageManager.RYE]: {\n name: 'rye',\n label: 'Rye',\n installCommand: 'rye add',\n runCommand: 'rye run',\n },\n [PythonPackageManager.PIPENV]: {\n name: 'pipenv',\n label: 'Pipenv',\n installCommand: 'pipenv install',\n runCommand: 'pipenv run',\n },\n [PythonPackageManager.CONDA]: {\n name: 'conda',\n label: 'Conda',\n installCommand: 'conda install',\n runCommand: 'conda run',\n },\n [PythonPackageManager.PIP]: {\n name: 'pip',\n label: 'pip',\n installCommand: 'pip install',\n },\n [PythonPackageManager.UNKNOWN]: {\n name: 'pip',\n label: 'pip (default)',\n installCommand: 'pip install',\n },\n};\n\n/**\n * Detect Python package managers via lockfiles and config files.\n * Wraps the existing detectPackageManager() from python/utils.ts.\n */\nexport async function detectPythonPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const pm = await detectPythonPM({ installDir } as any);\n const info = PYTHON_PM_INFO[pm];\n\n return {\n detected: [info],\n primary: info,\n recommendation: `Use ${info.label} (${info.installCommand}).`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PHP (Composer) helper\n// ---------------------------------------------------------------------------\n\nconst COMPOSER: DetectedPackageManager = {\n name: 'composer',\n label: 'Composer',\n installCommand: 'composer require',\n};\n\nexport function composerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [COMPOSER],\n primary: COMPOSER,\n recommendation: 'Use Composer (composer require).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Swift (SPM) helper\n// ---------------------------------------------------------------------------\n\nconst SPM: DetectedPackageManager = {\n name: 'spm',\n label: 'Swift Package Manager',\n installCommand: 'swift package add-dependency',\n};\n\nexport function swiftPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [SPM],\n primary: SPM,\n recommendation:\n 'Use Swift Package Manager. Add the dependency to Package.swift or via Xcode.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ruby (Bundler) helper\n// ---------------------------------------------------------------------------\n\nconst BUNDLER: DetectedPackageManager = {\n name: 'bundler',\n label: 'Bundler',\n installCommand: 'bundle add',\n runCommand: 'bundle exec',\n};\n\nexport function bundlerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [BUNDLER],\n primary: BUNDLER,\n recommendation: 'Use Bundler (bundle add). Run commands with bundle exec.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Android (Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst GRADLE: DetectedPackageManager = {\n name: 'gradle',\n label: 'Gradle',\n installCommand: 'implementation',\n};\n\nexport function gradlePackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GRADLE],\n primary: GRADLE,\n recommendation:\n 'Add dependencies to build.gradle(.kts) using implementation().',\n });\n}\n"],"mappings":";;;;;;AAkBA,SAAgB,iBACd,SACoB;AACpB,KAAI;AAOF,SANgB,SAAS,yCAAyC;GAChE,KAAK,QAAQ;GACb,UAAU;GACX,CAAC,CACC,MAAM,CACN,QAAQ,WAAW,GAAG;SAEnB;AACN;;;;;;AAOJ,SAAgB,uBAAuB,SAAyB;CAC9D,MAAM,QAAQ,QAAQ,MAAM,cAAc;AAC1C,QAAO,QAAQ,MAAM,KAAK;;;;;AAM5B,eAAsB,qBACpB,SAC+B;CAC/B,MAAM,EAAE,eAAe;CACvB,MAAM,KAAK,MAAM,OAAO;CACxB,MAAM,OAAO,MAAM,OAAO;AAG1B,KAAI,GAAG,WAAW,KAAK,KAAK,YAAY,UAAU,CAAC,CACjD,QAAA;AAIF,KAAI,GAAG,WAAW,KAAK,KAAK,YAAY,iBAAiB,CAAC,CACxD,KAAI;EACF,MAAM,UAAU,GAAG,aACjB,KAAK,KAAK,YAAY,iBAAiB,EACvC,QACD;AAGD,MAAI,QAAQ,SAAS,gBAAgB,CACnC,QAAA;AAIF,MAAI,QAAQ,SAAS,aAAa,CAChC,QAAA;AAIF,MAAI,QAAQ,SAAS,eAAe,CAClC,QAAA;AAIF,MAAI,QAAQ,SAAS,aAAa,CAChC,QAAA;SAEI;AAMV,KAAI,GAAG,WAAW,KAAK,KAAK,YAAY,cAAc,CAAC,CACrD,QAAA;AAIF,KAAI,GAAG,WAAW,KAAK,KAAK,YAAY,WAAW,CAAC,CAClD,QAAA;AAIF,KACE,GAAG,WAAW,KAAK,KAAK,YAAY,UAAU,CAAC,IAC/C,GAAG,WAAW,KAAK,KAAK,YAAY,eAAe,CAAC,CAEpD,QAAA;AAIF,KACE,GAAG,WAAW,KAAK,KAAK,YAAY,kBAAkB,CAAC,IACvD,GAAG,WAAW,KAAK,KAAK,YAAY,mBAAmB,CAAC,CAExD,QAAA;AAIF,KACE,GAAG,WAAW,KAAK,KAAK,YAAY,mBAAmB,CAAC,IACxD,GAAG,WAAW,KAAK,KAAK,YAAY,WAAW,CAAC,IAChD,GAAG,WAAW,KAAK,KAAK,YAAY,YAAY,CAAC,IACjD,GAAG,WAAW,KAAK,KAAK,YAAY,iBAAiB,CAAC,CAEtD,QAAA;AAIF,KAAI;EACF,MAAM,kBAAkB,KAAK,KAAK,YAAY,eAAe;AAC7D,MACE,GAAG,WAAW,gBAAgB,IAC9B,GAAG,SAAS,gBAAgB,CAAC,aAAa;OAE5B,GAAG,YAAY,gBAAgB,CACnC,MAAM,MAAM,EAAE,SAAS,OAAO,CAAC,CACvC,QAAA;;SAGE;AAIR,QAAA;;;;;AAMF,SAAgB,sBACd,gBACQ;AACR,SAAQ,gBAAR;EACE,KAAA,KACE,QAAO;EACT,KAAA,SACE,QAAO;EACT,KAAA,MACE,QAAO;EACT,KAAA,QACE,QAAO;EACT,KAAA,MACE,QAAO;EACT,KAAA,SACE,QAAO;EACT,KAAA,QACE,QAAO;EACT,KAAA,MACE,QAAO;EACT,KAAA,UACE,QAAO;;;;;;;;;;;;;AC1Hb,SAAS,gBAAgB,IAA4C;AACnE,QAAO;EACL,MAAM,GAAG;EACT,OAAO,GAAG;EACV,gBAAgB,GAAG;EACnB,YAAY,GAAG;EAChB;;;;;;AAOH,SAAgB,0BACd,YAC6B;CAC7B,MAAM,WAAW,yBAAyB,EAAE,YAAY,CAAC,CAAC,IACxD,gBACD;AAED,KAAI,SAAS,WAAW,EACtB,QAAO,QAAQ,QAAQ;EACrB,UAAU,EAAE;EACZ,SAAS;EACT,gBAAgB;EACjB,CAAC;CAGJ,MAAM,UAAU,SAAS;AACzB,QAAO,QAAQ,QAAQ;EACrB;EACA;EACA,gBACE,SAAS,WAAW,IAChB,OAAO,QAAQ,MAAM,IAAI,QAAQ,eAAe,MAChD,8CAA8C,QAAQ,MAAM,IAAI,QAAQ,eAAe;EAC9F,CAAC;;AAOJ,MAAM,iBAAuE;SAChD;EACzB,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;aAC8B;EAC7B,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;UAC2B;EAC1B,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;YAC6B;EAC5B,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;UAC2B;EAC1B,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;aAC8B;EAC7B,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;YAC6B;EAC5B,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,YAAY;EACb;UAC2B;EAC1B,MAAM;EACN,OAAO;EACP,gBAAgB;EACjB;cAC+B;EAC9B,MAAM;EACN,OAAO;EACP,gBAAgB;EACjB;CACF;;;;;AAMD,eAAsB,4BACpB,YAC6B;CAE7B,MAAM,OAAO,eADF,MAAMA,qBAAe,EAAE,YAAY,CAAQ;AAGtD,QAAO;EACL,UAAU,CAAC,KAAK;EAChB,SAAS;EACT,gBAAgB,OAAO,KAAK,MAAM,IAAI,KAAK,eAAe;EAC3D;;AAOH,MAAM,WAAmC;CACvC,MAAM;CACN,OAAO;CACP,gBAAgB;CACjB;AAED,SAAgB,yBAAsD;AACpE,QAAO,QAAQ,QAAQ;EACrB,UAAU,CAAC,SAAS;EACpB,SAAS;EACT,gBAAgB;EACjB,CAAC;;AAOJ,MAAM,MAA8B;CAClC,MAAM;CACN,OAAO;CACP,gBAAgB;CACjB;AAED,SAAgB,sBAAmD;AACjE,QAAO,QAAQ,QAAQ;EACrB,UAAU,CAAC,IAAI;EACf,SAAS;EACT,gBACE;EACH,CAAC;;AAOJ,MAAM,UAAkC;CACtC,MAAM;CACN,OAAO;CACP,gBAAgB;CAChB,YAAY;CACb;AAED,SAAgB,wBAAqD;AACnE,QAAO,QAAQ,QAAQ;EACrB,UAAU,CAAC,QAAQ;EACnB,SAAS;EACT,gBAAgB;EACjB,CAAC;;AAOJ,MAAM,SAAiC;CACrC,MAAM;CACN,OAAO;CACP,gBAAgB;CACjB;AAED,SAAgB,uBAAoD;AAClE,QAAO,QAAQ,QAAQ;EACrB,UAAU,CAAC,OAAO;EAClB,SAAS;EACT,gBACE;EACH,CAAC"}
1
+ {"version":3,"file":"package-manager-Bl2KOUFK.js","names":["detectPythonPM"],"sources":["../src/frameworks/python/utils.ts","../src/lib/detection/package-manager.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport enum PythonPackageManager {\n UV = 'uv',\n POETRY = 'poetry',\n PDM = 'pdm',\n HATCH = 'hatch',\n RYE = 'rye',\n PIPENV = 'pipenv',\n CONDA = 'conda',\n PIP = 'pip',\n UNKNOWN = 'unknown',\n}\n\n/**\n * Get the installed Python version\n */\nexport function getPythonVersion(\n options: WizardRunOptions,\n): string | undefined {\n try {\n const version = execSync('python --version || python3 --version', {\n cwd: options.installDir,\n encoding: 'utf-8',\n })\n .trim()\n .replace('Python ', '');\n return version;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Bucket Python version for analytics (e.g., \"3.11.x\" -> \"3.11\")\n */\nexport function getPythonVersionBucket(version: string): string {\n const match = version.match(/^(\\d+\\.\\d+)/);\n return match ? match[1] : version;\n}\n\n/**\n * Detect which package manager the project uses\n */\nexport async function detectPackageManager(\n options: WizardRunOptions,\n): Promise<PythonPackageManager> {\n const { installDir } = options;\n const fs = await import('node:fs');\n const path = await import('node:path');\n\n // Check for uv (uv.lock)\n if (fs.existsSync(path.join(installDir, 'uv.lock'))) {\n return PythonPackageManager.UV;\n }\n\n // Check pyproject.toml for various tools\n if (fs.existsSync(path.join(installDir, 'pyproject.toml'))) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, 'pyproject.toml'),\n 'utf-8',\n );\n\n // Check for Poetry\n if (content.includes('[tool.poetry]')) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM\n if (content.includes('[tool.pdm]')) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Hatch\n if (content.includes('[tool.hatch]')) {\n return PythonPackageManager.HATCH;\n }\n\n // Check for Rye\n if (content.includes('[tool.rye]')) {\n return PythonPackageManager.RYE;\n }\n } catch {\n // Continue checking\n }\n }\n\n // Check for Poetry lock file\n if (fs.existsSync(path.join(installDir, 'poetry.lock'))) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM lock file\n if (fs.existsSync(path.join(installDir, 'pdm.lock'))) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Pipenv (Pipfile or Pipfile.lock)\n if (\n fs.existsSync(path.join(installDir, 'Pipfile')) ||\n fs.existsSync(path.join(installDir, 'Pipfile.lock'))\n ) {\n return PythonPackageManager.PIPENV;\n }\n\n // Check for Conda (environment.yml or environment.yaml)\n if (\n fs.existsSync(path.join(installDir, 'environment.yml')) ||\n fs.existsSync(path.join(installDir, 'environment.yaml'))\n ) {\n return PythonPackageManager.CONDA;\n }\n\n // Check for pip (requirements.txt, setup.py, setup.cfg, or pyproject.toml)\n if (\n fs.existsSync(path.join(installDir, 'requirements.txt')) ||\n fs.existsSync(path.join(installDir, 'setup.py')) ||\n fs.existsSync(path.join(installDir, 'setup.cfg')) ||\n fs.existsSync(path.join(installDir, 'pyproject.toml'))\n ) {\n return PythonPackageManager.PIP;\n }\n\n // Check for requirements directory\n try {\n const requirementsDir = path.join(installDir, 'requirements');\n if (\n fs.existsSync(requirementsDir) &&\n fs.statSync(requirementsDir).isDirectory()\n ) {\n const files = fs.readdirSync(requirementsDir);\n if (files.some((f) => f.endsWith('.txt'))) {\n return PythonPackageManager.PIP;\n }\n }\n } catch {\n // Continue\n }\n\n return PythonPackageManager.UNKNOWN;\n}\n\n/**\n * Get package manager display name\n */\nexport function getPackageManagerName(\n packageManager: PythonPackageManager,\n): string {\n switch (packageManager) {\n case PythonPackageManager.UV:\n return 'uv';\n case PythonPackageManager.POETRY:\n return 'Poetry';\n case PythonPackageManager.PDM:\n return 'PDM';\n case PythonPackageManager.HATCH:\n return 'Hatch';\n case PythonPackageManager.RYE:\n return 'Rye';\n case PythonPackageManager.PIPENV:\n return 'Pipenv';\n case PythonPackageManager.CONDA:\n return 'Conda';\n case PythonPackageManager.PIP:\n return 'pip';\n case PythonPackageManager.UNKNOWN:\n return 'unknown';\n }\n}\n","/**\n * Cross-ecosystem package manager detection.\n *\n * Provides a common interface (PackageManagerDetector) that each FrameworkConfig\n * implements, plus shared helpers for Node.js, Python, PHP, and Swift ecosystems.\n * The MCP tool in wizard-tools.ts delegates to whatever detector the\n * current framework supplies.\n */\n\nimport {\n detectAllPackageManagers,\n type PackageManager,\n} from '@utils/package-manager';\nimport {\n detectPackageManager as detectPythonPM,\n PythonPackageManager,\n} from '@frameworks/python/utils';\n\n// ---------------------------------------------------------------------------\n// Common types\n// ---------------------------------------------------------------------------\n\n/** Structured package manager info the agent can act on */\nexport interface DetectedPackageManager {\n name: string;\n label: string;\n installCommand: string;\n runCommand?: string;\n}\n\n/** Result returned by every detector */\nexport interface PackageManagerInfo {\n detected: DetectedPackageManager[];\n primary: DetectedPackageManager | null;\n recommendation: string;\n}\n\n/** Signature each framework implements */\nexport type PackageManagerDetector = (\n installDir: string,\n) => Promise<PackageManagerInfo>;\n\n// ---------------------------------------------------------------------------\n// Node.js helper\n// ---------------------------------------------------------------------------\n\nfunction serializeNodePM(pm: PackageManager): DetectedPackageManager {\n return {\n name: pm.name,\n label: pm.label,\n installCommand: pm.installCommand,\n runCommand: pm.runScriptCommand,\n };\n}\n\n/**\n * Detect Node.js package managers via lockfiles.\n * Wraps the existing detectAllPackageManagers() from utils/package-manager.ts.\n */\nexport function detectNodePackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const detected = detectAllPackageManagers({ installDir }).map(\n serializeNodePM,\n );\n\n if (detected.length === 0) {\n return Promise.resolve({\n detected: [],\n primary: null,\n recommendation: 'No lockfile found. Default to npm (npm add, npm run).',\n });\n }\n\n const primary = detected[0];\n return Promise.resolve({\n detected,\n primary,\n recommendation:\n detected.length === 1\n ? `Use ${primary.label} (${primary.installCommand}).`\n : `Multiple package managers detected. Prefer ${primary.label} (${primary.installCommand}).`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Python helper\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PM_INFO: Record<PythonPackageManager, DetectedPackageManager> = {\n [PythonPackageManager.UV]: {\n name: 'uv',\n label: 'uv',\n installCommand: 'uv add',\n runCommand: 'uv run',\n },\n [PythonPackageManager.POETRY]: {\n name: 'poetry',\n label: 'Poetry',\n installCommand: 'poetry add',\n runCommand: 'poetry run',\n },\n [PythonPackageManager.PDM]: {\n name: 'pdm',\n label: 'PDM',\n installCommand: 'pdm add',\n runCommand: 'pdm run',\n },\n [PythonPackageManager.HATCH]: {\n name: 'hatch',\n label: 'Hatch',\n installCommand: 'hatch add',\n runCommand: 'hatch run',\n },\n [PythonPackageManager.RYE]: {\n name: 'rye',\n label: 'Rye',\n installCommand: 'rye add',\n runCommand: 'rye run',\n },\n [PythonPackageManager.PIPENV]: {\n name: 'pipenv',\n label: 'Pipenv',\n installCommand: 'pipenv install',\n runCommand: 'pipenv run',\n },\n [PythonPackageManager.CONDA]: {\n name: 'conda',\n label: 'Conda',\n installCommand: 'conda install',\n runCommand: 'conda run',\n },\n [PythonPackageManager.PIP]: {\n name: 'pip',\n label: 'pip',\n installCommand: 'pip install',\n },\n [PythonPackageManager.UNKNOWN]: {\n name: 'pip',\n label: 'pip (default)',\n installCommand: 'pip install',\n },\n};\n\n/**\n * Detect Python package managers via lockfiles and config files.\n * Wraps the existing detectPackageManager() from python/utils.ts.\n */\nexport async function detectPythonPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const pm = await detectPythonPM({ installDir } as any);\n const info = PYTHON_PM_INFO[pm];\n\n return {\n detected: [info],\n primary: info,\n recommendation: `Use ${info.label} (${info.installCommand}).`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PHP (Composer) helper\n// ---------------------------------------------------------------------------\n\nconst COMPOSER: DetectedPackageManager = {\n name: 'composer',\n label: 'Composer',\n installCommand: 'composer require',\n};\n\nexport function composerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [COMPOSER],\n primary: COMPOSER,\n recommendation: 'Use Composer (composer require).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Swift (SPM) helper\n// ---------------------------------------------------------------------------\n\nconst SPM: DetectedPackageManager = {\n name: 'spm',\n label: 'Swift Package Manager',\n installCommand: 'swift package add-dependency',\n};\n\nexport function swiftPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [SPM],\n primary: SPM,\n recommendation:\n 'Use Swift Package Manager. Add the dependency to Package.swift or via Xcode.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ruby (Bundler) helper\n// ---------------------------------------------------------------------------\n\nconst BUNDLER: DetectedPackageManager = {\n name: 'bundler',\n label: 'Bundler',\n installCommand: 'bundle add',\n runCommand: 'bundle exec',\n};\n\nexport function bundlerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [BUNDLER],\n primary: BUNDLER,\n recommendation: 'Use Bundler (bundle add). Run commands with bundle exec.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Android (Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst GRADLE: DetectedPackageManager = {\n name: 'gradle',\n label: 'Gradle',\n installCommand: 'implementation',\n};\n\nexport function gradlePackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GRADLE],\n primary: GRADLE,\n recommendation:\n 'Add dependencies to build.gradle(.kts) using implementation().',\n });\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { J as VERSION, l as WIZARD_LOG_FILE, y as getBlockingServiceKeys } from "./debug-ubpO6102.js";
1
+ import { J as VERSION, l as WIZARD_LOG_FILE, y as getBlockingServiceKeys } from "./debug-BorYMfpE.js";
2
2
  import "./wizard-ui-YdGFRyu_.js";
3
- import { o as Colors, s as Icons } from "./TextBlock-CdeZog_6.js";
3
+ import { f as Colors, p as Icons } from "./posthog-integration-B_DLodqr.js";
4
4
  import { c as getContentBlocks, r as PROGRAM_REGISTRY } from "./bin.js";
5
- import { A as WizardStore, D as LoadingBox, E as ProgressList, O as SplitView, S as GroupedPickerMenu, _ as ScreenContainer, a as McpSuggestedPromptsScreen, b as ModalOverlay, c as IssueTable, d as ServiceHealthList, f as TipsCard, g as TabContainer, h as HNViewer, i as AuditChecksViewer, k as CardLayout, m as ContentSequencer, n as AUDIT_AREA_SLIDES, o as TAILORED_ROLES, p as LearnCard, s as McpScreen, t as AUDIT_3000_AREA_SLIDES, v as EventPlanViewer, w as PickerMenu, x as ConfirmationInput, y as LogViewer } from "./slides-CL1mv_Kq.js";
5
+ import { A as WizardStore, D as LoadingBox, E as ProgressList, O as SplitView, S as GroupedPickerMenu, _ as ScreenContainer, a as McpSuggestedPromptsScreen, b as ModalOverlay, c as IssueTable, d as ServiceHealthList, f as TipsCard, g as TabContainer, h as HNViewer, i as AuditChecksViewer, k as CardLayout, m as ContentSequencer, n as AUDIT_AREA_SLIDES, o as TAILORED_ROLES, p as LearnCard, s as McpScreen, t as AUDIT_3000_AREA_SLIDES, v as EventPlanViewer, w as PickerMenu, x as ConfirmationInput, y as LogViewer } from "./slides-DwvXZ8iS.js";
6
6
  import * as fs$1 from "fs";
7
7
  import * as path$1 from "path";
8
8
  import { Box, Text, render, useInput } from "ink";
@@ -823,10 +823,10 @@ const McpDemo = ({ store }) => {
823
823
  * suggested-prompts screen.
824
824
  *
825
825
  * Mounts the real McpSuggestedPromptsScreen with mock services so every
826
- * phase (Choose → Authenticating → PromptPicker → Running) can be
827
- * previewed without touching the network. No special-case branches in
828
- * the screen itself the mock just satisfies the same interface
829
- * production wires.
826
+ * phase (Choose → Authenticating → Greeting → PromptPicker → Running
827
+ * FollowUp) can be previewed without touching the network. The Greeting
828
+ * phase auto-advances; FollowUp re-enters Running when a follow-up is
829
+ * picked, building a conversation tree up to MAX_PROMPT_RUNS deep.
830
830
  *
831
831
  * R cycle role (null → founder → product → ... → data → null)
832
832
  * F cycle framework (null → nextjs → vue → swift → django → null)
@@ -836,6 +836,11 @@ const McpDemo = ({ store }) => {
836
836
  * L login delay: 0ms (skip UI) | 2000ms | 6000ms
837
837
  * S stream script: short-text | with-tools | mid-stream-error
838
838
  * C chunk delay: 50ms | 200ms | 800ms
839
+ *
840
+ * Tip: switch S to "with-tools" and the FollowUp picker after the run
841
+ * will show context-aware suggestions based on the last tool (mock
842
+ * tool names are MCP-prefixed and pass through the normalization in
843
+ * getFollowUps).
839
844
  */
840
845
  const FAMILY_INTEGRATIONS = [
841
846
  null,
@@ -879,7 +884,10 @@ const SCRIPTS = {
879
884
  kind: "text",
880
885
  text: "\n\nNothing unusual stood out."
881
886
  },
882
- { kind: "done" }
887
+ {
888
+ kind: "done",
889
+ sessionId: "mock-session-aaa"
890
+ }
883
891
  ],
884
892
  "with-tools": [
885
893
  {
@@ -914,7 +922,10 @@ const SCRIPTS = {
914
922
  kind: "text",
915
923
  text: "\nInsight saved as \"Weekly signups\" — pinned to your team dashboard."
916
924
  },
917
- { kind: "done" }
925
+ {
926
+ kind: "done",
927
+ sessionId: "mock-session-aaa"
928
+ }
918
929
  ],
919
930
  "mid-stream-error": [
920
931
  {
@@ -1711,4 +1722,4 @@ function runPlayground() {
1711
1722
  //#endregion
1712
1723
  export { runPlayground };
1713
1724
 
1714
- //# sourceMappingURL=playground-DlE5RNfE.js.map
1725
+ //# sourceMappingURL=playground-ZLG68cvx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playground-ZLG68cvx.js","names":["path","MOCK_TASKS","getMigrationContentBlocks"],"sources":["../src/ui/tui/playground/demos/WelcomeDemo.tsx","../src/ui/tui/playground/demos/LayoutDemo.tsx","../src/ui/tui/playground/demos/InputDemo.tsx","../src/ui/tui/playground/demos/ProgressDemo.tsx","../src/ui/tui/playground/demos/LogDemo.tsx","../src/ui/tui/playground/demos/RunScreenDemo.tsx","../src/ui/tui/playground/demos/HealthCheckDemo.tsx","../src/ui/tui/playground/demos/DoctorReportDemo.tsx","../src/ui/tui/playground/demos/ModalDemo.tsx","../src/ui/tui/playground/demos/McpDemo.tsx","../src/ui/tui/playground/demos/McpSuggestedPromptsDemo.tsx","../src/ui/tui/playground/demos/KeyboardHintsDemo.tsx","../src/ui/tui/playground/demos/AuditChecksDemo.tsx","../src/ui/tui/playground/demos/LearnDeckDemo.tsx","../src/ui/tui/playground/PlaygroundApp.tsx","../src/ui/tui/playground/start-playground.ts","../src/commands/basic-integration/playground.ts"],"sourcesContent":["/**\n * WelcomeDemo — Splash screen. Press enter to push the tabbed view.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport type { WizardStore } from '@ui/tui/store';\nimport { Colors, Icons } from '@ui/tui/styles';\n\ninterface WelcomeDemoProps {\n store: WizardStore;\n}\n\nexport const WelcomeDemo = ({ store }: WelcomeDemoProps) => {\n useInput((_input, key) => {\n if (key.return) {\n store.completeSetup();\n }\n });\n\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <Text bold color={Colors.accent}>\n {Icons.diamond} PostHog Setup Wizard layout primitives playground\n </Text>\n <Box height={1} />\n <Text>Layout primitives for the PostHog Setup Wizard TUI.</Text>\n <Text dimColor>\n CardLayout, SplitView, TabContainer, ProgressList, and more.\n </Text>\n <Box height={1} />\n <Text color={Colors.primary}>\n Press enter to continue {Icons.triangleRight}\n </Text>\n </Box>\n );\n};\n","/**\n * LayoutDemo — Demonstrates CardLayout + SplitView.\n * Cycles alignment enums with keyboard shortcuts.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useState } from 'react';\nimport { CardLayout, SplitView } from '@ui/tui/primitives/index';\nimport { HAlign, VAlign, Colors } from '@ui/tui/styles';\n\nconst hAligns = [HAlign.Left, HAlign.Center, HAlign.Right];\nconst vAligns = [VAlign.Top, VAlign.Center, VAlign.Bottom];\nconst hLabels = ['Left', 'Center', 'Right'];\nconst vLabels = ['Top', 'Center', 'Bottom'];\n\nexport const LayoutDemo = () => {\n const [hIdx, setHIdx] = useState(0);\n const [vIdx, setVIdx] = useState(0);\n\n useInput((input) => {\n if (input === 'h') setHIdx((i) => (i + 1) % hAligns.length);\n if (input === 'v') setVIdx((i) => (i + 1) % vAligns.length);\n });\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Layout Demo\n </Text>\n <Text dimColor>\n Press [h] to cycle hAlign ({hLabels[hIdx]}), [v] to cycle vAlign (\n {vLabels[vIdx]})\n </Text>\n <Box height={1} />\n <SplitView\n left={\n <CardLayout hAlign={hAligns[hIdx]} vAlign={vAligns[vIdx]}>\n <Box borderStyle=\"single\" borderColor={Colors.primary} paddingX={1}>\n <Text color={Colors.primary}>Left Pane</Text>\n </Box>\n </CardLayout>\n }\n right={\n <CardLayout hAlign={HAlign.Center} vAlign={VAlign.Center}>\n <Box borderStyle=\"single\" borderColor={Colors.accent} paddingX={1}>\n <Text color={Colors.accent}>Right Pane</Text>\n </Box>\n </CardLayout>\n }\n />\n </Box>\n );\n};\n","/**\n * InputDemo — Demonstrates PickerMenu (single + multi) and ConfirmationInput.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { PickerMenu, ConfirmationInput } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nenum DemoStep {\n Single = 'single',\n Multi = 'multi',\n Confirm = 'confirm',\n Done = 'done',\n}\n\nexport const InputDemo = () => {\n const [step, setStep] = useState<DemoStep>(DemoStep.Single);\n const [results, setResults] = useState<string[]>([]);\n\n if (step === DemoStep.Single) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Single Select\n </Text>\n <Box height={1} />\n <PickerMenu\n message=\"Pick a color\"\n options={[\n { label: 'Red', value: 'red', hint: 'warm' },\n { label: 'Blue', value: 'blue', hint: 'cool' },\n { label: 'Green', value: 'green', hint: 'natural' },\n ]}\n onSelect={(value) => {\n setResults((prev) => [...prev, `Single: ${value}`]);\n setStep(DemoStep.Multi);\n }}\n />\n </Box>\n );\n }\n\n if (step === DemoStep.Multi) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Multi Select\n </Text>\n <Box height={1} />\n <PickerMenu\n message=\"Pick toppings\"\n mode=\"multi\"\n options={[\n { label: 'Cheese', value: 'cheese' },\n { label: 'Pepperoni', value: 'pepperoni' },\n { label: 'Mushrooms', value: 'mushrooms' },\n { label: 'Onions', value: 'onions' },\n ]}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n setResults((prev) => [...prev, `Multi: ${arr.join(', ')}`]);\n setStep(DemoStep.Confirm);\n }}\n />\n </Box>\n );\n }\n\n if (step === DemoStep.Confirm) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Confirmation\n </Text>\n <Box height={1} />\n <ConfirmationInput\n message=\"Are you satisfied with your choices?\"\n onConfirm={() => {\n setResults((prev) => [...prev, 'Confirmed: Yes']);\n setStep(DemoStep.Done);\n }}\n onCancel={() => {\n setResults((prev) => [...prev, 'Confirmed: No']);\n setStep(DemoStep.Done);\n }}\n />\n </Box>\n );\n }\n\n // done\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Results\n </Text>\n <Box height={1} />\n {results.map((r, i) => (\n <Text key={i} color={Colors.success}>\n {'\\u2714'} {r}\n </Text>\n ))}\n <Box height={1} />\n <Text dimColor>Switch away from this tab and back to restart.</Text>\n </Box>\n );\n};\n","/**\n * ProgressDemo — Demonstrates ProgressList + LoadingBox.\n * Auto-animates task progression through states.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { ProgressList, LoadingBox } from '@ui/tui/primitives/index';\nimport type { ProgressItem } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nconst INITIAL_ITEMS: ProgressItem[] = [\n {\n label: 'Detect framework',\n activeForm: 'Detecting framework',\n status: 'pending',\n },\n {\n label: 'Install dependencies',\n activeForm: 'Installing dependencies',\n status: 'pending',\n },\n {\n label: 'Configure PostHog',\n activeForm: 'Configuring PostHog',\n status: 'pending',\n },\n {\n label: 'Add analytics provider',\n activeForm: 'Adding analytics provider',\n status: 'pending',\n },\n { label: 'Verify setup', activeForm: 'Verifying setup', status: 'pending' },\n];\n\nexport const ProgressDemo = () => {\n const [items, setItems] = useState<ProgressItem[]>(INITIAL_ITEMS);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n const timer = setInterval(() => {\n setTick((t) => t + 1);\n }, 1500);\n return () => clearInterval(timer);\n }, []);\n\n useEffect(() => {\n // Cycle: each tick advances the \"active\" task\n const total = INITIAL_ITEMS.length;\n // After all tasks complete, restart\n const cycle = tick % (total + 2); // +2 for a pause at the end\n\n setItems(\n INITIAL_ITEMS.map((item, i) => {\n if (i < cycle) return { ...item, status: 'completed' as const };\n if (i === cycle) return { ...item, status: 'in_progress' as const };\n return { ...item, status: 'pending' as const };\n }),\n );\n }, [tick]);\n\n const allDone = items.every((i) => i.status === 'completed');\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Progress Demo\n </Text>\n <Text dimColor>Tasks auto-advance every 1.5s (cycles continuously)</Text>\n <Box height={1} />\n <ProgressList items={items} title=\"Setup in progress:\" />\n <Box height={1} />\n {!allDone && <LoadingBox message=\"Working...\" />}\n {allDone && (\n <Text color={Colors.success} bold>\n {'\\u2714'} All tasks complete! Restarting...\n </Text>\n )}\n </Box>\n );\n};\n","/**\n * LogDemo — Demonstrates LogViewer.\n * Writes demo log lines to a temp file, then tails it.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useState } from 'react';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { LogViewer } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nconst DEMO_LOG_PATH = path.join(os.tmpdir(), 'posthog-playground.log');\n\nconst LOG_MESSAGES = [\n '[info] Playground started',\n '[info] Initializing demo components...',\n '[debug] Loading primitives barrel export',\n '[info] ScreenContainer mounted',\n '[info] TabContainer initialized with 6 tabs',\n '[debug] LayoutDemo: hAlign=Left, vAlign=Top',\n '[info] NavigationDemo: screenStack depth = 1',\n '[warn] TabDemo: arrow key conflict with outer container',\n '[info] InputDemo: waiting for user selection',\n '[info] ProgressDemo: tick 0, cycling tasks',\n '[debug] LogViewer: watching file for changes',\n '[info] All demos loaded successfully',\n];\n\nexport const LogDemo = () => {\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n // Write initial log content\n fs.writeFileSync(DEMO_LOG_PATH, LOG_MESSAGES.join('\\n') + '\\n');\n setReady(true);\n\n // Append lines periodically\n let lineNum = LOG_MESSAGES.length;\n const timer = setInterval(() => {\n lineNum++;\n const msg = `[info] Demo log line #${lineNum} — ${new Date().toISOString()}\\n`;\n fs.appendFileSync(DEMO_LOG_PATH, msg);\n }, 2000);\n\n return () => {\n clearInterval(timer);\n try {\n fs.unlinkSync(DEMO_LOG_PATH);\n } catch {\n // ignore\n }\n };\n }, []);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Log Demo\n </Text>\n <Text dimColor>Tailing {DEMO_LOG_PATH} (new line every 2s)</Text>\n <Box height={1} />\n {ready && <LogViewer filePath={DEMO_LOG_PATH} height={15} />}\n </Box>\n );\n};\n","/**\n * RunScreenDemo — Renders the real RunScreen with a mock store.\n * Tasks auto-advance every 1.5s. Discovered features (Stripe, LLM)\n * are pre-populated so conditional tips appear.\n */\n\nimport { useEffect, useRef, useSyncExternalStore } from 'react';\nimport { WizardStore, TaskStatus } from '@ui/tui/store';\nimport { DiscoveredFeature } from '@lib/wizard-session';\nimport {\n TabContainer,\n SplitView,\n ProgressList,\n LogViewer,\n EventPlanViewer,\n HNViewer,\n} from '@ui/tui/primitives/index';\nimport type { ProgressItem } from '@ui/tui/primitives/index';\nimport { LearnCard } from '@ui/tui/components/LearnCard';\nimport { TipsCard } from '@ui/tui/components/TipsCard';\nimport { getContentBlocks as getMigrationContentBlocks } from '@lib/programs/migration/content/index';\nimport { WIZARD_LOG_FILE } from '@utils/paths';\n\nconst MOCK_TASKS = [\n {\n label: 'Checking project structure and finding files for event tracking',\n activeForm: 'Checking project structure',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Verify PostHog dependencies',\n activeForm: 'Verifying PostHog dependencies',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Generate events plan (.posthog-events.json)',\n activeForm: 'Generating events plan',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Install posthog-js and posthog-node packages',\n activeForm: 'Installing packages',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Set up environment variables',\n activeForm: 'Setting up environment variables',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Create instrumentation-client.ts',\n activeForm: 'Creating instrumentation-client.ts',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Update next.config with rewrites',\n activeForm: 'Updating next.config',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Create posthog-server.ts',\n activeForm: 'Creating posthog-server.ts',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Add PostHog capture events to project files',\n activeForm: 'Adding capture events',\n status: TaskStatus.Pending,\n done: false,\n },\n];\n\nconst MOCK_EVENTS = [\n { name: 'page_viewed', description: 'Fires when a user views any page' },\n {\n name: 'button_clicked',\n description: 'Fires when the CTA button is clicked',\n },\n {\n name: 'form_submitted',\n description: 'Fires when the contact form is submitted',\n },\n {\n name: 'signup_started',\n description: 'Fires when a user begins the signup flow',\n },\n];\n\ninterface RunScreenDemoProps {\n store: WizardStore;\n}\n\nexport const RunScreenDemo = ({ store }: RunScreenDemoProps) => {\n const tickRef = useRef(0);\n const lastStatusRef = useRef('');\n\n // Seed the store with mock data on mount\n useEffect(() => {\n store.addDiscoveredFeature(DiscoveredFeature.Stripe);\n store.addDiscoveredFeature(DiscoveredFeature.LLM);\n store.setEventPlan(MOCK_EVENTS);\n store.pushStatus('Checking project structure.');\n lastStatusRef.current = 'Checking project structure.';\n\n // Set initial tasks\n const initial = MOCK_TASKS.map((t, i) =>\n i === 0 ? { ...t, status: TaskStatus.InProgress } : t,\n );\n store.setTasks(initial);\n }, []);\n\n // Auto-advance tasks every 1.5s\n useEffect(() => {\n const timer = setInterval(() => {\n tickRef.current += 1;\n const tick = tickRef.current;\n const total = MOCK_TASKS.length;\n const cycle = tick % (total + 3); // +3 for pause at end before restart\n\n const tasks = MOCK_TASKS.map((t, i) => {\n if (i < cycle)\n return { ...t, status: TaskStatus.Completed, done: true };\n if (i === cycle)\n return { ...t, status: TaskStatus.InProgress, done: false };\n return { ...t, status: TaskStatus.Pending, done: false };\n });\n\n store.setTasks(tasks);\n\n // Only push status when the message actually changes\n if (cycle < total) {\n const msg = MOCK_TASKS[cycle].activeForm + '...';\n if (msg !== lastStatusRef.current) {\n store.pushStatus(msg);\n lastStatusRef.current = msg;\n }\n }\n }, 1500);\n\n return () => clearInterval(timer);\n }, []);\n\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const progressItems: ProgressItem[] = store.tasks.map((t) => ({\n label: t.label,\n activeForm: t.activeForm,\n status: t.status,\n }));\n\n const statuses =\n store.statusMessages.length > 0 ? store.statusMessages : undefined;\n\n const learnBlocks = getMigrationContentBlocks(store);\n\n const tabs = [\n {\n id: 'status',\n label: 'Status',\n component: (\n <SplitView\n left={\n store.learnCardComplete ? (\n <TipsCard store={store} />\n ) : (\n <LearnCard\n store={store}\n blocks={learnBlocks}\n onComplete={() => store.setLearnCardComplete()}\n />\n )\n }\n right={<ProgressList items={progressItems} title=\"Tasks\" />}\n />\n ),\n },\n ...(store.eventPlan.length > 0\n ? [\n {\n id: 'events',\n label: 'Event plan',\n component: <EventPlanViewer events={store.eventPlan} />,\n },\n ]\n : []),\n {\n id: 'logs',\n label: 'Tail logs',\n component: <LogViewer filePath={WIZARD_LOG_FILE} />,\n },\n {\n id: 'hn',\n label: 'HN',\n component: <HNViewer />,\n },\n ];\n\n return (\n <TabContainer\n tabs={tabs}\n statusMessage={statuses}\n expandableStatus\n store={store}\n />\n );\n};\n","/**\n * HealthCheckDemo — Playground demo for health check UI components.\n *\n * Shows the ModalOverlay with ServiceHealthList, cycling through states:\n * 1. Checking (spinner) — 2 seconds\n * 2. Blocking outage modal (Anthropic down, npm degraded)\n *\n * Renders components directly (not HealthCheckScreen) to avoid useInput\n * conflicts with TabContainer's key handling.\n */\n\nimport { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { LoadingBox, ModalOverlay } from '@ui/tui/primitives/index';\nimport { Icons } from '@ui/tui/styles';\nimport { ServiceHealthList } from '@ui/tui/components/ServiceHealthList';\nimport { getBlockingServiceKeys } from '@lib/health-checks/readiness';\nimport { ServiceHealthStatus } from '@lib/health-checks/types';\nimport type { AllServicesHealth } from '@lib/health-checks/types';\n\nconst HEALTHY = { status: ServiceHealthStatus.Healthy } as const;\n\nconst MOCK_HEALTH: AllServicesHealth = {\n anthropic: { status: ServiceHealthStatus.Down, rawIndicator: 'major' },\n posthogOverall: HEALTHY,\n posthogComponents: { status: ServiceHealthStatus.Healthy },\n github: HEALTHY,\n npmOverall: {\n status: ServiceHealthStatus.Degraded,\n rawIndicator: 'minor',\n },\n npmComponents: {\n status: ServiceHealthStatus.Degraded,\n degradedOrDownComponents: [\n {\n name: 'Registry API',\n status: ServiceHealthStatus.Degraded,\n rawStatus: 'degraded_performance',\n },\n ],\n },\n cloudflareOverall: HEALTHY,\n cloudflareComponents: { status: ServiceHealthStatus.Healthy },\n llmGateway: HEALTHY,\n mcp: HEALTHY,\n githubReleases: HEALTHY,\n};\n\nexport const HealthCheckDemo = () => {\n const [showOutage, setShowOutage] = useState(false);\n\n useEffect(() => {\n const timer = setTimeout(() => setShowOutage(true), 2000);\n return () => clearTimeout(timer);\n }, []);\n\n if (!showOutage) {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <LoadingBox message=\"Checking service status...\" />\n </Box>\n );\n }\n\n const blockingKeys = getBlockingServiceKeys(MOCK_HEALTH);\n\n return (\n <ModalOverlay\n borderColor=\"red\"\n title={`${Icons.warning} Ongoing service disruptions`}\n width={72}\n footer={\n <Box marginLeft={2}>\n <Text dimColor>\n Continue [Enter] / Exit [Esc] (disabled in playground)\n </Text>\n </Box>\n }\n >\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box marginBottom={1}>\n <Text>\n <Text color=\"red\">{Icons.squareFilled}</Text>\n <Text dimColor> Down </Text>\n <Text color=\"#DC9300\">{Icons.squareFilled}</Text>\n <Text dimColor> Degraded</Text>\n </Text>\n </Box>\n\n <ServiceHealthList\n health={MOCK_HEALTH}\n filterKeys={blockingKeys}\n showHealthy={false}\n />\n </Box>\n\n <Text dimColor>\n The wizard may not work reliably while services are affected.\n </Text>\n </ModalOverlay>\n );\n};\n","import { Box, Text } from 'ink';\nimport { Colors, Icons } from '@ui/tui/styles';\nimport { IssueTable } from '@ui/tui/screens/doctor/IssueTable';\nimport type { HealthIssue } from '@lib/programs/posthog-doctor/index';\n\nconst NOW = '2026-04-27T15:00:00Z';\n\nconst MOCK_ISSUES: HealthIssue[] = [\n mock('1', 'ingestion_lag', 'critical'),\n mock('2', 'ingestion_warning', 'critical'),\n mock('3', 'materialized_view_failure', 'critical'),\n mock('4', 'sdk_outdated', 'warning'),\n mock('5', 'no_pageleave_events', 'warning'),\n mock('6', 'scroll_depth', 'warning'),\n mock('7', 'web_vitals', 'warning'),\n mock('8', 'reverse_proxy', 'info'),\n mock('9', 'authorized_urls', 'info'),\n mock('10', 'unrecognised_kind_with_a_long_slug_that_should_truncate', 'info'),\n];\n\nfunction mock(\n id: string,\n kind: string,\n severity: HealthIssue['severity'],\n): HealthIssue {\n return {\n id,\n kind,\n severity,\n status: 'active',\n dismissed: false,\n created_at: NOW,\n updated_at: NOW,\n };\n}\n\nexport const DoctorReportDemo = () => {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n PostHog Doctor Report\n </Text>\n <Text dimColor>\n Project 12345 {Icons.bullet} https://us.i.posthog.com\n </Text>\n <Box marginTop={1}>\n <Text>\n {MOCK_ISSUES.length} active issues: 3 critical, 4 warning, 3 info\n </Text>\n </Box>\n <IssueTable issues={MOCK_ISSUES} />\n </Box>\n );\n};\n","/**\n * ModalDemo — Playground demo for the ModalOverlay primitive.\n *\n * Shows several modal variants: info, warning, error, and one with feedback text.\n */\n\nimport { Box, Text } from 'ink';\nimport { ModalOverlay } from '@ui/tui/primitives/index';\nimport { Icons } from '@ui/tui/styles';\n\nexport const ModalDemo = () => {\n return (\n <Box flexDirection=\"column\" gap={1} flexGrow={1}>\n <ModalOverlay borderColor=\"cyan\" title=\"Info Modal\" width={60}>\n <Text>A simple informational modal with default styling.</Text>\n </ModalOverlay>\n\n <ModalOverlay\n borderColor=\"#DC9300\"\n title={`${Icons.warning} Warning Modal`}\n width={60}\n feedback=\"Something needs your attention.\"\n >\n <Text>This modal includes a feedback message shown in yellow.</Text>\n </ModalOverlay>\n\n <ModalOverlay\n borderColor=\"red\"\n title={`${Icons.warning} Error Modal`}\n width={60}\n footer={\n <Box marginLeft={2}>\n <Text dimColor>\n Continue [Enter] / Exit [Esc] (disabled in playground)\n </Text>\n </Box>\n }\n >\n <Text>This modal has a footer section below a divider.</Text>\n </ModalOverlay>\n </Box>\n );\n};\n","/**\n * McpDemo — Playground demo for the MCP client selection screen.\n *\n * Uses a mock McpInstaller that simulates detecting three editors,\n * a short install delay, and a successful result.\n */\n\nimport { WizardStore } from '@ui/tui/store';\nimport { McpScreen } from '@ui/tui/screens/McpScreen';\nimport type { McpInstaller } from '@ui/tui/services/mcp-installer';\n\nconst MOCK_CLIENTS = [\n { name: 'Claude Code', supportsPlugin: true },\n { name: 'Cursor', supportsPlugin: true },\n { name: 'VS Code', supportsPlugin: false },\n];\n\nfunction createMockInstaller(): McpInstaller {\n return {\n async detectClients() {\n await new Promise((r) => setTimeout(r, 800));\n return MOCK_CLIENTS;\n },\n async install(clientNames) {\n await new Promise((r) => setTimeout(r, 1500));\n return clientNames;\n },\n async installPlugins(clientNames) {\n await new Promise((r) => setTimeout(r, 800));\n return clientNames.filter(\n (name) => MOCK_CLIENTS.find((c) => c.name === name)?.supportsPlugin,\n );\n },\n async remove() {\n await new Promise((r) => setTimeout(r, 1000));\n return MOCK_CLIENTS.map((c) => c.name);\n },\n };\n}\n\ninterface McpDemoProps {\n store: WizardStore;\n}\n\nexport const McpDemo = ({ store }: McpDemoProps) => {\n return (\n <McpScreen store={store} installer={createMockInstaller()} mode=\"install\" />\n );\n};\n","/**\n * McpSuggestedPromptsDemo — Playground demo for the post-MCP\n * suggested-prompts screen.\n *\n * Mounts the real McpSuggestedPromptsScreen with mock services so every\n * phase (Choose → Authenticating → Greeting → PromptPicker → Running →\n * FollowUp) can be previewed without touching the network. The Greeting\n * phase auto-advances; FollowUp re-enters Running when a follow-up is\n * picked, building a conversation tree up to MAX_PROMPT_RUNS deep.\n *\n * R cycle role (null → founder → product → ... → data → null)\n * F cycle framework (null → nextjs → vue → swift → django → null)\n * X remount the screen (useful after Exit)\n *\n * O OAuth outcome: success | error\n * L login delay: 0ms (skip UI) | 2000ms | 6000ms\n * S stream script: short-text | with-tools | mid-stream-error\n * C chunk delay: 50ms | 200ms | 800ms\n *\n * Tip: switch S to \"with-tools\" and the FollowUp picker after the run\n * will show context-aware suggestions based on the last tool (mock\n * tool names are MCP-prefixed and pass through the normalization in\n * getFollowUps).\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport type { WizardStore } from '@ui/tui/store';\nimport { McpSuggestedPromptsScreen } from '@ui/tui/screens/McpSuggestedPromptsScreen';\nimport { Colors } from '@ui/tui/styles';\nimport { Integration } from '@lib/constants';\nimport { McpOutcome } from '@lib/wizard-session';\nimport { TAILORED_ROLES } from '@lib/mcp-role-prompts';\nimport type {\n AgentChunk,\n McpSuggestedPromptsServices,\n} from '@ui/tui/services/mcp-suggested-prompts-services';\n\n// One Integration per framework family so cycling exercises every\n// override bucket in mcp-role-prompts.ts.\nconst FAMILY_INTEGRATIONS: Array<Integration | null> = [\n null,\n Integration.nextjs, // fullstack\n Integration.vue, // frontend-web\n Integration.swift, // mobile\n Integration.django, // backend\n];\n\nconst ROLE_CYCLE: Array<string | null> = [null, ...TAILORED_ROLES];\n\nconst LOGIN_DELAYS_MS = [0, 2000, 6000] as const;\nconst CHUNK_DELAYS_MS = [50, 200, 800] as const;\ntype LoginOutcome = 'success' | 'error';\ntype StreamScript = 'short-text' | 'with-tools' | 'mid-stream-error';\nconst LOGIN_OUTCOMES: LoginOutcome[] = ['success', 'error'];\nconst STREAM_SCRIPTS: StreamScript[] = [\n 'short-text',\n 'with-tools',\n 'mid-stream-error',\n];\n\nconst SCRIPTS: Record<StreamScript, AgentChunk[]> = {\n 'short-text': [\n { kind: 'text', text: 'Looking at your project…' },\n { kind: 'text', text: ' here is a quick read of the last 24 hours.' },\n {\n kind: 'text',\n text: ' You had 12,308 events from 2,144 distinct users.',\n },\n { kind: 'text', text: '\\n\\nNothing unusual stood out.' },\n { kind: 'done', sessionId: 'mock-session-aaa' },\n ],\n 'with-tools': [\n { kind: 'text', text: 'Looking up your project…' },\n {\n kind: 'tool-call',\n toolName: 'mcp__posthog-wizard__query-trends',\n detail: '{ event: \"signup\", interval: \"day\", window: \"7d\" }',\n },\n {\n kind: 'tool-result',\n toolName: 'mcp__posthog-wizard__query-trends',\n detail: '{ rows: 7, total: 482, change: +8.4% }',\n },\n {\n kind: 'text',\n text: '\\nSignups are up 8.4% week-over-week — 482 over the last 7 days.',\n },\n {\n kind: 'tool-call',\n toolName: 'mcp__posthog-wizard__create-insight',\n detail: '{ name: \"Weekly signups\", query: <trends>, save: true }',\n },\n {\n kind: 'tool-result',\n toolName: 'mcp__posthog-wizard__create-insight',\n detail:\n '{ id: \"ins_abc123\", url: \"https://app.posthog.com/i/ins_abc123\" }',\n },\n {\n kind: 'text',\n text: '\\nInsight saved as \"Weekly signups\" — pinned to your team dashboard.',\n },\n { kind: 'done', sessionId: 'mock-session-aaa' },\n ],\n 'mid-stream-error': [\n { kind: 'text', text: 'Looking at the most recent errors…' },\n {\n kind: 'tool-call',\n toolName: 'mcp__posthog-wizard__list-errors',\n detail: '{ window: \"7d\", limit: 5 }',\n },\n {\n kind: 'error',\n text: 'MCP server returned 503 — try again in a moment.',\n },\n ],\n};\n\ninterface MockConfig {\n role: string | null;\n loginOutcome: LoginOutcome;\n loginDelayMs: number;\n script: StreamScript;\n chunkDelayMs: number;\n}\n\ninterface McpSuggestedPromptsDemoProps {\n store: WizardStore;\n}\n\nconst delay = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Returns a McpSuggestedPromptsServices instance whose behavior is read\n * fresh from `configRef` on every call. Hotkey changes take effect on\n * the *next* invocation without remounting the screen.\n */\nfunction createMockServices(\n store: WizardStore,\n configRef: { current: MockConfig },\n): McpSuggestedPromptsServices {\n return {\n performLogin: async () => {\n const cfg = configRef.current;\n store.setLoginUrl('https://app.posthog.com/oauth/playground-mock');\n await delay(cfg.loginDelayMs);\n store.setLoginUrl(null);\n\n if (cfg.loginOutcome === 'error') {\n throw new Error('Mock OAuth rejected — exercising error path.');\n }\n\n return {\n credentials: {\n accessToken: 'phx_mock',\n projectApiKey: 'phc_mock',\n host: 'http://127.0.0.1:1',\n projectId: 1,\n },\n roleAtOrganization: cfg.role,\n user: {\n distinct_id: 'demo-distinct-id',\n uuid: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',\n id: 1,\n email: 'joe@demo.example.com',\n first_name: 'Joe',\n last_name: 'Demo',\n role_at_organization: cfg.role,\n team: {\n id: 1,\n uuid: 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',\n organization: 'cccccccc-cccc-cccc-cccc-cccccccccccc',\n api_token: 'phc_mock',\n project_id: 1,\n name: 'Demo team',\n timezone: 'UTC',\n },\n organization: {\n id: 'cccccccc-cccc-cccc-cccc-cccccccccccc',\n name: 'Demo org',\n slug: 'demo-org',\n membership_level: 1,\n },\n organizations: [\n {\n id: 'cccccccc-cccc-cccc-cccc-cccccccccccc',\n name: 'Demo org',\n membership_level: 1,\n },\n ],\n },\n };\n },\n\n runPromptStreaming: ({ signal }) => mockStream(configRef, signal),\n };\n}\n\nasync function* mockStream(\n configRef: { current: MockConfig },\n signal: AbortSignal,\n): AsyncIterable<AgentChunk> {\n const cfg = configRef.current;\n const chunks = SCRIPTS[cfg.script];\n for (const chunk of chunks) {\n if (signal.aborted) return;\n await delay(cfg.chunkDelayMs);\n if (signal.aborted) return;\n yield chunk;\n }\n}\n\nexport const McpSuggestedPromptsDemo = ({\n store,\n}: McpSuggestedPromptsDemoProps) => {\n const [roleIdx, setRoleIdx] = useState(2); // 'product' — has overrides\n const [familyIdx, setFamilyIdx] = useState(1); // nextjs (fullstack)\n const [resetKey, setResetKey] = useState(0);\n const [loginOutcomeIdx, setLoginOutcomeIdx] = useState(0);\n const [loginDelayIdx, setLoginDelayIdx] = useState(1); // 2000ms default\n const [scriptIdx, setScriptIdx] = useState(1); // 'with-tools' default\n const [chunkDelayIdx, setChunkDelayIdx] = useState(1); // 200ms default\n\n const role = ROLE_CYCLE[roleIdx];\n const integration = FAMILY_INTEGRATIONS[familyIdx];\n const loginOutcome = LOGIN_OUTCOMES[loginOutcomeIdx];\n const loginDelayMs = LOGIN_DELAYS_MS[loginDelayIdx];\n const script = STREAM_SCRIPTS[scriptIdx];\n const chunkDelayMs = CHUNK_DELAYS_MS[chunkDelayIdx];\n\n // Ref-based config so hotkeys can update behavior without remounting.\n const configRef = useRef<MockConfig>({\n role,\n loginOutcome,\n loginDelayMs,\n script,\n chunkDelayMs,\n });\n configRef.current = {\n role,\n loginOutcome,\n loginDelayMs,\n script,\n chunkDelayMs,\n };\n\n // Stable services instance — reads from configRef each call.\n const services = useMemo(() => createMockServices(store, configRef), [store]);\n\n // Seed framework + a fake \"installed\" MCP state. setMcpComplete here\n // is harmless — production would have set it from the McpScreen step\n // before this screen mounts.\n useEffect(() => {\n store.setMcpComplete(McpOutcome.Installed, ['Claude Code']);\n store.setFrameworkConfig(integration ?? null, null);\n }, [store, integration]);\n\n useInput((input) => {\n if (input === 'R' || input === 'r') {\n setRoleIdx((i) => (i + 1) % ROLE_CYCLE.length);\n setResetKey((k) => k + 1);\n } else if (input === 'F' || input === 'f') {\n setFamilyIdx((i) => (i + 1) % FAMILY_INTEGRATIONS.length);\n setResetKey((k) => k + 1);\n } else if (input === 'X' || input === 'x') {\n store.setCredentials(null);\n store.setRoleAtOrganization(null);\n setResetKey((k) => k + 1);\n } else if (input === 'O' || input === 'o') {\n setLoginOutcomeIdx((i) => (i + 1) % LOGIN_OUTCOMES.length);\n } else if (input === 'L' || input === 'l') {\n setLoginDelayIdx((i) => (i + 1) % LOGIN_DELAYS_MS.length);\n } else if (input === 'S' || input === 's') {\n setScriptIdx((i) => (i + 1) % STREAM_SCRIPTS.length);\n } else if (input === 'C' || input === 'c') {\n setChunkDelayIdx((i) => (i + 1) % CHUNK_DELAYS_MS.length);\n }\n });\n\n const familyLabel = integration ?? 'unknown';\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <Text dimColor>\n R role · F framework · X reset · O oauth · L login-delay · S script · C\n chunk-delay\n </Text>\n <Text dimColor>\n role={String(role)} · integration={familyLabel} · login={loginOutcome}/\n {loginDelayMs}ms · script={script}/{chunkDelayMs}ms\n </Text>\n <Box marginTop={1} flexDirection=\"column\" flexGrow={1}>\n <McpSuggestedPromptsScreen\n key={resetKey}\n store={store}\n services={services}\n />\n </Box>\n <Box marginTop={1}>\n <Text color={Colors.muted} dimColor>\n (mock services — no real OAuth, no real LLM. Press R/F to preview\n different prompt kits; O/L/S/C to flip mock outcomes.)\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * KeyboardHintsDemo — Demonstrates the KeyboardHintsBar with all input types.\n *\n * Cycles through SinglePicker, MultiPicker, GroupedPicker, and Confirmation\n * so the user can see the hints bar update automatically for each component.\n * The bar appears at the bottom of the screen and stays visible, updating to\n * match the active component.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, type ReactNode } from 'react';\nimport {\n PickerMenu,\n GroupedPickerMenu,\n ConfirmationInput,\n} from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nenum DemoStep {\n SingleSelect = 'single',\n MultiSelect = 'multi',\n GroupedSelect = 'grouped',\n Confirmation = 'confirm',\n Done = 'done',\n}\n\nconst STEP_LABELS: Record<DemoStep, string> = {\n [DemoStep.SingleSelect]: 'Single Select — hints: ↑↓ navigate, enter select',\n [DemoStep.MultiSelect]:\n 'Multi Select — hints: ↑↓ navigate, space toggle, enter confirm',\n [DemoStep.GroupedSelect]:\n 'Grouped Select — hints: ↑↓ navigate, space toggle, a toggle all, enter confirm',\n [DemoStep.Confirmation]:\n 'Confirmation — hints: ←→ switch, enter confirm, esc cancel',\n [DemoStep.Done]: 'Done',\n};\n\nexport const KeyboardHintsDemo = () => {\n const [step, setStep] = useState<DemoStep>(DemoStep.SingleSelect);\n const [log, setLog] = useState<string[]>([]);\n\n const addLog = (msg: string) => setLog((prev) => [...prev.slice(-4), msg]);\n\n if (step === DemoStep.SingleSelect) {\n return (\n <Wrapper step={step} log={log}>\n <PickerMenu\n message=\"Pick a framework\"\n options={[\n { label: 'Next.js', value: 'next' },\n { label: 'React', value: 'react' },\n { label: 'Vue', value: 'vue' },\n { label: 'Svelte', value: 'svelte' },\n ]}\n columns={2}\n onSelect={(v) => {\n addLog(`Single: ${String(v)}`);\n setStep(DemoStep.MultiSelect);\n }}\n />\n </Wrapper>\n );\n }\n\n if (step === DemoStep.MultiSelect) {\n return (\n <Wrapper step={step} log={log}>\n <PickerMenu\n message=\"Pick features to enable\"\n mode=\"multi\"\n options={[\n { label: 'Analytics', value: 'analytics' },\n { label: 'Session Replay', value: 'replay' },\n { label: 'Feature Flags', value: 'flags' },\n { label: 'Surveys', value: 'surveys' },\n ]}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n addLog(`Multi: ${arr.join(', ')}`);\n setStep(DemoStep.GroupedSelect);\n }}\n />\n </Wrapper>\n );\n }\n\n if (step === DemoStep.GroupedSelect) {\n return (\n <Wrapper step={step} log={log}>\n <GroupedPickerMenu\n message=\"Select integrations\"\n groups={{\n Frontend: [\n { label: 'React SDK', value: 'react-sdk' },\n { label: 'Web Analytics', value: 'web-analytics' },\n ],\n Backend: [\n { label: 'Node SDK', value: 'node-sdk' },\n { label: 'Python SDK', value: 'python-sdk' },\n ],\n Tooling: [\n { label: 'MCP Server', value: 'mcp' },\n { label: 'CLI', value: 'cli' },\n ],\n }}\n onSelect={(values) => {\n addLog(`Grouped: ${values.join(', ')}`);\n setStep(DemoStep.Confirmation);\n }}\n />\n </Wrapper>\n );\n }\n\n if (step === DemoStep.Confirmation) {\n return (\n <Wrapper step={step} log={log}>\n <ConfirmationInput\n message=\"Apply these settings?\"\n onConfirm={() => {\n addLog('Confirmed!');\n setStep(DemoStep.Done);\n }}\n onCancel={() => {\n addLog('Cancelled');\n setStep(DemoStep.Done);\n }}\n />\n </Wrapper>\n );\n }\n\n return (\n <Wrapper step={step} log={log}>\n <Text dimColor>\n All steps complete. Switch away from this tab and back to restart.\n </Text>\n </Wrapper>\n );\n};\n\nconst Wrapper = ({\n step,\n log,\n children,\n}: {\n step: DemoStep;\n log: string[];\n children: ReactNode;\n}) => (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Keyboard Hints Demo\n </Text>\n <Text dimColor>{STEP_LABELS[step]}</Text>\n <Box height={1} />\n {children}\n {log.length > 0 && (\n <>\n <Box height={1} />\n <Text dimColor>Log:</Text>\n {log.map((entry, i) => (\n <Text key={i} color={Colors.muted}>\n {' '}\n {entry}\n </Text>\n ))}\n </>\n )}\n </Box>\n);\n","/**\n * AuditChecksDemo — renders the AuditChecksViewer against a mock ledger so\n * the scroll/expand/sort behavior can be verified in the playground without\n * running the actual audit agent.\n */\n\nimport { Box } from 'ink';\nimport type { AuditCheck } from '@lib/programs/audit/types';\nimport { AuditChecksViewer } from '@ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer';\n\nconst MOCK_CHECKS: AuditCheck[] = [\n {\n id: 'sdk-installed',\n area: 'Installation',\n label: 'PostHog SDK installed',\n status: 'pass',\n file: 'package.json',\n details: 'posthog-js@1.260.0 found in dependencies.',\n },\n {\n id: 'sdk-up-to-date',\n area: 'Installation',\n label: 'SDK version up to date',\n status: 'warning',\n details: 'installed 1.260.0, latest 1.372.6 — more than one minor behind.',\n },\n {\n id: 'init-correct',\n area: 'Installation',\n label: 'Initialization is correct',\n status: 'warning',\n file: 'index.js:12',\n details:\n 'Init runs at module load with no singleton guard; calling posthog.init() multiple times can cause duplicate events.',\n },\n {\n id: 'identify-stable-distinct-id',\n area: 'Identification',\n label: 'Stable distinct_id (not session UUID)',\n status: 'error',\n file: 'index.js:18',\n details:\n 'distinct_id is crypto.randomUUID() — a per-session ephemeral UUID that resets on every page load. Replace with an authenticated user id.',\n },\n {\n id: 'identify-not-late',\n area: 'Identification',\n label: 'identify() called before captures / flag evals',\n status: 'pass',\n file: 'index.js:18',\n details:\n 'posthog.identify() is called before any posthog.capture() calls in this module.',\n },\n {\n id: 'cross-runtime-distinct-id',\n area: 'Identification',\n label: 'Same distinct_id across client and server',\n status: 'pass',\n details: 'Single runtime — no cross-runtime check needed.',\n },\n {\n id: 'identify-reset-on-logout',\n area: 'Identification',\n label: 'reset() called on logout / account switch',\n status: 'error',\n file: 'auth.ts:44',\n details:\n 'signOut() clears app auth state but never calls posthog.reset(), so the next identify() on this device can merge into the prior user profile.',\n },\n {\n id: 'capture-event-names-static',\n area: 'Event Capture',\n label: 'Event names are static and consistent',\n status: 'pass',\n file: 'index.js:21',\n details:\n \"All posthog.capture() calls use static string literals ('pageview', 'cta_clicked'); no template literals or dynamic variables found.\",\n },\n {\n id: 'capture-uses-proxy',\n area: 'Event Capture',\n label: 'Captures route through a reverse proxy',\n status: 'warning',\n file: 'index.js:13',\n details:\n 'api_host is set to the default PostHog US ingest host (https://us.i.posthog.com) rather than a first-party reverse proxy — ad/tracking blockers can silently drop these events.',\n },\n {\n id: 'capture-growth-events',\n area: 'Event Capture',\n label: 'Key activation events captured',\n status: 'pending',\n },\n];\n\nexport const AuditChecksDemo = () => (\n <Box flexDirection=\"column\" flexGrow={1}>\n <AuditChecksViewer checks={MOCK_CHECKS} />\n </Box>\n);\n","/**\n * LearnDeckDemo — flip through every program's content deck one block at\n * a time so wording, pauses, and visual blocks can be reviewed without\n * waiting for the auto-advance timer.\n *\n * n / p step block (next / previous)\n * [ / ] switch deck\n * r replay current block (re-runs the reveal animation)\n *\n * Arrow keys are reserved for the playground's tab switcher, so this demo\n * uses letter keys.\n *\n * Decks are pulled from `PROGRAM_REGISTRY` so every program that ships a\n * deck is reviewable here. Migration also gets per-variant entries (one\n * per `--product=<id>` choice) so the variant composer in\n * `migration/content/index.tsx` can be exercised side-by-side with the\n * generic deck.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useMemo, useState } from 'react';\nimport {\n ContentSequencer,\n ProgressList,\n SplitView,\n TextRevealMode,\n} from '@ui/tui/primitives/index';\nimport type { ContentBlock, ProgressItem } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\nimport type { WizardStore } from '@ui/tui/store';\nimport { PROGRAM_REGISTRY } from '@lib/programs/program-registry';\nimport { AUDIT_AREA_SLIDES } from '@ui/tui/screens/audit/slides/index';\nimport { AUDIT_3000_AREA_SLIDES } from '@ui/tui/screens/audit-3000/slides/index';\nimport type { AreaSlide } from '@ui/tui/screens/audit/slides/shared';\n\ninterface Deck {\n id: string;\n label: string;\n blocks: ContentBlock[];\n}\n\n/**\n * Fake task list to fill the right-hand pane so the SplitView layout matches\n * what operators actually see during a real run. Mix of statuses so the\n * spinner glyph, the in-progress row, and completed rows all render.\n */\nconst MOCK_TASKS: ProgressItem[] = [\n {\n label: 'Confirm Statsig is in use',\n activeForm: 'Confirming Statsig is in use',\n status: 'completed',\n },\n {\n label: 'Install PostHog',\n activeForm: 'Installing PostHog',\n status: 'completed',\n },\n {\n label: 'Plan call site replacements',\n activeForm: 'Planning call site replacements',\n status: 'in_progress',\n },\n {\n label: 'Rewrite call sites',\n activeForm: 'Rewriting call sites',\n status: 'pending',\n },\n {\n label: 'Remove Statsig',\n activeForm: 'Removing Statsig',\n status: 'pending',\n },\n {\n label: 'Verify the project still builds',\n activeForm: 'Verifying the build',\n status: 'pending',\n },\n {\n label: 'Write migration report',\n activeForm: 'Writing migration report',\n status: 'pending',\n },\n];\n\ninterface LearnDeckDemoProps {\n store: WizardStore;\n}\n\nexport const LearnDeckDemo = ({ store }: LearnDeckDemoProps) => {\n const decks: Deck[] = useMemo(() => {\n const all: Deck[] = [];\n\n // Every program in the registry that ships a deck. Seed the store's\n // skillId from the program config so decks that template the skill\n // name (e.g. agent-skill's \"Running the <skill> skill...\") render the\n // real value instead of \"unknown\".\n for (const program of PROGRAM_REGISTRY) {\n if (!program.getContentBlocks) continue;\n const stub = program.skillId\n ? withSessionOverride(store, { skillId: program.skillId })\n : store;\n all.push({\n id: `program:${program.id}`,\n label: `${program.id} (${program.command ?? 'default'})${\n program.skillId ? ` · skill: ${program.skillId}` : ''\n }`,\n blocks: program.getContentBlocks(stub),\n });\n }\n\n // Audit + audit-3000 ship their own per-area slide model (not the\n // ContentBlock deck most programs use). Adapt each AreaSlide into a\n // flat ContentBlock list so the flipper can review them the same way.\n all.push({\n id: 'audit:area-slides',\n label: 'audit · area slides',\n blocks: areaSlidesToBlocks(AUDIT_AREA_SLIDES),\n });\n all.push({\n id: 'audit-3000:area-slides',\n label: 'audit-3000 · area slides',\n blocks: areaSlidesToBlocks(AUDIT_3000_AREA_SLIDES),\n });\n\n return all;\n }, [store]);\n\n const [deckIdx, setDeckIdx] = useState(0);\n const [blockIdx, setBlockIdx] = useState(0);\n const [replayKey, setReplayKey] = useState(0);\n\n const deck = decks[deckIdx];\n const block = deck.blocks[blockIdx];\n\n useInput((input) => {\n if (input === 'p') {\n setBlockIdx((i) => Math.max(0, i - 1));\n } else if (input === 'n') {\n setBlockIdx((i) => Math.min(deck.blocks.length - 1, i + 1));\n } else if (input === '[') {\n setDeckIdx((i) => (i - 1 + decks.length) % decks.length);\n setBlockIdx(0);\n } else if (input === ']') {\n setDeckIdx((i) => (i + 1) % decks.length);\n setBlockIdx(0);\n } else if (input === 'r') {\n setReplayKey((k) => k + 1);\n }\n });\n\n const pauseMs =\n typeof block === 'object' && 'pause' in block ? block.pause : '—';\n const blockKind = describeBlockKind(block);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <Text bold color={Colors.accent}>\n Learn deck flipper\n </Text>\n <Text dimColor>n/p step block · [ ] switch deck · r replay</Text>\n <Box height={1} />\n\n <Text>\n <Text bold>Deck:</Text> {deck.label}{' '}\n <Text dimColor>\n ({deckIdx + 1}/{decks.length})\n </Text>\n </Text>\n <Text>\n <Text bold>Block:</Text> {blockIdx + 1}/{deck.blocks.length}{' '}\n <Text dimColor>\n · kind: {blockKind} · pause: {String(pauseMs)}ms\n </Text>\n </Text>\n <Box height={1} />\n\n <Box flexGrow={1}>\n <SplitView\n left={\n <ContentSequencer\n key={`${deck.id}-${blockIdx}-${replayKey}`}\n blocks={deck.blocks.slice(0, blockIdx + 1)}\n mode={TextRevealMode.SentenceBySentence}\n startDelay={0}\n initialBlockIdx={blockIdx}\n />\n }\n right={<ProgressList items={MOCK_TASKS} title=\"Tasks\" />}\n />\n </Box>\n </Box>\n );\n};\n\n/**\n * Build a store proxy that exposes an overridden `session` while keeping\n * every prototype method (e.g. `setStatusExpanded`) and atom reference\n * intact. A plain `{...store, session: ...}` spread would drop the\n * prototype, so anything that called a store method on the result would\n * crash at render time.\n */\nfunction withSessionOverride(\n store: WizardStore,\n patch: Partial<WizardStore['session']>,\n): WizardStore {\n const stub = Object.create(Object.getPrototypeOf(store)) as WizardStore;\n Object.assign(stub, store);\n Object.defineProperty(stub, 'session', {\n value: { ...store.session, ...patch },\n writable: false,\n configurable: true,\n });\n return stub;\n}\n\n/**\n * Adapter: turn each audit AreaSlide into a sequence of ContentBlocks so it\n * fits the flipper's renderer. One block per intro paragraph, one for the\n * visual when present. Each slide is preceded by a heading block naming the\n * area so flipping between areas is obvious.\n */\nfunction areaSlidesToBlocks(slides: AreaSlide[]): ContentBlock[] {\n const out: ContentBlock[] = [];\n for (const slide of slides) {\n out.push({\n content: (\n <Text bold color={Colors.accent}>\n {slide.area}\n </Text>\n ),\n pause: 3000,\n });\n for (const paragraph of slide.intro) {\n out.push({ content: paragraph, pause: 5000 });\n }\n if (slide.visual) {\n out.push({\n content: slide.visual,\n pause: 8000,\n persist: true,\n });\n }\n out.push({ type: 'clear', pause: 1000 });\n }\n return out;\n}\n\nfunction describeBlockKind(block: ContentBlock): string {\n if (typeof block === 'string') return 'string';\n if (typeof block === 'object' && block !== null) {\n if ('type' in block && block.type === 'clear') return 'clear';\n if ('type' in block && block.type === 'lines') return 'lines';\n if ('content' in block) {\n return typeof block.content === 'string' ? 'text' : 'jsx';\n }\n }\n return 'unknown';\n}\n","/**\n * PlaygroundApp — Root component for the primitives playground.\n *\n * Two screens mirroring the real wizard flow:\n * intro → (press enter) → run (tabbed demo view)\n */\n\nimport { ScreenContainer, TabContainer } from '@ui/tui/primitives/index';\nimport type { WizardStore } from '@ui/tui/store';\nimport { WelcomeDemo } from './demos/WelcomeDemo.js';\nimport { LayoutDemo } from './demos/LayoutDemo.js';\nimport { InputDemo } from './demos/InputDemo.js';\nimport { ProgressDemo } from './demos/ProgressDemo.js';\nimport { LogDemo } from './demos/LogDemo.js';\nimport { RunScreenDemo } from './demos/RunScreenDemo.js';\nimport { HealthCheckDemo } from './demos/HealthCheckDemo.js';\nimport { DoctorReportDemo } from './demos/DoctorReportDemo.js';\nimport { ModalDemo } from './demos/ModalDemo.js';\nimport { McpDemo } from './demos/McpDemo.js';\nimport { McpSuggestedPromptsDemo } from './demos/McpSuggestedPromptsDemo.js';\nimport { KeyboardHintsDemo } from './demos/KeyboardHintsDemo.js';\nimport { AuditChecksDemo } from './demos/AuditChecksDemo.js';\nimport { LearnDeckDemo } from './demos/LearnDeckDemo.js';\n\ninterface PlaygroundAppProps {\n store: WizardStore;\n}\n\nexport const PlaygroundApp = ({ store }: PlaygroundAppProps) => {\n const tabs = [\n { id: 'layout', label: 'Layout', component: <LayoutDemo /> },\n { id: 'input', label: 'Input', component: <InputDemo /> },\n { id: 'progress', label: 'Progress', component: <ProgressDemo /> },\n { id: 'logs', label: 'Logs', component: <LogDemo /> },\n {\n id: 'run',\n label: 'RunScreen',\n component: <RunScreenDemo store={store} />,\n },\n {\n id: 'health',\n label: 'HealthCheck',\n component: <HealthCheckDemo />,\n },\n {\n id: 'doctor',\n label: 'Doctor',\n component: <DoctorReportDemo />,\n },\n {\n id: 'modal',\n label: 'Modal',\n component: <ModalDemo />,\n },\n {\n id: 'mcp',\n label: 'MCP',\n component: <McpDemo store={store} />,\n },\n {\n id: 'mcp-tutorial',\n label: 'MCP tutorial',\n component: <McpSuggestedPromptsDemo store={store} />,\n },\n {\n id: 'hints',\n label: 'KeyHints',\n component: <KeyboardHintsDemo />,\n },\n {\n id: 'audit-checks',\n label: 'Audit checks',\n component: <AuditChecksDemo />,\n },\n {\n id: 'learn-deck',\n label: 'Learn deck',\n component: <LearnDeckDemo store={store} />,\n },\n ];\n\n return (\n <ScreenContainer\n store={store}\n screens={{\n intro: <WelcomeDemo store={store} />,\n run: (\n <TabContainer\n tabs={tabs}\n statusMessage=\"Primitives Playground — use arrow keys to switch tabs\"\n />\n ),\n }}\n />\n );\n};\n","/**\n * start-playground.ts — Launches the TUI primitives playground.\n */\n\nimport { render } from 'ink';\nimport { createElement } from 'react';\nimport { WizardStore } from '@ui/tui/store';\nimport { PlaygroundApp } from './PlaygroundApp.js';\nimport { WizardReadiness } from '@lib/health-checks/readiness';\n\nexport function startPlayground(version: string): void {\n const store = new WizardStore();\n store.version = version;\n\n // Pre-fill session so the router skips health-check, auth, and setup,\n // landing on 'run' after the intro screen.\n // dismissOutage() guards against the onInit health-check async result\n // overwriting this with WizardReadiness.No before the user presses enter.\n store.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n store.dismissOutage();\n store.setCredentials({\n accessToken: 'fake',\n projectApiKey: 'fake',\n host: 'https://app.posthog.com',\n projectId: 0,\n });\n\n const { unmount, waitUntilExit } = render(\n createElement(PlaygroundApp, { store }),\n );\n\n void waitUntilExit().then(() => {\n unmount();\n process.exit(0);\n });\n}\n","import { VERSION } from '@lib/version';\nimport { startPlayground } from '@ui/tui/playground/start-playground';\n\n/** Launch the TUI primitives playground. */\nexport function runPlayground(): void {\n startPlayground(VERSION);\n}\n"],"mappings":"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"}