@posthog/wizard 2.19.0 → 2.21.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.
- package/README.md +11 -0
- package/dist/{slides-mT2s9wM_.js → OutroScreen-CqF6SdBo.js} +614 -122
- package/dist/OutroScreen-CqF6SdBo.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-CjnvTVj0.js → add-mcp-server-to-clients-DQHGhzt6.js} +4 -4
- package/dist/{add-mcp-server-to-clients-CjnvTVj0.js.map → add-mcp-server-to-clients-DQHGhzt6.js.map} +1 -1
- package/dist/{agent-interface-CQU6x4Hj.js → agent-interface-DE7txTqh.js} +163 -52
- package/dist/agent-interface-DE7txTqh.js.map +1 -0
- package/dist/{agent-runner-Cj7saDkL.js → agent-runner-DUZ5OD6e.js} +10 -9
- package/dist/{agent-runner-Cj7saDkL.js.map → agent-runner-DUZ5OD6e.js.map} +1 -1
- package/dist/{analytics-Df-Xb81i.js → analytics-Bl5DPj_0.js} +2 -2
- package/dist/{analytics-Df-Xb81i.js.map → analytics-Bl5DPj_0.js.map} +1 -1
- package/dist/{api-Dw6_orDE.js → api-DuA0_88V.js} +25 -4
- package/dist/{api-Dw6_orDE.js.map → api-DuA0_88V.js.map} +1 -1
- package/dist/bin.js +74 -47
- package/dist/bin.js.map +1 -1
- package/dist/check-screens.tsx +124 -0
- package/dist/{ci-install-BKAvFfK6.js → ci-install-BnOYI4mZ.js} +4 -4
- package/dist/{ci-install-BKAvFfK6.js.map → ci-install-BnOYI4mZ.js.map} +1 -1
- package/dist/{debug-Cp_wNn8i.js → debug-BVC48wlb.js} +1 -1
- package/dist/{debug-DnMO6O8O.js → debug-h7Z9zEbD.js} +2 -2
- package/dist/{debug-DnMO6O8O.js.map → debug-h7Z9zEbD.js.map} +1 -1
- package/dist/{environment-Ls0H9ljT.js → environment-uaLmtlH_.js} +3 -3
- package/dist/{environment-Ls0H9ljT.js.map → environment-uaLmtlH_.js.map} +1 -1
- package/dist/{interactive-D15byhpc.js → interactive-CW5gjyDd.js} +2 -2
- package/dist/{interactive-D15byhpc.js.map → interactive-CW5gjyDd.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-DQOTQfW1.js → mcp-prompt-streaming-DMDwaark.js} +4 -4
- package/dist/{mcp-prompt-streaming-DQOTQfW1.js.map → mcp-prompt-streaming-DMDwaark.js.map} +1 -1
- package/dist/{non-interactive-DcFLJtl_.js → non-interactive-DJrVQ4nS.js} +2 -2
- package/dist/{non-interactive-DcFLJtl_.js.map → non-interactive-DJrVQ4nS.js.map} +1 -1
- package/dist/{package-manager-DUPgLGpQ.js → package-manager-DCUBRbr-.js} +2 -2
- package/dist/{package-manager-DUPgLGpQ.js.map → package-manager-DCUBRbr-.js.map} +1 -1
- package/dist/{playground-BZ0hGjbL.js → playground-DCVaVeVD.js} +138 -9
- package/dist/playground-DCVaVeVD.js.map +1 -0
- package/dist/{posthog-integration-C8qhJnI3.js → posthog-integration-ChdwFPMj.js} +17 -11
- package/dist/posthog-integration-ChdwFPMj.js.map +1 -0
- package/dist/{provisioning-C-2ExcqY.js → provisioning-GeMkBMSR.js} +3 -3
- package/dist/{provisioning-C-2ExcqY.js.map → provisioning-GeMkBMSR.js.map} +1 -1
- package/dist/{registry-hBUgaWFx.js → registry-VSSRH3sU.js} +4 -4
- package/dist/{registry-hBUgaWFx.js.map → registry-VSSRH3sU.js.map} +1 -1
- package/dist/{setup-utils-DetnhXo0.js → setup-utils-BfV4pydt.js} +12 -10
- package/dist/setup-utils-BfV4pydt.js.map +1 -0
- package/dist/{start-tui-BfXoErKg.js → start-tui-BRvm5VP9.js} +93 -228
- package/dist/start-tui-BRvm5VP9.js.map +1 -0
- package/dist/{steps-SoDXSUxe.js → steps-DA4uvSbg.js} +6 -6
- package/dist/{steps-SoDXSUxe.js.map → steps-DA4uvSbg.js.map} +1 -1
- package/dist/{task-stream-CZRj6auI.js → task-stream-CZawuzlz.js} +2 -2
- package/dist/{task-stream-CZRj6auI.js.map → task-stream-CZawuzlz.js.map} +1 -1
- package/dist/{telemetry-CPcMFxcO.js → telemetry-BRAonUea.js} +2 -2
- package/dist/{telemetry-CPcMFxcO.js.map → telemetry-BRAonUea.js.map} +1 -1
- package/dist/{urls-BO7doNJG.js → urls-B66Ib2jT.js} +2 -2
- package/dist/{urls-BO7doNJG.js.map → urls-B66Ib2jT.js.map} +1 -1
- package/dist/{wizard-abort-CDXufkqJ.js → wizard-abort-D1_DnFjm.js} +12 -7
- package/dist/wizard-abort-D1_DnFjm.js.map +1 -0
- package/dist/wizard-abort-gMB1eV6T.js +2 -0
- package/dist/{wizard-session-d27JGRGi.js → wizard-session-G3VWD6hv.js} +3 -1
- package/dist/{wizard-session-d27JGRGi.js.map → wizard-session-G3VWD6hv.js.map} +1 -1
- package/dist/{wizard-session-y304gEEI.js → wizard-session-wPJtNl4c.js} +1 -1
- package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
- package/package.json +4 -2
- package/dist/agent-interface-CQU6x4Hj.js.map +0 -1
- package/dist/playground-BZ0hGjbL.js.map +0 -1
- package/dist/posthog-integration-C8qhJnI3.js.map +0 -1
- package/dist/setup-utils-DetnhXo0.js.map +0 -1
- package/dist/slides-mT2s9wM_.js.map +0 -1
- package/dist/start-tui-BfXoErKg.js.map +0 -1
- package/dist/wizard-abort-CDXufkqJ.js.map +0 -1
- package/dist/wizard-abort-CtMY57ZE.js +0 -2
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"playground-BZ0hGjbL.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 {\n McpInstaller,\n McpClientInfo,\n} from '@ui/tui/services/mcp-installer';\n\nconst MOCK_CLIENTS: McpClientInfo[] = [\n { name: 'Claude Code', supportsPlugin: true },\n { name: 'Cursor', supportsPlugin: true },\n { name: 'VS Code', supportsPlugin: false },\n {\n name: 'Claude Desktop/Web',\n supportsPlugin: false,\n finish: {\n url: 'https://claude.ai/directory/connectors/posthog',\n instruction: 'Sign in and click \"Connect\" to finish.',\n },\n },\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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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-integration-C8qhJnI3.js","names":[],"sources":["../src/lib/detection/framework.ts","../src/lib/detection/features.ts","../src/lib/detection/context.ts","../src/lib/programs/shared/health-check-step.ts","../src/lib/programs/posthog-integration/detect.ts","../src/lib/programs/posthog-integration/steps.ts","../src/ui/tui/styles.ts","../src/ui/tui/primitives/text-helpers.ts","../src/ui/tui/primitives/content-types.ts","../src/ui/tui/primitives/layout-helpers.ts","../src/ui/tui/primitives/TextBlock.tsx","../src/ui/tui/components/StatusPeekTrigger.tsx","../src/lib/programs/posthog-integration/content/data-flow.tsx","../src/lib/programs/posthog-integration/content/product-suite.tsx","../src/lib/programs/posthog-integration/content/line-chart.tsx","../src/lib/programs/posthog-integration/content/funnel.tsx","../src/lib/programs/posthog-integration/content/index.tsx","../src/lib/programs/posthog-integration/index.ts"],"sourcesContent":["/**\n * Framework detection — identify which PostHog-supported framework\n * is present in the project directory.\n *\n * Pure function: takes an install dir, returns the detected integration\n * (or undefined). No store mutations, no UI calls.\n */\n\nimport { Integration, DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\n\n/**\n * Loop through all registered frameworks and return the first one\n * whose `detect()` predicate matches the given directory.\n * Returns undefined if no framework is detected or detection times out.\n */\nexport async function detectFramework(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\n }\n}\n","/**\n * Feature discovery — scan project dependencies for known SDK patterns\n * that indicate additional PostHog programs are relevant.\n *\n * Pure function: takes an install dir, returns a set of discovered features.\n * No store mutations, no UI calls.\n */\n\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { DiscoveredFeature } from '@lib/wizard-session';\n\nconst STRIPE_PACKAGES = ['stripe', '@stripe/stripe-js'];\n\nconst LLM_PACKAGES = [\n 'openai',\n '@anthropic-ai/sdk',\n 'ai',\n '@ai-sdk/openai',\n 'langchain',\n '@langchain/openai',\n '@langchain/langgraph',\n '@google/generative-ai',\n '@google/genai',\n '@instructor-ai/instructor',\n '@mastra/core',\n 'portkey-ai',\n];\n\n// PyPI normalizes `_` to `-` and is case-insensitive; compare via normalizePyName.\nconst PYTHON_LLM_PACKAGES = [\n 'openai',\n 'anthropic',\n 'langchain',\n 'langchain-openai',\n 'langchain-anthropic',\n 'langchain-google-genai',\n 'langgraph',\n 'litellm',\n 'llama-index',\n 'pydantic-ai',\n 'crewai',\n 'instructor',\n 'dspy-ai',\n 'mistralai',\n 'cohere',\n 'google-generativeai',\n 'google-genai',\n 'portkey-ai',\n];\n\nexport function discoverFeatures(installDir: string): DiscoveredFeature[] {\n const features: DiscoveredFeature[] = [];\n discoverNodeFeatures(installDir, features);\n discoverPythonFeatures(installDir, features);\n return features;\n}\n\nfunction discoverNodeFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n const packageJsonText = safeRead(installDir, 'package.json');\n if (!packageJsonText) return;\n\n let packageJson: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n try {\n packageJson = JSON.parse(packageJsonText);\n } catch {\n return;\n }\n\n const depNames = Object.keys({\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n });\n\n if (depNames.some((depName) => STRIPE_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.Stripe);\n }\n if (depNames.some((depName) => LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction discoverPythonFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n if (features.includes(DiscoveredFeature.LLM)) return;\n\n const depNames: string[] = [];\n\n const requirementsTxt = safeRead(installDir, 'requirements.txt');\n if (requirementsTxt) depNames.push(...parseRequirementsTxt(requirementsTxt));\n\n const pyprojectToml = safeRead(installDir, 'pyproject.toml');\n if (pyprojectToml) depNames.push(...parsePyprojectToml(pyprojectToml));\n\n const pipfile = safeRead(installDir, 'Pipfile');\n if (pipfile) depNames.push(...parsePipfile(pipfile));\n\n if (depNames.some((depName) => PYTHON_LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction safeRead(installDir: string, file: string): string | null {\n try {\n return readFileSync(join(installDir, file), 'utf-8');\n } catch {\n return null;\n }\n}\n\nfunction normalizePyName(name: string): string {\n return name.toLowerCase().replace(/_/g, '-');\n}\n\nexport function parseRequirementsTxt(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#') && !line.startsWith('-'))\n .map((line) => line.replace(/\\[[^\\]]*\\]/, ''))\n .map((line) => line.split(/[<>=!~;\\s]/)[0])\n .filter(Boolean)\n .map(normalizePyName);\n}\n\n// Pragmatic, not a full TOML parser — only the dep shapes we care about.\nexport function parsePyprojectToml(content: string): string[] {\n const depNames: string[] = [];\n\n for (const arrayMatch of content.matchAll(\n /dependencies\\s*=\\s*\\[([^\\]]*)\\]/g,\n )) {\n const arrayBody = arrayMatch[1];\n for (const quotedMatch of arrayBody.matchAll(/[\"']([^\"']+)[\"']/g)) {\n const depSpec = quotedMatch[1];\n const name = depSpec.replace(/\\[[^\\]]*\\]/, '').split(/[<>=!~;\\s]/)[0];\n if (name) depNames.push(normalizePyName(name));\n }\n }\n\n const poetrySectionRe =\n /\\[tool\\.poetry\\.(?:dev-dependencies|dependencies|group\\.[^.\\]]+\\.dependencies)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(poetrySectionRe)) {\n const sectionBody = sectionMatch[1];\n depNames.push(...extractTomlSectionKeys(sectionBody, { skip: ['python'] }));\n }\n\n return depNames;\n}\n\nexport function parsePipfile(content: string): string[] {\n const depNames: string[] = [];\n const sectionRe = /\\[(packages|dev-packages)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(sectionRe)) {\n const sectionBody = sectionMatch[2];\n depNames.push(...extractTomlSectionKeys(sectionBody));\n }\n return depNames;\n}\n\nfunction extractTomlSectionKeys(\n sectionBody: string,\n opts: { skip?: string[] } = {},\n): string[] {\n const skipNames = new Set(opts.skip ?? []);\n const depNames: string[] = [];\n for (const line of sectionBody.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const equalsIndex = trimmed.indexOf('=');\n if (equalsIndex <= 0) continue;\n const name = trimmed.slice(0, equalsIndex).trim();\n if (!/^[a-zA-Z0-9._-]+$/.test(name)) continue;\n if (skipNames.has(name.toLowerCase())) continue;\n depNames.push(normalizePyName(name));\n }\n return depNames;\n}\n","/**\n * Framework context gathering — run gatherContext and version checks\n * for a detected framework.\n *\n * Pure functions: take a framework config and options, return results.\n * No store mutations, no UI calls.\n */\n\nimport * as semver from 'semver';\nimport { DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport type { FrameworkConfig } from '@lib/framework-config';\nimport type { WizardRunOptions } from '@utils/types';\n\n/**\n * Run a framework's `gatherContext()` to collect variant-specific\n * metadata (e.g., router type for Next.js, Expo vs bare for React Native).\n *\n * Returns the gathered context, or an empty object on failure/timeout.\n */\nexport async function gatherFrameworkContext(\n config: FrameworkConfig,\n options: WizardRunOptions,\n): Promise<Record<string, unknown>> {\n if (!config.metadata.gatherContext) return {};\n\n try {\n return await Promise.race([\n config.metadata.gatherContext(options),\n new Promise<Record<string, never>>((resolve) =>\n setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS),\n ),\n ]);\n } catch {\n return {};\n }\n}\n\nexport interface VersionCheckResult {\n /** Whether the installed version is supported */\n supported:\n | true\n | {\n current: string;\n minimum: string;\n docsUrl: string;\n };\n}\n\n/**\n * Check whether the installed framework version meets the minimum requirement.\n *\n * Returns `{ supported: true }` if the version is fine (or no check is needed).\n * Returns the version details if unsupported.\n */\nexport async function checkFrameworkVersion(\n config: FrameworkConfig,\n options: WizardRunOptions,\n): Promise<VersionCheckResult> {\n if (\n !config.detection.minimumVersion ||\n !config.detection.getInstalledVersion\n ) {\n return { supported: true };\n }\n\n const version = await config.detection.getInstalledVersion(options);\n if (!version) return { supported: true };\n\n const coerced = semver.coerce(version);\n if (coerced && semver.lt(coerced, config.detection.minimumVersion)) {\n return {\n supported: {\n current: version,\n minimum: config.detection.minimumVersion,\n docsUrl:\n config.metadata.unsupportedVersionDocsUrl ?? config.metadata.docsUrl,\n },\n };\n }\n\n return { supported: true };\n}\n","/**\n * Shared health-check step used by every program that runs an agent.\n *\n * Renders the HealthCheckScreen between intro and auth, kicks off the\n * readiness probe in onInit, and gates the screen on either a clean\n * readiness result or an explicit user dismissal of the outage.\n *\n * Programs without this step that hit a blocking outage gridlock the\n * router: agent-runner calls wizardAbort, which awaits outroDismissed,\n * but the router can't advance past the still-incomplete auth step to\n * render the OutroScreen.\n */\n\nimport type { ProgramStep } from '@lib/programs/program-step';\nimport type { WizardSession } from '@lib/wizard-session';\nimport {\n evaluateWizardReadiness,\n WizardReadiness,\n SIGNUP_WIZARD_READINESS_CONFIG,\n getBlockingServiceKeys,\n} from '@lib/health-checks/readiness';\nimport { logToFile } from '@utils/debug';\n\nexport function healthCheckReady(session: WizardSession): boolean {\n if (!session.readinessResult) return false;\n\n if (session.signup) {\n const hardBlocking = getBlockingServiceKeys(\n session.readinessResult.health,\n SIGNUP_WIZARD_READINESS_CONFIG,\n );\n const defaultBlocking = getBlockingServiceKeys(\n session.readinessResult.health,\n );\n if (hardBlocking.length === 0 && defaultBlocking.length === 0) return true;\n return session.outageDismissed;\n }\n\n if (session.readinessResult.decision === WizardReadiness.No) {\n return session.outageDismissed;\n }\n return true;\n}\n\nexport const HEALTH_CHECK_STEP: ProgramStep = {\n id: 'health-check',\n label: 'Health check',\n screenId: 'health-check',\n gate: healthCheckReady,\n onInit: (ctx) => {\n evaluateWizardReadiness()\n .then((readiness) => {\n logToFile(\n `[health-checks] TUI pre-flight complete: decision=${readiness.decision}`,\n );\n ctx.setReadinessResult(readiness);\n })\n .catch((err) => {\n logToFile('[health-checks] TUI pre-flight failed:', err);\n ctx.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n });\n },\n};\n","/**\n * Core integration detection step.\n *\n * Runs framework detection, context gathering, version checking,\n * and feature discovery. Writes results to the store via the\n * ProgramReadyContext so the IntroScreen can display them.\n *\n * This is the same work that bin.ts $0 handler does inline —\n * extracted here so the `integrate` subcommand can reuse it.\n */\n\nimport type { ProgramReadyContext } from '@lib/programs/program-step';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\nimport {\n detectFramework,\n discoverFeatures,\n gatherFrameworkContext,\n checkFrameworkVersion,\n} from '@lib/detection/index';\n\nexport async function detectPostHogIntegration(\n ctx: ProgramReadyContext,\n): Promise<void> {\n const session = ctx.session;\n const installDir = session.installDir;\n\n const detectedIntegration = await detectFramework(installDir);\n\n if (detectedIntegration) {\n const config = FRAMEWORK_REGISTRY[detectedIntegration];\n\n const sessionOptions = {\n installDir,\n debug: session.debug,\n default: false,\n signup: session.signup,\n localMcp: session.localMcp,\n ci: session.ci,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n };\n\n // Gather framework-specific context (e.g., router type)\n const context = await gatherFrameworkContext(config, sessionOptions);\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n ctx.setFrameworkContext(key, value);\n }\n }\n\n ctx.setFrameworkConfig(detectedIntegration, config);\n session.skillId = detectedIntegration;\n\n if (!session.detectedFrameworkLabel) {\n ctx.setDetectedFramework(config.metadata.name);\n }\n\n // Version check\n const versionResult = await checkFrameworkVersion(config, sessionOptions);\n if (versionResult.supported !== true) {\n ctx.setUnsupportedVersion(versionResult.supported);\n }\n }\n\n // Feature discovery\n for (const feature of discoverFeatures(installDir)) {\n ctx.addDiscoveredFeature(feature);\n }\n\n ctx.setDetectionComplete();\n}\n","/**\n * PostHog integration program — the default wizard flow.\n *\n * Steps define their own gate predicates and onInit callbacks.\n * The store derives gate promises and fires init work from these\n * definitions — no hardcoded per-flow logic in the store.\n */\n\nimport type { ProgramStep } from '@lib/programs/program-step';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { RunPhase } from '@lib/wizard-session';\nimport { HEALTH_CHECK_STEP } from '@lib/programs/shared/health-check-step';\nimport { detectPostHogIntegration } from './detect.js';\n\nfunction needsSetup(session: WizardSession): boolean {\n const config = session.frameworkConfig;\n if (!config?.metadata.setup?.questions) return false;\n\n return config.metadata.setup.questions.some(\n (q: { key: string }) => !(q.key in session.frameworkContext),\n );\n}\n\nexport const POSTHOG_INTEGRATION_PROGRAM: ProgramStep[] = [\n {\n id: 'detect',\n label: 'Detecting framework',\n // Headless step: no screen. onReady fires after bin.ts assigns the\n // session — runs framework detection, context gathering, version\n // check, and feature discovery. Results are written to the store\n // for the IntroScreen to render.\n onReady: (ctx) => detectPostHogIntegration(ctx),\n },\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'intro',\n gate: (session) => session.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'setup',\n label: 'Setup',\n screenId: 'setup',\n show: needsSetup,\n isComplete: (session) => !needsSetup(session),\n },\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: (session) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Integration',\n screenId: 'run',\n isComplete: (session) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'mcp',\n label: 'MCP servers',\n screenId: 'mcp',\n isComplete: (session) => session.mcpComplete,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (session) => session.outroDismissed,\n },\n {\n id: 'keep-skills',\n label: 'Keep Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * Shared style constants for TUI layout primitives.\n */\n\nexport enum HAlign {\n Left = 'flex-start',\n Center = 'center',\n Right = 'flex-end',\n}\n\nexport enum VAlign {\n Top = 'flex-start',\n Center = 'center',\n Bottom = 'flex-end',\n}\n\nexport const Colors = {\n primary: 'cyan',\n accent: '#DC9300',\n titleColor: '#3D2800',\n success: 'green',\n error: 'red',\n muted: 'gray',\n} as const;\n\nexport const Icons = {\n diamond: '\\u25C6',\n diamondOpen: '\\u25C7',\n check: '\\u2714',\n warning: '\\u26A0',\n squareFilled: '\\u25FC',\n squareOpen: '\\u25FB',\n triangleRight: '\\u25B6',\n triangleSmallRight: '\\u25B8',\n bullet: '\\u2022',\n} as const;\n","/**\n * Text-splitting helpers for sentence boundary detection.\n * Used by TextBlock for animation pauses at punctuation.\n */\n\n/** Split text into sentences (keeps the delimiter attached) */\nexport function splitSentences(text: string): string[] {\n const parts: string[] = [];\n const re = /[^.!?]*[.!?]+\\s*/g;\n let match: RegExpExecArray | null;\n let lastIndex = 0;\n while ((match = re.exec(text)) !== null) {\n parts.push(match[0]);\n lastIndex = re.lastIndex;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\n/** Build a set of character indices where sentences end (for typewriter pause) */\nexport function sentenceEndChars(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let pos = 0;\n for (const s of sentences) {\n pos += s.length;\n ends.add(pos - 1);\n }\n return ends;\n}\n\n/** Build a set of word indices where sentences end (for word-by-word pause) */\nexport function sentenceEndWords(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let wordCount = 0;\n for (const s of sentences) {\n const words = s.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n ends.add(wordCount - 1);\n }\n return ends;\n}\n","/**\n * Content block types and type guards.\n *\n * Extracted from ContentSequencer so that pure-logic modules (like\n * layout-helpers) can import them without pulling in Ink/React.\n */\n\nimport type { ReactNode } from 'react';\nimport type { TextRevealMode } from './TextBlock.js';\n\n/** Object form — string or ReactNode content with per-block overrides. */\nexport interface ContentObjectBlock {\n content: string | ReactNode;\n mode?: TextRevealMode;\n animationInterval?: number;\n sentenceInterval?: number;\n pause?: number;\n persist?: boolean;\n /**\n * When the sequencer advances past this block, should it render dim?\n * Defaults to `true` — the standard \"completed step\" treatment. Set to\n * `false` to keep the block at full opacity even after it's complete\n * (useful for headings or greetings that should stay readable while\n * later blocks animate in).\n *\n * Only meaningful for blocks whose `content` is a string (TextBlock\n * renders the dim treatment). NodeBlocks render whatever JSX you pass\n * verbatim regardless of completion state.\n */\n dimWhenComplete?: boolean;\n}\n\n/** Lines block — reveals ReactNode lines one at a time. */\nexport interface ContentLinesBlock {\n type: 'lines';\n lines: ReactNode[];\n interval?: number;\n pause?: number;\n}\n\n/** Clear block — page break that hides all prior blocks. */\nexport interface ContentClearBlock {\n type: 'clear';\n pause?: number;\n}\n\n/** A content block in the sequence. Bare strings are sugar for { content: '...' }. */\nexport type ContentBlock =\n | string\n | ContentObjectBlock\n | ContentLinesBlock\n | ContentClearBlock;\n\n/** Type guard for lines blocks. */\nexport function isLinesBlock(block: ContentBlock): block is ContentLinesBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'lines';\n}\n\n/** Type guard for clear blocks. */\nexport function isClearBlock(block: ContentBlock): block is ContentClearBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'clear';\n}\n\n/** Type guard for object blocks (text or node content). */\nexport function isObjectBlock(\n block: ContentBlock,\n): block is ContentObjectBlock {\n return typeof block !== 'string' && !('type' in block);\n}\n","/**\n * Layout helpers — pure functions for height estimation and viewport eviction.\n *\n * These are the core of the responsive content system. They estimate how many\n * terminal rows a content block will occupy and determine which blocks fit\n * within a given height budget.\n */\n\nimport type { ContentBlock } from './content-types.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\n/**\n * Estimate the number of terminal rows a content block will occupy,\n * including 1 row of marginBottom.\n */\nexport function estimateBlockHeight(\n block: ContentBlock,\n availableWidth: number,\n): number {\n if (typeof block === 'string') {\n return wordWrap(block, availableWidth).length + 1; // +1 for marginBottom\n }\n\n if (isClearBlock(block)) return 0;\n\n if (isLinesBlock(block)) {\n return block.lines.length + 1;\n }\n\n if (isObjectBlock(block)) {\n if (typeof block.content === 'string') {\n return wordWrap(block.content, availableWidth).length + 1;\n }\n return 4; // conservative fixed estimate for ReactNode\n }\n\n return 1;\n}\n\n/**\n * Given all blocks, the active index, available width, and a row budget,\n * return [startIdx, endIdx] — the range of blocks to render.\n *\n * Always includes activeIdx. Walks backward to include as many completed\n * blocks as fit within maxHeight.\n */\nexport function computeVisibleRange(\n blocks: ContentBlock[],\n activeIdx: number,\n availableWidth: number,\n maxHeight: number,\n): [number, number] {\n // Reserve a 2-row buffer so resize-induced estimate drift doesn't\n // cause overflow=\"hidden\" to clip the margin between blocks.\n const budget = Math.max(4, maxHeight - 2);\n\n let totalHeight = estimateBlockHeight(blocks[activeIdx], availableWidth);\n let start = activeIdx;\n\n for (let i = activeIdx - 1; i >= 0; i--) {\n // Clear blocks act as a hard boundary — don't show anything before them\n if (isClearBlock(blocks[i])) break;\n const h = estimateBlockHeight(blocks[i], availableWidth);\n if (totalHeight + h > budget) break;\n totalHeight += h;\n start = i;\n }\n\n return [start, activeIdx];\n}\n\n/**\n * Word-wrap text at clean word boundaries. Always returns pre-wrapped text\n * joined with \\n — this avoids Ink's native wrap which can leave leading\n * spaces on continuation lines.\n *\n * Uses a 1-char safety margin so slight width estimate mismatches don't\n * cause Ink to re-wrap our already-wrapped lines.\n */\nexport function wordWrap(text: string, availableWidth: number): string[] {\n const safeWidth = Math.max(10, availableWidth - 1);\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (\n currentLine.length + word.length + 1 > safeWidth &&\n currentLine.length > 0\n ) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine += (currentLine.length > 0 ? ' ' : '') + word;\n }\n }\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n\n return lines;\n}\n\n/**\n * Word-wrap text and return only the last `maxRows` lines.\n * Used for intra-block truncation when a single text block exceeds the viewport.\n * Also used for normal rendering to avoid Ink's leading-space wrap artifacts.\n */\nexport function wrapAndTruncate(\n text: string,\n availableWidth: number,\n maxRows: number,\n): string {\n const lines = wordWrap(text, availableWidth);\n\n if (lines.length <= maxRows) {\n return lines.join('\\n');\n }\n\n return lines.slice(-maxRows).join('\\n');\n}\n","/**\n * TextBlock — Animates a single string paragraph.\n *\n * Self-contained: owns its own animIdx and timer.\n * Calls onComplete() when the animation finishes.\n *\n * Five animation modes:\n * 1. Typewriter — character-by-character reveal\n * 2. Word by word — each word appears in order\n * 3. Sentence by sentence — sentences appear one at a time\n * 4. Paragraph fade — paragraph appears at full opacity immediately\n * 5. Sentence fade — paragraph dim, sentences light up in order\n */\n\nimport { Text } from 'ink';\nimport { useState, useEffect, useRef, useMemo, type ReactNode } from 'react';\nimport { Colors } from '@ui/tui/styles';\nimport {\n splitSentences,\n sentenceEndChars,\n sentenceEndWords,\n} from './text-helpers.js';\nimport { wrapAndTruncate } from './layout-helpers.js';\n\nexport enum TextRevealMode {\n Typewriter = 0,\n WordByWord = 1,\n SentenceBySentence = 2,\n ParagraphFade = 3,\n SentenceFade = 4,\n}\n\nexport const TEXT_REVEAL_MODE_LABELS = [\n 'Typewriter',\n 'Word by word',\n 'Sentence by sentence',\n 'Paragraph fade',\n 'Sentence fade',\n];\n\nexport const TEXT_REVEAL_MODE_COUNT = 5;\n\n/** Default interval per mode (ms) */\nexport const TEXT_REVEAL_MODE_DEFAULTS: Record<TextRevealMode, number> = {\n [TextRevealMode.WordByWord]: 240,\n [TextRevealMode.Typewriter]: 32,\n [TextRevealMode.SentenceBySentence]: 1800,\n [TextRevealMode.ParagraphFade]: 4800,\n [TextRevealMode.SentenceFade]: 2400,\n};\n\ninterface TextBlockProps {\n text: string;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n /** Available text width in columns (for truncation wrapping). */\n availableWidth?: number;\n /**\n * When `completed === true`, render the text dim. Defaults to `true` —\n * the standard \"completed step\" treatment. Pass `false` to keep the\n * text at full opacity even after the sequencer has moved on.\n */\n dimWhenComplete?: boolean;\n}\n\nexport const TextBlock = ({\n text,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval = 1600,\n maxHeight,\n availableWidth,\n dimWhenComplete = true,\n}: TextBlockProps) => {\n const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];\n\n const [animIdx, setAnimIdx] = useState(\n mode === TextRevealMode.SentenceFade ? 1 : 0,\n );\n\n // Reset synchronously during render to avoid a one-frame flash\n const resetRef = useRef(0);\n const prevMode = useRef(mode);\n if (prevMode.current !== mode) {\n prevMode.current = mode;\n resetRef.current += 1;\n setAnimIdx(mode === TextRevealMode.SentenceFade ? 1 : 0);\n }\n\n const words = text.split(/\\s+/);\n const sentences = splitSentences(text);\n\n const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);\n const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);\n\n const isDone =\n mode === TextRevealMode.Typewriter\n ? animIdx >= text.length\n : mode === TextRevealMode.ParagraphFade\n ? true\n : mode === TextRevealMode.WordByWord\n ? animIdx >= words.length\n : mode === TextRevealMode.SentenceFade ||\n mode === TextRevealMode.SentenceBySentence\n ? animIdx >= sentences.length\n : true;\n\n // Fire onComplete when done\n useEffect(() => {\n if (isDone && active) onComplete();\n }, [isDone, active, onComplete]);\n\n // Animate: single effect for all tick-based modes\n useEffect(() => {\n if (!active || mode === TextRevealMode.ParagraphFade || isDone) return;\n const token = resetRef.current;\n\n const isFirstTick = animIdx === 0;\n\n let delay = isFirstTick ? 0 : speed;\n if (\n !isFirstTick &&\n mode === TextRevealMode.Typewriter &&\n animIdx > 0 &&\n sentenceCharEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n } else if (\n !isFirstTick &&\n mode === TextRevealMode.WordByWord &&\n animIdx > 0 &&\n sentenceWordEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n }\n\n const timer = setTimeout(() => {\n if (token !== resetRef.current) return;\n setAnimIdx((c) => c + 1);\n }, delay);\n return () => clearTimeout(timer);\n }, [\n active,\n mode,\n animIdx,\n isDone,\n speed,\n sentenceInterval,\n sentenceCharEnds,\n sentenceWordEnds,\n ]);\n\n // Pre-wrap text ourselves to avoid Ink's native wrap leaving leading spaces\n // on continuation lines. When maxHeight is set, also truncates to last N rows.\n const wrap = (visibleText: string): string => {\n if (availableWidth == null) return visibleText;\n if (maxHeight == null) {\n return wrapAndTruncate(visibleText, availableWidth, Infinity);\n }\n return wrapAndTruncate(visibleText, availableWidth, maxHeight);\n };\n\n // Completed: dimmed by default, but can be overridden per-block.\n if (completed) {\n return (\n <Text dimColor={dimWhenComplete}>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n // Active: mode-specific rendering\n if (mode === TextRevealMode.Typewriter) {\n const revealed = text.slice(0, animIdx);\n const atSentenceEnd = /[.!?]\\s*$/.test(revealed);\n const display = atSentenceEnd ? revealed.trimEnd() : revealed;\n return (\n <Text>\n {bullet}\n {wrap(display)}\n <Text color={Colors.muted}>{'\\u258C'}</Text>\n </Text>\n );\n }\n\n if (mode === TextRevealMode.WordByWord) {\n const visible = words.slice(0, animIdx).join(' ');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.ParagraphFade) {\n return (\n <Text>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.SentenceBySentence) {\n const visible = sentences.slice(0, animIdx).join('');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n // SentenceFade\n return (\n <Text>\n {bullet}\n {sentences.map((s, si) => (\n <Text key={si} dimColor={si >= animIdx}>\n {s}\n </Text>\n ))}\n </Text>\n );\n};\n","/**\n * StatusPeekTrigger — Fires the status-bar expansion once, renders a hint.\n *\n * Module-level `peekedOnce` guards against re-mounts (resize, tab switch)\n * so the peek only happens a single time per process.\n */\n\nimport { Text } from 'ink';\nimport { useEffect } from 'react';\nimport type { WizardStore } from '@ui/tui/store';\n\nlet peekedOnce = false;\n\ninterface StatusPeekTriggerProps {\n store?: WizardStore;\n /** How long the status bar stays expanded, in ms. */\n duration?: number;\n}\n\nexport const StatusPeekTrigger = ({\n store,\n duration = 10000,\n}: StatusPeekTriggerProps) => {\n useEffect(() => {\n if (peekedOnce) return;\n peekedOnce = true;\n store?.setStatusExpanded(true);\n // No cleanup — the store call is safe after unmount and the component\n // may be evicted before the timer fires (non-persist NodeBlock).\n setTimeout(() => {\n store?.setStatusExpanded(false);\n }, duration);\n }, [store, duration]);\n\n return <Text>You can view the Wizard's status below.</Text>;\n};\n","/**\n * POSTHOG_DATA_FLOW — ASCII diagram of the PostHog event ingestion flow.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@ui/tui/styles';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const POSTHOG_DATA_FLOW: ContentBlock = {\n type: 'lines',\n interval: 500,\n pause: 8000,\n // Box is 30 chars wide between │ borders.\n // Labels: 1-char indent. Arrows: \" ↓ \" (5). Sub-items: \" │ \" (7).\n lines: [\n <Text color=\"gray\">{' ┌──────────────────────────────┐'}</Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"cyan\">\n Your App\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text>posthog.capture()</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom events</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom properties</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>person profiles</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text dimColor>groups</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog SDK\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>HTTP</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog Cloud\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>query + visualize</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"green\">\n Dashboards & Insights\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text color=\"gray\">{' └──────────────────────────────┘'}</Text>,\n ],\n};\n","/**\n * PRODUCT_SUITE_BLOCK — Two-column listing of PostHog products.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const PRODUCT_SUITE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 1000,\n pause: 15000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Error Tracking'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Web Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Session Replay'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Feature Flags '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Pipelines'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Experiments '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Warehouse'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'LLM Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Surveys'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Workflows '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Logs'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Tours '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Support'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Revenue Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Endpoints'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Customer Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'PostHog Code'}\n </Text>,\n ],\n};\n","/**\n * LINE_CHART_BLOCK — ASCII trends chart illustrating an insight.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const LINE_CHART_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 300,\n pause: 6000,\n lines: [\n <Text bold>{' Trends · user signups (monthly)'}</Text>,\n <Text> </Text>,\n // 10k\n <Text>\n <Text color=\"gray\">{' 10k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──'}</Text>\n <Text dimColor>{' 9,575'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n // 7.5k\n <Text>\n <Text color=\"gray\">{' 7.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n // 5k\n <Text>\n <Text color=\"gray\">{' 5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──╯'}</Text>\n </Text>,\n // 2.5k\n <Text>\n <Text color=\"gray\">{' 2.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭───╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──────╯'}</Text>\n </Text>,\n // 0\n <Text>\n <Text color=\"gray\">{' 0 ┤'}</Text>\n <Text color=\"cyan\">{'──────╯'}</Text>\n </Text>,\n // X-axis\n <Text color=\"gray\">{' └┬─────┬─────┬─────┬─────┬──'}</Text>,\n <Text dimColor>{' May Aug Nov Feb May'}</Text>,\n ],\n};\n","/**\n * FUNNEL_BLOCK — ASCII funnel illustrating step conversion.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const FUNNEL_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 200,\n pause: 8000,\n lines: [\n <Text bold>{' Funnel · ride conversion'}</Text>,\n <Text> </Text>,\n // Step 1\n <Text>\n {' '}\n <Text bold>1</Text>\n {' app_launched'}\n {' '}\n <Text bold color=\"green\">\n 100.00%\n </Text>\n </Text>,\n <Text color=\"cyan\">{' ██████████████████████████████'}</Text>,\n <Text dimColor>{' → 1,200 users'}</Text>,\n <Text> </Text>,\n // Step 2\n <Text>\n {' '}\n <Text bold>2</Text>\n {' ride_requested'}\n {' '}\n <Text dimColor>{'avg 2m 30s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 72.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 864 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 336 (28%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 3\n <Text>\n {' '}\n <Text bold>3</Text>\n {' ride_accepted'}\n {' '}\n <Text dimColor>{'avg 5m 12s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 51.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 612 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 252 (29%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 4\n <Text>\n {' '}\n <Text bold>4</Text>\n {' ride_started'}\n {' '}\n <Text dimColor>{'avg 1m 45s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 38.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'█████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 456 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 156 (25%)'}</Text>\n </Text>,\n ],\n};\n","/**\n * Integration learn-deck — the narrative script played while the agent\n * runs the PostHog integration flow. Weaves typewriter lines, pauses,\n * `clear` markers, and the diagram blocks into one sequence.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@ui/tui/styles';\nimport type { WizardStore } from '@ui/tui/store';\nimport { TextRevealMode } from '@ui/tui/primitives/TextBlock';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@ui/tui/components/StatusPeekTrigger';\nimport { POSTHOG_DATA_FLOW } from './data-flow.js';\nimport { PRODUCT_SUITE_BLOCK } from './product-suite.js';\nimport { LINE_CHART_BLOCK } from './line-chart.js';\nimport { FUNNEL_BLOCK } from './funnel.js';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => [\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: 'It handles the entire PostHog setup process on your behalf.',\n pause: 5000,\n },\n\n {\n content:\n \"As we speak, it's building a plan to set up PostHog in your project.\",\n pause: 6000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n content: 'It takes about eight minutes.',\n pause: 2000,\n },\n\n {\n content: 'So grab some coffee ☕️.',\n pause: 2000,\n },\n\n {\n content: 'Or stick around and learn about PostHog.',\n pause: 5000,\n },\n\n { type: 'clear', pause: 3000 },\n\n {\n content: 'Events are the foundation of the PostHog platform.',\n pause: 4000,\n },\n\n {\n content:\n 'Every time an action is performed in your codebase — like button clicks, function calls, or thrown errors — we can capture an event.',\n pause: 6000,\n },\n\n {\n content: 'Events are sent to PostHog and joined with other product data.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1000 },\n\n { content: \"Here's the flow.\", pause: 1000 },\n\n POSTHOG_DATA_FLOW,\n\n { type: 'clear', pause: 2000 },\n\n {\n content:\n 'With enough event data, you can answer powerful questions about your product.',\n pause: 4000,\n },\n\n { content: 'And create insights.', pause: 4000 },\n\n { type: 'clear', pause: 500 },\n\n { content: 'Like trends to measure growth.', pause: 2500 },\n\n LINE_CHART_BLOCK,\n\n { type: 'clear', pause: 500 },\n\n { content: 'Or funnels to reveal bottlenecks.', pause: 2500 },\n\n FUNNEL_BLOCK,\n\n { type: 'clear', pause: 1000 },\n\n {\n content: 'Use those signals to decide what to build next.',\n pause: 4000,\n },\n\n { content: 'PostHog has all the dev tools you need.', pause: 3000 },\n\n PRODUCT_SUITE_BLOCK,\n];\n","import opn from 'opn';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport type { ProgramRun } from '@lib/agent/agent-runner';\nimport { WIZARD_TOOL_NAMES } from '@lib/wizard-tools';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { OutroKind } from '@lib/wizard-session';\nimport { AgentSignals } from '@lib/agent/agent-interface';\nimport {\n DEFAULT_PACKAGE_INSTALLATION,\n SPINNER_MESSAGE,\n} from '@lib/framework-config';\nimport { tryGetPackageJson, isUsingTypeScript } from '@utils/setup-utils';\nimport { analytics } from '@utils/analytics';\nimport { detectFramework, gatherFrameworkContext } from '@lib/detection/index';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\nimport { wizardAbort } from '@utils/wizard-abort';\nimport { WIZARD_INTERACTION_EVENT_NAME } from '@lib/constants';\nimport { getUI } from '@ui/index';\nimport { getCloudUrlFromRegion } from '@utils/urls';\nimport { requestDeepLink } from '@utils/provisioning';\nimport type { CloudRegion } from '@utils/types';\nimport { POSTHOG_INTEGRATION_PROGRAM } from './steps.js';\nimport { getContentBlocks } from './content/index.js';\n\nconst DASHBOARD_DEEP_LINK_KEY = 'dashboardDeepLink';\n\nfunction resolveContinueUrl(\n sess: WizardSession,\n cloudRegion: CloudRegion | undefined,\n deepLink: unknown,\n): string | undefined {\n if (!sess.signup) return undefined;\n if (typeof deepLink === 'string' && deepLink) return deepLink;\n if (cloudRegion)\n return `${getCloudUrlFromRegion(cloudRegion)}/products?source=wizard`;\n return undefined;\n}\n\nexport const SETUP_REPORT_FILE = 'posthog-setup-report.md';\nexport const EVENT_PLAN_FILE = '.posthog-events.json';\n\nexport const posthogIntegrationConfig: ProgramConfig = {\n command: 'integrate',\n description: 'Set up PostHog SDK integration',\n id: 'posthog-integration',\n steps: POSTHOG_INTEGRATION_PROGRAM,\n getContentBlocks,\n // Basic integration runs without structured user input; drop wizard_ask\n // so the model can't pop modal prompts mid-run. The runner forwards this\n // list to the general-purpose subagent as well, so dispatched subagents\n // can't reach around the parent and ask either.\n disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],\n\n // CI-mode prerequisite work: the headless equivalent of the detect step's\n // onReady hook. Auto-detect the framework, then gather context.\n ciPreRun: async (session: WizardSession): Promise<void> => {\n const integration = await detectFramework(session.installDir);\n if (!integration) {\n await wizardAbort({\n message: 'Could not auto-detect your framework for this project.',\n });\n return;\n }\n session.integration = integration;\n analytics.setTag('integration', integration);\n\n const frameworkConfig = FRAMEWORK_REGISTRY[integration];\n session.frameworkConfig = frameworkConfig;\n\n const context = await gatherFrameworkContext(frameworkConfig, {\n installDir: session.installDir,\n debug: session.debug,\n // `default` is required by WizardRunOptions but unused by detection; the\n // --default CLI flag was removed, so this is always false here.\n default: false,\n signup: session.signup,\n localMcp: session.localMcp,\n ci: true,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n });\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n session.frameworkContext[key] = value;\n }\n }\n },\n\n run: async (session: WizardSession): Promise<ProgramRun> => {\n const config = session.frameworkConfig!;\n\n const typeScriptDetected = isUsingTypeScript({\n installDir: session.installDir,\n });\n session.typescript = typeScriptDetected;\n\n // Read package.json and resolve framework version\n const usesPackageJson = config.detection.usesPackageJson !== false;\n let frameworkVersion: string | undefined;\n\n if (usesPackageJson) {\n const packageJson = await tryGetPackageJson({\n installDir: session.installDir,\n });\n if (packageJson) {\n const { hasDeclaredDependency } = await import('@utils/package-json');\n if (!hasDeclaredDependency(config.detection.packageName, packageJson)) {\n getUI().log.warn(\n `${config.detection.packageDisplayName} does not seem to be installed. Continuing anyway — the agent will handle it.`,\n );\n }\n frameworkVersion = config.detection.getVersion(packageJson);\n } else {\n getUI().log.warn(\n 'Could not find package.json. Continuing anyway — the agent will handle it.',\n );\n }\n } else {\n frameworkVersion = config.detection.getVersion(null);\n }\n\n // Analytics tags\n if (frameworkVersion && config.detection.getVersionBucket) {\n const versionBucket = config.detection.getVersionBucket(frameworkVersion);\n analytics.setTag(`${config.metadata.integration}-version`, versionBucket);\n }\n const frameworkContext = session.frameworkContext;\n const contextTags = config.analytics.getTags(frameworkContext);\n Object.entries(contextTags).forEach(([key, value]) => {\n analytics.setTag(key, value);\n });\n\n return {\n integrationLabel: config.metadata.integration,\n additionalMcpServers: config.metadata.additionalMcpServers,\n detectPackageManager: config.detection.detectPackageManager,\n spinnerMessage: SPINNER_MESSAGE,\n successMessage: config.ui.successMessage,\n estimatedDurationMinutes: config.ui.estimatedDurationMinutes,\n reportFile: SETUP_REPORT_FILE,\n docsUrl: config.metadata.docsUrl,\n errorMessage: 'Integration failed',\n additionalFeatureQueue: session.additionalFeatureQueue,\n\n customPrompt: (ctx) => {\n const additionalLines = config.prompts.getAdditionalContextLines\n ? config.prompts.getAdditionalContextLines(frameworkContext)\n : [];\n const additionalContext =\n additionalLines.length > 0\n ? '\\n' + additionalLines.map((line) => `- ${line}`).join('\\n')\n : '';\n\n return `You have access to the PostHog MCP server which provides skills to integrate PostHog into this ${\n config.metadata.name\n } project.\n\nProject context:\n- PostHog Project ID: ${ctx.projectId}\n- Framework: ${config.metadata.name} ${frameworkVersion || 'latest'}\n- TypeScript: ${typeScriptDetected ? 'Yes' : 'No'}\n- PostHog public token: ${ctx.projectApiKey}\n- PostHog Host: ${ctx.host}\n- Project type: ${config.prompts.projectTypeDetection}\n- Package installation: ${\n config.prompts.packageInstallation ?? DEFAULT_PACKAGE_INSTALLATION\n }${additionalContext}\n\nInstructions (follow these steps IN ORDER - do not skip or reorder):\n\nSTEP 1: Call load_skill_menu (from the wizard-tools MCP server) to see available skills.\n If the tool fails, emit: ${\n AgentSignals.ERROR_MCP_MISSING\n } Could not load skill menu and halt.\n\n Choose a skill from the \\`integration\\` category that matches this project's framework. Do NOT pick skills from other categories (llm-analytics, error-tracking, feature-flags, omnibus, etc.) — those are handled separately.\n If no suitable integration skill is found, emit: ${\n AgentSignals.ERROR_RESOURCE_MISSING\n } Could not find a suitable skill for this project.\n\nSTEP 2: Call install_skill (from the wizard-tools MCP server) with the chosen skill ID (e.g., \"integration-nextjs-app-router\").\n Do NOT run any shell commands to install skills.\n\nSTEP 3: Load the installed skill's SKILL.md file to understand what references are available.\n\nSTEP 4: Follow the skill's program files in sequence. Look for numbered program files in the references (e.g., files with patterns like \"1.0-\", \"1.1-\", \"1.2-\"). Start with the first one and proceed through each step until completion. Each program file will tell you what to do and which file comes next. Never directly write PostHog tokens directly to code files; always use environment variables.\n\nSTEP 5: Set up environment variables for PostHog using the wizard-tools MCP server (this runs locally — secret values never leave the machine):\n - Use check_env_keys to see which keys already exist in the project's .env file (e.g. .env.local or .env).\n - Use set_env_values to create or update the PostHog public token and host, using the appropriate environment variable naming convention for ${\n config.metadata.name\n }, which you'll find in example code. The tool will also ensure .gitignore coverage. Don't assume the presence of keys means the value is up to date. Write the correct value each time.\n - Reference these environment variables in the code files you create instead of hardcoding the public token and host.\n\nImportant: Use the detect_package_manager tool (from the wizard-tools MCP server) to determine which package manager the project uses. Do not manually search for lockfiles or config files. Always install packages as a background task. Don't await completion; proceed with other work immediately after starting the installation. You must read a file immediately before attempting to write it, even if you have previously read it; failure to do so will cause a tool failure.\n\n\n`;\n },\n\n postRun: async (sess, credentials) => {\n const envVars = config.environment.getEnvVars(\n credentials.projectApiKey,\n credentials.host,\n );\n if (config.environment.uploadToHosting) {\n const { uploadEnvironmentVariablesStep } = await import(\n '@steps/index'\n );\n const uploadedEnvVars = await uploadEnvironmentVariablesStep(\n envVars,\n {\n integration: config.metadata.integration,\n session: sess,\n },\n );\n if (uploadedEnvVars.length > 0) {\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'wizard_env_vars_uploaded',\n integration: config.metadata.integration,\n variable_count: uploadedEnvVars.length,\n variable_keys: uploadedEnvVars,\n });\n }\n }\n\n if (sess.signup) {\n const deepLink = await requestDeepLink(\n credentials.accessToken,\n credentials.host,\n );\n if (deepLink) {\n sess.frameworkContext[DASHBOARD_DEEP_LINK_KEY] = deepLink;\n if (process.env.NODE_ENV !== 'test') {\n opn(deepLink, { wait: false }).catch(() => {\n // opn throws in environments without a browser\n });\n }\n }\n }\n },\n\n buildOutroData: (sess, credentials, cloudRegion) => {\n const envVars = config.environment.getEnvVars(\n credentials.projectApiKey,\n credentials.host,\n );\n const deepLink = sess.frameworkContext[DASHBOARD_DEEP_LINK_KEY];\n const continueUrl = resolveContinueUrl(sess, cloudRegion, deepLink);\n\n const changes = [\n ...config.ui.getOutroChanges(frameworkContext),\n Object.keys(envVars).length > 0\n ? 'Added environment variables to .env file'\n : '',\n ].filter(Boolean);\n\n return {\n kind: OutroKind.Success as const,\n message: 'Successfully installed PostHog!',\n reportFile: SETUP_REPORT_FILE,\n changes,\n docsUrl: config.metadata.docsUrl,\n continueUrl,\n };\n },\n };\n },\n};\n\nexport { POSTHOG_INTEGRATION_PROGRAM } from './steps.js';\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"setup-utils-DetnhXo0.js","names":["fs","path","fs"],"sources":["../src/utils/package-manager.ts","../src/lib/oauth/program-scopes.ts","../src/utils/oauth.ts","../src/utils/semver.ts","../src/utils/setup-utils.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { withProgress } from '../telemetry';\nimport { getPackageDotJson, updatePackageDotJson } from './setup-utils';\nimport type { PackageJson } from './package-json';\nimport { analytics } from './analytics';\nimport type { WizardRunOptions } from './types';\n\ntype InstallDirOpt = Pick<WizardRunOptions, 'installDir'>;\n\nexport interface PackageManager {\n name: string;\n label: string;\n installCommand: string;\n buildCommand: string;\n /** Command the manager uses to execute a `package.json` script. */\n runScriptCommand: string;\n flags: string;\n detect: (opts: InstallDirOpt) => boolean;\n addOverride: (\n pkgName: string,\n pkgVersion: string,\n opts: InstallDirOpt,\n ) => Promise<void>;\n}\n\nfunction hasLockfile(installDir: string, file: string): boolean {\n return fs.existsSync(path.join(installDir, file));\n}\n\nfunction lockfileHeaderContains(\n installDir: string,\n file: string,\n needle: string,\n): boolean {\n try {\n const head = fs\n .readFileSync(path.join(installDir, file), 'utf-8')\n .slice(0, 500);\n return head.includes(needle);\n } catch {\n return false;\n }\n}\n\ntype OverrideSlot = 'npm' | 'yarn' | 'pnpm';\n\nasync function writeOverride(\n slot: OverrideSlot,\n pkgName: string,\n pkgVersion: string,\n { installDir }: InstallDirOpt,\n): Promise<void> {\n const pkg = await getPackageDotJson({ installDir });\n let next: PackageJson;\n if (slot === 'yarn') {\n next = {\n ...pkg,\n resolutions: { ...(pkg.resolutions ?? {}), [pkgName]: pkgVersion },\n };\n } else if (slot === 'pnpm') {\n next = {\n ...pkg,\n pnpm: {\n ...(pkg.pnpm ?? {}),\n overrides: { ...(pkg.pnpm?.overrides ?? {}), [pkgName]: pkgVersion },\n },\n };\n } else {\n next = {\n ...pkg,\n overrides: { ...(pkg.overrides ?? {}), [pkgName]: pkgVersion },\n };\n }\n await updatePackageDotJson(next, { installDir });\n}\n\nexport const BUN: PackageManager = {\n name: 'bun',\n label: 'Bun',\n installCommand: 'bun add',\n buildCommand: 'bun run build',\n runScriptCommand: 'bun run',\n flags: '',\n detect: ({ installDir }) =>\n hasLockfile(installDir, 'bun.lockb') || hasLockfile(installDir, 'bun.lock'),\n addOverride: (pkgName, pkgVersion, opts) =>\n writeOverride('npm', pkgName, pkgVersion, opts),\n};\n\nexport const YARN_V1: PackageManager = {\n name: 'yarn',\n label: 'Yarn V1',\n installCommand: 'yarn add',\n buildCommand: 'yarn build',\n runScriptCommand: 'yarn',\n flags: '--ignore-workspace-root-check',\n detect: ({ installDir }) =>\n lockfileHeaderContains(installDir, 'yarn.lock', 'yarn lockfile v1'),\n addOverride: (pkgName, pkgVersion, opts) =>\n writeOverride('yarn', pkgName, pkgVersion, opts),\n};\n\n/** YARN V2/3/4 */\nexport const YARN_V2: PackageManager = {\n name: 'yarn',\n label: 'Yarn V2/3/4',\n installCommand: 'yarn add',\n buildCommand: 'yarn build',\n runScriptCommand: 'yarn',\n flags: '',\n detect: ({ installDir }) =>\n lockfileHeaderContains(installDir, 'yarn.lock', '__metadata'),\n addOverride: (pkgName, pkgVersion, opts) =>\n writeOverride('yarn', pkgName, pkgVersion, opts),\n};\n\nexport const PNPM: PackageManager = {\n name: 'pnpm',\n label: 'pnpm',\n installCommand: 'pnpm add',\n buildCommand: 'pnpm build',\n runScriptCommand: 'pnpm',\n flags: '--ignore-workspace-root-check',\n detect: ({ installDir }) => hasLockfile(installDir, 'pnpm-lock.yaml'),\n addOverride: (pkgName, pkgVersion, opts) =>\n writeOverride('pnpm', pkgName, pkgVersion, opts),\n};\n\nexport const NPM: PackageManager = {\n name: 'npm',\n label: 'npm',\n installCommand: 'npm add',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n detect: ({ installDir }) => hasLockfile(installDir, 'package-lock.json'),\n addOverride: (pkgName, pkgVersion, opts) =>\n writeOverride('npm', pkgName, pkgVersion, opts),\n};\n\n// Expo is selected by upstream config (app.json / app.config.*) rather than\n// a lockfile, so its detect always returns false here.\nexport const EXPO: PackageManager = {\n name: 'expo',\n label: 'Expo',\n installCommand: 'npx expo install',\n buildCommand: 'npx expo build',\n runScriptCommand: 'npx expo run',\n flags: '',\n detect: () => false,\n addOverride: (pkgName, pkgVersion, opts) =>\n writeOverride('npm', pkgName, pkgVersion, opts),\n};\n\nexport const packageManagers: PackageManager[] = [\n BUN,\n YARN_V1,\n YARN_V2,\n PNPM,\n NPM,\n EXPO,\n];\n\nexport function detectAllPackageManagers({\n installDir,\n}: InstallDirOpt): PackageManager[] {\n return withProgress('detect-package-manager', () => {\n const matches = packageManagers.filter((pm) => pm.detect({ installDir }));\n if (matches.length === 0) {\n analytics.setTag('package-manager', 'not-detected');\n }\n return matches;\n });\n}\n","/**\n * OAuth scope resolver — every program starts from the shared\n * `WIZARD_OAUTH_SCOPES` base set and a program can layer additional\n * scopes on top via `PROGRAM_SCOPE_ADDITIONS`.\n *\n * final scope set = WIZARD_OAUTH_SCOPES ∪ programAdditions\n *\n * Additions are merged in declaration order and deduped, so a program\n * never accidentally weakens the base set — only widens it. Programs\n * not listed in `PROGRAM_SCOPE_ADDITIONS` request the unchanged\n * base set, exactly like before.\n *\n * Today only `McpTutorial` adds anything: read-only on every product\n * surface (feature flags, experiments, surveys, replays, errors, web\n * analytics, LLM analytics, cohorts, persons) plus read/write on\n * annotations. Persistence writes (dashboard:write, insight:write,\n * notebook:write, query:read) come for free from the base set, so the\n * tutorial's \"save as insight / pin to dashboard / add to notebook\"\n * follow-ups keep working.\n *\n * Add a new program override by extending `PROGRAM_SCOPE_ADDITIONS`\n * below — no other call-site changes required as long as the program's\n * `programId` is threaded into `getOrAskForProjectData`.\n */\n\n// IMPORTANT: type-only import. A value import would create a circular\n// dependency (setup-utils → program-scopes → program-registry →\n// posthog-integration → ... → setup-utils), and `Program` would be\n// read as `undefined` at module init. Keep this type-only and reference\n// program IDs by their string-literal value below — TypeScript still\n// catches renames via the `Partial<Record<ProgramId, ...>>` keying.\nimport type { ProgramId } from '@lib/programs/program-registry';\nimport { WIZARD_OAUTH_SCOPES } from '@lib/constants';\n\n/**\n * Extra scopes the MCP tutorial needs on top of `WIZARD_OAUTH_SCOPES`.\n *\n * Mirrors the wizard partner's full OAuth ceiling on the PostHog side\n * (see the comma-delimited list in the wizard OAuth app's\n * `OAuthApplication.scopes`). The tutorial's prompts and follow-ups\n * touch most of the read surface, plus annotation write for the\n * \"PostHog wizard install\" verify-prompt.\n *\n * Already in the base `WIZARD_OAUTH_SCOPES` (and therefore not\n * repeated here):\n * • user:read, project:read, llm_gateway:read — auth + gateway\n * • query:read — HogQL\n * • dashboard:write, insight:write, notebook:write — Phase-5 persist\n *\n * Deliberately omitted (writes on read-only product surfaces):\n * • feature_flag:write, experiment:write, survey:write,\n * cohort:write, session_recording:write, error_tracking:write,\n * alert:write, subscription:write\n */\nexport const MCP_TUTORIAL_SCOPE_ADDITIONS = [\n // Explicit reads on the persistence surfaces. `*:write` usually\n // implies read on PostHog, but the consent flow grants exactly the\n // strings requested — explicit reads avoid a 403 when the agent\n // lists existing dashboards/insights/notebooks before saving.\n 'dashboard:read',\n 'insight:read',\n 'notebook:read',\n\n // Read on every product surface the tutorial demos.\n 'feature_flag:read',\n 'experiment:read',\n 'experiment_saved_metric:read',\n 'survey:read',\n 'session_recording:read',\n 'error_tracking:read',\n 'web_analytics:read',\n 'llm_analytics:read',\n 'cohort:read',\n 'person:read',\n\n // Annotation read + write — the verify prompt's \"annotate today\"\n // is the only mutation the tutorial performs outside the\n // dashboard/insight/notebook persistence triplet.\n 'annotation:read',\n 'annotation:write',\n\n // Metadata / exploration reads — for \"break down by user property\",\n // \"did that change land alongside a deploy\", autocapture actions,\n // etc. Otherwise the agent 403s on the supporting catalog calls\n // even though the parent query has `query:read`.\n 'activity_log:read',\n 'property_definition:read',\n 'event_definition:read',\n 'action:read',\n\n // Data warehouse reads — for the data-role cross-sells that join\n // event data with Stripe / Salesforce / S3.\n 'warehouse_table:read',\n 'warehouse_view:read',\n\n // Inspection-only — we don't write alerts or subscriptions, but the\n // model might want to read existing ones (e.g. \"is there already an\n // alert on this metric?\").\n 'alert:read',\n 'subscription:read',\n] as const;\n\n/**\n * Extra scopes the agent-skill program needs on top of `WIZARD_OAUTH_SCOPES`.\n *\n * Skills under this program (e.g. `creating-product-tours`) create feature\n * flags during the install flow. PostHog's consent grants exactly the scope\n * strings requested — `:write` does not imply `:read` — so listing existing\n * flags to avoid key collisions needs `feature_flag:read` explicitly.\n * `property_definition:read` lets the agent discover person properties when\n * building flag rollout filters instead of having to ask the user verbatim.\n */\nexport const AGENT_SKILL_SCOPE_ADDITIONS = [\n 'feature_flag:read',\n 'feature_flag:write',\n 'property_definition:read',\n] as const;\n\n/**\n * Per-program scope additions, layered on top of `WIZARD_OAUTH_SCOPES`.\n *\n * Programs not listed here request the unchanged base set. Use this\n * map only for programs that need *more* than the base — never for\n * narrowing, since narrowing risks breaking shared infrastructure\n * (e.g. dropping `llm_gateway:read` would 401 every agent call).\n *\n * Keyed by `ProgramId` so TypeScript catches stale entries when a\n * program is renamed or removed.\n */\nconst PROGRAM_SCOPE_ADDITIONS: Partial<Record<ProgramId, readonly string[]>> = {\n // String literal (not `Program.McpTutorial`) to avoid a runtime cycle\n // with `program-registry.ts`. The `Partial<Record<ProgramId, ...>>`\n // key constraint catches renames at compile time — if `mcpTutorialConfig.id`\n // ever changes, this line will fail to type-check.\n 'mcp-tutorial': MCP_TUTORIAL_SCOPE_ADDITIONS,\n 'agent-skill': AGENT_SKILL_SCOPE_ADDITIONS,\n};\n\n/**\n * Resolve the OAuth scope list to request for a given program. Returns\n * `WIZARD_OAUTH_SCOPES` for programs without an addition entry; for\n * programs that do have one, returns the union of base + additions\n * with duplicates dropped (declaration order preserved, base first).\n *\n * `null` / `undefined` programId falls through to the default — same\n * behavior as the historical hardcoded `WIZARD_OAUTH_SCOPES` reference\n * in `askForWizardLogin`, so call sites that haven't been updated to\n * pass a programId continue to work unchanged.\n */\nexport function getOAuthScopesForProgram(\n programId: ProgramId | null | undefined,\n): readonly string[] {\n const additions = (programId && PROGRAM_SCOPE_ADDITIONS[programId]) || [];\n if (additions.length === 0) {\n return WIZARD_OAUTH_SCOPES;\n }\n // Dedupe while preserving order; base scopes appear first so the\n // consent screen shows them in their familiar slot.\n const seen = new Set<string>();\n const merged: string[] = [];\n for (const s of [...WIZARD_OAUTH_SCOPES, ...additions]) {\n if (seen.has(s)) continue;\n seen.add(s);\n merged.push(s);\n }\n return merged;\n}\n","import * as crypto from 'node:crypto';\nimport * as http from 'node:http';\nimport { execSync } from 'node:child_process';\nimport axios from 'axios';\nimport { logToFile } from './debug';\nimport opn from 'opn';\nimport { z } from 'zod';\nimport { getUI } from '@ui';\nimport {\n IS_DEV,\n ISSUES_URL,\n OAUTH_PORTS,\n OAUTH_TIMEOUT_MS,\n POSTHOG_DEV_CLIENT_ID,\n POSTHOG_OAUTH_URL,\n POSTHOG_PROXY_CLIENT_ID,\n WIZARD_USER_AGENT,\n} from '@lib/constants';\nimport { NODE_ENV } from '@env';\nimport { abort } from './setup-utils';\nimport { analytics } from './analytics';\n\nconst OAUTH_CALLBACK_STYLES = `\n <style>\n * {\n font-family: monospace;\n background-color: #1b0a00;\n color: #F7A502;\n font-weight: medium;\n font-size: 24px;\n margin: .25rem;\n }\n\n .blink {\n animation: blink-animation 1s steps(2, start) infinite;\n }\n\n @keyframes blink-animation {\n to {\n opacity: 0;\n }\n }\n </style>\n`;\n\nconst OAuthTokenResponseSchema = z.object({\n access_token: z.string(),\n expires_in: z.number(),\n token_type: z.string(),\n scope: z.string(),\n refresh_token: z.string().optional(),\n scoped_teams: z.array(z.number()).optional(),\n scoped_organizations: z.array(z.string()).optional(),\n});\n\nexport type OAuthTokenResponse = z.infer<typeof OAuthTokenResponseSchema>;\n\ninterface OAuthConfig {\n scopes: string[];\n signup?: boolean;\n}\n\nfunction getLocalOAuthOrigin(port: number): string {\n return `http://localhost:${port}`;\n}\n\nfunction getCallbackUrl(port: number): string {\n return `${getLocalOAuthOrigin(port)}/callback`;\n}\n\nfunction getLocalLoginUrl(port: number): string {\n return `${getLocalOAuthOrigin(port)}/authorize`;\n}\n\nfunction getLocalSignupUrl(port: number): string {\n return `${getLocalLoginUrl(port)}?signup=true`;\n}\n\n/**\n * Extract an OAuth authorization code from raw user input. Accepts either the\n * bare code, the full callback URL the browser was redirected to\n * (`http://localhost:8239/callback?code=abc123&...`), or just the query\n * string. Returns null when no code can be found.\n *\n * This backs the manual-entry fallback: in headless/remote environments the\n * browser can't reach the wizard's local callback server, so the user copies\n * the failed callback URL (or the code from it) back into the terminal.\n */\nexport function extractOAuthCode(input: string): string | null {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n // Full URL — pull the `code` query param.\n let looksLikeUrl = false;\n try {\n const url = new URL(trimmed);\n looksLikeUrl = true;\n const code = url.searchParams.get('code');\n if (code) return code;\n } catch {\n // Not a parseable URL — fall through to the looser checks below.\n }\n\n // A pasted query string or `code=...` fragment.\n const match = trimmed.match(/[?&]?code=([^&\\s]+)/);\n if (match) return decodeURIComponent(match[1]);\n\n // A URL with no code is invalid — don't mistake the whole URL for a code.\n if (looksLikeUrl) return null;\n\n // Otherwise treat the whole input as the bare code (no embedded whitespace).\n if (!/\\s/.test(trimmed)) return trimmed;\n\n return null;\n}\n\nfunction generateCodeVerifier(): string {\n return crypto.randomBytes(32).toString('base64url');\n}\n\nfunction generateCodeChallenge(verifier: string): string {\n return crypto.createHash('sha256').update(verifier).digest('base64url');\n}\n\nasync function startCallbackServer(\n authUrl: string,\n signupUrl: string,\n port: number,\n): Promise<{\n port: number;\n server: http.Server;\n waitForCallback: () => Promise<string>;\n}> {\n return new Promise((resolve, reject) => {\n let callbackResolve: (code: string) => void;\n let callbackReject: (error: Error) => void;\n\n const waitForCallback = () =>\n new Promise<string>((res, rej) => {\n callbackResolve = res;\n callbackReject = rej;\n });\n\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end();\n return;\n }\n const url = new URL(req.url, getLocalOAuthOrigin(port));\n\n if (url.pathname === '/authorize') {\n const isSignup = url.searchParams.get('signup') === 'true';\n const redirectUrl = isSignup ? signupUrl : authUrl;\n res.writeHead(302, { Location: redirectUrl });\n res.end();\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n const isAccessDenied = error === 'access_denied';\n const safeError = error.replace(/[^\\x20-\\x7e]/g, '').slice(0, 200);\n logToFile(`[oauth] callback received with error: ${safeError}`);\n res.writeHead(isAccessDenied ? 200 : 400, {\n 'Content-Type': 'text/html; charset=utf-8',\n });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Authorization ${\n isAccessDenied ? 'cancelled' : 'failed'\n }</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>${\n isAccessDenied\n ? 'Authorization cancelled.'\n : `Authorization failed.`\n }</p>\n <p>Return to your terminal. This window will close automatically.</p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackReject(new Error(`OAuth error: ${error}`));\n return;\n }\n\n if (code) {\n logToFile('[oauth] callback received with authorization code');\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard is ready</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>PostHog login complete!</p>\n <p>Return to your terminal: the wizard is hard at work on your project<span class=\"blink\">█</span></p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackResolve(code);\n } else {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Invalid request</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>Invalid request - no authorization code received.</p>\n <p>You can close this window.</p>\n </body>\n </html>\n `);\n }\n });\n\n server.listen(port, () => {\n resolve({ port, server, waitForCallback });\n });\n\n server.on('error', reject);\n });\n}\n\nfunction getPortProcessInfo(port: number): {\n command: string;\n pid: string;\n port: number;\n user: string;\n} {\n try {\n const output = execSync(`lsof -i :${port} -sTCP:LISTEN 2>/dev/null`, {\n encoding: 'utf-8',\n timeout: 3000,\n }).trim();\n const lines = output.split('\\n');\n // First line is header, second is the process\n if (lines.length < 2)\n return { command: 'unknown', pid: 'unknown', port, user: 'unknown' };\n const fields = lines[1].split(/\\s+/);\n // lsof columns: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n const command = fields[0] ?? 'unknown';\n const pid = fields[1] ?? 'unknown';\n const user = fields[2] ?? 'unknown';\n return { command, pid, port, user };\n } catch {\n return { command: 'unknown', pid: 'unknown', port, user: 'unknown' };\n }\n}\n\nfunction isPortInUseError(error: unknown): boolean {\n return (\n error instanceof Error &&\n 'code' in error &&\n (error as NodeJS.ErrnoException).code === 'EADDRINUSE'\n );\n}\n\nasync function exchangeCodeForToken(\n code: string,\n codeVerifier: string,\n callbackUrl: string,\n): Promise<OAuthTokenResponse> {\n const clientId = IS_DEV ? POSTHOG_DEV_CLIENT_ID : POSTHOG_PROXY_CLIENT_ID;\n\n logToFile(\n `[oauth] exchanging code for token at ${POSTHOG_OAUTH_URL}/oauth/token`,\n );\n let response;\n try {\n response = await axios.post(\n `${POSTHOG_OAUTH_URL}/oauth/token`,\n {\n grant_type: 'authorization_code',\n code,\n redirect_uri: callbackUrl,\n client_id: clientId,\n code_verifier: codeVerifier,\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n },\n );\n } catch (e) {\n const status = axios.isAxiosError(e) ? e.response?.status : undefined;\n logToFile(\n `[oauth] token exchange failed${status ? ` (HTTP ${status})` : ''}:`,\n e instanceof Error ? e.message : e,\n );\n throw e;\n }\n\n const token = OAuthTokenResponseSchema.parse(response.data);\n logToFile(\n `[oauth] token exchange succeeded, granted scopes: ${token.scope}` +\n `${\n token.scoped_teams\n ? `, scoped_teams: [${token.scoped_teams.join(', ')}]`\n : ''\n }` +\n `${\n token.scoped_organizations\n ? `, scoped_organizations: ${token.scoped_organizations.length}`\n : ''\n }`,\n );\n return token;\n}\n\nexport async function performOAuthFlow(\n config: OAuthConfig,\n): Promise<OAuthTokenResponse> {\n const clientId = IS_DEV ? POSTHOG_DEV_CLIENT_ID : POSTHOG_PROXY_CLIENT_ID;\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n let shouldRetry = false;\n\n logToFile(\n `[oauth] starting flow against ${POSTHOG_OAUTH_URL} ` +\n `(${\n IS_DEV ? 'dev' : 'prod'\n } client), requested scopes: ${config.scopes.join(' ')}`,\n );\n\n do {\n shouldRetry = false;\n let lastProcessInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n } | null = null;\n\n for (const port of OAUTH_PORTS) {\n const callbackUrl = getCallbackUrl(port);\n const authUrl = new URL(`${POSTHOG_OAUTH_URL}/oauth/authorize`);\n authUrl.searchParams.set('client_id', clientId);\n authUrl.searchParams.set('redirect_uri', callbackUrl);\n authUrl.searchParams.set('response_type', 'code');\n authUrl.searchParams.set('code_challenge', codeChallenge);\n authUrl.searchParams.set('code_challenge_method', 'S256');\n authUrl.searchParams.set('scope', config.scopes.join(' '));\n authUrl.searchParams.set('required_access_level', 'project');\n\n const signupUrl = new URL(\n `${POSTHOG_OAUTH_URL}/signup?next=${encodeURIComponent(\n authUrl.toString(),\n )}`,\n );\n const localSignupUrl = getLocalSignupUrl(port);\n const localLoginUrl = getLocalLoginUrl(port);\n const urlToOpen = config.signup ? localSignupUrl : localLoginUrl;\n\n logToFile(`[oauth] attempting callback server on port ${port}`);\n\n let server: http.Server;\n let waitForCallback: () => Promise<string>;\n try {\n ({ server, waitForCallback } = await startCallbackServer(\n authUrl.toString(),\n signupUrl.toString(),\n port,\n ));\n } catch (e) {\n if (!isPortInUseError(e)) throw e;\n lastProcessInfo = getPortProcessInfo(port);\n continue;\n }\n\n logToFile('[oauth] callback server ready, showing login URL');\n\n getUI().setLoginUrl(urlToOpen);\n // The localhost proxy above only works on this machine. Surface the\n // direct PostHog authorize URL too, for the manual-paste modal — on a\n // remote/headless box the user opens it from another machine, where\n // localhost:<port> is unreachable.\n getUI().setAuthorizeUrl(\n config.signup ? signupUrl.toString() : authUrl.toString(),\n );\n\n if (NODE_ENV !== 'test') {\n opn(urlToOpen, { wait: false }).catch(() => {\n // opn throws in environments without a browser\n });\n }\n\n const loginSpinner = getUI().spinner();\n loginSpinner.start('Waiting for authorization...');\n\n try {\n // Race the local callback server against a manually-pasted code. The\n // manual path is the fallback for headless/remote shells where the\n // browser can't reach localhost — the user opens the auth screen's\n // paste modal and submits the callback URL or code by hand.\n const code = await Promise.race([\n waitForCallback(),\n getUI().waitForManualAuthCode(),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error('Authorization timed out')),\n OAUTH_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const token = await exchangeCodeForToken(\n code,\n codeVerifier,\n callbackUrl,\n );\n\n server.close();\n getUI().setLoginUrl(null);\n getUI().setAuthorizeUrl(null);\n loginSpinner.stop('Authorization complete!');\n\n return token;\n } catch (e) {\n loginSpinner.stop('Authorization failed.');\n server.close();\n\n const error = e instanceof Error ? e : new Error('Unknown error');\n logToFile('[oauth] flow failed:', error);\n\n if (error.message.includes('timeout')) {\n getUI().log.error('Authorization timed out. Please try again.');\n } else if (error.message.includes('access_denied')) {\n getUI().log.info(\n `Authorization was cancelled.\\n\\nYou denied access to PostHog. To use the wizard, you need to authorize access to your PostHog account.\\n\\nYou can try again by re-running the wizard.`,\n );\n } else {\n getUI().log.error(\n `Authorization failed:\\n\\n${error.message}\\n\\nIf you think this is a bug in the PostHog wizard, please create an issue:\\n${ISSUES_URL}`,\n );\n }\n\n const oauthErrorCode = error.message.startsWith('OAuth error: ')\n ? error.message.slice('OAuth error: '.length)\n : error.message.includes('timeout')\n ? 'timeout'\n : 'unknown';\n\n analytics.captureException(error, {\n step: 'oauth_flow',\n oauth_error_code: oauthErrorCode,\n client_id: clientId,\n requested_scopes: config.scopes.join(' '),\n // Collapse OAuth callback failures of the same kind into one issue\n // instead of fragmenting by each user's install path in the stack trace.\n $exception_fingerprint: `wizard_oauth_${oauthErrorCode}`,\n });\n\n await abort();\n throw error;\n }\n }\n\n if (!lastProcessInfo) {\n throw new Error('No OAuth callback ports configured');\n }\n\n await getUI().showPortConflict(lastProcessInfo);\n shouldRetry = true;\n } while (shouldRetry);\n\n throw new Error('OAuth port retry loop exited unexpectedly');\n}\n","import {\n major,\n minVersion,\n satisfies,\n subset,\n valid,\n validRange,\n} from 'semver';\n\n/**\n * Version strings from package.json that are not semver ranges.\n * URLs, git refs, dist-tags, local paths, workspace protocol, npm aliases, etc.\n * These should be rejected early — we can't determine a clear version from them.\n */\nfunction isNonSemverVersion(version: string): boolean {\n const v = version.trim();\n return (\n v === '' ||\n v.startsWith('http://') ||\n v.startsWith('https://') ||\n v.startsWith('git+') ||\n v.startsWith('git://') ||\n v.startsWith('file:') ||\n v.startsWith('npm:') ||\n v.startsWith('workspace:') ||\n v.startsWith('/') ||\n v.includes('/') // user/repo shorthand\n );\n}\n\nexport function versionSatisfiesRange({\n version,\n acceptableVersions,\n canBeLatest,\n}: {\n version: string;\n acceptableVersions: string;\n canBeLatest: boolean;\n}): boolean {\n if (version === 'latest') return canBeLatest;\n if (isNonSemverVersion(version)) return false;\n\n const concrete = valid(version);\n if (concrete !== null) {\n return satisfies(concrete, acceptableVersions);\n }\n\n const userRange = validRange(version);\n if (userRange === null) return false;\n return subset(userRange, acceptableVersions);\n}\n\n/**\n * Creates a version bucket function for analytics.\n * Converts versions like \"1.2.3\" to \"1.x\" for grouping in analytics.\n *\n * @param minMajorVersion - Optional minimum major version threshold.\n * Versions below this will be bucketed as \"<{min}.0.0\"\n *\n * @example\n * const getVersionBucket = createVersionBucket(); // no minimum\n * getVersionBucket(\"1.2.3\") // \"1.x\"\n *\n * const getVersionBucket = createVersionBucket(11);\n * getVersionBucket(\"15.3.0\") // \"15.x\"\n * getVersionBucket(\"10.0.0\") // \"<11.0.0\"\n */\nexport function createVersionBucket(minMajorVersion?: number) {\n return (version: string | undefined): string => {\n if (!version) {\n return 'none';\n }\n\n if (isNonSemverVersion(version)) {\n return 'unknown';\n }\n\n try {\n const minVer = minVersion(version);\n if (!minVer) {\n return 'invalid';\n }\n const majorVersion = major(minVer);\n if (minMajorVersion !== undefined && majorVersion < minMajorVersion) {\n return `<${minMajorVersion}.0.0`;\n }\n return `${majorVersion}.x`;\n } catch {\n return 'unknown';\n }\n };\n}\n","import * as childProcess from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport { basename, isAbsolute, join, relative } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { withProgress } from '../telemetry';\nimport { debug } from './debug';\nimport type { PackageJson } from './package-json';\nimport {\n type PackageManager,\n detectAllPackageManagers,\n NPM as npm,\n} from './package-manager';\nimport type { CloudRegion, WizardRunOptions } from './types';\nimport { getDeclaredVersion } from './package-json';\nimport {\n DEFAULT_HOST_URL,\n DUMMY_PROJECT_API_KEY,\n ISSUES_URL,\n} from '@lib/constants';\nimport { getOAuthScopesForProgram } from '@lib/oauth/program-scopes';\nimport type { ProgramId } from '@lib/programs/program-registry';\nimport { analytics } from './analytics';\nimport { getUI } from '@ui';\nimport {\n getCloudUrlFromRegion,\n getHostFromRegion,\n detectRegionFromToken,\n} from './urls';\nimport { performOAuthFlow } from './oauth';\nimport { provisionNewAccount } from './provisioning';\nimport { fetchUserData, fetchProjectData, type ApiUser } from '@lib/api';\nimport { versionSatisfiesRange } from './semver';\nimport { wizardAbort } from './wizard-abort';\n\ninterface ProjectData {\n projectApiKey: string;\n accessToken: string;\n host: string;\n distinctId: string;\n projectId: number;\n /**\n * Optional `role_at_organization` from `/api/users/@me/`. Drives the\n * role-tailored prompt suggestions on the McpSuggestedPromptsScreen. Null\n * for signup flows (no role picked yet) and older accounts.\n */\n roleAtOrganization?: string | null;\n /**\n * Full user payload from `/api/users/@me/`. Carried through so\n * `getOrAskForProjectData` can forward it to the session as\n * `session.apiUser`. Null when the request failed or the CI key\n * lacked permissions.\n */\n user?: ApiUser | null;\n}\n\nexport interface CliSetupConfig {\n filename: string;\n name: string;\n gitignore: boolean;\n\n likelyAlreadyHasAuthToken(contents: string): boolean;\n tokenContent(authToken: string): string;\n\n likelyAlreadyHasOrgAndProject(contents: string): boolean;\n orgAndProjContent(org: string, project: string): string;\n\n likelyAlreadyHasUrl?(contents: string): boolean;\n urlContent?(url: string): string;\n}\n\nexport interface CliSetupConfigContent {\n authToken: string;\n org?: string;\n project?: string;\n url?: string;\n}\n\n/** @deprecated Use wizardAbort() directly for new code. */\nexport async function abort(message?: string, status?: number): Promise<never> {\n return wizardAbort({ message, exitCode: status });\n}\n\nexport function isInGitRepo(): boolean {\n try {\n childProcess.execSync('git rev-parse --show-toplevel', {\n stdio: 'ignore',\n });\n } catch {\n return false;\n }\n return true;\n}\n\nconst FREEMAIL_DOMAINS = new Set([\n 'gmail.com',\n 'googlemail.com',\n 'hotmail.com',\n 'outlook.com',\n 'yahoo.com',\n 'icloud.com',\n 'me.com',\n 'mail.com',\n 'protonmail.com',\n 'proton.me',\n 'live.com',\n 'aol.com',\n 'yandex.com',\n 'zoho.com',\n 'gmx.com',\n 'fastmail.com',\n]);\n\nfunction parseGitRemote(): { org: string; repo: string } | null {\n try {\n const url = childProcess\n .execSync('git remote get-url origin', {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n .toString()\n .trim();\n // git@github.com:acme-corp/my-app.git or https://github.com/acme-corp/my-app.git\n const match = url.match(/[/:]([\\w.-]+)\\/([\\w.-]+?)(?:\\.git)?$/);\n if (match) return { org: match[1], repo: match[2] };\n } catch {\n // not in a git repo or no remote\n }\n return null;\n}\n\nexport function detectOrgAndProject(email: string): {\n orgName: string | undefined;\n projectName: string | undefined;\n} {\n const remote = parseGitRemote();\n\n // Project name: git repo name > directory name\n const projectName = remote?.repo || basename(process.cwd()) || undefined;\n\n // Org name: git remote org > email domain (skip freemail)\n let orgName: string | undefined;\n if (remote?.org) {\n orgName = remote.org;\n } else {\n const domain = email.split('@')[1]?.toLowerCase();\n if (domain && !FREEMAIL_DOMAINS.has(domain)) {\n orgName = domain.split('.')[0];\n }\n }\n\n return { orgName, projectName };\n}\n\nexport function getUncommittedOrUntrackedFiles(): string[] {\n let gitStatus: string;\n try {\n gitStatus = childProcess\n .execSync('git status --porcelain=v1', {\n // we only care about stdout\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n .toString();\n } catch {\n return [];\n }\n\n const result: string[] = [];\n for (const rawLine of gitStatus.split(os.EOL)) {\n const line = rawLine.trim();\n if (!line) continue;\n const match = /^\\S+\\s+(\\S+)/.exec(line);\n result.push(`- ${match?.[1]}`);\n }\n return result;\n}\n\nexport async function isReact19Installed({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n try {\n const packageJson = await tryGetPackageJson({ installDir });\n if (!packageJson) return false;\n const reactVersion = getDeclaredVersion('react', packageJson);\n\n if (!reactVersion) {\n return false;\n }\n\n return versionSatisfiesRange({\n version: reactVersion,\n acceptableVersions: '>=19.0.0',\n canBeLatest: true,\n });\n } catch {\n return false;\n }\n}\n\n/**\n * Installs or updates a package with the user's package manager.\n *\n * IMPORTANT: This function modifies the `package.json`! Be sure to re-read\n * it if you make additional modifications to it after calling this function!\n */\nexport async function installPackage({\n packageName,\n alreadyInstalled,\n packageNameDisplayLabel,\n packageManager,\n integration,\n installDir,\n}: {\n packageName: string;\n alreadyInstalled: boolean;\n packageNameDisplayLabel?: string;\n packageManager?: PackageManager;\n integration?: string;\n installDir: string;\n}): Promise<{ packageManager?: PackageManager }> {\n return withProgress('install-package', async () => {\n const sdkInstallSpinner = getUI().spinner();\n\n const pkgManager =\n packageManager || (await getPackageManager({ installDir }));\n\n const isReact19 = await isReact19Installed({ installDir });\n const legacyPeerDepsFlag =\n isReact19 && pkgManager.name === 'npm' ? '--legacy-peer-deps' : '';\n\n sdkInstallSpinner.start(\n `${alreadyInstalled ? 'Updating' : 'Installing'} ${\n packageNameDisplayLabel ?? packageName\n } with ${pkgManager.label}.`,\n );\n\n const execAsync = promisify(childProcess.exec);\n const installCommand =\n `${pkgManager.installCommand} ${packageName} ${pkgManager.flags} ${legacyPeerDepsFlag}`.trim();\n\n try {\n await execAsync(installCommand, { cwd: installDir });\n } catch (e) {\n const { stdout = '', stderr = '' } = (e ?? {}) as {\n stdout?: string;\n stderr?: string;\n };\n fs.writeFileSync(\n join(\n process.cwd(),\n `posthog-wizard-installation-error-${Date.now()}.log`,\n ),\n JSON.stringify({ stdout, stderr }),\n { encoding: 'utf8' },\n );\n sdkInstallSpinner.stop('Installation failed.');\n getUI().log.error(\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n `Encountered the following error during installation:\\n\\n${e}\\n\\nThe wizard has created a \\`posthog-wizard-installation-error-*.log\\` file. If you think this issue is caused by the PostHog wizard, create an issue on GitHub and include the log file's content:\\n${ISSUES_URL}`,\n );\n await abort();\n }\n\n sdkInstallSpinner.stop(\n `${alreadyInstalled ? 'Updated' : 'Installed'} ${\n packageNameDisplayLabel ?? packageName\n } with ${pkgManager.label}.`,\n );\n\n analytics.wizardCapture('package installed', {\n package_name: packageName,\n package_manager: pkgManager.name,\n integration,\n });\n\n return { packageManager: pkgManager };\n });\n}\n\n/**\n * Get package.json or abort the wizard if not found.\n * Only use where package.json is required (e.g., package install, overrides).\n * For detection/version-checks, use tryGetPackageJson() instead.\n */\nexport async function getPackageDotJson({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<PackageJson> {\n const pkgPath = join(installDir, 'package.json');\n\n let raw: string;\n try {\n raw = await fs.promises.readFile(pkgPath, 'utf8');\n } catch {\n getUI().log.error(\n 'Could not find package.json. Make sure to run the wizard in the root of your app!',\n );\n await abort();\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw) as PackageJson | null;\n return parsed ?? {};\n } catch {\n getUI().log.error(\n `Unable to parse your package.json. Make sure it has a valid format!`,\n );\n await abort();\n return {};\n }\n}\n\n/**\n * Try to get package.json, returning null if it doesn't exist.\n * Use this for detection purposes where missing package.json is expected (e.g., Python projects).\n */\nexport async function tryGetPackageJson({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<PackageJson | null> {\n try {\n const packageJsonFileContents = await fs.promises.readFile(\n join(installDir, 'package.json'),\n 'utf8',\n );\n return JSON.parse(packageJsonFileContents) as PackageJson;\n } catch {\n return null;\n }\n}\n\nexport async function updatePackageDotJson(\n packageDotJson: PackageJson,\n { installDir }: Pick<WizardRunOptions, 'installDir'>,\n): Promise<void> {\n const pkgPath = join(installDir, 'package.json');\n const serialized = JSON.stringify(packageDotJson, null, 2);\n\n try {\n await fs.promises.writeFile(pkgPath, serialized, {\n encoding: 'utf8',\n flag: 'w',\n });\n return;\n } catch {\n getUI().log.error(`Unable to update your package.json.`);\n await abort();\n }\n}\n\n/**\n * Detect and return the package manager. Pure — no prompts.\n * Falls back to first detected or npm if ambiguous.\n */\n// eslint-disable-next-line @typescript-eslint/require-await\nexport async function getPackageManager(\n options: Pick<WizardRunOptions, 'installDir'> & { ci?: boolean },\n): Promise<PackageManager> {\n const detectedPackageManagers = detectAllPackageManagers({\n installDir: options.installDir,\n });\n\n if (detectedPackageManagers.length >= 1) {\n const selected = detectedPackageManagers[0];\n analytics.setTag('package-manager', selected.name);\n return selected;\n }\n\n // No package manager detected — default to npm\n analytics.setTag('package-manager', npm.name);\n return npm;\n}\n\nexport function isUsingTypeScript({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): boolean {\n try {\n fs.accessSync(join(installDir, 'tsconfig.json'));\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get project data for the wizard via OAuth or CI API key.\n */\nexport async function getOrAskForProjectData(\n _options: Pick<WizardRunOptions, 'signup' | 'ci' | 'apiKey' | 'projectId'> & {\n email?: string;\n region?: CloudRegion;\n /** Optional — picks the OAuth scope set via\n * `getOAuthScopesForProgram`. Omitted → default\n * `WIZARD_OAUTH_SCOPES`. Threaded into `askForWizardLogin`. */\n programId?: ProgramId | null;\n },\n): Promise<{\n host: string;\n projectApiKey: string;\n accessToken: string;\n projectId: number;\n cloudRegion: CloudRegion;\n roleAtOrganization: string | null;\n user: ApiUser | null;\n}> {\n // CI mode: bypass OAuth, use personal API key for LLM gateway\n if (_options.ci && _options.apiKey) {\n getUI().log.info('Using provided API key (CI mode - OAuth bypassed)');\n\n const cloudRegion = await detectRegionFromToken(_options.apiKey);\n const host = getHostFromRegion(cloudRegion);\n const cloudUrl = getCloudUrlFromRegion(cloudRegion);\n\n const projectData =\n _options.projectId != null\n ? await fetchProjectDataById(\n _options.apiKey,\n _options.projectId,\n cloudUrl,\n )\n : await fetchProjectDataWithApiKey(_options.apiKey, cloudUrl);\n\n // Best-effort user fetch — CI flows may run with project-scoped keys\n // that 403 on /api/users/@me/, so swallow errors and continue with\n // a null user (and null role).\n let user: ApiUser | null = null;\n let roleAtOrganization: string | null = null;\n try {\n user = await fetchUserData(_options.apiKey, cloudUrl);\n roleAtOrganization = user.role_at_organization ?? null;\n } catch {\n // best-effort\n }\n\n return {\n host,\n projectApiKey: projectData.api_token,\n accessToken: _options.apiKey,\n projectId: projectData.id,\n cloudRegion,\n roleAtOrganization,\n user,\n };\n }\n\n const {\n host,\n projectApiKey,\n accessToken,\n projectId,\n cloudRegion,\n roleAtOrganization,\n user,\n } = await withProgress('login', () =>\n askForWizardLogin({\n signup: _options.signup,\n email: _options.email,\n region: _options.region,\n programId: _options.programId,\n }),\n );\n\n if (!projectApiKey) {\n const cloudUrl = getCloudUrlFromRegion(cloudRegion);\n getUI().log.error(`Didn't receive a project token. This shouldn't happen :(\n\nPlease let us know if you think this is a bug in the wizard:\n${ISSUES_URL}`);\n\n getUI().log\n .info(`In the meantime, we'll add a dummy project token (\"${DUMMY_PROJECT_API_KEY}\") for you to replace later.\nYou can find your project token here:\n${cloudUrl}/settings/project#variables`);\n }\n\n return {\n accessToken,\n host: host || DEFAULT_HOST_URL,\n projectApiKey: projectApiKey || DUMMY_PROJECT_API_KEY,\n projectId,\n cloudRegion,\n roleAtOrganization: roleAtOrganization ?? null,\n user: user ?? null,\n };\n}\n\nasync function fetchProjectDataWithApiKey(\n apiKey: string,\n cloudUrl: string,\n): Promise<{ api_token: string; id: number }> {\n const userData = await fetchUserData(apiKey, cloudUrl);\n const projectId = userData.team?.id;\n\n if (!projectId) {\n throw new Error(\n 'Could not determine project ID from API key. Please ensure your API key has access to a project in this cloud region.',\n );\n }\n\n const projectData = await fetchProjectData(apiKey, projectId, cloudUrl);\n return {\n api_token: projectData.api_token,\n id: projectId,\n };\n}\n\nasync function fetchProjectDataById(\n apiKey: string,\n projectId: number,\n cloudUrl: string,\n): Promise<{ api_token: string; id: number }> {\n const projectData = await fetchProjectData(apiKey, projectId, cloudUrl);\n return {\n api_token: projectData.api_token,\n id: projectId,\n };\n}\n\nasync function askForWizardLogin(options: {\n signup: boolean;\n email?: string;\n region?: CloudRegion;\n /** Used to pick the right scope set via `getOAuthScopesForProgram`.\n * Omitted → default `WIZARD_OAUTH_SCOPES`. */\n programId?: ProgramId | null;\n}): Promise<ProjectData & { cloudRegion: CloudRegion }> {\n if (options.signup) {\n return askForProvisioningSignup(options.email, options.region);\n }\n\n const tokenResponse = await performOAuthFlow({\n scopes: [...getOAuthScopesForProgram(options.programId)],\n signup: false,\n });\n\n const projectId = tokenResponse.scoped_teams?.[0];\n\n if (projectId === undefined) {\n const error = new Error(\n 'No project access granted. Please authorize with project-level access.',\n );\n analytics.captureException(error, {\n step: 'wizard_login',\n has_scoped_teams: !!tokenResponse.scoped_teams,\n });\n getUI().log.error(error.message);\n await abort();\n }\n\n const cloudRegion = await detectRegionFromToken(tokenResponse.access_token);\n const cloudUrl = getCloudUrlFromRegion(cloudRegion);\n const host = getHostFromRegion(cloudRegion);\n\n const projectData = await fetchProjectData(\n tokenResponse.access_token,\n projectId!,\n cloudUrl,\n );\n const userData = await fetchUserData(tokenResponse.access_token, cloudUrl);\n\n const data = {\n accessToken: tokenResponse.access_token,\n projectApiKey: projectData.api_token,\n host,\n distinctId: userData.distinct_id,\n projectId: projectId!,\n cloudRegion,\n roleAtOrganization: userData.role_at_organization ?? null,\n user: userData,\n };\n\n getUI().log.success('Login complete.');\n analytics.setTag('opened-wizard-link', true);\n analytics.setDistinctId(data.distinctId);\n\n return data;\n}\n\nasync function askForProvisioningSignup(\n email?: string,\n region?: CloudRegion,\n): Promise<ProjectData & { cloudRegion: CloudRegion }> {\n if (!email || !email.includes('@')) {\n getUI().log.error(\n 'Email is required for signup. Use --email your@email.com with --signup.',\n );\n await abort();\n throw new Error('unreachable');\n }\n\n const spinner = getUI().spinner();\n spinner.start('Creating your PostHog account...');\n\n try {\n const provisionRegion = (region ?? 'us').toUpperCase() as 'US' | 'EU';\n const { orgName, projectName } = detectOrgAndProject(email);\n const result = await provisionNewAccount(email, '', provisionRegion, {\n orgName,\n projectName,\n });\n\n spinner.stop('Account created!');\n getUI().log.success('Welcome to PostHog!');\n\n const host = result.host;\n const cloudRegion: CloudRegion = host.includes('eu.') ? 'eu' : 'us';\n\n analytics.setTag('provisioning-signup', true);\n\n return {\n accessToken: result.accessToken,\n projectApiKey: result.projectApiKey,\n host,\n distinctId: email,\n projectId: parseInt(result.projectId, 10) || 0,\n cloudRegion,\n };\n } catch (error) {\n spinner.stop('Account creation failed.');\n const message = error instanceof Error ? error.message : 'Unknown error';\n\n if (message.includes('already associated')) {\n getUI().log.info(\n 'This email already has a PostHog account. Switching to login flow...',\n );\n return askForWizardLogin({ signup: false });\n }\n\n getUI().log.error(`Failed to create account: ${message}`);\n analytics.captureException(\n error instanceof Error ? error : new Error(message),\n { step: 'provisioning_signup' },\n );\n await abort();\n throw error;\n }\n}\n\n/**\n * Creates a new config file with the given filepath and codeSnippet.\n */\nexport async function createNewConfigFile(\n filepath: string,\n codeSnippet: string,\n { installDir }: Pick<WizardRunOptions, 'installDir'>,\n moreInformation?: string,\n): Promise<boolean> {\n if (!isAbsolute(filepath)) {\n debug(`createNewConfigFile: filepath is not absolute: ${filepath}`);\n return false;\n }\n\n const prettyFilename = relative(installDir, filepath);\n\n try {\n await fs.promises.writeFile(filepath, codeSnippet);\n\n getUI().log.success(`Added new ${prettyFilename} file.`);\n\n if (moreInformation) {\n getUI().log.info(moreInformation);\n }\n\n return true;\n } catch (e) {\n debug(e);\n getUI().log.warn(\n `Could not create a new ${prettyFilename} file. Please create one manually and follow the instructions below.`,\n );\n }\n\n return false;\n}\n"],"mappings":"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"}
|