@posthog/wizard 1.24.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/src/lib/agent-interface.d.ts +7 -1
  2. package/dist/src/lib/agent-interface.js +121 -28
  3. package/dist/src/lib/agent-interface.js.map +1 -1
  4. package/dist/src/lib/agent-runner.d.ts +1 -1
  5. package/dist/src/lib/agent-runner.js +41 -13
  6. package/dist/src/lib/agent-runner.js.map +1 -1
  7. package/dist/src/lib/config.d.ts +12 -1
  8. package/dist/src/lib/config.js +22 -0
  9. package/dist/src/lib/config.js.map +1 -1
  10. package/dist/src/lib/constants.d.ts +5 -1
  11. package/dist/src/lib/constants.js +8 -1
  12. package/dist/src/lib/constants.js.map +1 -1
  13. package/dist/src/lib/framework-config.d.ts +8 -6
  14. package/dist/src/lib/framework-config.js +12 -0
  15. package/dist/src/lib/framework-config.js.map +1 -1
  16. package/dist/src/lib/safe-tools.d.ts +2 -0
  17. package/dist/src/lib/safe-tools.js +215 -0
  18. package/dist/src/lib/safe-tools.js.map +1 -0
  19. package/dist/src/mcp.d.ts +0 -3
  20. package/dist/src/mcp.js +2 -32
  21. package/dist/src/mcp.js.map +1 -1
  22. package/dist/src/nextjs/nextjs-wizard-agent.js +0 -3
  23. package/dist/src/nextjs/nextjs-wizard-agent.js.map +1 -1
  24. package/dist/src/react-router/react-router-wizard-agent.d.ts +5 -0
  25. package/dist/src/react-router/react-router-wizard-agent.js +151 -0
  26. package/dist/src/react-router/react-router-wizard-agent.js.map +1 -0
  27. package/dist/src/react-router/utils.d.ts +19 -0
  28. package/dist/src/react-router/utils.js +276 -0
  29. package/dist/src/react-router/utils.js.map +1 -0
  30. package/dist/src/run.js +13 -0
  31. package/dist/src/run.js.map +1 -1
  32. package/dist/src/steps/add-mcp-server-to-clients/MCPClient.d.ts +5 -4
  33. package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js +6 -6
  34. package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js.map +1 -1
  35. package/dist/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.d.ts +1 -0
  36. package/dist/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.js +92 -0
  37. package/dist/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.js.map +1 -0
  38. package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.js +11 -1
  39. package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.js.map +1 -1
  40. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.d.ts +2 -1
  41. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js +5 -3
  42. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js.map +1 -1
  43. package/dist/src/steps/add-mcp-server-to-clients/clients/codex.d.ts +2 -1
  44. package/dist/src/steps/add-mcp-server-to-clients/clients/codex.js +2 -2
  45. package/dist/src/steps/add-mcp-server-to-clients/clients/codex.js.map +1 -1
  46. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.d.ts +3 -2
  47. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js +4 -4
  48. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js.map +1 -1
  49. package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.d.ts +3 -2
  50. package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.js +4 -4
  51. package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.js.map +1 -1
  52. package/dist/src/steps/add-mcp-server-to-clients/clients/zed.d.ts +3 -2
  53. package/dist/src/steps/add-mcp-server-to-clients/clients/zed.js +4 -4
  54. package/dist/src/steps/add-mcp-server-to-clients/clients/zed.js.map +1 -1
  55. package/dist/src/steps/add-mcp-server-to-clients/defaults.d.ts +8 -8
  56. package/dist/src/steps/add-mcp-server-to-clients/defaults.js +34 -13
  57. package/dist/src/steps/add-mcp-server-to-clients/defaults.js.map +1 -1
  58. package/dist/src/steps/add-mcp-server-to-clients/index.d.ts +1 -1
  59. package/dist/src/steps/add-mcp-server-to-clients/index.js +4 -5
  60. package/dist/src/steps/add-mcp-server-to-clients/index.js.map +1 -1
  61. package/package.json +1 -1
@@ -22,7 +22,11 @@ export declare enum AgentErrorType {
22
22
  /** Agent could not access the PostHog MCP server */
23
23
  MCP_MISSING = "WIZARD_MCP_MISSING",
24
24
  /** Agent could not access the setup resource */
25
- RESOURCE_MISSING = "WIZARD_RESOURCE_MISSING"
25
+ RESOURCE_MISSING = "WIZARD_RESOURCE_MISSING",
26
+ /** API rate limit exceeded */
27
+ RATE_LIMIT = "WIZARD_RATE_LIMIT",
28
+ /** Generic API error */
29
+ API_ERROR = "WIZARD_API_ERROR"
26
30
  }
27
31
  export type AgentConfig = {
28
32
  workingDirectory: string;
@@ -44,6 +48,7 @@ type AgentRunConfig = {
44
48
  * - Build/typecheck/lint commands for verification
45
49
  * - Piping to tail/head for output limiting is allowed
46
50
  * - Stderr redirection (2>&1) is allowed
51
+ * - PostHog skill installation commands from MCP
47
52
  */
48
53
  export declare function wizardCanUseTool(toolName: string, input: Record<string, unknown>): {
49
54
  behavior: 'allow';
@@ -69,5 +74,6 @@ export declare function runAgent(agentConfig: AgentRunConfig, prompt: string, op
69
74
  errorMessage?: string;
70
75
  }): Promise<{
71
76
  error?: AgentErrorType;
77
+ message?: string;
72
78
  }>;
73
79
  export {};
@@ -17,6 +17,7 @@ const debug_1 = require("../utils/debug");
17
17
  const analytics_1 = require("../utils/analytics");
18
18
  const constants_1 = require("./constants");
19
19
  const urls_1 = require("../utils/urls");
20
+ const safe_tools_1 = require("./safe-tools");
20
21
  // Dynamic import cache for ESM module
21
22
  let _sdkModule = null;
22
23
  async function getSDKModule() {
@@ -52,6 +53,10 @@ var AgentErrorType;
52
53
  AgentErrorType["MCP_MISSING"] = "WIZARD_MCP_MISSING";
53
54
  /** Agent could not access the setup resource */
54
55
  AgentErrorType["RESOURCE_MISSING"] = "WIZARD_RESOURCE_MISSING";
56
+ /** API rate limit exceeded */
57
+ AgentErrorType["RATE_LIMIT"] = "WIZARD_RATE_LIMIT";
58
+ /** Generic API error */
59
+ AgentErrorType["API_ERROR"] = "WIZARD_API_ERROR";
55
60
  })(AgentErrorType || (exports.AgentErrorType = AgentErrorType = {}));
56
61
  /**
57
62
  * Package managers that can be used to run commands.
@@ -60,6 +65,7 @@ const PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun', 'npx'];
60
65
  /**
61
66
  * Safe scripts/commands that can be run with any package manager.
62
67
  * Uses startsWith matching, so 'build' matches 'build', 'build:prod', etc.
68
+ * Note: Linting tools are in LINTING_TOOLS and checked separately.
63
69
  */
64
70
  const SAFE_SCRIPTS = [
65
71
  // Package installation
@@ -74,19 +80,32 @@ const SAFE_SCRIPTS = [
74
80
  'type-check',
75
81
  'check-types',
76
82
  'types',
77
- // Linting
83
+ // Linting/formatting script names (actual tools are in LINTING_TOOLS)
78
84
  'lint',
79
- 'eslint',
80
- 'next lint',
81
- // Formatting
82
85
  'format',
83
- 'prettier',
84
86
  ];
85
87
  /**
86
88
  * Dangerous shell operators that could allow command injection.
87
89
  * Note: We handle `2>&1` and `| tail/head` separately as safe patterns.
90
+ * Note: `&&` is allowed for specific safe patterns like skill installation.
88
91
  */
89
92
  const DANGEROUS_OPERATORS = /[;`$()]/;
93
+ /**
94
+ * Check if command is a PostHog skill installation from MCP.
95
+ * We control the MCP server, so we only need to verify:
96
+ * 1. It installs to .claude/skills/
97
+ * 2. It downloads from our GitHub releases or localhost (dev)
98
+ */
99
+ function isSkillInstallCommand(command) {
100
+ if (!command.startsWith('mkdir -p .claude/skills/'))
101
+ return false;
102
+ const urlMatch = command.match(/curl -sL ['"]([^'"]+)['"]/);
103
+ if (!urlMatch)
104
+ return false;
105
+ const url = urlMatch[1];
106
+ return (url.startsWith('https://github.com/PostHog/examples/releases/') ||
107
+ /^http:\/\/localhost:\d+\//.test(url));
108
+ }
90
109
  /**
91
110
  * Check if command is an allowed package manager command.
92
111
  * Matches: <pkg-manager> [run|exec] <safe-script> [args...]
@@ -103,8 +122,9 @@ function matchesAllowedPrefix(command) {
103
122
  }
104
123
  // Get the script/command portion (may include args)
105
124
  const scriptPart = parts.slice(scriptIndex).join(' ');
106
- // Check if script starts with any safe script name
107
- return SAFE_SCRIPTS.some((safe) => scriptPart.startsWith(safe));
125
+ // Check if script starts with any safe script name or linting tool
126
+ return (SAFE_SCRIPTS.some((safe) => scriptPart.startsWith(safe)) ||
127
+ safe_tools_1.LINTING_TOOLS.some((tool) => scriptPart.startsWith(tool)));
108
128
  }
109
129
  /**
110
130
  * Permission hook that allows only safe commands.
@@ -112,6 +132,7 @@ function matchesAllowedPrefix(command) {
112
132
  * - Build/typecheck/lint commands for verification
113
133
  * - Piping to tail/head for output limiting is allowed
114
134
  * - Stderr redirection (2>&1) is allowed
135
+ * - PostHog skill installation commands from MCP
115
136
  */
116
137
  function wizardCanUseTool(toolName, input) {
117
138
  // Allow all non-Bash tools
@@ -119,6 +140,13 @@ function wizardCanUseTool(toolName, input) {
119
140
  return { behavior: 'allow', updatedInput: input };
120
141
  }
121
142
  const command = (typeof input.command === 'string' ? input.command : '').trim();
143
+ // Check for PostHog skill installation command (before dangerous operator check)
144
+ // These commands use && chaining but are generated by MCP with a strict format
145
+ if (isSkillInstallCommand(command)) {
146
+ (0, debug_1.logToFile)(`Allowing skill installation command: ${command}`);
147
+ (0, debug_1.debug)(`Allowing skill installation command: ${command}`);
148
+ return { behavior: 'allow', updatedInput: input };
149
+ }
122
150
  // Block definitely dangerous operators: ; ` $ ( )
123
151
  if (DANGEROUS_OPERATORS.test(command)) {
124
152
  (0, debug_1.logToFile)(`Denying bash command with dangerous operators: ${command}`);
@@ -173,7 +201,7 @@ function wizardCanUseTool(toolName, input) {
173
201
  message: `Bash command not allowed. Pipes are only permitted with tail/head for output limiting.`,
174
202
  };
175
203
  }
176
- // Check if command starts with any allowed prefix
204
+ // Check if command starts with any allowed prefix (package manager commands)
177
205
  if (matchesAllowedPrefix(normalized)) {
178
206
  (0, debug_1.logToFile)(`Allowing bash command: ${command}`);
179
207
  (0, debug_1.debug)(`Allowing bash command: ${command}`);
@@ -188,7 +216,7 @@ function wizardCanUseTool(toolName, input) {
188
216
  });
189
217
  return {
190
218
  behavior: 'deny',
191
- message: `Bash command not allowed. Only install, build, typecheck, and lint commands are permitted.`,
219
+ message: `Bash command not allowed. Only install, build, typecheck, lint, and formatting commands are permitted.`,
192
220
  };
193
221
  }
194
222
  /**
@@ -265,25 +293,42 @@ async function runAgent(agentConfig, prompt, options, spinner, config) {
265
293
  (0, debug_1.logToFile)('Prompt:', prompt);
266
294
  const startTime = Date.now();
267
295
  const collectedText = [];
268
- try {
269
- // Workaround for SDK bug: stdin closes before canUseTool responses can be sent.
270
- // The fix is to use an async generator for the prompt that stays open until
271
- // the result is received, keeping the stdin stream alive for permission responses.
272
- // See: https://github.com/anthropics/claude-code/issues/4775
273
- // See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/41
274
- let signalDone;
275
- const resultReceived = new Promise((resolve) => {
276
- signalDone = resolve;
277
- });
278
- const createPromptStream = async function* () {
279
- yield {
280
- type: 'user',
281
- session_id: '',
282
- message: { role: 'user', content: prompt },
283
- parent_tool_use_id: null,
284
- };
285
- await resultReceived;
296
+ // Workaround for SDK bug: stdin closes before canUseTool responses can be sent.
297
+ // The fix is to use an async generator for the prompt that stays open until
298
+ // the result is received, keeping the stdin stream alive for permission responses.
299
+ // See: https://github.com/anthropics/claude-code/issues/4775
300
+ // See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/41
301
+ let signalDone;
302
+ const resultReceived = new Promise((resolve) => {
303
+ signalDone = resolve;
304
+ });
305
+ const createPromptStream = async function* () {
306
+ yield {
307
+ type: 'user',
308
+ session_id: '',
309
+ message: { role: 'user', content: prompt },
310
+ parent_tool_use_id: null,
286
311
  };
312
+ await resultReceived;
313
+ };
314
+ try {
315
+ // Tools needed for the wizard:
316
+ // - File operations: Read, Write, Edit
317
+ // - Search: Glob, Grep
318
+ // - Commands: Bash (with restrictions via canUseTool)
319
+ // - MCP discovery: ListMcpResourcesTool (to find available skills)
320
+ // - Skills: Skill (to load installed PostHog skills)
321
+ // MCP tools (PostHog) come from mcpServers, not allowedTools
322
+ const allowedTools = [
323
+ 'Read',
324
+ 'Write',
325
+ 'Edit',
326
+ 'Glob',
327
+ 'Grep',
328
+ 'Bash',
329
+ 'ListMcpResourcesTool',
330
+ 'Skill',
331
+ ];
287
332
  const response = query({
288
333
  prompt: createPromptStream(),
289
334
  options: {
@@ -291,6 +336,10 @@ async function runAgent(agentConfig, prompt, options, spinner, config) {
291
336
  cwd: agentConfig.workingDirectory,
292
337
  permissionMode: 'acceptEdits',
293
338
  mcpServers: agentConfig.mcpServers,
339
+ // Load skills from project's .claude/skills/ directory
340
+ settingSources: ['project'],
341
+ // Explicitly enable required tools including Skill
342
+ allowedTools,
294
343
  env: { ...process.env },
295
344
  canUseTool: (toolName, input) => {
296
345
  (0, debug_1.logToFile)('canUseTool called:', { toolName, input });
@@ -329,6 +378,17 @@ async function runAgent(agentConfig, prompt, options, spinner, config) {
329
378
  spinner.stop('Agent could not access setup resource');
330
379
  return { error: AgentErrorType.RESOURCE_MISSING };
331
380
  }
381
+ // Check for API errors (rate limits, etc.)
382
+ if (outputText.includes('API Error: 429')) {
383
+ (0, debug_1.logToFile)('Agent error: RATE_LIMIT');
384
+ spinner.stop('Rate limit exceeded');
385
+ return { error: AgentErrorType.RATE_LIMIT, message: outputText };
386
+ }
387
+ if (outputText.includes('API Error:')) {
388
+ (0, debug_1.logToFile)('Agent error: API_ERROR');
389
+ spinner.stop('API error occurred');
390
+ return { error: AgentErrorType.API_ERROR, message: outputText };
391
+ }
332
392
  (0, debug_1.logToFile)(`Agent run completed in ${Math.round(durationMs / 1000)}s`);
333
393
  analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
334
394
  action: 'agent integration completed',
@@ -339,6 +399,26 @@ async function runAgent(agentConfig, prompt, options, spinner, config) {
339
399
  return {};
340
400
  }
341
401
  catch (error) {
402
+ // Signal done to unblock the async generator
403
+ signalDone();
404
+ // Check if we collected an API error before the exception was thrown
405
+ const outputText = collectedText.join('\n');
406
+ // Extract just the API error line(s), not the entire output
407
+ const apiErrorMatch = outputText.match(/API Error: [^\n]+/g);
408
+ const apiErrorMessage = apiErrorMatch
409
+ ? apiErrorMatch.join('\n')
410
+ : 'Unknown API error';
411
+ if (outputText.includes('API Error: 429')) {
412
+ (0, debug_1.logToFile)('Agent error (caught): RATE_LIMIT');
413
+ spinner.stop('Rate limit exceeded');
414
+ return { error: AgentErrorType.RATE_LIMIT, message: apiErrorMessage };
415
+ }
416
+ if (outputText.includes('API Error:')) {
417
+ (0, debug_1.logToFile)('Agent error (caught): API_ERROR');
418
+ spinner.stop('API error occurred');
419
+ return { error: AgentErrorType.API_ERROR, message: apiErrorMessage };
420
+ }
421
+ // No API error found, re-throw the original exception
342
422
  spinner.stop(errorMessage);
343
423
  clack_1.default.log.error(`Error: ${error.message}`);
344
424
  (0, debug_1.logToFile)('Agent run failed:', error);
@@ -375,7 +455,20 @@ function handleSDKMessage(message, options, spinner, collectedText) {
375
455
  break;
376
456
  }
377
457
  case 'result': {
378
- if (message.subtype === 'success') {
458
+ // Check is_error flag - can be true even when subtype is 'success'
459
+ if (message.is_error) {
460
+ (0, debug_1.logToFile)('Agent result with error:', message.result);
461
+ if (typeof message.result === 'string') {
462
+ collectedText.push(message.result);
463
+ }
464
+ if (message.errors) {
465
+ for (const err of message.errors) {
466
+ clack_1.default.log.error(`Error: ${err}`);
467
+ (0, debug_1.logToFile)('ERROR:', err);
468
+ }
469
+ }
470
+ }
471
+ else if (message.subtype === 'success') {
379
472
  (0, debug_1.logToFile)('Agent completed successfully');
380
473
  if (typeof message.result === 'string') {
381
474
  collectedText.push(message.result);
@@ -1 +1 @@
1
- {"version":3,"file":"agent-interface.js","sourceRoot":"","sources":["../../../src/lib/agent-interface.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AA2IH,4CA6FC;AAKD,0CA+DC;AAQD,4BA6HC;AA/aD,gDAAwB;AACxB,2DAAmC;AACnC,0CAA8E;AAE9E,kDAA+C;AAC/C,2CAA4D;AAC5D,wCAAyD;AAEzD,sCAAsC;AACtC,IAAI,UAAU,GAAQ,IAAI,CAAC;AAC3B,KAAK,UAAU,YAAY;IACzB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,UAAU,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,2BAA2B;IAClC,mFAAmF;IACnF,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IACzE,OAAO,cAAI,CAAC,IAAI,CAAC,cAAI,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAOY,QAAA,YAAY,GAAG;IAC1B,iEAAiE;IACjE,MAAM,EAAE,UAAU;IAClB,yEAAyE;IACzE,iBAAiB,EAAE,qBAAqB;IACxC,qEAAqE;IACrE,sBAAsB,EAAE,0BAA0B;CAC1C,CAAC;AAIX;;;GAGG;AACH,IAAY,cAKX;AALD,WAAY,cAAc;IACxB,oDAAoD;IACpD,oDAAkC,CAAA;IAClC,gDAAgD;IAChD,8DAA4C,CAAA;AAC9C,CAAC,EALW,cAAc,8BAAd,cAAc,QAKzB;AAkBD;;GAEG;AACH,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE/D;;;GAGG;AACH,MAAM,YAAY,GAAG;IACnB,uBAAuB;IACvB,SAAS;IACT,KAAK;IACL,IAAI;IACJ,QAAQ;IACR,OAAO;IACP,6CAA6C;IAC7C,KAAK;IACL,WAAW;IACX,YAAY;IACZ,aAAa;IACb,OAAO;IACP,UAAU;IACV,MAAM;IACN,QAAQ;IACR,WAAW;IACX,aAAa;IACb,QAAQ;IACR,UAAU;CACX,CAAC;AAEF;;;GAGG;AACH,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAEtC;;;GAGG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kCAAkC;IAClC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,KAAK,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,MAAM,EAAE,CAAC;QAClE,WAAW,EAAE,CAAC;IAChB,CAAC;IAED,oDAAoD;IACpD,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEtD,mDAAmD;IACnD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAC9B,QAAgB,EAChB,KAA8B;IAI9B,2BAA2B;IAC3B,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC;IAED,MAAM,OAAO,GAAG,CACd,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACvD,CAAC,IAAI,EAAE,CAAC;IAET,kDAAkD;IAClD,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,IAAA,iBAAS,EAAC,kDAAkD,OAAO,EAAE,CAAC,CAAC;QACvE,IAAA,aAAK,EAAC,kDAAkD,OAAO,EAAE,CAAC,CAAC;QACnE,qBAAS,CAAC,OAAO,CAAC,yCAA6B,EAAE;YAC/C,MAAM,EAAE,qBAAqB;YAC7B,MAAM,EAAE,qBAAqB;YAC7B,OAAO;SACR,CAAC,CAAC;QACH,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,8EAA8E;SACxF,CAAC;IACJ,CAAC;IAED,+DAA+D;IAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAElE,qDAAqD;IACrD,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC7E,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAExC,2DAA2D;QAC3D,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,IAAA,iBAAS,EAAC,6CAA6C,OAAO,EAAE,CAAC,CAAC;YAClE,IAAA,aAAK,EAAC,6CAA6C,OAAO,EAAE,CAAC,CAAC;YAC9D,qBAAS,CAAC,OAAO,CAAC,yCAA6B,EAAE;gBAC/C,MAAM,EAAE,qBAAqB;gBAC7B,MAAM,EAAE,gBAAgB;gBACxB,OAAO;aACR,CAAC,CAAC;YACH,OAAO;gBACL,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,uEAAuE;aACjF,CAAC;QACJ,CAAC;QAED,IAAI,oBAAoB,CAAC,WAAW,CAAC,EAAE,CAAC;YACtC,IAAA,iBAAS,EAAC,8CAA8C,OAAO,EAAE,CAAC,CAAC;YACnE,IAAA,aAAK,EAAC,8CAA8C,OAAO,EAAE,CAAC,CAAC;YAC/D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,IAAA,iBAAS,EAAC,qCAAqC,OAAO,EAAE,CAAC,CAAC;QAC1D,IAAA,aAAK,EAAC,qCAAqC,OAAO,EAAE,CAAC,CAAC;QACtD,qBAAS,CAAC,OAAO,CAAC,yCAA6B,EAAE;YAC/C,MAAM,EAAE,qBAAqB;YAC7B,MAAM,EAAE,iBAAiB;YACzB,OAAO;SACR,CAAC,CAAC;QACH,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,wFAAwF;SAClG,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,IAAI,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,IAAA,iBAAS,EAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;QAC/C,IAAA,aAAK,EAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC;IAED,IAAA,iBAAS,EAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAC9C,IAAA,aAAK,EAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAC1C,qBAAS,CAAC,OAAO,CAAC,yCAA6B,EAAE;QAC/C,MAAM,EAAE,qBAAqB;QAC7B,MAAM,EAAE,kBAAkB;QAC1B,OAAO;KACR,CAAC,CAAC;IACH,OAAO;QACL,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,4FAA4F;KACtG,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAC7B,MAAmB,EACnB,OAAsB;IAEtB,mCAAmC;IACnC,IAAA,mBAAW,GAAE,CAAC;IACd,IAAA,iBAAS,EAAC,+BAA+B,CAAC,CAAC;IAC3C,IAAA,iBAAS,EAAC,oBAAoB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAEpD,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAE/C,IAAI,CAAC;QACH,4EAA4E;QAC5E,MAAM,UAAU,GAAG,IAAA,+BAAwB,EAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,UAAU,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,MAAM,CAAC,aAAa,CAAC;QACxD,wFAAwF;QACxF,OAAO,CAAC,GAAG,CAAC,sCAAsC,GAAG,MAAM,CAAC;QAE5D,IAAA,iBAAS,EAAC,yBAAyB,EAAE,UAAU,CAAC,CAAC;QAEjD,mDAAmD;QACnD,MAAM,UAAU,GAAqB;YACnC,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,GAAG,EAAE,MAAM,CAAC,aAAa;gBACzB,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,MAAM,CAAC,aAAa,EAAE;iBAChD;aACF;SACF,CAAC;QAEF,MAAM,cAAc,GAAmB;YACrC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,UAAU;YACV,KAAK,EAAE,0BAA0B;SAClC,CAAC;QAEF,IAAA,iBAAS,EAAC,eAAe,EAAE;YACzB,gBAAgB,EAAE,cAAc,CAAC,gBAAgB;YACjD,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,UAAU;YACV,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa;SACtC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,IAAA,aAAK,EAAC,eAAe,EAAE;gBACrB,gBAAgB,EAAE,cAAc,CAAC,gBAAgB;gBACjD,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,UAAU;gBACV,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa;aACtC,CAAC,CAAC;QACL,CAAC;QAED,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,qBAAa,EAAE,CAAC,CAAC;QACjD,eAAK,CAAC,GAAG,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC;QAC3D,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAK,CAAC,GAAG,CAAC,KAAK,CAAC,+BAAgC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,IAAA,iBAAS,EAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QAChD,IAAA,aAAK,EAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,QAAQ,CAC5B,WAA2B,EAC3B,MAAc,EACd,OAAsB,EACtB,OAAyC,EACzC,MAKC;IAED,MAAM,EACJ,wBAAwB,GAAG,CAAC,EAC5B,cAAc,GAAG,mCAAmC,EACpD,cAAc,GAAG,8BAA8B,EAC/C,YAAY,GAAG,oBAAoB,GACpC,GAAG,MAAM,IAAI,EAAE,CAAC;IAEjB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,eAAK,CAAC,GAAG,CAAC,IAAI,CACZ,wCAAwC,wBAAwB,mEAAmE,CACpI,CAAC;IAEF,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAE9B,MAAM,OAAO,GAAG,2BAA2B,EAAE,CAAC;IAC9C,IAAA,iBAAS,EAAC,oBAAoB,CAAC,CAAC;IAChC,IAAA,iBAAS,EAAC,yBAAyB,EAAE,OAAO,CAAC,CAAC;IAC9C,IAAA,iBAAS,EAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,IAAI,CAAC;QACH,gFAAgF;QAChF,4EAA4E;QAC5E,mFAAmF;QACnF,6DAA6D;QAC7D,2EAA2E;QAC3E,IAAI,UAAsB,CAAC;QAC3B,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnD,UAAU,GAAG,OAAO,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,MAAM,kBAAkB,GAAG,KAAK,SAAS,CAAC;YACxC,MAAM;gBACJ,IAAI,EAAE,MAAM;gBACZ,UAAU,EAAE,EAAE;gBACd,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;gBAC1C,kBAAkB,EAAE,IAAI;aACzB,CAAC;YACF,MAAM,cAAc,CAAC;QACvB,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,KAAK,CAAC;YACrB,MAAM,EAAE,kBAAkB,EAAE;YAC5B,OAAO,EAAE;gBACP,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,GAAG,EAAE,WAAW,CAAC,gBAAgB;gBACjC,cAAc,EAAE,aAAa;gBAC7B,UAAU,EAAE,WAAW,CAAC,UAAU;gBAClC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;gBACvB,UAAU,EAAE,CAAC,QAAgB,EAAE,KAAc,EAAE,EAAE;oBAC/C,IAAA,iBAAS,EAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;oBACrD,MAAM,MAAM,GAAG,gBAAgB,CAC7B,QAAQ,EACR,KAAgC,CACjC,CAAC;oBACF,IAAA,iBAAS,EAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;oBACxC,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACjC,CAAC;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE;gBAChD,mDAAmD;gBACnD,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;oBACvB,IAAA,iBAAS,EAAC,aAAa,EAAE,IAAI,CAAC,CAAC;oBAC/B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;wBAClB,IAAA,aAAK,EAAC,aAAa,EAAE,IAAI,CAAC,CAAC;oBAC7B,CAAC;gBACH,CAAC;aACF;SACF,CAAC,CAAC;QAEH,8BAA8B;QAC9B,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YACrC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;YAC3D,yCAAyC;YACzC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,UAAW,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAC1C,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5C,gDAAgD;QAChD,IAAI,UAAU,CAAC,QAAQ,CAAC,oBAAY,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACxD,IAAA,iBAAS,EAAC,0BAA0B,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;YACnD,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,WAAW,EAAE,CAAC;QAC/C,CAAC;QAED,IAAI,UAAU,CAAC,QAAQ,CAAC,oBAAY,CAAC,sBAAsB,CAAC,EAAE,CAAC;YAC7D,IAAA,iBAAS,EAAC,+BAA+B,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;YACtD,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,gBAAgB,EAAE,CAAC;QACpD,CAAC;QAED,IAAA,iBAAS,EAAC,0BAA0B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtE,qBAAS,CAAC,OAAO,CAAC,yCAA6B,EAAE;YAC/C,MAAM,EAAE,6BAA6B;YACrC,WAAW,EAAE,UAAU;YACvB,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;SAChD,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3B,eAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAW,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACtD,IAAA,iBAAS,EAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;QACtC,IAAA,aAAK,EAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QAC5B,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,OAAmB,EACnB,OAAsB,EACtB,OAAyC,EACzC,aAAuB;IAEvB,IAAA,iBAAS,EAAC,gBAAgB,OAAO,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE5E,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,IAAA,aAAK,EAAC,qBAAqB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,+CAA+C;YAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;YACzC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBAC5D,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAE/B,6BAA6B;wBAC7B,MAAM,WAAW,GAAG,IAAI,MAAM,CAC5B,MAAM,oBAAY,CAAC,MAAM,CAAC,OAAO,CAC/B,qBAAqB,EACrB,MAAM,CACP,YAAY,EACb,GAAG,CACJ,CAAC;wBACF,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;wBAClD,IAAI,WAAW,EAAE,CAAC;4BAChB,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;4BACpC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;wBAC1C,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBAClC,IAAA,iBAAS,EAAC,8BAA8B,CAAC,CAAC;gBAC1C,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACvC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,eAAe;gBACf,IAAA,iBAAS,EAAC,qBAAqB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;gBAClD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACnB,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;wBACjC,eAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;wBACjC,IAAA,iBAAS,EAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;oBAC3B,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;gBAC/B,IAAA,iBAAS,EAAC,2BAA2B,EAAE;oBACrC,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM;oBAC5B,UAAU,EAAE,OAAO,CAAC,WAAW;iBAChC,CAAC,CAAC;YACL,CAAC;YACD,MAAM;QACR,CAAC;QAED;YACE,wCAAwC;YACxC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,IAAA,aAAK,EAAC,2BAA2B,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,MAAM;IACV,CAAC;AACH,CAAC","sourcesContent":["/**\n * Shared agent interface for PostHog wizards\n * Uses Claude Agent SDK directly with PostHog LLM gateway\n */\n\nimport path from 'path';\nimport clack from '../utils/clack';\nimport { debug, logToFile, initLogFile, LOG_FILE_PATH } from '../utils/debug';\nimport type { WizardOptions } from '../utils/types';\nimport { analytics } from '../utils/analytics';\nimport { WIZARD_INTERACTION_EVENT_NAME } from './constants';\nimport { getLlmGatewayUrlFromHost } from '../utils/urls';\n\n// Dynamic import cache for ESM module\nlet _sdkModule: any = null;\nasync function getSDKModule(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\n/**\n * Get the path to the bundled Claude Code CLI from the SDK package.\n * This ensures we use the SDK's bundled version rather than the user's installed Claude Code.\n */\nfunction getClaudeCodeExecutablePath(): string {\n // require.resolve finds the package's main entry, then we get cli.js from same dir\n const sdkPackagePath = require.resolve('@anthropic-ai/claude-agent-sdk');\n return path.join(path.dirname(sdkPackagePath), 'cli.js');\n}\n\n// Using `any` because typed imports from ESM modules require import attributes\n// syntax which prettier cannot parse. See PR discussion for details.\ntype SDKMessage = any;\ntype McpServersConfig = any;\n\nexport const AgentSignals = {\n /** Signal emitted when the agent reports progress to the user */\n STATUS: '[STATUS]',\n /** Signal emitted when the agent cannot access the PostHog MCP server */\n ERROR_MCP_MISSING: '[ERROR-MCP-MISSING]',\n /** Signal emitted when the agent cannot access the setup resource */\n ERROR_RESOURCE_MISSING: '[ERROR-RESOURCE-MISSING]',\n} as const;\n\nexport type AgentSignal = (typeof AgentSignals)[keyof typeof AgentSignals];\n\n/**\n * Error types that can be returned from agent execution.\n * These correspond to the error signals that the agent emits.\n */\nexport enum AgentErrorType {\n /** Agent could not access the PostHog MCP server */\n MCP_MISSING = 'WIZARD_MCP_MISSING',\n /** Agent could not access the setup resource */\n RESOURCE_MISSING = 'WIZARD_RESOURCE_MISSING',\n}\n\nexport type AgentConfig = {\n workingDirectory: string;\n posthogMcpUrl: string;\n posthogApiKey: string;\n posthogApiHost: string;\n};\n\n/**\n * Internal configuration object returned by initializeAgent\n */\ntype AgentRunConfig = {\n workingDirectory: string;\n mcpServers: McpServersConfig;\n model: string;\n};\n\n/**\n * Package managers that can be used to run commands.\n */\nconst PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun', 'npx'];\n\n/**\n * Safe scripts/commands that can be run with any package manager.\n * Uses startsWith matching, so 'build' matches 'build', 'build:prod', etc.\n */\nconst SAFE_SCRIPTS = [\n // Package installation\n 'install',\n 'add',\n 'ci',\n // Build\n 'build',\n // Type checking (various naming conventions)\n 'tsc',\n 'typecheck',\n 'type-check',\n 'check-types',\n 'types',\n // Linting\n 'lint',\n 'eslint',\n 'next lint',\n // Formatting\n 'format',\n 'prettier',\n];\n\n/**\n * Dangerous shell operators that could allow command injection.\n * Note: We handle `2>&1` and `| tail/head` separately as safe patterns.\n */\nconst DANGEROUS_OPERATORS = /[;`$()]/;\n\n/**\n * Check if command is an allowed package manager command.\n * Matches: <pkg-manager> [run|exec] <safe-script> [args...]\n */\nfunction matchesAllowedPrefix(command: string): boolean {\n const parts = command.split(/\\s+/);\n if (parts.length === 0 || !PACKAGE_MANAGERS.includes(parts[0])) {\n return false;\n }\n\n // Skip 'run' or 'exec' if present\n let scriptIndex = 1;\n if (parts[scriptIndex] === 'run' || parts[scriptIndex] === 'exec') {\n scriptIndex++;\n }\n\n // Get the script/command portion (may include args)\n const scriptPart = parts.slice(scriptIndex).join(' ');\n\n // Check if script starts with any safe script name\n return SAFE_SCRIPTS.some((safe) => scriptPart.startsWith(safe));\n}\n\n/**\n * Permission hook that allows only safe commands.\n * - Package manager install commands\n * - Build/typecheck/lint commands for verification\n * - Piping to tail/head for output limiting is allowed\n * - Stderr redirection (2>&1) is allowed\n */\nexport function wizardCanUseTool(\n toolName: string,\n input: Record<string, unknown>,\n):\n | { behavior: 'allow'; updatedInput: Record<string, unknown> }\n | { behavior: 'deny'; message: string } {\n // Allow all non-Bash tools\n if (toolName !== 'Bash') {\n return { behavior: 'allow', updatedInput: input };\n }\n\n const command = (\n typeof input.command === 'string' ? input.command : ''\n ).trim();\n\n // Block definitely dangerous operators: ; ` $ ( )\n if (DANGEROUS_OPERATORS.test(command)) {\n logToFile(`Denying bash command with dangerous operators: ${command}`);\n debug(`Denying bash command with dangerous operators: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'dangerous operators',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Shell operators like ; \\` $ ( ) are not permitted.`,\n };\n }\n\n // Normalize: remove safe stderr redirection (2>&1, 2>&2, etc.)\n const normalized = command.replace(/\\s*\\d*>&\\d+\\s*/g, ' ').trim();\n\n // Check for pipe to tail/head (safe output limiting)\n const pipeMatch = normalized.match(/^(.+?)\\s*\\|\\s*(tail|head)(\\s+\\S+)*\\s*$/);\n if (pipeMatch) {\n const baseCommand = pipeMatch[1].trim();\n\n // Block if base command has pipes or & (multiple chaining)\n if (/[|&]/.test(baseCommand)) {\n logToFile(`Denying bash command with multiple pipes: ${command}`);\n debug(`Denying bash command with multiple pipes: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'multiple pipes',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Only single pipe to tail/head is permitted.`,\n };\n }\n\n if (matchesAllowedPrefix(baseCommand)) {\n logToFile(`Allowing bash command with output limiter: ${command}`);\n debug(`Allowing bash command with output limiter: ${command}`);\n return { behavior: 'allow', updatedInput: input };\n }\n }\n\n // Block remaining pipes and & (not covered by tail/head case above)\n if (/[|&]/.test(normalized)) {\n logToFile(`Denying bash command with pipe/&: ${command}`);\n debug(`Denying bash command with pipe/&: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'disallowed pipe',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Pipes are only permitted with tail/head for output limiting.`,\n };\n }\n\n // Check if command starts with any allowed prefix\n if (matchesAllowedPrefix(normalized)) {\n logToFile(`Allowing bash command: ${command}`);\n debug(`Allowing bash command: ${command}`);\n return { behavior: 'allow', updatedInput: input };\n }\n\n logToFile(`Denying bash command: ${command}`);\n debug(`Denying bash command: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'not in allowlist',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Only install, build, typecheck, and lint commands are permitted.`,\n };\n}\n\n/**\n * Initialize agent configuration for the LLM gateway\n */\nexport function initializeAgent(\n config: AgentConfig,\n options: WizardOptions,\n): AgentRunConfig {\n // Initialize log file for this run\n initLogFile();\n logToFile('Agent initialization starting');\n logToFile('Install directory:', options.installDir);\n\n clack.log.step('Initializing Claude agent...');\n\n try {\n // Configure LLM gateway environment variables (inherited by SDK subprocess)\n const gatewayUrl = getLlmGatewayUrlFromHost(config.posthogApiHost);\n process.env.ANTHROPIC_BASE_URL = gatewayUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = config.posthogApiKey;\n // Disable experimental betas (like input_examples) that the LLM gateway doesn't support\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n\n logToFile('Configured LLM gateway:', gatewayUrl);\n\n // Configure MCP server with PostHog authentication\n const mcpServers: McpServersConfig = {\n posthog: {\n type: 'http',\n url: config.posthogMcpUrl,\n headers: {\n Authorization: `Bearer ${config.posthogApiKey}`,\n },\n },\n };\n\n const agentRunConfig: AgentRunConfig = {\n workingDirectory: config.workingDirectory,\n mcpServers,\n model: 'claude-opus-4-5-20251101',\n };\n\n logToFile('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n posthogMcpUrl: config.posthogMcpUrl,\n gatewayUrl,\n apiKeyPresent: !!config.posthogApiKey,\n });\n\n if (options.debug) {\n debug('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n posthogMcpUrl: config.posthogMcpUrl,\n gatewayUrl,\n apiKeyPresent: !!config.posthogApiKey,\n });\n }\n\n clack.log.step(`Verbose logs: ${LOG_FILE_PATH}`);\n clack.log.success(\"Agent initialized. Let's get cooking!\");\n return agentRunConfig;\n } catch (error) {\n clack.log.error(`Failed to initialize agent: ${(error as Error).message}`);\n logToFile('Agent initialization error:', error);\n debug('Agent initialization error:', error);\n throw error;\n }\n}\n\n/**\n * Execute an agent with the provided prompt and options\n * Handles the full lifecycle: spinner, execution, error handling\n *\n * @returns An object containing any error detected in the agent's output\n */\nexport async function runAgent(\n agentConfig: AgentRunConfig,\n prompt: string,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n config?: {\n estimatedDurationMinutes?: number;\n spinnerMessage?: string;\n successMessage?: string;\n errorMessage?: string;\n },\n): Promise<{ error?: AgentErrorType }> {\n const {\n estimatedDurationMinutes = 8,\n spinnerMessage = 'Customizing your PostHog setup...',\n successMessage = 'PostHog integration complete',\n errorMessage = 'Integration failed',\n } = config ?? {};\n\n const { query } = await getSDKModule();\n\n clack.log.step(\n `This whole process should take about ${estimatedDurationMinutes} minutes including error checking and fixes.\\n\\nGrab some coffee!`,\n );\n\n spinner.start(spinnerMessage);\n\n const cliPath = getClaudeCodeExecutablePath();\n logToFile('Starting agent run');\n logToFile('Claude Code executable:', cliPath);\n logToFile('Prompt:', prompt);\n\n const startTime = Date.now();\n const collectedText: string[] = [];\n\n try {\n // Workaround for SDK bug: stdin closes before canUseTool responses can be sent.\n // The fix is to use an async generator for the prompt that stays open until\n // the result is received, keeping the stdin stream alive for permission responses.\n // See: https://github.com/anthropics/claude-code/issues/4775\n // See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/41\n let signalDone: () => void;\n const resultReceived = new Promise<void>((resolve) => {\n signalDone = resolve;\n });\n\n const createPromptStream = async function* () {\n yield {\n type: 'user',\n session_id: '',\n message: { role: 'user', content: prompt },\n parent_tool_use_id: null,\n };\n await resultReceived;\n };\n\n const response = query({\n prompt: createPromptStream(),\n options: {\n model: agentConfig.model,\n cwd: agentConfig.workingDirectory,\n permissionMode: 'acceptEdits',\n mcpServers: agentConfig.mcpServers,\n env: { ...process.env },\n canUseTool: (toolName: string, input: unknown) => {\n logToFile('canUseTool called:', { toolName, input });\n const result = wizardCanUseTool(\n toolName,\n input as Record<string, unknown>,\n );\n logToFile('canUseTool result:', result);\n return Promise.resolve(result);\n },\n tools: { type: 'preset', preset: 'claude_code' },\n // Capture stderr from CLI subprocess for debugging\n stderr: (data: string) => {\n logToFile('CLI stderr:', data);\n if (options.debug) {\n debug('CLI stderr:', data);\n }\n },\n },\n });\n\n // Process the async generator\n for await (const message of response) {\n handleSDKMessage(message, options, spinner, collectedText);\n // Signal completion when result received\n if (message.type === 'result') {\n signalDone!();\n }\n }\n\n const durationMs = Date.now() - startTime;\n const outputText = collectedText.join('\\n');\n\n // Check for error markers in the agent's output\n if (outputText.includes(AgentSignals.ERROR_MCP_MISSING)) {\n logToFile('Agent error: MCP_MISSING');\n spinner.stop('Agent could not access PostHog MCP');\n return { error: AgentErrorType.MCP_MISSING };\n }\n\n if (outputText.includes(AgentSignals.ERROR_RESOURCE_MISSING)) {\n logToFile('Agent error: RESOURCE_MISSING');\n spinner.stop('Agent could not access setup resource');\n return { error: AgentErrorType.RESOURCE_MISSING };\n }\n\n logToFile(`Agent run completed in ${Math.round(durationMs / 1000)}s`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'agent integration completed',\n duration_ms: durationMs,\n duration_seconds: Math.round(durationMs / 1000),\n });\n\n spinner.stop(successMessage);\n return {};\n } catch (error) {\n spinner.stop(errorMessage);\n clack.log.error(`Error: ${(error as Error).message}`);\n logToFile('Agent run failed:', error);\n debug('Full error:', error);\n throw error;\n }\n}\n\n/**\n * Handle SDK messages and provide user feedback\n */\nfunction handleSDKMessage(\n message: SDKMessage,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n collectedText: string[],\n): void {\n logToFile(`SDK Message: ${message.type}`, JSON.stringify(message, null, 2));\n\n if (options.debug) {\n debug(`SDK Message type: ${message.type}`);\n }\n\n switch (message.type) {\n case 'assistant': {\n // Extract text content from assistant messages\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'text' && typeof block.text === 'string') {\n collectedText.push(block.text);\n\n // Check for [STATUS] markers\n const statusRegex = new RegExp(\n `^.*${AgentSignals.STATUS.replace(\n /[.*+?^${}()|[\\]\\\\]/g,\n '\\\\$&',\n )}\\\\s*(.+?)$`,\n 'm',\n );\n const statusMatch = block.text.match(statusRegex);\n if (statusMatch) {\n spinner.stop(statusMatch[1].trim());\n spinner.start('Integrating PostHog...');\n }\n }\n }\n }\n break;\n }\n\n case 'result': {\n if (message.subtype === 'success') {\n logToFile('Agent completed successfully');\n if (typeof message.result === 'string') {\n collectedText.push(message.result);\n }\n } else {\n // Error result\n logToFile('Agent error result:', message.subtype);\n if (message.errors) {\n for (const err of message.errors) {\n clack.log.error(`Error: ${err}`);\n logToFile('ERROR:', err);\n }\n }\n }\n break;\n }\n\n case 'system': {\n if (message.subtype === 'init') {\n logToFile('Agent session initialized', {\n model: message.model,\n tools: message.tools?.length,\n mcpServers: message.mcp_servers,\n });\n }\n break;\n }\n\n default:\n // Log other message types for debugging\n if (options.debug) {\n debug(`Unhandled message type: ${message.type}`);\n }\n break;\n }\n}\n"]}
1
+ {"version":3,"file":"agent-interface.js","sourceRoot":"","sources":["../../../src/lib/agent-interface.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared agent interface for PostHog wizards\n * Uses Claude Agent SDK directly with PostHog LLM gateway\n */\n\nimport path from 'path';\nimport clack from '../utils/clack';\nimport { debug, logToFile, initLogFile, LOG_FILE_PATH } from '../utils/debug';\nimport type { WizardOptions } from '../utils/types';\nimport { analytics } from '../utils/analytics';\nimport { WIZARD_INTERACTION_EVENT_NAME } from './constants';\nimport { getLlmGatewayUrlFromHost } from '../utils/urls';\nimport { LINTING_TOOLS } from './safe-tools';\n\n// Dynamic import cache for ESM module\nlet _sdkModule: any = null;\nasync function getSDKModule(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\n/**\n * Get the path to the bundled Claude Code CLI from the SDK package.\n * This ensures we use the SDK's bundled version rather than the user's installed Claude Code.\n */\nfunction getClaudeCodeExecutablePath(): string {\n // require.resolve finds the package's main entry, then we get cli.js from same dir\n const sdkPackagePath = require.resolve('@anthropic-ai/claude-agent-sdk');\n return path.join(path.dirname(sdkPackagePath), 'cli.js');\n}\n\n// Using `any` because typed imports from ESM modules require import attributes\n// syntax which prettier cannot parse. See PR discussion for details.\ntype SDKMessage = any;\ntype McpServersConfig = any;\n\nexport const AgentSignals = {\n /** Signal emitted when the agent reports progress to the user */\n STATUS: '[STATUS]',\n /** Signal emitted when the agent cannot access the PostHog MCP server */\n ERROR_MCP_MISSING: '[ERROR-MCP-MISSING]',\n /** Signal emitted when the agent cannot access the setup resource */\n ERROR_RESOURCE_MISSING: '[ERROR-RESOURCE-MISSING]',\n} as const;\n\nexport type AgentSignal = (typeof AgentSignals)[keyof typeof AgentSignals];\n\n/**\n * Error types that can be returned from agent execution.\n * These correspond to the error signals that the agent emits.\n */\nexport enum AgentErrorType {\n /** Agent could not access the PostHog MCP server */\n MCP_MISSING = 'WIZARD_MCP_MISSING',\n /** Agent could not access the setup resource */\n RESOURCE_MISSING = 'WIZARD_RESOURCE_MISSING',\n /** API rate limit exceeded */\n RATE_LIMIT = 'WIZARD_RATE_LIMIT',\n /** Generic API error */\n API_ERROR = 'WIZARD_API_ERROR',\n}\n\nexport type AgentConfig = {\n workingDirectory: string;\n posthogMcpUrl: string;\n posthogApiKey: string;\n posthogApiHost: string;\n};\n\n/**\n * Internal configuration object returned by initializeAgent\n */\ntype AgentRunConfig = {\n workingDirectory: string;\n mcpServers: McpServersConfig;\n model: string;\n};\n\n/**\n * Package managers that can be used to run commands.\n */\nconst PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun', 'npx'];\n\n/**\n * Safe scripts/commands that can be run with any package manager.\n * Uses startsWith matching, so 'build' matches 'build', 'build:prod', etc.\n * Note: Linting tools are in LINTING_TOOLS and checked separately.\n */\nconst SAFE_SCRIPTS = [\n // Package installation\n 'install',\n 'add',\n 'ci',\n // Build\n 'build',\n // Type checking (various naming conventions)\n 'tsc',\n 'typecheck',\n 'type-check',\n 'check-types',\n 'types',\n // Linting/formatting script names (actual tools are in LINTING_TOOLS)\n 'lint',\n 'format',\n];\n\n/**\n * Dangerous shell operators that could allow command injection.\n * Note: We handle `2>&1` and `| tail/head` separately as safe patterns.\n * Note: `&&` is allowed for specific safe patterns like skill installation.\n */\nconst DANGEROUS_OPERATORS = /[;`$()]/;\n\n/**\n * Check if command is a PostHog skill installation from MCP.\n * We control the MCP server, so we only need to verify:\n * 1. It installs to .claude/skills/\n * 2. It downloads from our GitHub releases or localhost (dev)\n */\nfunction isSkillInstallCommand(command: string): boolean {\n if (!command.startsWith('mkdir -p .claude/skills/')) return false;\n\n const urlMatch = command.match(/curl -sL ['\"]([^'\"]+)['\"]/);\n if (!urlMatch) return false;\n\n const url = urlMatch[1];\n return (\n url.startsWith('https://github.com/PostHog/examples/releases/') ||\n /^http:\\/\\/localhost:\\d+\\//.test(url)\n );\n}\n\n/**\n * Check if command is an allowed package manager command.\n * Matches: <pkg-manager> [run|exec] <safe-script> [args...]\n */\nfunction matchesAllowedPrefix(command: string): boolean {\n const parts = command.split(/\\s+/);\n if (parts.length === 0 || !PACKAGE_MANAGERS.includes(parts[0])) {\n return false;\n }\n\n // Skip 'run' or 'exec' if present\n let scriptIndex = 1;\n if (parts[scriptIndex] === 'run' || parts[scriptIndex] === 'exec') {\n scriptIndex++;\n }\n\n // Get the script/command portion (may include args)\n const scriptPart = parts.slice(scriptIndex).join(' ');\n\n // Check if script starts with any safe script name or linting tool\n return (\n SAFE_SCRIPTS.some((safe) => scriptPart.startsWith(safe)) ||\n LINTING_TOOLS.some((tool) => scriptPart.startsWith(tool))\n );\n}\n\n/**\n * Permission hook that allows only safe commands.\n * - Package manager install commands\n * - Build/typecheck/lint commands for verification\n * - Piping to tail/head for output limiting is allowed\n * - Stderr redirection (2>&1) is allowed\n * - PostHog skill installation commands from MCP\n */\nexport function wizardCanUseTool(\n toolName: string,\n input: Record<string, unknown>,\n):\n | { behavior: 'allow'; updatedInput: Record<string, unknown> }\n | { behavior: 'deny'; message: string } {\n // Allow all non-Bash tools\n if (toolName !== 'Bash') {\n return { behavior: 'allow', updatedInput: input };\n }\n\n const command = (\n typeof input.command === 'string' ? input.command : ''\n ).trim();\n\n // Check for PostHog skill installation command (before dangerous operator check)\n // These commands use && chaining but are generated by MCP with a strict format\n if (isSkillInstallCommand(command)) {\n logToFile(`Allowing skill installation command: ${command}`);\n debug(`Allowing skill installation command: ${command}`);\n return { behavior: 'allow', updatedInput: input };\n }\n\n // Block definitely dangerous operators: ; ` $ ( )\n if (DANGEROUS_OPERATORS.test(command)) {\n logToFile(`Denying bash command with dangerous operators: ${command}`);\n debug(`Denying bash command with dangerous operators: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'dangerous operators',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Shell operators like ; \\` $ ( ) are not permitted.`,\n };\n }\n\n // Normalize: remove safe stderr redirection (2>&1, 2>&2, etc.)\n const normalized = command.replace(/\\s*\\d*>&\\d+\\s*/g, ' ').trim();\n\n // Check for pipe to tail/head (safe output limiting)\n const pipeMatch = normalized.match(/^(.+?)\\s*\\|\\s*(tail|head)(\\s+\\S+)*\\s*$/);\n if (pipeMatch) {\n const baseCommand = pipeMatch[1].trim();\n\n // Block if base command has pipes or & (multiple chaining)\n if (/[|&]/.test(baseCommand)) {\n logToFile(`Denying bash command with multiple pipes: ${command}`);\n debug(`Denying bash command with multiple pipes: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'multiple pipes',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Only single pipe to tail/head is permitted.`,\n };\n }\n\n if (matchesAllowedPrefix(baseCommand)) {\n logToFile(`Allowing bash command with output limiter: ${command}`);\n debug(`Allowing bash command with output limiter: ${command}`);\n return { behavior: 'allow', updatedInput: input };\n }\n }\n\n // Block remaining pipes and & (not covered by tail/head case above)\n if (/[|&]/.test(normalized)) {\n logToFile(`Denying bash command with pipe/&: ${command}`);\n debug(`Denying bash command with pipe/&: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'disallowed pipe',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Pipes are only permitted with tail/head for output limiting.`,\n };\n }\n\n // Check if command starts with any allowed prefix (package manager commands)\n if (matchesAllowedPrefix(normalized)) {\n logToFile(`Allowing bash command: ${command}`);\n debug(`Allowing bash command: ${command}`);\n return { behavior: 'allow', updatedInput: input };\n }\n\n logToFile(`Denying bash command: ${command}`);\n debug(`Denying bash command: ${command}`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'bash command denied',\n reason: 'not in allowlist',\n command,\n });\n return {\n behavior: 'deny',\n message: `Bash command not allowed. Only install, build, typecheck, lint, and formatting commands are permitted.`,\n };\n}\n\n/**\n * Initialize agent configuration for the LLM gateway\n */\nexport function initializeAgent(\n config: AgentConfig,\n options: WizardOptions,\n): AgentRunConfig {\n // Initialize log file for this run\n initLogFile();\n logToFile('Agent initialization starting');\n logToFile('Install directory:', options.installDir);\n\n clack.log.step('Initializing Claude agent...');\n\n try {\n // Configure LLM gateway environment variables (inherited by SDK subprocess)\n const gatewayUrl = getLlmGatewayUrlFromHost(config.posthogApiHost);\n process.env.ANTHROPIC_BASE_URL = gatewayUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = config.posthogApiKey;\n // Disable experimental betas (like input_examples) that the LLM gateway doesn't support\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n\n logToFile('Configured LLM gateway:', gatewayUrl);\n\n // Configure MCP server with PostHog authentication\n const mcpServers: McpServersConfig = {\n posthog: {\n type: 'http',\n url: config.posthogMcpUrl,\n headers: {\n Authorization: `Bearer ${config.posthogApiKey}`,\n },\n },\n };\n\n const agentRunConfig: AgentRunConfig = {\n workingDirectory: config.workingDirectory,\n mcpServers,\n model: 'claude-opus-4-5-20251101',\n };\n\n logToFile('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n posthogMcpUrl: config.posthogMcpUrl,\n gatewayUrl,\n apiKeyPresent: !!config.posthogApiKey,\n });\n\n if (options.debug) {\n debug('Agent config:', {\n workingDirectory: agentRunConfig.workingDirectory,\n posthogMcpUrl: config.posthogMcpUrl,\n gatewayUrl,\n apiKeyPresent: !!config.posthogApiKey,\n });\n }\n\n clack.log.step(`Verbose logs: ${LOG_FILE_PATH}`);\n clack.log.success(\"Agent initialized. Let's get cooking!\");\n return agentRunConfig;\n } catch (error) {\n clack.log.error(`Failed to initialize agent: ${(error as Error).message}`);\n logToFile('Agent initialization error:', error);\n debug('Agent initialization error:', error);\n throw error;\n }\n}\n\n/**\n * Execute an agent with the provided prompt and options\n * Handles the full lifecycle: spinner, execution, error handling\n *\n * @returns An object containing any error detected in the agent's output\n */\nexport async function runAgent(\n agentConfig: AgentRunConfig,\n prompt: string,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n config?: {\n estimatedDurationMinutes?: number;\n spinnerMessage?: string;\n successMessage?: string;\n errorMessage?: string;\n },\n): Promise<{ error?: AgentErrorType; message?: string }> {\n const {\n estimatedDurationMinutes = 8,\n spinnerMessage = 'Customizing your PostHog setup...',\n successMessage = 'PostHog integration complete',\n errorMessage = 'Integration failed',\n } = config ?? {};\n\n const { query } = await getSDKModule();\n\n clack.log.step(\n `This whole process should take about ${estimatedDurationMinutes} minutes including error checking and fixes.\\n\\nGrab some coffee!`,\n );\n\n spinner.start(spinnerMessage);\n\n const cliPath = getClaudeCodeExecutablePath();\n logToFile('Starting agent run');\n logToFile('Claude Code executable:', cliPath);\n logToFile('Prompt:', prompt);\n\n const startTime = Date.now();\n const collectedText: string[] = [];\n\n // Workaround for SDK bug: stdin closes before canUseTool responses can be sent.\n // The fix is to use an async generator for the prompt that stays open until\n // the result is received, keeping the stdin stream alive for permission responses.\n // See: https://github.com/anthropics/claude-code/issues/4775\n // See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/41\n let signalDone: () => void;\n const resultReceived = new Promise<void>((resolve) => {\n signalDone = resolve;\n });\n\n const createPromptStream = async function* () {\n yield {\n type: 'user',\n session_id: '',\n message: { role: 'user', content: prompt },\n parent_tool_use_id: null,\n };\n await resultReceived;\n };\n\n try {\n // Tools needed for the wizard:\n // - File operations: Read, Write, Edit\n // - Search: Glob, Grep\n // - Commands: Bash (with restrictions via canUseTool)\n // - MCP discovery: ListMcpResourcesTool (to find available skills)\n // - Skills: Skill (to load installed PostHog skills)\n // MCP tools (PostHog) come from mcpServers, not allowedTools\n const allowedTools = [\n 'Read',\n 'Write',\n 'Edit',\n 'Glob',\n 'Grep',\n 'Bash',\n 'ListMcpResourcesTool',\n 'Skill',\n ];\n\n const response = query({\n prompt: createPromptStream(),\n options: {\n model: agentConfig.model,\n cwd: agentConfig.workingDirectory,\n permissionMode: 'acceptEdits',\n mcpServers: agentConfig.mcpServers,\n // Load skills from project's .claude/skills/ directory\n settingSources: ['project'],\n // Explicitly enable required tools including Skill\n allowedTools,\n env: { ...process.env },\n canUseTool: (toolName: string, input: unknown) => {\n logToFile('canUseTool called:', { toolName, input });\n const result = wizardCanUseTool(\n toolName,\n input as Record<string, unknown>,\n );\n logToFile('canUseTool result:', result);\n return Promise.resolve(result);\n },\n tools: { type: 'preset', preset: 'claude_code' },\n // Capture stderr from CLI subprocess for debugging\n stderr: (data: string) => {\n logToFile('CLI stderr:', data);\n if (options.debug) {\n debug('CLI stderr:', data);\n }\n },\n },\n });\n\n // Process the async generator\n for await (const message of response) {\n handleSDKMessage(message, options, spinner, collectedText);\n // Signal completion when result received\n if (message.type === 'result') {\n signalDone!();\n }\n }\n\n const durationMs = Date.now() - startTime;\n const outputText = collectedText.join('\\n');\n\n // Check for error markers in the agent's output\n if (outputText.includes(AgentSignals.ERROR_MCP_MISSING)) {\n logToFile('Agent error: MCP_MISSING');\n spinner.stop('Agent could not access PostHog MCP');\n return { error: AgentErrorType.MCP_MISSING };\n }\n\n if (outputText.includes(AgentSignals.ERROR_RESOURCE_MISSING)) {\n logToFile('Agent error: RESOURCE_MISSING');\n spinner.stop('Agent could not access setup resource');\n return { error: AgentErrorType.RESOURCE_MISSING };\n }\n\n // Check for API errors (rate limits, etc.)\n if (outputText.includes('API Error: 429')) {\n logToFile('Agent error: RATE_LIMIT');\n spinner.stop('Rate limit exceeded');\n return { error: AgentErrorType.RATE_LIMIT, message: outputText };\n }\n\n if (outputText.includes('API Error:')) {\n logToFile('Agent error: API_ERROR');\n spinner.stop('API error occurred');\n return { error: AgentErrorType.API_ERROR, message: outputText };\n }\n\n logToFile(`Agent run completed in ${Math.round(durationMs / 1000)}s`);\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'agent integration completed',\n duration_ms: durationMs,\n duration_seconds: Math.round(durationMs / 1000),\n });\n\n spinner.stop(successMessage);\n return {};\n } catch (error) {\n // Signal done to unblock the async generator\n signalDone!();\n\n // Check if we collected an API error before the exception was thrown\n const outputText = collectedText.join('\\n');\n\n // Extract just the API error line(s), not the entire output\n const apiErrorMatch = outputText.match(/API Error: [^\\n]+/g);\n const apiErrorMessage = apiErrorMatch\n ? apiErrorMatch.join('\\n')\n : 'Unknown API error';\n\n if (outputText.includes('API Error: 429')) {\n logToFile('Agent error (caught): RATE_LIMIT');\n spinner.stop('Rate limit exceeded');\n return { error: AgentErrorType.RATE_LIMIT, message: apiErrorMessage };\n }\n\n if (outputText.includes('API Error:')) {\n logToFile('Agent error (caught): API_ERROR');\n spinner.stop('API error occurred');\n return { error: AgentErrorType.API_ERROR, message: apiErrorMessage };\n }\n\n // No API error found, re-throw the original exception\n spinner.stop(errorMessage);\n clack.log.error(`Error: ${(error as Error).message}`);\n logToFile('Agent run failed:', error);\n debug('Full error:', error);\n throw error;\n }\n}\n\n/**\n * Handle SDK messages and provide user feedback\n */\nfunction handleSDKMessage(\n message: SDKMessage,\n options: WizardOptions,\n spinner: ReturnType<typeof clack.spinner>,\n collectedText: string[],\n): void {\n logToFile(`SDK Message: ${message.type}`, JSON.stringify(message, null, 2));\n\n if (options.debug) {\n debug(`SDK Message type: ${message.type}`);\n }\n\n switch (message.type) {\n case 'assistant': {\n // Extract text content from assistant messages\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'text' && typeof block.text === 'string') {\n collectedText.push(block.text);\n\n // Check for [STATUS] markers\n const statusRegex = new RegExp(\n `^.*${AgentSignals.STATUS.replace(\n /[.*+?^${}()|[\\]\\\\]/g,\n '\\\\$&',\n )}\\\\s*(.+?)$`,\n 'm',\n );\n const statusMatch = block.text.match(statusRegex);\n if (statusMatch) {\n spinner.stop(statusMatch[1].trim());\n spinner.start('Integrating PostHog...');\n }\n }\n }\n }\n break;\n }\n\n case 'result': {\n // Check is_error flag - can be true even when subtype is 'success'\n if (message.is_error) {\n logToFile('Agent result with error:', message.result);\n if (typeof message.result === 'string') {\n collectedText.push(message.result);\n }\n if (message.errors) {\n for (const err of message.errors) {\n clack.log.error(`Error: ${err}`);\n logToFile('ERROR:', err);\n }\n }\n } else if (message.subtype === 'success') {\n logToFile('Agent completed successfully');\n if (typeof message.result === 'string') {\n collectedText.push(message.result);\n }\n } else {\n // Error result\n logToFile('Agent error result:', message.subtype);\n if (message.errors) {\n for (const err of message.errors) {\n clack.log.error(`Error: ${err}`);\n logToFile('ERROR:', err);\n }\n }\n }\n break;\n }\n\n case 'system': {\n if (message.subtype === 'init') {\n logToFile('Agent session initialized', {\n model: message.model,\n tools: message.tools?.length,\n mcpServers: message.mcp_servers,\n });\n }\n break;\n }\n\n default:\n // Log other message types for debugging\n if (options.debug) {\n debug(`Unhandled message type: ${message.type}`);\n }\n break;\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { FrameworkConfig } from './framework-config';
1
+ import { type FrameworkConfig } from './framework-config';
2
2
  import type { WizardOptions } from '../utils/types';
3
3
  /**
4
4
  * Universal agent-powered wizard runner.
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runAgentWizard = runAgentWizard;
7
+ const framework_config_1 = require("./framework-config");
7
8
  const clack_utils_1 = require("../utils/clack-utils");
8
9
  const analytics_1 = require("../utils/analytics");
9
10
  const constants_1 = require("./constants");
@@ -18,11 +19,11 @@ const steps_1 = require("../steps");
18
19
  */
19
20
  async function runAgentWizard(config, options) {
20
21
  // Setup phase
21
- (0, clack_utils_1.printWelcome)({ wizardName: config.ui.welcomeMessage });
22
+ (0, clack_utils_1.printWelcome)({ wizardName: (0, framework_config_1.getWelcomeMessage)(config.metadata.name) });
22
23
  clack_1.default.log.info(`🧙 The wizard has chosen you to try the next-generation agent integration for ${config.metadata.name}.\n\nStand by for the good stuff, and let the robot minders know how it goes:\n\nwizard@posthog.com`);
23
24
  const aiConsent = await (0, clack_utils_1.askForAIConsent)(options);
24
25
  if (!aiConsent) {
25
- await (0, clack_utils_1.abort)(config.metadata.abortMessage, 0);
26
+ await (0, clack_utils_1.abort)(`This wizard uses an LLM agent to intelligently modify your project. Please view the docs to set up ${config.metadata.name} manually instead: ${config.metadata.docsUrl}`, 0);
26
27
  }
27
28
  const cloudRegion = options.cloudRegion ?? (await (0, clack_utils_1.askForCloudRegion)());
28
29
  const typeScriptDetected = (0, clack_utils_1.isUsingTypeScript)(options);
@@ -75,7 +76,7 @@ async function runAgentWizard(config, options) {
75
76
  }, options);
76
77
  const agentResult = await (0, agent_interface_1.runAgent)(agent, integrationPrompt, options, spinner, {
77
78
  estimatedDurationMinutes: config.ui.estimatedDurationMinutes,
78
- spinnerMessage: config.ui.spinnerMessage,
79
+ spinnerMessage: framework_config_1.SPINNER_MESSAGE,
79
80
  successMessage: config.ui.successMessage,
80
81
  errorMessage: 'Integration failed',
81
82
  });
@@ -115,6 +116,28 @@ ${chalk_1.default.cyan(config.metadata.docsUrl)}`;
115
116
  await analytics_1.analytics.shutdown('error');
116
117
  process.exit(1);
117
118
  }
119
+ if (agentResult.error === agent_interface_1.AgentErrorType.RATE_LIMIT ||
120
+ agentResult.error === agent_interface_1.AgentErrorType.API_ERROR) {
121
+ analytics_1.analytics.capture(constants_1.WIZARD_INTERACTION_EVENT_NAME, {
122
+ action: 'api error',
123
+ integration: config.metadata.integration,
124
+ error_type: agentResult.error,
125
+ error_message: agentResult.message,
126
+ });
127
+ analytics_1.analytics.captureException(new Error(`API error: ${agentResult.message}`), {
128
+ integration: config.metadata.integration,
129
+ error_type: agentResult.error,
130
+ });
131
+ const errorMessage = `
132
+ ${chalk_1.default.red('❌ API Error')}
133
+
134
+ ${chalk_1.default.yellow(agentResult.message || 'Unknown error')}
135
+
136
+ Please report this error to: ${chalk_1.default.cyan('wizard@posthog.com')}`;
137
+ clack_1.default.outro(errorMessage);
138
+ await analytics_1.analytics.shutdown('error');
139
+ process.exit(1);
140
+ }
118
141
  // Build environment variables from OAuth credentials
119
142
  const envVars = config.environment.getEnvVars(projectApiKey, host);
120
143
  // Upload environment variables to hosting providers (if configured)
@@ -178,7 +201,7 @@ function buildIntegrationPrompt(config, context, frameworkContext) {
178
201
  const additionalContext = additionalLines.length > 0
179
202
  ? '\n' + additionalLines.map((line) => `- ${line}`).join('\n')
180
203
  : '';
181
- return `You have access to the PostHog MCP server which provides an integration resource to integrate PostHog into this ${config.metadata.name} project.
204
+ return `You have access to the PostHog MCP server which provides skills to integrate PostHog into this ${config.metadata.name} project.
182
205
 
183
206
  Project context:
184
207
  - Framework: ${config.metadata.name} ${context.frameworkVersion}
@@ -186,21 +209,26 @@ Project context:
186
209
  - PostHog API Key: ${context.projectApiKey}
187
210
  - PostHog Host: ${context.host}${additionalContext}
188
211
 
189
- Instructions:
212
+ Instructions (follow these steps IN ORDER - do not skip or reorder):
213
+
214
+ STEP 1: List available skills from the PostHog MCP server using ListMcpResourcesTool.
215
+ Review the skill descriptions and choose the one that best matches this project's framework and configuration.
216
+ If no suitable skill is found, or you cannot access the MCP server, emit: ${agent_interface_1.AgentSignals.ERROR_RESOURCE_MISSING} Could not find a suitable skill for this project.
190
217
 
191
- 1. Call the PostHog MCP's resource for setup: posthog://workflows/basic-integration/begin
192
- 2. Follow all instructions provided; do package installation as soon as possible.
193
- 3. Set up environment variables for PostHog in a .env file with the API key and host provided above, using the appropriate naming convention for ${config.metadata.name}. Make sure to use these environment variables in the code files you create instead of hardcoding the API key and host.
218
+ STEP 2: Fetch the chosen skill resource (e.g., posthog://skills/{skill-id}).
219
+ The resource returns a shell command to install the skill.
194
220
 
195
- The PostHog MCP will provide specific integration code and instructions. Please follow them carefully. Be sure to look for lockfiles to determine the appropriate package manager to use when installing PostHog. Do not manually edit the package.json file.
221
+ STEP 3: Run the installation command using Bash:
222
+ - Execute the EXACT command returned by the resource (do not modify it)
223
+ - This will download and extract the skill to .claude/skills/{skill-id}/
196
224
 
197
- Before beginning, confirm that you can access the PostHog MCP. If the PostHog MCP is not accessible, emit the following string:
225
+ STEP 4: Load the installed skill's SKILL.md file to understand what references are available.
198
226
 
199
- ${agent_interface_1.AgentSignals.ERROR_MCP_MISSING} Could not access the PostHog MCP.
227
+ STEP 5: Follow the skill's workflow files in sequence. Look for numbered workflow files in the references (e.g., files with patterns like "1.0-", "1.1-", "1.2-"). Start with the first one and proceed through each step until completion. Each workflow file will tell you what to do and which file comes next.
200
228
 
201
- If the PostHog MCP is accessible, attempt to access the setup resource. If the setup resource is not accessible, emit the following string:
229
+ STEP 6: Set up environment variables for PostHog in a .env file with the API key and host provided above, using the appropriate naming convention for ${config.metadata.name}. Make sure to use these environment variables in the code files you create instead of hardcoding the API key and host.
202
230
 
203
- ${agent_interface_1.AgentSignals.ERROR_RESOURCE_MISSING} Could not access the setup resource.
231
+ Important: Look for lockfiles (pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lockb) to determine the package manager. Do not manually edit package.json. Always install packages as a background task. Don't await completion; proceed with other work immediately after starting the installation.
204
232
 
205
233
  `;
206
234
  }