@whisperr/wizard 0.1.0 → 0.1.1

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 CHANGED
@@ -1,151 +1,43 @@
1
- # Whisperr Wizard
1
+ # @whisperr/wizard
2
2
 
3
- > One command to integrate Whisperr into any app. The user pastes a command,
4
- > authenticates with their onboarded account, and an AI coding agent wires up
5
- > `identify()` and the exact business events Whisperr needs — then they push and
6
- > deploy. Inspired by the PostHog wizard, but onboarding-aware.
7
-
8
- Run it in your project root. No install, no setup — `npx` fetches the wizard and
9
- its dependencies (including the coding-agent runtime) and runs it from the
10
- current directory. The only thing you do is authenticate.
3
+ Integrate Whisperr into your app with one command.
11
4
 
12
5
  ```bash
13
- cd your-app
14
6
  npx @whisperr/wizard
15
7
  ```
16
8
 
17
- ## What it does (the flow)
18
-
19
- ```
20
- detect stack ─▶ authenticate (browser) ─▶ load manifest ─▶ git checkpoint ─▶ agent edits ─▶ verify first event
21
- ```
22
-
23
- 1. **Detect** the repo's language/framework (Flutter, Web/JS, Next.js, React
24
- Native, Swift…).
25
- 2. **Authenticate** via an OAuth device flow — the browser opens, the user (who
26
- is already logged in from onboarding) approves, and the CLI gets a short-lived
27
- session token bound to their app.
28
- 3. **Load the integration manifest** from whisperr-go: the ingestion API key, the
29
- specific snake_case events to instrument, the interventions each event drives,
30
- and `identify()` guidance — all derived from the user's onboarding.
31
- 4. **Checkpoint** with git so the auto-applied edits are reversible.
32
- 5. **Run the coding agent** (Claude Agent SDK) inside the repo: add the SDK
33
- dependency, initialize it, wire `identify()`, and place `track()` calls at the
34
- correct call sites for each manifest event.
35
- 6. **Verify** by polling for the first event — the "Whisperr is receiving
36
- events ✓" moment, which also lights up the dashboard.
37
-
38
- ## Why it's better than a generic wizard
39
-
40
- Whisperr already knows **what the app needs to track** (from onboarding), so the
41
- agent doesn't just install a snippet — it instruments the *specific named events*
42
- that drive this customer's churn interventions, at the right places in their code.
9
+ Run it in your project's root. The wizard detects your framework, opens your
10
+ browser to sign in to Whisperr, and wires up the Whisperr SDK for you — then you
11
+ review the changes, commit, and deploy.
43
12
 
44
- ## Architecture (SDK-agnostic)
45
-
46
- The core is dumb about any specific SDK. All SDK knowledge lives in **playbooks**
47
- (`src/core/playbooks/`). Each playbook carries:
48
-
49
- - a `detect()` function (how to recognize the stack),
50
- - the package reference,
51
- - an SDK-specific **system prompt** (the best-practice integration guide), and
52
- - an optional verify command.
53
-
54
- **Adding a new SDK = adding one playbook file** and registering it in
55
- `playbooks/index.ts`. Nothing else changes.
56
-
57
- ```
58
- src/
59
- index.ts CLI entry + arg parsing
60
- cli.ts orchestration + terminal UX (@clack/prompts)
61
- types.ts shared contracts
62
- ui/ theme + banner (signal-blue, tasteful)
63
- core/
64
- config.ts env/flag resolution
65
- detect.ts runs all playbook detectors
66
- auth.ts device-authorization flow (+ offline stub)
67
- manifest.ts fetch integration manifest (+ mock)
68
- agent.ts Claude Agent SDK runner (file edits)
69
- git.ts checkpoint + diff + revert hint
70
- verify.ts first-event activation poll
71
- playbooks/ ← the only SDK-aware code
72
- shared-prompt.ts base wizard prompt + manifest renderer
73
- flutter.ts (available)
74
- web.ts (planned)
75
- nextjs.ts (planned)
76
- react-native.ts (planned)
77
- swift.ts (planned)
78
- ```
13
+ ## What it does
79
14
 
80
- ## Model & auth
15
+ - **Detects your stack** — Flutter, and more frameworks coming soon.
16
+ - **Authenticates** with your Whisperr account in the browser.
17
+ - **Sets up the SDK** — installs it, initializes it, identifies your users, and
18
+ instruments the product events your Whisperr workspace is configured for.
81
19
 
82
- The agent runs on Claude via the **Claude Agent SDK**. The CLI **never ships an
83
- Anthropic key**:
20
+ ## Requirements
84
21
 
85
- - **Production:** the SDK is pointed at Whisperr's Anthropic-compatible gateway
86
- via `ANTHROPIC_BASE_URL`, with the wizard session token as
87
- `ANTHROPIC_AUTH_TOKEN`. The gateway injects the real key server-side and meters
88
- usage per app.
89
- - **Local dev:** set `WHISPERR_WIZARD_DIRECT_ANTHROPIC_KEY` (or `ANTHROPIC_API_KEY`)
90
- and run `--offline` to exercise the whole flow against a real model + a mock
91
- manifest, with no backend.
22
+ - Node.js 18.17+
23
+ - A Whisperr account with onboarding completed
92
24
 
93
- Default model: `claude-opus-4-8` (override with `WHISPERR_WIZARD_MODEL`, e.g.
94
- `claude-sonnet-4-6`).
95
-
96
- ## Contributing / local dev
97
-
98
- Only needed if you're working **on** the wizard (not using it). End users just
99
- run `npx @whisperr/wizard`.
25
+ ## Usage
100
26
 
101
27
  ```bash
102
- npm install
103
- export ANTHROPIC_API_KEY=sk-ant-... # local dev only
104
- npm run dev:local -- --offline ../some-flutter-app
28
+ # in your project root
29
+ npx @whisperr/wizard
105
30
  ```
106
31
 
107
- `--offline` uses a demo manifest (trial_started, feature_activated,
108
- payment_failed, subscription_cancelled) so you can watch the agent integrate a
109
- real repo end-to-end without the backend.
110
-
111
- To publish: `npm publish` (the package is scoped `@whisperr` with restricted
112
- access; `prepublishOnly` runs the build). Once published, `npx @whisperr/wizard`
113
- works for anyone with access.
114
-
115
- ## Backend (whisperr-go — IMPLEMENTED)
116
-
117
- The wizard talks to these endpoints on the runtime API (default
118
- `https://api.whisperr.net`), all implemented in `whisperr-go/internal/wizard/`:
32
+ Options:
119
33
 
120
- | Endpoint | Auth | Purpose |
121
- |---|---|---|
122
- | `POST /wizard/device/authorize` | public | Start device flow → `device_code`, `user_code`, `verification_uri` |
123
- | `POST /wizard/device/token` | public (polled) | → `{ token, app_id, expires_at }` once approved (`428` while pending) |
124
- | `POST /dashboard/wizard/approve` | Supabase JWT | The whisperr-watch approval page binds a `user_code` to the user's app |
125
- | `GET /wizard/manifest` | wizard session | → `IntegrationManifest`: **mints the ingestion key** + events + interventions + identify |
126
- | `GET /wizard/first-event` | wizard session | → `{ received, event_type? }` for the activation poll |
127
- | `POST /wizard/llm/*` | wizard session | Anthropic-compatible gateway: injects Whisperr's real key, streams the response |
128
-
129
- whisperr-go env to set:
130
- - `WHISPERR_WIZARD_ANTHROPIC_API_KEY` (or `ANTHROPIC_API_KEY`) — the gateway's real key
131
- - `WHISPERR_WIZARD_ACTIVATE_URL` — the watch approval page (default `https://app.whisperr.net/wizard/activate`)
132
- - `WHISPERR_PUBLIC_API_BASE_URL` — base URL surfaced in the manifest for the SDK (default `https://api.whisperr.net`)
133
- - `WHISPERR_WIZARD_LLM_UPSTREAM` — Anthropic base (default `https://api.anthropic.com`)
134
-
135
- Run migration `0010_wizard_device_authorizations.sql` (`whisperr migrate up`).
136
-
137
- ## Still to build
138
-
139
- - The `/wizard/activate` page in **whisperr-watch** (reuse existing Supabase
140
- login; show the `user_code`, let the user pick an app, POST to
141
- `/dashboard/wizard/approve`).
142
- - The `@whisperr/web` SDK (then flip the web/nextjs playbooks to `available`).
34
+ ```
35
+ --api <url> Point at a specific Whisperr API (advanced)
36
+ -h, --help Show help
37
+ -v, --version Show version
38
+ ```
143
39
 
144
- ## Status
40
+ ---
145
41
 
146
- - CLI: detection, playbook registry, terminal UX, agent runner, git
147
- checkpoint, offline demo manifest. Typechecks + builds; npx-standalone.
148
- - ✅ whisperr-go backend: device auth, manifest (with key minting), first-event,
149
- LLM gateway, migration. Builds + vets clean.
150
- - ⏳ whisperr-watch activate page.
151
- - ⏳ `@whisperr/web` SDK (Flutter is the first live target — SDK on pub.dev).
42
+ Whisperr predict churn, automate interventions, recover revenue.
43
+ [whisperr.net](https://whisperr.net)
package/dist/index.js CHANGED
@@ -1134,7 +1134,7 @@ async function main() {
1134
1134
  return;
1135
1135
  }
1136
1136
  if ("version" in parsed) {
1137
- console.log("0.1.0");
1137
+ console.log("0.1.1");
1138
1138
  return;
1139
1139
  }
1140
1140
  try {
@@ -1146,4 +1146,3 @@ async function main() {
1146
1146
  }
1147
1147
  }
1148
1148
  void main();
1149
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whisperr/wizard",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
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
5
  "license": "UNLICENSED",
6
6
  "private": false,
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
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"]}