@whisperr/wizard 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/core/config.ts","../src/core/detect.ts","../src/core/playbooks/flutter.ts","../src/core/playbooks/nextjs.ts","../src/core/playbooks/web.ts","../src/core/playbooks/react-native.ts","../src/core/playbooks/swift.ts","../src/core/playbooks/index.ts","../src/core/auth.ts","../src/ui/theme.ts","../src/core/manifest.ts","../src/core/agent.ts","../src/core/playbooks/shared-prompt.ts","../src/core/git.ts","../src/core/verify.ts","../src/ui/banner.ts","../src/index.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport type { CliFlags } from \"./core/config.js\";\nimport { resolveConfig } from \"./core/config.js\";\nimport { detectStack } from \"./core/detect.js\";\nimport { playbookByTargetId, ALL_PLAYBOOKS } from \"./core/playbooks/index.js\";\nimport { authenticate } from \"./core/auth.js\";\nimport { fetchManifest } from \"./core/manifest.js\";\nimport { runIntegrationAgent } from \"./core/agent.js\";\nimport { takeCheckpoint, changedFiles, revertHint } from \"./core/git.js\";\nimport { pollFirstEvent } from \"./core/verify.js\";\nimport { banner } from \"./ui/banner.js\";\nimport { theme } from \"./ui/theme.js\";\nimport type { Detection, Playbook } from \"./types.js\";\n\nexport interface RunOptions extends CliFlags {\n /** Target repo (defaults to cwd). */\n path?: string;\n}\n\nexport async function run(options: RunOptions): Promise<number> {\n const repoPath = resolve(options.path ?? process.cwd());\n const config = resolveConfig(options);\n\n // eslint-disable-next-line no-console\n console.log(banner());\n p.intro(theme.signal(\"Let's wire Whisperr into your app.\"));\n\n if (config.offline) {\n p.log.warn(\n theme.warn(\"offline mode\") +\n theme.muted(\" — using a demo manifest, no account needed.\"),\n );\n }\n\n // 1. Detect the stack.\n const detections = await withSpinner(\"Scanning your repository\", () =>\n detectStack(repoPath),\n );\n const chosen = await chooseTarget(detections);\n if (!chosen) {\n p.cancel(\"No supported stack selected.\");\n return 1;\n }\n\n if (chosen.playbook.target.availability === \"planned\") {\n p.note(\n `We can detect ${theme.bright(chosen.playbook.target.displayName)} but the ` +\n `Whisperr SDK for it isn't shipped yet.\\n` +\n `Flutter is live today; ${theme.bright(\n chosen.playbook.target.displayName,\n )} is next on the roadmap.`,\n theme.warn(\"SDK coming soon\"),\n );\n const cont = await p.confirm({\n message: \"Continue anyway and let the agent scaffold against the planned SDK?\",\n initialValue: false,\n });\n if (p.isCancel(cont) || !cont) {\n p.outro(theme.muted(\"No problem — come back when the SDK lands.\"));\n return 0;\n }\n } else {\n p.log.success(\n `Detected ${theme.bright(chosen.playbook.target.displayName)} ` +\n theme.muted(`(${chosen.detection?.evidence.join(\", \") ?? \"selected\"})`),\n );\n }\n\n // 2. Authenticate (device flow opens the browser).\n let session;\n try {\n session = config.offline\n ? await authenticate(config)\n : await withBrowserAuth(config);\n } catch (err) {\n p.cancel(theme.alert((err as Error).message));\n return 1;\n }\n\n // 3. Pull the integration manifest (events/interventions/key).\n const manifest = await withSpinner(\"Loading your onboarding context\", () =>\n fetchManifest(config, session, chosen.playbook.target.id),\n );\n p.note(\n summarizeManifest(manifest),\n theme.signal(`Plan for ${manifest.appName ?? manifest.appId}`),\n );\n\n // 4. Git checkpoint so auto-applied edits are reversible.\n const checkpoint = await takeCheckpoint(repoPath);\n if (!checkpoint.isRepo) {\n p.log.warn(\n theme.warn(\"not a git repo\") +\n theme.muted(\" — edits will apply with no automatic undo.\"),\n );\n }\n\n // 5. Run the coding agent.\n const spin = p.spinner();\n spin.start(theme.bright(\"Integrating\") + theme.muted(\" — the agent is working in your code\"));\n let lastLine = \"\";\n const outcome = await runIntegrationAgent({\n repoPath,\n config,\n session,\n playbook: chosen.playbook,\n manifest,\n progress: {\n onActivity(line) {\n lastLine = line;\n spin.message(theme.bright(\"Integrating\") + theme.muted(` — ${line}`));\n },\n },\n }).catch((err) => {\n spin.stop(theme.alert(\"Integration failed\"));\n p.log.error((err as Error).message);\n return null;\n });\n\n if (!outcome) return 1;\n spin.stop(\n outcome.ok\n ? theme.success(\"Integration complete\")\n : theme.warn(\"Integration finished with notes\"),\n );\n\n // 6. Show what changed + the agent's summary.\n const files = await changedFiles(repoPath, checkpoint);\n if (files.length) {\n p.note(files.map((f) => theme.muted(\"• \") + f).join(\"\\n\"), \"Files changed\");\n }\n if (outcome.summary.trim()) {\n p.log.message(outcome.summary.trim());\n }\n\n // 7. Activation: wait for the first event (skipped offline).\n if (!config.offline) {\n p.log.step(\n theme.bright(\"Run your app once\") +\n theme.muted(\" and trigger any tracked action — I'll watch for the first event.\"),\n );\n const verifySpin = p.spinner();\n verifySpin.start(\"Waiting for the first event from your app\");\n const first = await pollFirstEvent(config, session, { timeoutMs: 120_000 });\n if (first.received) {\n verifySpin.stop(\n theme.success(\n `Whisperr is receiving events ✓` +\n (first.eventType ? theme.muted(` (first: ${first.eventType})`) : \"\"),\n ),\n );\n } else {\n verifySpin.stop(\n theme.warn(\n \"No events yet — that's fine. They'll flow once you run the app with the changes.\",\n ),\n );\n }\n }\n\n // 8. Outro with next steps + undo.\n const undo = revertHint(checkpoint);\n const nextSteps = [\n `${theme.signal(\"1.\")} Review the diff above.`,\n `${theme.signal(\"2.\")} Run / rebuild your app to start sending events.`,\n `${theme.signal(\"3.\")} Commit & deploy — Whisperr starts working on real users.`,\n undo ? theme.muted(`Undo everything: ${undo}`) : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n p.note(nextSteps, theme.bright(\"Next\"));\n p.outro(theme.signal(\"⌁ \") + theme.bright(\"Whisperr is wired in.\"));\n void lastLine;\n return 0;\n}\n\n// --- helpers ---\n\ninterface Chosen {\n playbook: Playbook;\n detection?: Detection;\n}\n\nasync function chooseTarget(detections: Detection[]): Promise<Chosen | null> {\n const top = detections[0];\n // Strong single match -> auto-pick.\n if (top && (detections.length === 1 || top.confidence >= 0.9)) {\n const playbook = playbookByTargetId(top.target.id);\n if (playbook) return { playbook, detection: top };\n }\n\n // Ambiguous or none -> ask, seeded by detections then all targets.\n const seen = new Set<string>();\n const options: { value: string; label: string; hint?: string }[] = [];\n for (const d of detections) {\n if (seen.has(d.target.id)) continue;\n seen.add(d.target.id);\n options.push({\n value: d.target.id,\n label: d.target.displayName,\n hint:\n (d.target.availability === \"available\" ? \"\" : \"coming soon · \") +\n `${Math.round(d.confidence * 100)}% match`,\n });\n }\n for (const pb of ALL_PLAYBOOKS) {\n if (seen.has(pb.target.id)) continue;\n options.push({\n value: pb.target.id,\n label: pb.target.displayName,\n hint: pb.target.availability === \"available\" ? undefined : \"coming soon\",\n });\n }\n\n const answer = await p.select({\n message: detections.length\n ? \"I found more than one possible stack — which should I integrate?\"\n : \"I couldn't auto-detect your stack. Which are you using?\",\n options,\n });\n if (p.isCancel(answer)) return null;\n const playbook = playbookByTargetId(answer as string);\n if (!playbook) return null;\n return {\n playbook,\n detection: detections.find((d) => d.target.id === answer),\n };\n}\n\nasync function withBrowserAuth(config: ReturnType<typeof resolveConfig>) {\n p.log.step(\n theme.bright(\"Authenticate\") +\n theme.muted(\" — opening your browser to approve this device…\"),\n );\n const spin = p.spinner();\n spin.start(\"Waiting for you to approve in the browser\");\n try {\n const session = await authenticate(config);\n spin.stop(theme.success(\"Authenticated ✓\"));\n return session;\n } catch (err) {\n spin.stop(theme.alert(\"Authentication failed\"));\n throw err;\n }\n}\n\nasync function withSpinner<T>(label: string, fn: () => Promise<T>): Promise<T> {\n const spin = p.spinner();\n spin.start(label);\n try {\n const result = await fn();\n spin.stop(theme.muted(label) + \" \" + theme.success(\"✓\"));\n return result;\n } catch (err) {\n spin.stop(theme.alert(`${label} — failed`));\n throw err;\n }\n}\n\nfunction summarizeManifest(m: {\n events: { eventType: string; importance?: number }[];\n identify: { channels?: string[] };\n}): string {\n const events = [...m.events]\n .sort((a, b) => (b.importance ?? 0) - (a.importance ?? 0))\n .map((e) => theme.muted(\"• \") + e.eventType);\n const channels = m.identify.channels?.length\n ? theme.muted(`channels: ${m.identify.channels.join(\", \")}`)\n : \"\";\n return [\n theme.bright(\"identify()\") + theme.muted(\" + \") + theme.bright(`${m.events.length} events`),\n ...events,\n channels,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import type { WizardConfig } from \"../types.js\";\n\n/**\n * Resolve wizard configuration from env + flags.\n *\n * Production: the CLI never carries an Anthropic key. It authenticates the user\n * (device flow), receives a short-lived wizard token, and points the Agent SDK\n * at Whisperr's Anthropic-compatible gateway via ANTHROPIC_BASE_URL +\n * ANTHROPIC_AUTH_TOKEN. The gateway injects the real key server-side and meters\n * usage per app.\n *\n * Local dev: set WHISPERR_WIZARD_DIRECT_ANTHROPIC_KEY (or ANTHROPIC_API_KEY) and\n * --offline to run the whole flow against a real model + a mock manifest, with\n * no backend required.\n */\n\nconst DEFAULT_API_BASE = \"https://api.whisperr.net\";\n// Current coding-agent default. Override with WHISPERR_WIZARD_MODEL.\n// claude-opus-4-8 — most capable, best for autonomous agentic edits\n// claude-sonnet-4-6 — faster/cheaper workhorse\nconst DEFAULT_MODEL = \"claude-opus-4-8\";\n\nexport interface CliFlags {\n offline?: boolean;\n apiBaseUrl?: string;\n model?: string;\n}\n\nexport function resolveConfig(flags: CliFlags = {}): WizardConfig {\n const apiBaseUrl = (\n flags.apiBaseUrl ??\n process.env.WHISPERR_WIZARD_API_BASE ??\n DEFAULT_API_BASE\n ).replace(/\\/+$/, \"\");\n\n const llmBaseUrl = (\n process.env.WHISPERR_WIZARD_LLM_BASE ?? `${apiBaseUrl}/wizard/llm`\n ).replace(/\\/+$/, \"\");\n\n const directAnthropicKey =\n process.env.WHISPERR_WIZARD_DIRECT_ANTHROPIC_KEY ??\n process.env.ANTHROPIC_API_KEY;\n\n const offline =\n flags.offline ??\n [\"1\", \"true\", \"yes\"].includes(\n (process.env.WHISPERR_WIZARD_OFFLINE ?? \"\").toLowerCase(),\n );\n\n return {\n apiBaseUrl,\n llmBaseUrl,\n model: flags.model ?? process.env.WHISPERR_WIZARD_MODEL ?? DEFAULT_MODEL,\n maxTurns: Number(process.env.WHISPERR_WIZARD_MAX_TURNS ?? 40),\n directAnthropicKey,\n offline,\n };\n}\n","import { readFile, stat, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Detection, DetectContext } from \"../types.js\";\nimport { ALL_PLAYBOOKS } from \"./playbooks/index.js\";\n\n/** Build a cached, bounded filesystem context rooted at `repoPath`. */\nexport function makeDetectContext(repoPath: string): DetectContext {\n const cache = new Map<string, string>();\n\n return {\n repoPath,\n async read(relPath: string): Promise<string> {\n if (cache.has(relPath)) return cache.get(relPath)!;\n let content = \"\";\n try {\n content = await readFile(join(repoPath, relPath), \"utf8\");\n } catch {\n content = \"\";\n }\n cache.set(relPath, content);\n return content;\n },\n async exists(relPath: string): Promise<boolean> {\n try {\n await stat(join(repoPath, relPath));\n return true;\n } catch {\n return false;\n }\n },\n async list(relDir: string): Promise<string[]> {\n try {\n const entries = await readdir(join(repoPath, relDir), {\n withFileTypes: true,\n });\n return entries.map((e) => e.name);\n } catch {\n return [];\n }\n },\n };\n}\n\n/**\n * Run every playbook's detector and return matches, highest confidence first.\n * Multiple matches are possible (e.g. a Next.js repo also matches generic web);\n * the caller decides whether to auto-pick or ask.\n */\nexport async function detectStack(repoPath: string): Promise<Detection[]> {\n const ctx = makeDetectContext(repoPath);\n const results = await Promise.all(\n ALL_PLAYBOOKS.map((p) => p.detect(ctx).catch(() => null)),\n );\n return results\n .filter((d): d is Detection => d !== null)\n .sort((a, b) => b.confidence - a.confidence);\n}\n","import type { Playbook, Detection, DetectContext } from \"../../types.js\";\n\nconst target = {\n id: \"flutter\",\n displayName: \"Flutter\",\n language: \"dart\",\n availability: \"available\" as const,\n};\n\nasync function detect(ctx: DetectContext): Promise<Detection | null> {\n const evidence: string[] = [];\n let confidence = 0;\n\n if (await ctx.exists(\"pubspec.yaml\")) {\n evidence.push(\"pubspec.yaml\");\n confidence += 0.6;\n const pubspec = await ctx.read(\"pubspec.yaml\");\n if (/\\bflutter\\s*:/.test(pubspec) || /sdk:\\s*flutter/.test(pubspec)) {\n evidence.push(\"flutter sdk in pubspec\");\n confidence += 0.3;\n }\n }\n if (await ctx.exists(\"lib/main.dart\")) {\n evidence.push(\"lib/main.dart\");\n confidence += 0.2;\n }\n if (confidence === 0) return null;\n return { target, confidence: Math.min(confidence, 1), evidence };\n}\n\nconst systemPrompt = `\n## SDK: Whisperr for Flutter (Dart) — package \\`whisperr\\`\n\nThis SDK is published on pub.dev. Integrate it as follows.\n\n1) Dependency. Add to pubspec.yaml under dependencies:\n whisperr: ^0.2.0\n Then the SDK expects \\`flutter pub get\\` to be run (run it via bash).\n\n2) Initialize once, early, before runApp(), in lib/main.dart:\n import 'package:whisperr/whisperr.dart';\n await Whisperr.initialize(\n apiKey: '<INGESTION_API_KEY from manifest>',\n baseUrl: '<INGESTION_BASE_URL from manifest>', // omit if it equals the SDK default\n );\n If main() is not async, make it async and \\`await\\` the initialize call, or use\n WidgetsFlutterBinding.ensureInitialized() first.\n\n3) identify(). Call right after the end-user is known — after successful\n login/signup and on session restore at startup:\n await Whisperr.instance.identify(\n '<stable external user id>',\n traits: { /* manifest traits, e.g. 'plan': user.plan */ },\n email: user.email, // optional shortcut -> opted-in email channel\n phone: user.phone, // optional shortcut -> SMS channel\n pushToken: fcmToken, // optional shortcut -> push channel\n );\n Use the app's real stable id (auth uid / customer id), never a device id.\n On logout call \\`await Whisperr.instance.reset();\\`.\n\n4) track(). For each manifest event, find where that user action actually\n happens and add:\n await Whisperr.instance.track('event_type_from_manifest', properties: { ... });\n event_type must be snake_case and copied verbatim from the manifest.\n\nNotes / gotchas:\n- The SDK queues + batches automatically; you do NOT need to await every track\n for delivery — awaiting just enqueues. Fire-and-forget is fine in UI handlers.\n- Do not call track() inside build() methods or render loops — only in event\n handlers / business logic (onPressed, on success of an API call, in a bloc/\n cubit/provider action, etc.).\n- Hardcoding the API key in Dart is acceptable for a client SDK (it is an\n ingestion key, scoped + rate-limited), but prefer --dart-define / a config\n file if the project already uses one.\n- Verify with \\`flutter analyze\\`.\n`.trim();\n\nexport const flutterPlaybook: Playbook = {\n target,\n detect,\n packageRef: \"whisperr (pub.dev)\",\n systemPrompt,\n verifyCommand: \"flutter analyze\",\n};\n","import type { Playbook, Detection, DetectContext } from \"../../types.js\";\n\nconst target = {\n id: \"nextjs\",\n displayName: \"Next.js\",\n language: \"typescript\",\n availability: \"planned\" as const,\n};\n\nasync function detect(ctx: DetectContext): Promise<Detection | null> {\n if (!(await ctx.exists(\"package.json\"))) return null;\n const pkgJson = await ctx.read(\"package.json\");\n let isNext = false;\n try {\n const pkg = JSON.parse(pkgJson);\n const all = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n isNext = \"next\" in all;\n } catch {\n isNext = false;\n }\n if (!isNext && !(await ctx.exists(\"next.config.js\")) && !(await ctx.exists(\"next.config.mjs\")))\n return null;\n const evidence = [\"next dependency\"];\n let confidence = 0.85;\n if (await ctx.exists(\"app\")) {\n evidence.push(\"app/ router\");\n confidence += 0.1;\n } else if (await ctx.exists(\"pages\")) {\n evidence.push(\"pages/ router\");\n confidence += 0.05;\n }\n return { target, confidence: Math.min(confidence, 1), evidence };\n}\n\nconst systemPrompt = `\n## SDK: Whisperr for Web in Next.js — package \\`@whisperr/web\\`\n\nSame SDK as plain web, with Next-specific wiring.\n\n1) Install \\`@whisperr/web\\`. Put the key in NEXT_PUBLIC_WHISPERR_KEY in\n .env.local (and add it to .env.example).\n\n2) Whisperr runs client-side. Create a client provider:\n - App Router: a 'use client' component (e.g. app/whisperr-provider.tsx) that\n calls Whisperr.init(...) in a useEffect and renders children; mount it in\n app/layout.tsx.\n - Pages Router: init in pages/_app.tsx inside a useEffect.\n\n3) identify() after auth resolves on the client (e.g. in your auth/session\n hook). reset() on sign-out.\n\n4) track() in client components / event handlers / mutation callbacks. Do NOT\n call track from server components, route handlers, or getServerSideProps —\n this SDK is a browser client. Copy event_type verbatim from the manifest.\n\nNotes:\n- Guard against double-init under React Strict Mode (init is idempotent, but\n wire it so it only runs once).\n`.trim();\n\nexport const nextjsPlaybook: Playbook = {\n target,\n detect,\n packageRef: \"@whisperr/web (npm)\",\n systemPrompt,\n};\n","import type { Playbook, Detection, DetectContext } from \"../../types.js\";\n\nconst target = {\n id: \"web-js\",\n displayName: \"Web (JavaScript / TypeScript)\",\n language: \"typescript\",\n // Flip to \"available\" once @whisperr/web ships (Phase 2).\n availability: \"planned\" as const,\n};\n\n/** True if package.json depends on any of `names`. */\nfunction dependsOn(pkgJson: string, names: string[]): boolean {\n try {\n const pkg = JSON.parse(pkgJson);\n const all = {\n ...(pkg.dependencies ?? {}),\n ...(pkg.devDependencies ?? {}),\n } as Record<string, string>;\n return names.some((n) => n in all);\n } catch {\n return false;\n }\n}\n\nasync function detect(ctx: DetectContext): Promise<Detection | null> {\n if (!(await ctx.exists(\"package.json\"))) return null;\n const pkgJson = await ctx.read(\"package.json\");\n const evidence = [\"package.json\"];\n let confidence = 0.4;\n\n // Defer to the more specific playbooks when their frameworks are present.\n if (dependsOn(pkgJson, [\"next\"])) return null;\n if (dependsOn(pkgJson, [\"react-native\", \"expo\"])) return null;\n\n if (dependsOn(pkgJson, [\"react\", \"vue\", \"svelte\", \"@angular/core\"])) {\n evidence.push(\"frontend framework dependency\");\n confidence += 0.4;\n }\n if (await ctx.exists(\"index.html\")) {\n evidence.push(\"index.html\");\n confidence += 0.1;\n }\n return { target, confidence: Math.min(confidence, 0.95), evidence };\n}\n\nconst systemPrompt = `\n## SDK: Whisperr for Web (TypeScript/JavaScript) — package \\`@whisperr/web\\`\n\n1) Dependency. Install with the repo's package manager (detect pnpm/yarn/npm\n from the lockfile): \\`<pm> add @whisperr/web\\`.\n\n2) Initialize once at app entry (e.g. src/main.tsx, src/index.ts, or the root\n layout). Create a singleton client:\n import { Whisperr } from '@whisperr/web';\n export const whisperr = Whisperr.init({\n apiKey: import.meta.env.VITE_WHISPERR_KEY, // or process.env.NEXT_PUBLIC_... etc\n baseUrl: '<INGESTION_BASE_URL from manifest>',\n });\n Put the key in the project's env mechanism (Vite VITE_*, CRA REACT_APP_*,\n plain .env) and write the example var into .env / .env.example.\n\n3) identify(). After auth resolves (login success, and on app load if a session\n is restored):\n whisperr.identify(user.id, {\n traits: { /* manifest traits */ },\n email: user.email, phone: user.phone,\n });\n Call whisperr.reset() on logout.\n\n4) track(). For each manifest event, instrument the real handler:\n whisperr.track('event_type_from_manifest', { /* properties */ });\n In React, this belongs in event handlers / effects / mutation callbacks, not\n in render. Copy event_type verbatim (snake_case) from the manifest.\n\nNotes:\n- The SDK batches via /v1/events/batch and flushes on a timer + on\n visibilitychange/unload (sendBeacon). Fire-and-forget is fine.\n- Only the NEXT_PUBLIC_/VITE_-style public env vars are exposed to the browser;\n the ingestion key is a public, rate-limited key so that is expected.\n- If the project uses an analytics wrapper/provider pattern, follow it rather\n than scattering raw whisperr.track calls.\n`.trim();\n\nexport const webPlaybook: Playbook = {\n target,\n detect,\n packageRef: \"@whisperr/web (npm)\",\n systemPrompt,\n verifyCommand: undefined,\n};\n","import type { Playbook, Detection, DetectContext } from \"../../types.js\";\n\nconst target = {\n id: \"react-native\",\n displayName: \"React Native\",\n language: \"typescript\",\n availability: \"planned\" as const,\n};\n\nasync function detect(ctx: DetectContext): Promise<Detection | null> {\n if (!(await ctx.exists(\"package.json\"))) return null;\n const pkgJson = await ctx.read(\"package.json\");\n let match = false;\n try {\n const pkg = JSON.parse(pkgJson);\n const all = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n match = \"react-native\" in all || \"expo\" in all;\n } catch {\n match = false;\n }\n if (!match) return null;\n const evidence = [\"react-native / expo dependency\"];\n let confidence = 0.85;\n if (await ctx.exists(\"app.json\")) {\n evidence.push(\"app.json\");\n confidence += 0.1;\n }\n return { target, confidence: Math.min(confidence, 1), evidence };\n}\n\nconst systemPrompt = `\n## SDK: Whisperr for React Native — package \\`@whisperr/react-native\\`\n\n1) Install \\`@whisperr/react-native\\` with the repo's package manager. If it has\n native modules, run pod install for iOS (mention it; don't attempt to build).\n\n2) Initialize once at the app root (App.tsx / app/_layout.tsx for Expo Router):\n import { Whisperr } from '@whisperr/react-native';\n Whisperr.init({ apiKey: <key from manifest/env>, baseUrl: <manifest baseUrl> });\n\n3) identify() after auth resolves / on session restore; reset() on logout.\n For channels: email/phone where known, and the push token (expo-notifications\n or @react-native-firebase/messaging) if the app has push set up.\n\n4) track() in event handlers / business logic, never in render. event_type\n verbatim from the manifest.\n\nNotes:\n- Persisted offline queue is built in (AsyncStorage); fire-and-forget is fine.\n- Prefer an env/config mechanism (react-native-config, app.config) for the key\n if one exists; otherwise a constants file is acceptable.\n`.trim();\n\nexport const reactNativePlaybook: Playbook = {\n target,\n detect,\n packageRef: \"@whisperr/react-native (npm)\",\n systemPrompt,\n};\n","import type { Playbook, Detection, DetectContext } from \"../../types.js\";\n\nconst target = {\n id: \"swift\",\n displayName: \"Swift (iOS)\",\n language: \"swift\",\n availability: \"planned\" as const,\n};\n\nasync function detect(ctx: DetectContext): Promise<Detection | null> {\n const evidence: string[] = [];\n let confidence = 0;\n\n if (await ctx.exists(\"Package.swift\")) {\n evidence.push(\"Package.swift\");\n confidence += 0.6;\n }\n const root = await ctx.list(\".\");\n if (root.some((f) => f.endsWith(\".xcodeproj\"))) {\n evidence.push(\"xcodeproj\");\n confidence += 0.5;\n }\n if (root.some((f) => f.endsWith(\".xcworkspace\"))) {\n evidence.push(\"xcworkspace\");\n confidence += 0.3;\n }\n if (await ctx.exists(\"Podfile\")) {\n evidence.push(\"Podfile\");\n confidence += 0.2;\n }\n if (confidence === 0) return null;\n return { target, confidence: Math.min(confidence, 1), evidence };\n}\n\nconst systemPrompt = `\n## SDK: Whisperr for Swift (iOS) — Swift Package \\`Whisperr\\`\n\n1) Add the Swift Package dependency (github.com/WhisperrAI/whisperr-swift). If the\n project uses Package.swift, add it there; if it's an .xcodeproj/.xcworkspace,\n you cannot edit the project graph reliably from the shell — instead leave a\n clearly commented setup note and the exact import + init code, and report it\n as a manual follow-up.\n\n2) Initialize once at launch in the App struct (SwiftUI) or\n application(_:didFinishLaunchingWithOptions:) (UIKit):\n import Whisperr\n Whisperr.initialize(apiKey: \"<key>\", baseUrl: \"<manifest baseUrl>\")\n\n3) identify() after the user is known / on session restore:\n Whisperr.shared.identify(\"<external user id>\", traits: [...], email: ..., phone: ...)\n reset() on logout. Push channel = APNs device token if the app registers for\n remote notifications.\n\n4) track() in action handlers / view-model methods, not in view body:\n Whisperr.shared.track(\"event_type_from_manifest\", properties: [ ... ])\n event_type verbatim (snake_case) from the manifest.\n\nNotes:\n- Prefer reading the key from Info.plist / an xcconfig if the project uses one.\n- Do not attempt to run xcodebuild; verification is the human's step here.\n`.trim();\n\nexport const swiftPlaybook: Playbook = {\n target,\n detect,\n packageRef: \"Whisperr (Swift Package)\",\n systemPrompt,\n};\n","import type { Playbook } from \"../../types.js\";\nimport { flutterPlaybook } from \"./flutter.js\";\nimport { nextjsPlaybook } from \"./nextjs.js\";\nimport { webPlaybook } from \"./web.js\";\nimport { reactNativePlaybook } from \"./react-native.js\";\nimport { swiftPlaybook } from \"./swift.js\";\n\n/**\n * The playbook registry. This is the ONLY place that knows about specific SDKs.\n * To add support for a new language/framework, add one playbook file and append\n * it here — detection, the SDK-specific system prompt, and verification all\n * travel with the playbook.\n *\n * Order matters only for display; detection confidence decides what's chosen.\n * More-specific playbooks (nextjs, react-native) return null when a more\n * specific match should win, so the generic web playbook doesn't shadow them.\n */\nexport const ALL_PLAYBOOKS: Playbook[] = [\n flutterPlaybook,\n nextjsPlaybook,\n reactNativePlaybook,\n webPlaybook,\n swiftPlaybook,\n];\n\nexport function playbookByTargetId(id: string): Playbook | undefined {\n return ALL_PLAYBOOKS.find((p) => p.target.id === id);\n}\n","import open from \"open\";\nimport type { WizardConfig, WizardSession } from \"../types.js\";\nimport { theme } from \"../ui/theme.js\";\n\n/**\n * Device-authorization flow against whisperr-go.\n *\n * Backend contract (to be built in whisperr-go, Phase 0):\n * POST {api}/v1/wizard/device/authorize\n * -> { device_code, user_code, verification_uri, verification_uri_complete,\n * interval, expires_in }\n * POST {api}/v1/wizard/device/token { device_code }\n * -> 200 { token, app_id, expires_at } when approved\n * -> 428 { error: \"authorization_pending\" } while waiting\n * -> 429 { error: \"slow_down\" } back off\n * -> 403/410 on deny/expiry\n *\n * The user is already logged in from onboarding, so the browser step is a single\n * \"Approve this device\" click that also binds the session to their app.\n */\n\nexport interface AuthHandle {\n /** Begin the flow; returns the URL to open + a poller. */\n start(): Promise<{ verificationUrl: string; userCode: string; poll: () => Promise<WizardSession> }>;\n}\n\ninterface AuthorizeResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n interval?: number;\n expires_in?: number;\n}\n\ninterface TokenResponse {\n token: string;\n app_id: string;\n expires_at: number;\n}\n\nexport async function authenticate(config: WizardConfig): Promise<WizardSession> {\n if (config.offline) return offlineSession();\n\n const authorize = await fetchJson<AuthorizeResponse>(\n `${config.apiBaseUrl}/wizard/device/authorize`,\n { method: \"POST\", body: JSON.stringify({ client: \"whisperr-wizard\" }) },\n );\n\n const url = authorize.verification_uri_complete ?? authorize.verification_uri;\n const intervalMs = (authorize.interval ?? 5) * 1000;\n const deadline =\n Date.now() + (authorize.expires_in ?? 600) * 1000;\n\n // Open the browser (best-effort; print the URL regardless).\n try {\n await open(url);\n } catch {\n /* headless / no browser — the printed URL covers it */\n }\n\n // Poll for approval.\n let wait = intervalMs;\n while (Date.now() < deadline) {\n await sleep(wait);\n const res = await fetch(\n `${config.apiBaseUrl}/wizard/device/token`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ device_code: authorize.device_code }),\n },\n );\n if (res.ok) {\n const tok = (await res.json()) as TokenResponse;\n return { token: tok.token, appId: tok.app_id, expiresAt: tok.expires_at };\n }\n if (res.status === 429) {\n wait += 2000; // slow_down\n continue;\n }\n if (res.status === 428) continue; // authorization_pending\n // 403 deny / 410 expired / anything else: stop.\n throw new Error(\n `Authorization failed (${res.status}). Run the wizard again to retry.`,\n );\n }\n throw new Error(\"Authorization timed out. Run the wizard again.\");\n}\n\n/** Used in --offline mode: no backend, fixed dev app. */\nfunction offlineSession(): WizardSession {\n return {\n token: \"offline-dev-token\",\n appId: \"app_offline_dev\",\n expiresAt: Math.floor(Date.now() / 1000) + 3600,\n };\n}\n\nasync function fetchJson<T>(url: string, init: RequestInit): Promise<T> {\n const res = await fetch(url, {\n ...init,\n headers: { \"content-type\": \"application/json\", ...(init.headers ?? {}) },\n });\n if (!res.ok) {\n throw new Error(\n `${theme.alert(\"Request failed\")}: ${init.method ?? \"GET\"} ${url} -> ${res.status}`,\n );\n }\n return (await res.json()) as T;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import pc from \"picocolors\";\n\n/**\n * Whisperr terminal palette. Restrained and tasteful — signal blue accent on a\n * mostly monochrome canvas, matching the product's dark, editorial brand.\n * Truecolor where supported, graceful fallback to picocolors' 16-color set.\n */\n\nconst truecolor =\n process.env.COLORTERM === \"truecolor\" || process.env.COLORTERM === \"24bit\";\n\nfunction rgb(r: number, g: number, b: number, text: string): string {\n if (!truecolor || !pc.isColorSupported) return text;\n return `\\x1b[38;2;${r};${g};${b}m${text}\\x1b[39m`;\n}\n\nexport const theme = {\n /** Signal blue — the one accent. */\n signal: (s: string) => rgb(91, 141, 239, s),\n /** Muted hairline grey for secondary text. */\n muted: (s: string) => rgb(140, 140, 150, s),\n /** Near-white primary text. */\n bright: (s: string) => pc.white(pc.bold(s)),\n dim: (s: string) => pc.dim(s),\n success: (s: string) => rgb(110, 207, 159, s),\n warn: (s: string) => rgb(240, 191, 105, s),\n alert: (s: string) => rgb(248, 113, 113, s),\n bold: (s: string) => pc.bold(s),\n} as const;\n\n/** The waveform mark, rendered in signal blue. */\nexport const wordmark = (() => {\n const mark = theme.signal(\"⌁\");\n return `${mark} ${theme.bright(\"whisperr\")} ${theme.muted(\"wizard\")}`;\n})();\n\n/** A thin divider. */\nexport const divider = theme.dim(\"─\".repeat(48));\n","import type {\n IntegrationManifest,\n WizardConfig,\n WizardSession,\n} from \"../types.js\";\n\n/**\n * Fetch the integration manifest for the authed app from whisperr-go.\n *\n * Backend contract (Phase 0, whisperr-go):\n * GET {api}/v1/wizard/manifest (Authorization: Bearer <wizard token>)\n * ?target=<detected sdk id> (optional hint)\n * -> IntegrationManifest\n *\n * The manifest is served from whisperr-go's own materialized runtime config:\n * app_runtime_event_definitions (code,label,description,event_schema_json)\n * + app_runtime_event_aliases (the literal event_type to emit)\n * + app_runtime_event_weights -> app_runtime_interventions (why it matters)\n * plus a freshly minted/returned ingestion API key for the app.\n */\nexport async function fetchManifest(\n config: WizardConfig,\n session: WizardSession,\n targetId?: string,\n): Promise<IntegrationManifest> {\n if (config.offline) return mockManifest(session.appId, config);\n\n const url = new URL(`${config.apiBaseUrl}/wizard/manifest`);\n if (targetId) url.searchParams.set(\"target\", targetId);\n\n const res = await fetch(url, {\n headers: { authorization: `Bearer ${session.token}` },\n });\n if (!res.ok) {\n throw new Error(\n `Could not load your integration manifest (${res.status}). ` +\n `Make sure onboarding is complete for this app.`,\n );\n }\n return (await res.json()) as IntegrationManifest;\n}\n\n/**\n * A representative manifest for --offline runs and demos. Shaped exactly like\n * what whisperr-go will return, so the agent + UI behave identically.\n */\nexport function mockManifest(\n appId: string,\n config: WizardConfig,\n): IntegrationManifest {\n return {\n appId,\n appName: \"Acme (dev)\",\n ingestionApiKey: \"wrk_offline_demo_key_do_not_use\",\n ingestionBaseUrl: config.apiBaseUrl,\n businessContext:\n \"B2C subscription app. Free trial converts to a paid monthly plan. \" +\n \"Churn risk concentrates around trial end and the first failed payment.\",\n identify: {\n traits: [\n { name: \"plan\", description: \"free | trial | pro\" },\n { name: \"signup_date\", description: \"ISO date the user signed up\" },\n ],\n channels: [\"email\", \"push\"],\n notes:\n \"Call identify on login and on session restore. Send email always; \" +\n \"push token when notifications are enabled.\",\n },\n events: [\n {\n eventType: \"trial_started\",\n label: \"Trial started\",\n description: \"User begins their free trial.\",\n importance: 0.7,\n properties: [{ name: \"plan\", description: \"trial tier chosen\" }],\n interventions: [{ code: \"onboarding_nudge\", label: \"Onboarding nudge\" }],\n },\n {\n eventType: \"feature_activated\",\n label: \"Core feature activated\",\n description:\n \"User completes the core 'aha' action for the first time. Strong \" +\n \"retention signal; fire on first successful completion only.\",\n importance: 0.6,\n interventions: [{ code: \"activation_boost\", label: \"Activation boost\" }],\n },\n {\n eventType: \"payment_failed\",\n label: \"Payment failed\",\n description:\n \"A subscription charge was declined. Fire from the billing webhook \" +\n \"handler / failed-charge path.\",\n importance: 0.95,\n properties: [\n { name: \"amount\", description: \"charge amount\" },\n { name: \"reason\", description: \"decline reason if known\" },\n ],\n interventions: [{ code: \"dunning_recovery\", label: \"Dunning recovery\", weight: 0.9 }],\n },\n {\n eventType: \"subscription_cancelled\",\n label: \"Subscription cancelled\",\n description: \"User cancels their paid plan. Fire at the moment of cancel.\",\n importance: 1,\n properties: [{ name: \"reason\", description: \"stated cancel reason\" }],\n interventions: [{ code: \"win_back\", label: \"Win-back\", weight: 1 }],\n },\n ],\n supportedTargets: [\"flutter\", \"web-js\", \"nextjs\", \"react-native\", \"swift\"],\n };\n}\n","import { query } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n IntegrationManifest,\n Playbook,\n WizardConfig,\n WizardSession,\n} from \"../types.js\";\nimport { BASE_WIZARD_PROMPT, renderManifestBrief } from \"./playbooks/shared-prompt.js\";\n\nexport interface AgentProgress {\n /** Free-text line, e.g. \"Editing lib/main.dart\". */\n onActivity?(line: string): void;\n /** Final result summary text from the agent. */\n onResult?(summary: string, costUsd?: number): void;\n}\n\nexport interface AgentRunOutcome {\n summary: string;\n costUsd?: number;\n durationMs?: number;\n ok: boolean;\n}\n\n/**\n * Run the coding agent over `repoPath` to perform the integration.\n *\n * Auth model:\n * - production: point the Agent SDK at Whisperr's Anthropic-compatible gateway\n * via ANTHROPIC_BASE_URL, with the short-lived wizard token as\n * ANTHROPIC_AUTH_TOKEN. The CLI never holds an Anthropic key; the gateway\n * injects it and meters usage per app.\n * - local dev: if a direct Anthropic key is configured, use it as-is.\n */\nexport async function runIntegrationAgent(opts: {\n repoPath: string;\n config: WizardConfig;\n session: WizardSession;\n playbook: Playbook;\n manifest: IntegrationManifest;\n progress?: AgentProgress;\n}): Promise<AgentRunOutcome> {\n const { repoPath, config, session, playbook, manifest, progress } = opts;\n\n applyModelAuthEnv(config, session);\n\n const systemPrompt = [BASE_WIZARD_PROMPT, playbook.systemPrompt].join(\"\\n\\n\");\n\n const verifyHint = playbook.verifyCommand\n ? `\\n\\nWhen finished, run \\`${playbook.verifyCommand}\\` and fix anything it flags.`\n : \"\";\n\n const prompt = [\n `Integrate the Whisperr ${playbook.target.displayName} SDK into this repository.`,\n `Project root: ${repoPath}`,\n \"\",\n \"Here is the integration manifest derived from this customer's Whisperr\",\n \"onboarding. Wire identify() and instrument every event below at the correct\",\n \"call site, following the SDK guide in your system prompt.\",\n \"\",\n \"----- MANIFEST -----\",\n renderManifestBrief(manifest),\n \"----- END MANIFEST -----\",\n verifyHint,\n ].join(\"\\n\");\n\n const started = Date.now();\n let summary = \"\";\n let costUsd: number | undefined;\n let ok = false;\n\n const response = query({\n prompt,\n options: {\n model: config.model,\n cwd: repoPath,\n systemPrompt,\n // Full file-system agent toolset.\n allowedTools: [\"Read\", \"Edit\", \"Write\", \"Bash\", \"Glob\", \"Grep\"],\n // Fully autonomous edits (the user opted into auto-apply; the wizard takes\n // a git checkpoint before this runs so revert is one command).\n permissionMode: \"bypassPermissions\",\n maxTurns: config.maxTurns,\n // Don't pick up the user's own CLAUDE.md / settings — the wizard's prompt\n // is the single source of truth.\n settingSources: [],\n },\n });\n\n for await (const message of response as AsyncIterable<AgentMessage>) {\n if (message.type === \"assistant\") {\n for (const block of message.message?.content ?? []) {\n if (isTextBlock(block) && block.text?.trim()) {\n progress?.onActivity?.(firstLine(block.text));\n } else if (isToolUseBlock(block)) {\n progress?.onActivity?.(describeToolUse(block));\n }\n }\n } else if (message.type === \"result\") {\n ok = message.subtype === \"success\";\n costUsd = message.total_cost_usd;\n summary = message.result ?? extractLastText(message) ?? summary;\n }\n }\n\n progress?.onResult?.(summary, costUsd);\n return { summary, costUsd, ok, durationMs: Date.now() - started };\n}\n\n/** Configure where the Agent SDK sends model calls. */\nfunction applyModelAuthEnv(config: WizardConfig, session: WizardSession): void {\n if (config.directAnthropicKey) {\n process.env.ANTHROPIC_API_KEY = config.directAnthropicKey;\n // Make sure a stale gateway base from a prior run doesn't leak in.\n delete process.env.ANTHROPIC_AUTH_TOKEN;\n return;\n }\n // Gateway mode: token is the wizard session token, base is our proxy.\n process.env.ANTHROPIC_BASE_URL = config.llmBaseUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = session.token;\n delete process.env.ANTHROPIC_API_KEY;\n}\n\n// --- minimal structural typings over the Agent SDK message stream ---\n// We keep these local + permissive so a minor SDK shape change doesn't break the\n// build; we only read a handful of fields.\ninterface AgentTextBlock {\n type: \"text\";\n text?: string;\n}\ninterface AgentToolUseBlock {\n type: \"tool_use\";\n name?: string;\n input?: Record<string, unknown>;\n}\ntype AgentBlock = AgentTextBlock | AgentToolUseBlock | { type: string };\n\nfunction isTextBlock(b: AgentBlock): b is AgentTextBlock {\n return b.type === \"text\";\n}\nfunction isToolUseBlock(b: AgentBlock): b is AgentToolUseBlock {\n return b.type === \"tool_use\";\n}\n\ninterface AgentMessage {\n type: \"assistant\" | \"result\" | string;\n subtype?: string;\n result?: string;\n total_cost_usd?: number;\n message?: { content?: AgentBlock[] };\n}\n\nfunction describeToolUse(block: AgentToolUseBlock): string {\n const file =\n (block.input?.file_path as string) ??\n (block.input?.path as string) ??\n (block.input?.pattern as string) ??\n \"\";\n switch (block.name) {\n case \"Edit\":\n return `Editing ${short(file)}`;\n case \"Write\":\n return `Writing ${short(file)}`;\n case \"Read\":\n return `Reading ${short(file)}`;\n case \"Bash\":\n return `Running ${short((block.input?.command as string) ?? \"command\")}`;\n case \"Grep\":\n return `Searching for ${short(file)}`;\n case \"Glob\":\n return `Scanning ${short(file)}`;\n default:\n return `${block.name ?? \"Working\"}…`;\n }\n}\n\nfunction extractLastText(message: AgentMessage): string | undefined {\n const blocks = message.message?.content ?? [];\n for (let i = blocks.length - 1; i >= 0; i--) {\n const b = blocks[i] as AgentTextBlock;\n if (b?.type === \"text\" && b.text) return b.text;\n }\n return undefined;\n}\n\nfunction firstLine(text: string): string {\n const line = text.split(\"\\n\").find((l) => l.trim()) ?? text;\n return short(line.trim(), 100);\n}\n\nfunction short(s: string, max = 60): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n","import type { IntegrationManifest } from \"../../types.js\";\n\n/**\n * The base wizard system prompt — SDK-agnostic. Each playbook appends its own\n * SDK-specific guide on top of this. The manifest (events/identify/key) is\n * injected separately as a structured user message so it stays cache-friendly\n * and unambiguous.\n */\nexport const BASE_WIZARD_PROMPT = `\nYou are the Whisperr Wizard — an expert integration agent. You are running\nINSIDE a customer's code repository. Your single job: integrate the Whisperr SDK\nso the product starts sending the right events to Whisperr, then stop.\n\nWhisperr is a churn-prevention engine. It needs two things from the app:\n 1. identify() — tell Whisperr who the end-user is (a stable external user id)\n plus traits and contact channels, called right after the user is known\n (login / session restore / signup).\n 2. track() — emit the specific business events listed in the integration\n manifest, at the exact places in the code where those user actions happen.\n These named events drive the customer's churn interventions, so placing\n them at the correct call sites matters more than anything else you do.\n\nOperating rules:\n- Work autonomously. Make the edits directly; do not ask for confirmation.\n- Be surgical. Add the SDK dependency, initialize it once at app startup, wire\n identify() where the user becomes known, and add track() calls for the\n manifest events. Do not refactor unrelated code, restyle, or \"improve\" things.\n- Find the RIGHT call site for each named event by reading the code, not by\n guessing. If you genuinely cannot find where an event occurs, add a clearly\n commented TODO with the exact Whisperr call to make, and report it at the end\n rather than firing the event from a wrong place.\n- Never invent event types. Use the exact snake_case event_type strings from the\n manifest. Custom data goes under properties.\n- Keep the API key out of source where the SDK/platform supports env/secrets;\n otherwise place it where the manifest guidance says and flag it.\n- Match the repository's existing conventions (imports, formatting, state\n management, file layout).\n\nWhen done, output a concise summary:\n - files changed\n - where identify() was wired\n - each manifest event -> the call site you instrumented (or TODO + reason)\n - any follow-ups the human must do (env var, push token, etc.)\n`.trim();\n\n/** Render the manifest into a compact, agent-readable brief. */\nexport function renderManifestBrief(m: IntegrationManifest): string {\n const lines: string[] = [];\n lines.push(`# Whisperr integration manifest for app: ${m.appName ?? m.appId}`);\n lines.push(\"\");\n lines.push(`Ingestion base URL: ${m.ingestionBaseUrl}`);\n lines.push(`Ingestion API key: ${m.ingestionApiKey}`);\n if (m.businessContext) {\n lines.push(\"\");\n lines.push(\"## Business context\");\n lines.push(m.businessContext);\n }\n\n lines.push(\"\");\n lines.push(\"## identify()\");\n if (m.identify.traits?.length) {\n lines.push(\"Traits to send when available:\");\n for (const t of m.identify.traits) {\n lines.push(` - ${t.name}${t.description ? ` — ${t.description}` : \"\"}`);\n }\n }\n if (m.identify.channels?.length) {\n lines.push(`Channels in use: ${m.identify.channels.join(\", \")}`);\n }\n if (m.identify.notes) lines.push(m.identify.notes);\n\n lines.push(\"\");\n lines.push(\"## Events to instrument (use these exact event_type strings)\");\n // Most important first so the agent prioritizes the load-bearing events.\n const events = [...m.events].sort(\n (a, b) => (b.importance ?? 0) - (a.importance ?? 0),\n );\n for (const e of events) {\n lines.push(\"\");\n lines.push(`### ${e.eventType}${e.label ? ` (${e.label})` : \"\"}`);\n if (e.description) lines.push(e.description);\n if (e.properties?.length) {\n lines.push(\"Properties:\");\n for (const p of e.properties) {\n lines.push(\n ` - ${p.name}${p.required ? \" (required)\" : \"\"}${\n p.description ? ` — ${p.description}` : \"\"\n }`,\n );\n }\n }\n if (e.interventions?.length) {\n const drv = e.interventions\n .map((i) => i.label ?? i.code)\n .join(\", \");\n lines.push(`Drives: ${drv}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","import { spawn } from \"node:child_process\";\n\n/**\n * The wizard auto-applies edits (user's choice). To make that safe, we take a\n * checkpoint before the agent runs so a revert is one command, and we can show\n * a clean diff of exactly what changed afterward.\n */\n\nexport interface GitCheckpoint {\n isRepo: boolean;\n /** Commit sha captured before edits (if a repo + had commits). */\n baseRef?: string;\n /** Branch the wizard is operating on. */\n branch?: string;\n}\n\nexport async function takeCheckpoint(repoPath: string): Promise<GitCheckpoint> {\n const isRepo = (await run(repoPath, [\"rev-parse\", \"--is-inside-work-tree\"])).ok;\n if (!isRepo) return { isRepo: false };\n\n const branch = (\n await run(repoPath, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n ).stdout.trim();\n const head = await run(repoPath, [\"rev-parse\", \"HEAD\"]);\n return {\n isRepo: true,\n baseRef: head.ok ? head.stdout.trim() : undefined,\n branch: branch || undefined,\n };\n}\n\n/** Names of files changed since the checkpoint (working tree + untracked). */\nexport async function changedFiles(\n repoPath: string,\n checkpoint: GitCheckpoint,\n): Promise<string[]> {\n if (!checkpoint.isRepo) return [];\n const tracked = await run(repoPath, [\"diff\", \"--name-only\"]);\n const untracked = await run(repoPath, [\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\",\n ]);\n const set = new Set<string>();\n for (const f of `${tracked.stdout}\\n${untracked.stdout}`.split(\"\\n\")) {\n if (f.trim()) set.add(f.trim());\n }\n return [...set];\n}\n\n/** The exact command a user runs to undo everything the wizard did. */\nexport function revertHint(checkpoint: GitCheckpoint): string | undefined {\n if (!checkpoint.isRepo || !checkpoint.baseRef) return undefined;\n return `git restore . && git clean -fd (back to ${checkpoint.baseRef.slice(0, 7)})`;\n}\n\nfunction run(\n cwd: string,\n args: string[],\n): Promise<{ ok: boolean; stdout: string; stderr: string }> {\n return new Promise((resolve) => {\n const child = spawn(\"git\", args, { cwd });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => (stdout += d.toString()));\n child.stderr.on(\"data\", (d) => (stderr += d.toString()));\n child.on(\"close\", (code) => resolve({ ok: code === 0, stdout, stderr }));\n child.on(\"error\", () => resolve({ ok: false, stdout, stderr }));\n });\n}\n","import type { WizardConfig, WizardSession } from \"../types.js\";\n\n/**\n * The activation moment: after integration, poll Whisperr for the first event\n * received from this app. In a real run the customer would run their app once;\n * the wizard waits for the green light and the dashboard lights up too.\n *\n * Backend contract (Phase 0, whisperr-go):\n * GET {api}/v1/wizard/first-event (Authorization: Bearer <wizard token>)\n * -> { received: boolean, event_type?: string, at?: string }\n *\n * Skipped in --offline mode.\n */\nexport async function pollFirstEvent(\n config: WizardConfig,\n session: WizardSession,\n opts: { timeoutMs?: number; intervalMs?: number; signal?: AbortSignal } = {},\n): Promise<{ received: boolean; eventType?: string }> {\n if (config.offline) return { received: false };\n\n const timeoutMs = opts.timeoutMs ?? 120_000;\n const intervalMs = opts.intervalMs ?? 3_000;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n if (opts.signal?.aborted) return { received: false };\n try {\n const res = await fetch(`${config.apiBaseUrl}/wizard/first-event`, {\n headers: { authorization: `Bearer ${session.token}` },\n });\n if (res.ok) {\n const body = (await res.json()) as {\n received: boolean;\n event_type?: string;\n };\n if (body.received) {\n return { received: true, eventType: body.event_type };\n }\n }\n } catch {\n /* transient — keep polling */\n }\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n return { received: false };\n}\n","import { theme } from \"./theme.js\";\n\n/**\n * Intro banner. Kept small and tasteful — a waveform glyph, the wordmark, and a\n * one-line promise. No oversized ASCII art.\n */\nexport function banner(): string {\n const wave = theme.signal(\"∿∿∿\");\n const title = `${theme.bright(\"Whisperr\")} ${theme.signal(\"Wizard\")}`;\n const tagline = theme.muted(\n \"Integrate Whisperr into your app — one command, fully wired.\",\n );\n return [\n \"\",\n ` ${wave} ${title}`,\n ` ${tagline}`,\n \"\",\n ].join(\"\\n\");\n}\n\n/** A compact step header, e.g. step(\"1\", \"Detecting your stack\"). */\nexport function step(n: string, label: string): string {\n return `${theme.signal(theme.bold(n))} ${theme.bright(label)}`;\n}\n","import { run, type RunOptions } from \"./cli.js\";\nimport { theme } from \"./ui/theme.js\";\n\n/**\n * Entry point for `npx @whisperr/wizard`.\n *\n * Usage:\n * npx @whisperr/wizard [init] [path] [--offline] [--api <url>] [--model <id>]\n *\n * `init` is accepted as an optional verb for readability; the wizard runs the\n * same flow with or without it.\n */\nfunction parseArgs(argv: string[]): RunOptions | { help: true } | { version: true } {\n const args = [...argv];\n const opts: RunOptions = {};\n\n // Drop a leading \"init\" verb.\n if (args[0] === \"init\") args.shift();\n\n for (let i = 0; i < args.length; i++) {\n const a = args[i];\n switch (a) {\n case \"-h\":\n case \"--help\":\n return { help: true };\n case \"-v\":\n case \"--version\":\n return { version: true };\n case \"--offline\":\n opts.offline = true;\n break;\n case \"--api\":\n opts.apiBaseUrl = args[++i];\n break;\n case \"--model\":\n opts.model = args[++i];\n break;\n default:\n if (a && !a.startsWith(\"-\") && !opts.path) {\n opts.path = a; // positional: target repo path\n }\n }\n }\n return opts;\n}\n\nfunction printHelp(): void {\n // eslint-disable-next-line no-console\n console.log(\n [\n \"\",\n ` ${theme.bright(\"Whisperr Wizard\")} — integrate Whisperr into your app.`,\n \"\",\n ` ${theme.bright(\"Usage\")}`,\n \" npx @whisperr/wizard [init] [path] [options]\",\n \"\",\n ` ${theme.bright(\"Options\")}`,\n \" --offline Use a demo manifest, no account/browser needed\",\n \" --api <url> Override the Whisperr API base URL\",\n \" --model <id> Override the coding-agent model\",\n \" -h, --help Show this help\",\n \" -v, --version Show version\",\n \"\",\n ` ${theme.muted(\"The wizard detects your stack, authenticates with your\")}`,\n ` ${theme.muted(\"onboarded account, and wires up identify() + your events.\")}`,\n \"\",\n ].join(\"\\n\"),\n );\n}\n\nasync function main(): Promise<void> {\n const parsed = parseArgs(process.argv.slice(2));\n\n if (\"help\" in parsed) {\n printHelp();\n return;\n }\n if (\"version\" in parsed) {\n // eslint-disable-next-line no-console\n console.log(\"0.1.0\");\n return;\n }\n\n try {\n const code = await run(parsed);\n process.exit(code);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"\\n\" + theme.alert(\"Unexpected error: \") + (err as Error).message);\n process.exit(1);\n }\n}\n\nvoid main();\n"],"mappings":"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","names":["target","detect","systemPrompt","target","detect","systemPrompt","target","detect","systemPrompt","target","detect","systemPrompt","p","p","p","systemPrompt","resolve","run","playbook","run"]}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@whisperr/wizard",
3
+ "version": "0.1.0",
4
+ "description": "Whisperr Wizard — one command to integrate the Whisperr SDK into your app. Authenticates with your onboarded account and uses an AI coding agent to wire up identify() and your business events automatically.",
5
+ "license": "UNLICENSED",
6
+ "private": false,
7
+ "type": "module",
8
+ "bin": {
9
+ "whisperr": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "engines": {
15
+ "node": ">=18.17"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "start": "node dist/index.js",
24
+ "typecheck": "tsc --noEmit",
25
+ "prepublishOnly": "npm run build",
26
+ "dev:local": "tsx src/index.ts"
27
+ },
28
+ "dependencies": {
29
+ "@anthropic-ai/claude-agent-sdk": "^0.3.168",
30
+ "@clack/prompts": "^1.5.1",
31
+ "open": "^11.0.0",
32
+ "picocolors": "^1.0.1"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.5.0",
36
+ "tsup": "^8.2.4",
37
+ "tsx": "^4.19.0",
38
+ "typescript": "^5.6.2"
39
+ }
40
+ }