@posthog/wizard 2.0.2 → 2.2.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 (110) hide show
  1. package/dist/bin.js +27 -4
  2. package/dist/bin.js.map +1 -1
  3. package/dist/src/__tests__/cli.test.js +50 -3
  4. package/dist/src/__tests__/cli.test.js.map +1 -1
  5. package/dist/src/__tests__/package-json.test.d.ts +1 -0
  6. package/dist/src/__tests__/package-json.test.js +173 -0
  7. package/dist/src/__tests__/package-json.test.js.map +1 -0
  8. package/dist/src/__tests__/run.test.js +4 -2
  9. package/dist/src/__tests__/run.test.js.map +1 -1
  10. package/dist/src/lib/__tests__/agent-interface.test.js +3 -1
  11. package/dist/src/lib/__tests__/agent-interface.test.js.map +1 -1
  12. package/dist/src/lib/__tests__/yara-hooks.test.d.ts +1 -0
  13. package/dist/src/lib/__tests__/yara-hooks.test.js +432 -0
  14. package/dist/src/lib/__tests__/yara-hooks.test.js.map +1 -0
  15. package/dist/src/lib/__tests__/yara-scanner.test.d.ts +1 -0
  16. package/dist/src/lib/__tests__/yara-scanner.test.js +613 -0
  17. package/dist/src/lib/__tests__/yara-scanner.test.js.map +1 -0
  18. package/dist/src/lib/agent-interface.d.ts +6 -3
  19. package/dist/src/lib/agent-interface.js +70 -34
  20. package/dist/src/lib/agent-interface.js.map +1 -1
  21. package/dist/src/lib/agent-runner.js +60 -23
  22. package/dist/src/lib/agent-runner.js.map +1 -1
  23. package/dist/src/lib/commandments.js +3 -1
  24. package/dist/src/lib/commandments.js.map +1 -1
  25. package/dist/src/lib/constants.d.ts +4 -3
  26. package/dist/src/lib/constants.js +3 -2
  27. package/dist/src/lib/constants.js.map +1 -1
  28. package/dist/src/lib/health-checks/readiness.d.ts +5 -0
  29. package/dist/src/lib/health-checks/readiness.js +79 -19
  30. package/dist/src/lib/health-checks/readiness.js.map +1 -1
  31. package/dist/src/lib/skill-install.d.ts +10 -0
  32. package/dist/src/lib/skill-install.js +23 -0
  33. package/dist/src/lib/skill-install.js.map +1 -0
  34. package/dist/src/lib/version.d.ts +1 -1
  35. package/dist/src/lib/version.js +1 -1
  36. package/dist/src/lib/version.js.map +1 -1
  37. package/dist/src/lib/wizard-session.d.ts +5 -4
  38. package/dist/src/lib/wizard-session.js +3 -1
  39. package/dist/src/lib/wizard-session.js.map +1 -1
  40. package/dist/src/lib/wizard-tools.d.ts +2 -0
  41. package/dist/src/lib/wizard-tools.js +119 -2
  42. package/dist/src/lib/wizard-tools.js.map +1 -1
  43. package/dist/src/lib/yara-hooks.d.ts +44 -0
  44. package/dist/src/lib/yara-hooks.js +377 -0
  45. package/dist/src/lib/yara-hooks.js.map +1 -0
  46. package/dist/src/lib/yara-scanner.d.ts +61 -0
  47. package/dist/src/lib/yara-scanner.js +328 -0
  48. package/dist/src/lib/yara-scanner.js.map +1 -0
  49. package/dist/src/run.d.ts +3 -0
  50. package/dist/src/run.js +10 -0
  51. package/dist/src/run.js.map +1 -1
  52. package/dist/src/steps/add-mcp-server-to-clients/index.d.ts +2 -1
  53. package/dist/src/steps/add-mcp-server-to-clients/index.js +1 -1
  54. package/dist/src/steps/add-mcp-server-to-clients/index.js.map +1 -1
  55. package/dist/src/ui/logging-ui.d.ts +2 -4
  56. package/dist/src/ui/logging-ui.js +12 -4
  57. package/dist/src/ui/logging-ui.js.map +1 -1
  58. package/dist/src/ui/tui/__tests__/store.test.js +81 -29
  59. package/dist/src/ui/tui/__tests__/store.test.js.map +1 -1
  60. package/dist/src/ui/tui/components/ServiceHealthList.d.ts +15 -0
  61. package/dist/src/ui/tui/components/ServiceHealthList.js +57 -0
  62. package/dist/src/ui/tui/components/ServiceHealthList.js.map +1 -0
  63. package/dist/src/ui/tui/flows.d.ts +1 -0
  64. package/dist/src/ui/tui/flows.js +12 -0
  65. package/dist/src/ui/tui/flows.js.map +1 -1
  66. package/dist/src/ui/tui/ink-ui.d.ts +2 -4
  67. package/dist/src/ui/tui/ink-ui.js +8 -4
  68. package/dist/src/ui/tui/ink-ui.js.map +1 -1
  69. package/dist/src/ui/tui/playground/PlaygroundApp.js +12 -0
  70. package/dist/src/ui/tui/playground/PlaygroundApp.js.map +1 -1
  71. package/dist/src/ui/tui/playground/demos/HealthCheckDemo.d.ts +11 -0
  72. package/dist/src/ui/tui/playground/demos/HealthCheckDemo.js +56 -0
  73. package/dist/src/ui/tui/playground/demos/HealthCheckDemo.js.map +1 -0
  74. package/dist/src/ui/tui/playground/demos/ModalDemo.d.ts +6 -0
  75. package/dist/src/ui/tui/playground/demos/ModalDemo.js +13 -0
  76. package/dist/src/ui/tui/playground/demos/ModalDemo.js.map +1 -0
  77. package/dist/src/ui/tui/primitives/ModalOverlay.d.ts +25 -0
  78. package/dist/src/ui/tui/primitives/ModalOverlay.js +7 -0
  79. package/dist/src/ui/tui/primitives/ModalOverlay.js.map +1 -0
  80. package/dist/src/ui/tui/primitives/ProgressList.js +3 -1
  81. package/dist/src/ui/tui/primitives/ProgressList.js.map +1 -1
  82. package/dist/src/ui/tui/primitives/index.d.ts +1 -0
  83. package/dist/src/ui/tui/primitives/index.js +1 -0
  84. package/dist/src/ui/tui/primitives/index.js.map +1 -1
  85. package/dist/src/ui/tui/router.d.ts +0 -1
  86. package/dist/src/ui/tui/router.js +0 -1
  87. package/dist/src/ui/tui/router.js.map +1 -1
  88. package/dist/src/ui/tui/screen-registry.js +2 -2
  89. package/dist/src/ui/tui/screen-registry.js.map +1 -1
  90. package/dist/src/ui/tui/screens/PortConflictScreen.js +13 -13
  91. package/dist/src/ui/tui/screens/PortConflictScreen.js.map +1 -1
  92. package/dist/src/ui/tui/screens/SettingsOverrideScreen.js +8 -8
  93. package/dist/src/ui/tui/screens/SettingsOverrideScreen.js.map +1 -1
  94. package/dist/src/ui/tui/screens/health/HealthCheckScreen.d.ts +14 -0
  95. package/dist/src/ui/tui/screens/health/HealthCheckScreen.js +32 -0
  96. package/dist/src/ui/tui/screens/health/HealthCheckScreen.js.map +1 -0
  97. package/dist/src/ui/tui/store.d.ts +15 -5
  98. package/dist/src/ui/tui/store.js +47 -3
  99. package/dist/src/ui/tui/store.js.map +1 -1
  100. package/dist/src/ui/wizard-ui.d.ts +4 -5
  101. package/dist/src/ui/wizard-ui.js.map +1 -1
  102. package/dist/src/utils/__tests__/setup-utils.test.js +2 -1
  103. package/dist/src/utils/__tests__/setup-utils.test.js.map +1 -1
  104. package/dist/src/utils/rules/universal.md +12 -0
  105. package/dist/src/utils/types.d.ts +9 -0
  106. package/dist/src/utils/types.js.map +1 -1
  107. package/package.json +2 -2
  108. package/dist/src/ui/tui/screens/OutageScreen.d.ts +0 -10
  109. package/dist/src/ui/tui/screens/OutageScreen.js +0 -17
  110. package/dist/src/ui/tui/screens/OutageScreen.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"commandments.js","sourceRoot":"","sources":["../../../src/lib/commandments.ts"],"names":[],"mappings":";;AA0BA,sDAEC;AA5BD;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG;IAC1B,gLAAgL;IAEhL,4OAA4O;IAE5O,4LAA4L;IAE5L,oLAAoL;IAEpL,uMAAuM;IAEvM,gVAAgV;IAEhV,gNAAgN;IAEhN,+DAA+D;IAE/D,8LAA8L;CAC/L,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,SAAgB,qBAAqB;IACnC,OAAO,mBAAmB,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * Wizard-wide commandments that are always appended as a system prompt.\n *\n * Keep this as a simple string so it can be inlined into the compiled bundle\n * without extra files, copying, or runtime I/O.\n */\nconst WIZARD_COMMANDMENTS = [\n 'Never hallucinate a PostHog API key, host, or any other secret. Always use the real values that have been configured for this project (for example via environment variables).',\n\n 'Never write API keys, access tokens, or other secrets directly into source code. Always reference environment variables instead, and rely on the wizard-tools MCP server (check_env_keys / set_env_values) to create or update .env files.',\n\n 'Always use the detect_package_manager tool from the wizard-tools MCP server to determine the package manager. Do not guess based on lockfiles or hard-code npm, yarn, pnpm, bun, pip, etc.',\n\n 'When installing packages, start the installation as a background task and then continue with other work. Do not block waiting for installs to finish unless explicitly instructed.',\n\n 'Before writing to any file, you MUST read that exact file immediately beforehand using the Read tool, even if you have already read it earlier in the run. This avoids tool failures and stale edits.',\n\n 'Treat feature flags, custom properties, and event names as part of an analytics contract. Prefer reusing existing names and patterns in the project. When you must introduce new ones, make them clear, descriptive, and consistent with existing conventions, and avoid scattering the same flag or property across many unrelated callsites.',\n\n 'Prefer minimal, targeted edits that achieve the requested behavior while preserving existing structure and style. Avoid large refactors, broad reformatting, or unrelated changes unless explicitly requested.',\n\n 'Do not spawn subagents unless explicitly instructed to do so.',\n\n 'Use the TodoWrite tool to track your progress. Create a todo list at the start describing the high-level areas of work, mark each as in_progress when you begin it, and completed when done.',\n].join('\\n');\n\nexport function getWizardCommandments(): string {\n return WIZARD_COMMANDMENTS;\n}\n"]}
1
+ {"version":3,"file":"commandments.js","sourceRoot":"","sources":["../../../src/lib/commandments.ts"],"names":[],"mappings":";;AA8BA,sDAEC;AAhCD;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG;IAC1B,gLAAgL;IAEhL,4OAA4O;IAE5O,4LAA4L;IAE5L,oLAAoL;IAEpL,uMAAuM;IAEvM,gVAAgV;IAEhV,gNAAgN;IAEhN,+DAA+D;IAE/D,qfAAqf;IAErf,+LAA+L;IAE/L,2SAA2S;CAC5S,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,SAAgB,qBAAqB;IACnC,OAAO,mBAAmB,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * Wizard-wide commandments that are always appended as a system prompt.\n *\n * Keep this as a simple string so it can be inlined into the compiled bundle\n * without extra files, copying, or runtime I/O.\n */\nconst WIZARD_COMMANDMENTS = [\n 'Never hallucinate a PostHog API key, host, or any other secret. Always use the real values that have been configured for this project (for example via environment variables).',\n\n 'Never write API keys, access tokens, or other secrets directly into source code. Always reference environment variables instead, and rely on the wizard-tools MCP server (check_env_keys / set_env_values) to create or update .env files.',\n\n 'Always use the detect_package_manager tool from the wizard-tools MCP server to determine the package manager. Do not guess based on lockfiles or hard-code npm, yarn, pnpm, bun, pip, etc.',\n\n 'When installing packages, start the installation as a background task and then continue with other work. Do not block waiting for installs to finish unless explicitly instructed.',\n\n 'Before writing to any file, you MUST read that exact file immediately beforehand using the Read tool, even if you have already read it earlier in the run. This avoids tool failures and stale edits.',\n\n 'Treat feature flags, custom properties, and event names as part of an analytics contract. Prefer reusing existing names and patterns in the project. When you must introduce new ones, make them clear, descriptive, and consistent with existing conventions, and avoid scattering the same flag or property across many unrelated callsites.',\n\n 'Prefer minimal, targeted edits that achieve the requested behavior while preserving existing structure and style. Avoid large refactors, broad reformatting, or unrelated changes unless explicitly requested.',\n\n 'Do not spawn subagents unless explicitly instructed to do so.',\n\n 'After reading the integration skill, use the TodoWrite tool to track your progress. Create a todo list at the describing the high-level areas of work, mark each as in_progress when you begin it, and completed when done. Describe high-level tasks from the workflow (\"inserting event tracking code\", etc), not specific files or lines. For each new stage of the integration, create additional todos if necessary. Create a final \"wrapping up\" step and mark it completed when the integration is complete.',\n\n 'Do not assume \"PostHog provider\" or \"PostHogProvider\" in todo labels, status messages, or code. Only use a provider if the skill workflow explicitly requires one for the specific framework.',\n\n 'If you see a [YARA WARNING] or [YARA VIOLATION] message, handle it silently. Fix the issue (revert the write, avoid the flagged pattern) without mentioning security warnings or YARA to the user. These are internal guardrails, not user-facing alerts. Never show scary security language to the user.',\n].join('\\n');\n\nexport function getWizardCommandments(): string {\n return WIZARD_COMMANDMENTS;\n}\n"]}
@@ -22,10 +22,10 @@ export declare enum Integration {
22
22
  swift = "swift",
23
23
  android = "android",
24
24
  rails = "rails",
25
- javascript_web = "javascript_web",
26
25
  python = "python",
27
26
  ruby = "ruby",
28
- javascriptNode = "javascript_node"
27
+ javascriptNode = "javascript_node",
28
+ javascript_web = "javascript_web"
29
29
  }
30
30
  export interface Args {
31
31
  debug: boolean;
@@ -46,13 +46,14 @@ export declare const POSTHOG_EU_CLIENT_ID = "bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRL
46
46
  export declare const POSTHOG_DEV_CLIENT_ID = "DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ";
47
47
  export declare const POSTHOG_PROXY_CLIENT_ID = "c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM";
48
48
  export declare const DUMMY_PROJECT_API_KEY = "_YOUR_POSTHOG_PROJECT_API_KEY_";
49
+ export declare const WIZARD_INTERACTION_EVENT_NAME = "wizard interaction";
49
50
  export declare const WIZARD_REMARK_EVENT_NAME = "wizard remark";
50
51
  /** Feature flag key whose value selects a variant from WIZARD_VARIANTS. */
51
52
  export declare const WIZARD_VARIANT_FLAG_KEY = "wizard-variant";
52
53
  /** Variant key -> metadata for wizard run (VARIANT flag selects which entry to use). */
53
54
  export declare const WIZARD_VARIANTS: Record<string, Record<string, string>>;
54
55
  /** User-Agent for wizard HTTP requests and MCP server identification. */
55
- export declare const WIZARD_USER_AGENT = "posthog/wizard; version: 2.0.2";
56
+ export declare const WIZARD_USER_AGENT = "posthog/wizard; version: 2.2.0";
56
57
  /** Header prefix for PostHog properties (e.g. X-POSTHOG-PROPERTY-VARIANT). */
57
58
  export declare const POSTHOG_PROPERTY_HEADER_PREFIX = "X-POSTHOG-PROPERTY-";
58
59
  /** Header prefix for PostHog feature flags. */
@@ -3,7 +3,7 @@
3
3
  * Shared constants for the PostHog wizard.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DETECTION_TIMEOUT_MS = exports.POSTHOG_FLAG_HEADER_PREFIX = exports.POSTHOG_PROPERTY_HEADER_PREFIX = exports.WIZARD_USER_AGENT = exports.WIZARD_VARIANTS = exports.WIZARD_VARIANT_FLAG_KEY = exports.WIZARD_REMARK_EVENT_NAME = exports.DUMMY_PROJECT_API_KEY = exports.POSTHOG_PROXY_CLIENT_ID = exports.POSTHOG_DEV_CLIENT_ID = exports.POSTHOG_EU_CLIENT_ID = exports.POSTHOG_US_CLIENT_ID = exports.OAUTH_PORT = exports.POSTHOG_OAUTH_URL = exports.ANALYTICS_TEAM_TAG = exports.ANALYTICS_HOST_URL = exports.ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = exports.ISSUES_URL = exports.DEFAULT_HOST_URL = exports.DEFAULT_URL = exports.DEBUG = exports.IS_DEV = exports.Integration = void 0;
6
+ exports.DETECTION_TIMEOUT_MS = exports.POSTHOG_FLAG_HEADER_PREFIX = exports.POSTHOG_PROPERTY_HEADER_PREFIX = exports.WIZARD_USER_AGENT = exports.WIZARD_VARIANTS = exports.WIZARD_VARIANT_FLAG_KEY = exports.WIZARD_REMARK_EVENT_NAME = exports.WIZARD_INTERACTION_EVENT_NAME = exports.DUMMY_PROJECT_API_KEY = exports.POSTHOG_PROXY_CLIENT_ID = exports.POSTHOG_DEV_CLIENT_ID = exports.POSTHOG_EU_CLIENT_ID = exports.POSTHOG_US_CLIENT_ID = exports.OAUTH_PORT = exports.POSTHOG_OAUTH_URL = exports.ANALYTICS_TEAM_TAG = exports.ANALYTICS_HOST_URL = exports.ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = exports.ISSUES_URL = exports.DEFAULT_HOST_URL = exports.DEFAULT_URL = exports.DEBUG = exports.IS_DEV = exports.Integration = void 0;
7
7
  const version_1 = require("./version");
8
8
  // ── Integration / CLI ───────────────────────────────────────────────
9
9
  /**
@@ -30,10 +30,10 @@ var Integration;
30
30
  Integration["android"] = "android";
31
31
  Integration["rails"] = "rails";
32
32
  // Language fallbacks
33
- Integration["javascript_web"] = "javascript_web";
34
33
  Integration["python"] = "python";
35
34
  Integration["ruby"] = "ruby";
36
35
  Integration["javascriptNode"] = "javascript_node";
36
+ Integration["javascript_web"] = "javascript_web";
37
37
  })(Integration || (exports.Integration = Integration = {}));
38
38
  // ── Environment ──────────────────────────────────────────────────────
39
39
  exports.IS_DEV = ['test', 'development'].includes(process.env.NODE_ENV ?? '');
@@ -61,6 +61,7 @@ exports.POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';
61
61
  exports.POSTHOG_PROXY_CLIENT_ID = exports.POSTHOG_US_CLIENT_ID;
62
62
  exports.DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';
63
63
  // ── Wizard run / variants ───────────────────────────────────────────
64
+ exports.WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';
64
65
  exports.WIZARD_REMARK_EVENT_NAME = 'wizard remark';
65
66
  /** Feature flag key whose value selects a variant from WIZARD_VARIANTS. */
66
67
  exports.WIZARD_VARIANT_FLAG_KEY = 'wizard-variant';
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAoC;AAEpC,uEAAuE;AAEvE;;GAEG;AACH,IAAY,WAyBX;AAzBD,WAAY,WAAW;IACrB,aAAa;IACb,gCAAiB,CAAA;IACjB,4BAAa,CAAA;IACb,0BAAW,CAAA;IACX,2CAA4B,CAAA;IAC5B,+CAAgC,CAAA;IAChC,iDAAkC,CAAA;IAClC,2CAA4B,CAAA;IAC5B,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IACf,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,kCAAmB,CAAA;IACnB,sCAAuB,CAAA;IACvB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IAEf,qBAAqB;IACrB,gDAAiC,CAAA;IACjC,gCAAiB,CAAA;IACjB,4BAAa,CAAA;IACb,iDAAkC,CAAA;AACpC,CAAC,EAzBW,WAAW,2BAAX,WAAW,QAyBtB;AAOD,wEAAwE;AAE3D,QAAA,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAC3B,CAAC;AACW,QAAA,KAAK,GAAG,KAAK,CAAC;AAE3B,wEAAwE;AAE3D,QAAA,WAAW,GAAG,cAAM;IAC/B,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,wBAAwB,CAAC;AAChB,QAAA,gBAAgB,GAAG,cAAM;IACpC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,0BAA0B,CAAC;AAClB,QAAA,UAAU,GAAG,0CAA0C,CAAC;AAErE,yEAAyE;AAE5D,QAAA,0CAA0C,GAAG,gBAAgB,CAAC;AAC9D,QAAA,kBAAkB,GAAG,gCAAgC,CAAC;AACtD,QAAA,kBAAkB,GAAG,iBAAiB,CAAC;AAEpD,uEAAuE;AAE1D,QAAA,iBAAiB,GAAG,cAAM;IACrC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,2BAA2B,CAAC;AACnB,QAAA,UAAU,GAAG,IAAI,CAAC;AAClB,QAAA,oBAAoB,GAAG,0CAA0C,CAAC;AAClE,QAAA,oBAAoB,GAAG,0CAA0C,CAAC;AAClE,QAAA,qBAAqB,GAAG,0CAA0C,CAAC;AACnE,QAAA,uBAAuB,GAAG,4BAAoB,CAAC;AAC/C,QAAA,qBAAqB,GAAG,gCAAgC,CAAC;AAEtE,uEAAuE;AAE1D,QAAA,wBAAwB,GAAG,eAAe,CAAC;AACxD,2EAA2E;AAC9D,QAAA,uBAAuB,GAAG,gBAAgB,CAAC;AACxD,wFAAwF;AAC3E,QAAA,eAAe,GAA2C;IACrE,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;IACzB,SAAS,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE;CACpC,CAAC;AACF,yEAAyE;AAC5D,QAAA,iBAAiB,GAAG,4BAA4B,iBAAO,EAAE,CAAC;AAEvE,wEAAwE;AAExE,8EAA8E;AACjE,QAAA,8BAA8B,GAAG,qBAAqB,CAAC;AACpE,+CAA+C;AAClC,QAAA,0BAA0B,GAAG,iBAAiB,CAAC;AAE5D,wEAAwE;AAExE,6DAA6D;AAChD,QAAA,oBAAoB,GAAG,MAAM,CAAC","sourcesContent":["/**\n * Shared constants for the PostHog wizard.\n */\n\nimport { VERSION } from './version';\n\n// ── Integration / CLI ───────────────────────────────────────────────\n\n/**\n * Detection order matters: put framework-specific integrations BEFORE basic language fallbacks.\n */\nexport enum Integration {\n // Frameworks\n nextjs = 'nextjs',\n nuxt = 'nuxt',\n vue = 'vue',\n reactRouter = 'react-router',\n tanstackStart = 'tanstack-start',\n tanstackRouter = 'tanstack-router',\n reactNative = 'react-native',\n angular = 'angular',\n astro = 'astro',\n django = 'django',\n flask = 'flask',\n fastapi = 'fastapi',\n laravel = 'laravel',\n sveltekit = 'sveltekit',\n swift = 'swift',\n android = 'android',\n rails = 'rails',\n\n // Language fallbacks\n javascript_web = 'javascript_web',\n python = 'python',\n ruby = 'ruby',\n javascriptNode = 'javascript_node',\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\n// ── Environment ──────────────────────────────────────────────────────\n\nexport const IS_DEV = ['test', 'development'].includes(\n process.env.NODE_ENV ?? '',\n);\nexport const DEBUG = false;\n\n// ── URLs ─────────────────────────────────────────────────────────────\n\nexport const DEFAULT_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.posthog.com';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.i.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\n\n// ── Analytics (internal) ──────────────────────────────────────────────\n\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';\nexport const ANALYTICS_TEAM_TAG = 'docs-and-wizard';\n\n// ── OAuth / Auth ────────────────────────────────────────────────────\n\nexport const POSTHOG_OAUTH_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://oauth.posthog.com';\nexport const OAUTH_PORT = 8239;\nexport const POSTHOG_US_CLIENT_ID = 'c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM';\nexport const POSTHOG_EU_CLIENT_ID = 'bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy';\nexport const POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';\nexport const POSTHOG_PROXY_CLIENT_ID = POSTHOG_US_CLIENT_ID;\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';\n\n// ── Wizard run / variants ───────────────────────────────────────────\n\nexport const WIZARD_REMARK_EVENT_NAME = 'wizard remark';\n/** Feature flag key whose value selects a variant from WIZARD_VARIANTS. */\nexport const WIZARD_VARIANT_FLAG_KEY = 'wizard-variant';\n/** Variant key -> metadata for wizard run (VARIANT flag selects which entry to use). */\nexport const WIZARD_VARIANTS: Record<string, Record<string, string>> = {\n base: { VARIANT: 'base' },\n subagents: { VARIANT: 'subagents' },\n};\n/** User-Agent for wizard HTTP requests and MCP server identification. */\nexport const WIZARD_USER_AGENT = `posthog/wizard; version: ${VERSION}`;\n\n// ── HTTP headers ─────────────────────────────────────────────────────\n\n/** Header prefix for PostHog properties (e.g. X-POSTHOG-PROPERTY-VARIANT). */\nexport const POSTHOG_PROPERTY_HEADER_PREFIX = 'X-POSTHOG-PROPERTY-';\n/** Header prefix for PostHog feature flags. */\nexport const POSTHOG_FLAG_HEADER_PREFIX = 'X-POSTHOG-FLAG-';\n\n// ── Timeouts ─────────────────────────────────────────────────────────\n\n/** Timeout for framework / project detection probes (ms). */\nexport const DETECTION_TIMEOUT_MS = 10_000;\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAoC;AAEpC,uEAAuE;AAEvE;;GAEG;AACH,IAAY,WAyBX;AAzBD,WAAY,WAAW;IACrB,aAAa;IACb,gCAAiB,CAAA;IACjB,4BAAa,CAAA;IACb,0BAAW,CAAA;IACX,2CAA4B,CAAA;IAC5B,+CAAgC,CAAA;IAChC,iDAAkC,CAAA;IAClC,2CAA4B,CAAA;IAC5B,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IACf,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,kCAAmB,CAAA;IACnB,sCAAuB,CAAA;IACvB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IAEf,qBAAqB;IACrB,gCAAiB,CAAA;IACjB,4BAAa,CAAA;IACb,iDAAkC,CAAA;IAClC,gDAAiC,CAAA;AACnC,CAAC,EAzBW,WAAW,2BAAX,WAAW,QAyBtB;AAOD,wEAAwE;AAE3D,QAAA,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAC3B,CAAC;AACW,QAAA,KAAK,GAAG,KAAK,CAAC;AAE3B,wEAAwE;AAE3D,QAAA,WAAW,GAAG,cAAM;IAC/B,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,wBAAwB,CAAC;AAChB,QAAA,gBAAgB,GAAG,cAAM;IACpC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,0BAA0B,CAAC;AAClB,QAAA,UAAU,GAAG,0CAA0C,CAAC;AAErE,yEAAyE;AAE5D,QAAA,0CAA0C,GAAG,gBAAgB,CAAC;AAC9D,QAAA,kBAAkB,GAAG,gCAAgC,CAAC;AACtD,QAAA,kBAAkB,GAAG,iBAAiB,CAAC;AAEpD,uEAAuE;AAE1D,QAAA,iBAAiB,GAAG,cAAM;IACrC,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,2BAA2B,CAAC;AACnB,QAAA,UAAU,GAAG,IAAI,CAAC;AAClB,QAAA,oBAAoB,GAAG,0CAA0C,CAAC;AAClE,QAAA,oBAAoB,GAAG,0CAA0C,CAAC;AAClE,QAAA,qBAAqB,GAAG,0CAA0C,CAAC;AACnE,QAAA,uBAAuB,GAAG,4BAAoB,CAAC;AAC/C,QAAA,qBAAqB,GAAG,gCAAgC,CAAC;AAEtE,uEAAuE;AAE1D,QAAA,6BAA6B,GAAG,oBAAoB,CAAC;AACrD,QAAA,wBAAwB,GAAG,eAAe,CAAC;AACxD,2EAA2E;AAC9D,QAAA,uBAAuB,GAAG,gBAAgB,CAAC;AACxD,wFAAwF;AAC3E,QAAA,eAAe,GAA2C;IACrE,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;IACzB,SAAS,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE;CACpC,CAAC;AACF,yEAAyE;AAC5D,QAAA,iBAAiB,GAAG,4BAA4B,iBAAO,EAAE,CAAC;AAEvE,wEAAwE;AAExE,8EAA8E;AACjE,QAAA,8BAA8B,GAAG,qBAAqB,CAAC;AACpE,+CAA+C;AAClC,QAAA,0BAA0B,GAAG,iBAAiB,CAAC;AAE5D,wEAAwE;AAExE,6DAA6D;AAChD,QAAA,oBAAoB,GAAG,MAAM,CAAC","sourcesContent":["/**\n * Shared constants for the PostHog wizard.\n */\n\nimport { VERSION } from './version';\n\n// ── Integration / CLI ───────────────────────────────────────────────\n\n/**\n * Detection order matters: put framework-specific integrations BEFORE basic language fallbacks.\n */\nexport enum Integration {\n // Frameworks\n nextjs = 'nextjs',\n nuxt = 'nuxt',\n vue = 'vue',\n reactRouter = 'react-router',\n tanstackStart = 'tanstack-start',\n tanstackRouter = 'tanstack-router',\n reactNative = 'react-native',\n angular = 'angular',\n astro = 'astro',\n django = 'django',\n flask = 'flask',\n fastapi = 'fastapi',\n laravel = 'laravel',\n sveltekit = 'sveltekit',\n swift = 'swift',\n android = 'android',\n rails = 'rails',\n\n // Language fallbacks\n python = 'python',\n ruby = 'ruby',\n javascriptNode = 'javascript_node',\n javascript_web = 'javascript_web',\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\n// ── Environment ──────────────────────────────────────────────────────\n\nexport const IS_DEV = ['test', 'development'].includes(\n process.env.NODE_ENV ?? '',\n);\nexport const DEBUG = false;\n\n// ── URLs ─────────────────────────────────────────────────────────────\n\nexport const DEFAULT_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.posthog.com';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.i.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\n\n// ── Analytics (internal) ──────────────────────────────────────────────\n\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';\nexport const ANALYTICS_TEAM_TAG = 'docs-and-wizard';\n\n// ── OAuth / Auth ────────────────────────────────────────────────────\n\nexport const POSTHOG_OAUTH_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://oauth.posthog.com';\nexport const OAUTH_PORT = 8239;\nexport const POSTHOG_US_CLIENT_ID = 'c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM';\nexport const POSTHOG_EU_CLIENT_ID = 'bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy';\nexport const POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';\nexport const POSTHOG_PROXY_CLIENT_ID = POSTHOG_US_CLIENT_ID;\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_API_KEY_';\n\n// ── Wizard run / variants ───────────────────────────────────────────\n\nexport const WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';\nexport const WIZARD_REMARK_EVENT_NAME = 'wizard remark';\n/** Feature flag key whose value selects a variant from WIZARD_VARIANTS. */\nexport const WIZARD_VARIANT_FLAG_KEY = 'wizard-variant';\n/** Variant key -> metadata for wizard run (VARIANT flag selects which entry to use). */\nexport const WIZARD_VARIANTS: Record<string, Record<string, string>> = {\n base: { VARIANT: 'base' },\n subagents: { VARIANT: 'subagents' },\n};\n/** User-Agent for wizard HTTP requests and MCP server identification. */\nexport const WIZARD_USER_AGENT = `posthog/wizard; version: ${VERSION}`;\n\n// ── HTTP headers ─────────────────────────────────────────────────────\n\n/** Header prefix for PostHog properties (e.g. X-POSTHOG-PROPERTY-VARIANT). */\nexport const POSTHOG_PROPERTY_HEADER_PREFIX = 'X-POSTHOG-PROPERTY-';\n/** Header prefix for PostHog feature flags. */\nexport const POSTHOG_FLAG_HEADER_PREFIX = 'X-POSTHOG-FLAG-';\n\n// ── Timeouts ─────────────────────────────────────────────────────────\n\n/** Timeout for framework / project detection probes (ms). */\nexport const DETECTION_TIMEOUT_MS = 10_000;\n"]}
@@ -1,4 +1,5 @@
1
1
  import { type AllServicesHealth, type HealthCheckKey } from './types';
2
+ export declare const SERVICE_LABELS: Record<HealthCheckKey, string>;
2
3
  export interface WizardReadinessConfig {
3
4
  /** Services where status=Down blocks the run (readiness=No). */
4
5
  downBlocksRun: HealthCheckKey[];
@@ -22,3 +23,7 @@ export interface WizardReadinessResult {
22
23
  reasons: string[];
23
24
  }
24
25
  export declare function evaluateWizardReadiness(config?: WizardReadinessConfig): Promise<WizardReadinessResult>;
26
+ /**
27
+ * Get the keys of services that would block a wizard run per the given config.
28
+ */
29
+ export declare function getBlockingServiceKeys(health: AllServicesHealth, config?: WizardReadinessConfig): HealthCheckKey[];
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WizardReadiness = exports.DEFAULT_WIZARD_READINESS_CONFIG = void 0;
3
+ exports.WizardReadiness = exports.DEFAULT_WIZARD_READINESS_CONFIG = exports.SERVICE_LABELS = void 0;
4
4
  exports.checkAllExternalServices = checkAllExternalServices;
5
5
  exports.evaluateWizardReadiness = evaluateWizardReadiness;
6
+ exports.getBlockingServiceKeys = getBlockingServiceKeys;
6
7
  const types_1 = require("./types");
7
8
  const statuspage_1 = require("./statuspage");
8
9
  const endpoints_1 = require("./endpoints");
9
10
  // ---------------------------------------------------------------------------
10
11
  // Service labels (used in human-readable reason strings)
11
12
  // ---------------------------------------------------------------------------
12
- const SERVICE_LABELS = {
13
+ exports.SERVICE_LABELS = {
13
14
  anthropic: 'Anthropic',
14
15
  posthogOverall: 'PostHog',
15
16
  posthogComponents: 'PostHog (components)',
@@ -94,26 +95,85 @@ function describeComponents(label, h) {
94
95
  : '';
95
96
  return `${label} components impacted: ${shown.join(', ')}${suffix}`;
96
97
  }
98
+ const READINESS_TIMEOUT_MS = 10_000;
97
99
  async function evaluateWizardReadiness(config = exports.DEFAULT_WIZARD_READINESS_CONFIG) {
98
- const health = await checkAllExternalServices();
99
- const reasons = [];
100
- for (const key of Object.keys(health)) {
101
- const result = health[key];
102
- const label = SERVICE_LABELS[key];
103
- reasons.push(describeResult(label, result));
104
- if ('degradedOrDownComponents' in result) {
105
- reasons.push(describeComponents(label, result));
100
+ try {
101
+ const health = await Promise.race([
102
+ checkAllExternalServices(),
103
+ new Promise((resolve) => setTimeout(() => resolve(allUnknown('Health check timed out')), READINESS_TIMEOUT_MS)),
104
+ ]);
105
+ const reasons = [];
106
+ for (const key of Object.keys(health)) {
107
+ const result = health[key];
108
+ const label = exports.SERVICE_LABELS[key];
109
+ reasons.push(describeResult(label, result));
110
+ if ('degradedOrDownComponents' in result) {
111
+ reasons.push(describeComponents(label, result));
112
+ }
106
113
  }
114
+ if (getBlockingServiceKeys(health, config).length > 0) {
115
+ return { decision: WizardReadiness.No, health, reasons };
116
+ }
117
+ const hasWarnings = Object.values(health).some((h) => h.status !== types_1.ServiceHealthStatus.Healthy);
118
+ if (hasWarnings) {
119
+ return { decision: WizardReadiness.YesWithWarnings, health, reasons };
120
+ }
121
+ return { decision: WizardReadiness.Yes, health, reasons };
107
122
  }
108
- const blocked = config.downBlocksRun.some((k) => health[k].status === types_1.ServiceHealthStatus.Down) ||
109
- (config.degradedBlocksRun ?? []).some((k) => health[k].status !== types_1.ServiceHealthStatus.Healthy);
110
- if (blocked) {
111
- return { decision: WizardReadiness.No, health, reasons };
112
- }
113
- const hasWarnings = Object.values(health).some((h) => h.status !== types_1.ServiceHealthStatus.Healthy);
114
- if (hasWarnings) {
115
- return { decision: WizardReadiness.YesWithWarnings, health, reasons };
123
+ catch {
124
+ // Health checks must never block the wizard run
125
+ return {
126
+ decision: WizardReadiness.Yes,
127
+ health: allUnknown('Unexpected error'),
128
+ reasons: ['Health check failed unexpectedly proceeding anyway'],
129
+ };
116
130
  }
117
- return { decision: WizardReadiness.Yes, health, reasons };
131
+ }
132
+ // ---------------------------------------------------------------------------
133
+ // Blocking service detection
134
+ // ---------------------------------------------------------------------------
135
+ /** Keys that are component-level detail, not top-level services. */
136
+ const COMPONENT_KEYS = [
137
+ 'posthogComponents',
138
+ 'npmComponents',
139
+ 'cloudflareComponents',
140
+ ];
141
+ /**
142
+ * Get the keys of services that would block a wizard run per the given config.
143
+ */
144
+ function getBlockingServiceKeys(health, config = exports.DEFAULT_WIZARD_READINESS_CONFIG) {
145
+ return Object.keys(health).filter((key) => {
146
+ if (COMPONENT_KEYS.includes(key))
147
+ return false;
148
+ const result = health[key];
149
+ if (config.downBlocksRun.includes(key) &&
150
+ result.status === types_1.ServiceHealthStatus.Down) {
151
+ return true;
152
+ }
153
+ if ((config.degradedBlocksRun ?? []).includes(key) &&
154
+ result.status !== types_1.ServiceHealthStatus.Healthy) {
155
+ return true;
156
+ }
157
+ return false;
158
+ });
159
+ }
160
+ /** Build an AllServicesHealth where every service is Degraded with the given error. */
161
+ function allUnknown(error) {
162
+ const base = {
163
+ status: types_1.ServiceHealthStatus.Degraded,
164
+ error,
165
+ };
166
+ return {
167
+ anthropic: base,
168
+ posthogOverall: base,
169
+ posthogComponents: { ...base },
170
+ github: base,
171
+ npmOverall: base,
172
+ npmComponents: { ...base },
173
+ cloudflareOverall: base,
174
+ cloudflareComponents: { ...base },
175
+ llmGateway: base,
176
+ mcp: base,
177
+ };
118
178
  }
119
179
  //# sourceMappingURL=readiness.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../../../src/lib/health-checks/readiness.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ServiceHealthStatus,\n type AllServicesHealth,\n type BaseHealthResult,\n type ComponentHealthResult,\n type HealthCheckKey,\n} from './types';\nimport {\n checkAnthropicHealth,\n checkPosthogOverallHealth,\n checkPosthogComponentHealth,\n checkGithubHealth,\n checkNpmOverallHealth,\n checkNpmComponentHealth,\n checkCloudflareOverallHealth,\n checkCloudflareComponentHealth,\n} from './statuspage';\nimport { checkLlmGatewayHealth, checkMcpHealth } from './endpoints';\n\n// ---------------------------------------------------------------------------\n// Service labels (used in human-readable reason strings)\n// ---------------------------------------------------------------------------\n\nconst SERVICE_LABELS: Record<HealthCheckKey, string> = {\n anthropic: 'Anthropic',\n posthogOverall: 'PostHog',\n posthogComponents: 'PostHog (components)',\n github: 'GitHub',\n npmOverall: 'npm',\n npmComponents: 'npm (components)',\n cloudflareOverall: 'Cloudflare',\n cloudflareComponents: 'Cloudflare (components)',\n llmGateway: 'LLM Gateway',\n mcp: 'MCP',\n};\n\n// ---------------------------------------------------------------------------\n// Readiness config\n// ---------------------------------------------------------------------------\n\nexport interface WizardReadinessConfig {\n /** Services where status=Down blocks the run (readiness=No). */\n downBlocksRun: HealthCheckKey[];\n /** Services where status=Degraded (or worse) blocks the run (readiness=No). */\n degradedBlocksRun?: HealthCheckKey[];\n}\n\n/**\n * See README section \"Health checks\" for the full rationale.\n * Adjust these arrays to change what blocks a wizard run.\n */\nexport const DEFAULT_WIZARD_READINESS_CONFIG: WizardReadinessConfig = {\n downBlocksRun: [\n 'anthropic',\n 'posthogOverall',\n 'npmOverall',\n 'llmGateway',\n 'mcp',\n ],\n degradedBlocksRun: ['anthropic'],\n};\n\n// ---------------------------------------------------------------------------\n// Aggregate check\n// ---------------------------------------------------------------------------\n\nexport async function checkAllExternalServices(): Promise<AllServicesHealth> {\n const [\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n ] = await Promise.all([\n checkAnthropicHealth(),\n checkPosthogOverallHealth(),\n checkPosthogComponentHealth(),\n checkGithubHealth(),\n checkNpmOverallHealth(),\n checkNpmComponentHealth(),\n checkCloudflareOverallHealth(),\n checkCloudflareComponentHealth(),\n checkLlmGatewayHealth(),\n checkMcpHealth(),\n ]);\n return {\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Wizard readiness evaluation\n// ---------------------------------------------------------------------------\n\nexport enum WizardReadiness {\n Yes = 'yes',\n No = 'no',\n YesWithWarnings = 'yes_with_warnings',\n}\n\nexport interface WizardReadinessResult {\n decision: WizardReadiness;\n health: AllServicesHealth;\n reasons: string[];\n}\n\nfunction describeResult(label: string, h: BaseHealthResult): string {\n const parts = [`${label}: ${h.status}`];\n if (h.rawIndicator) parts.push(`indicator=${h.rawIndicator}`);\n if (h.error) parts.push(h.error);\n return parts.join(' — ');\n}\n\nconst MAX_COMPONENT_NAMES = 8;\n\nfunction describeComponents(label: string, h: ComponentHealthResult): string {\n const affected = h.degradedOrDownComponents;\n if (!affected || affected.length === 0)\n return `${label} components: all operational`;\n const shown = affected\n .slice(0, MAX_COMPONENT_NAMES)\n .map((c) => `${c.name} (${c.status})`);\n const suffix =\n affected.length > MAX_COMPONENT_NAMES\n ? `, +${affected.length - MAX_COMPONENT_NAMES} more`\n : '';\n return `${label} components impacted: ${shown.join(', ')}${suffix}`;\n}\n\nexport async function evaluateWizardReadiness(\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): Promise<WizardReadinessResult> {\n const health = await checkAllExternalServices();\n const reasons: string[] = [];\n\n for (const key of Object.keys(health) as HealthCheckKey[]) {\n const result = health[key];\n const label = SERVICE_LABELS[key];\n\n reasons.push(describeResult(label, result));\n\n if ('degradedOrDownComponents' in result) {\n reasons.push(describeComponents(label, result));\n }\n }\n\n const blocked =\n config.downBlocksRun.some(\n (k) => health[k].status === ServiceHealthStatus.Down,\n ) ||\n (config.degradedBlocksRun ?? []).some(\n (k) => health[k].status !== ServiceHealthStatus.Healthy,\n );\n\n if (blocked) {\n return { decision: WizardReadiness.No, health, reasons };\n }\n\n const hasWarnings = Object.values(health).some(\n (h) => h.status !== ServiceHealthStatus.Healthy,\n );\n\n if (hasWarnings) {\n return { decision: WizardReadiness.YesWithWarnings, health, reasons };\n }\n\n return { decision: WizardReadiness.Yes, health, reasons };\n}\n"]}
1
+ {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../../../src/lib/health-checks/readiness.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ServiceHealthStatus,\n type AllServicesHealth,\n type BaseHealthResult,\n type ComponentHealthResult,\n type HealthCheckKey,\n} from './types';\nimport {\n checkAnthropicHealth,\n checkPosthogOverallHealth,\n checkPosthogComponentHealth,\n checkGithubHealth,\n checkNpmOverallHealth,\n checkNpmComponentHealth,\n checkCloudflareOverallHealth,\n checkCloudflareComponentHealth,\n} from './statuspage';\nimport { checkLlmGatewayHealth, checkMcpHealth } from './endpoints';\n\n// ---------------------------------------------------------------------------\n// Service labels (used in human-readable reason strings)\n// ---------------------------------------------------------------------------\n\nexport const SERVICE_LABELS: Record<HealthCheckKey, string> = {\n anthropic: 'Anthropic',\n posthogOverall: 'PostHog',\n posthogComponents: 'PostHog (components)',\n github: 'GitHub',\n npmOverall: 'npm',\n npmComponents: 'npm (components)',\n cloudflareOverall: 'Cloudflare',\n cloudflareComponents: 'Cloudflare (components)',\n llmGateway: 'LLM Gateway',\n mcp: 'MCP',\n};\n\n// ---------------------------------------------------------------------------\n// Readiness config\n// ---------------------------------------------------------------------------\n\nexport interface WizardReadinessConfig {\n /** Services where status=Down blocks the run (readiness=No). */\n downBlocksRun: HealthCheckKey[];\n /** Services where status=Degraded (or worse) blocks the run (readiness=No). */\n degradedBlocksRun?: HealthCheckKey[];\n}\n\n/**\n * See README section \"Health checks\" for the full rationale.\n * Adjust these arrays to change what blocks a wizard run.\n */\nexport const DEFAULT_WIZARD_READINESS_CONFIG: WizardReadinessConfig = {\n downBlocksRun: [\n 'anthropic',\n 'posthogOverall',\n 'npmOverall',\n 'llmGateway',\n 'mcp',\n ],\n degradedBlocksRun: ['anthropic'],\n};\n\n// ---------------------------------------------------------------------------\n// Aggregate check\n// ---------------------------------------------------------------------------\n\nexport async function checkAllExternalServices(): Promise<AllServicesHealth> {\n const [\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n ] = await Promise.all([\n checkAnthropicHealth(),\n checkPosthogOverallHealth(),\n checkPosthogComponentHealth(),\n checkGithubHealth(),\n checkNpmOverallHealth(),\n checkNpmComponentHealth(),\n checkCloudflareOverallHealth(),\n checkCloudflareComponentHealth(),\n checkLlmGatewayHealth(),\n checkMcpHealth(),\n ]);\n return {\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Wizard readiness evaluation\n// ---------------------------------------------------------------------------\n\nexport enum WizardReadiness {\n Yes = 'yes',\n No = 'no',\n YesWithWarnings = 'yes_with_warnings',\n}\n\nexport interface WizardReadinessResult {\n decision: WizardReadiness;\n health: AllServicesHealth;\n reasons: string[];\n}\n\nfunction describeResult(label: string, h: BaseHealthResult): string {\n const parts = [`${label}: ${h.status}`];\n if (h.rawIndicator) parts.push(`indicator=${h.rawIndicator}`);\n if (h.error) parts.push(h.error);\n return parts.join(' — ');\n}\n\nconst MAX_COMPONENT_NAMES = 8;\n\nfunction describeComponents(label: string, h: ComponentHealthResult): string {\n const affected = h.degradedOrDownComponents;\n if (!affected || affected.length === 0)\n return `${label} components: all operational`;\n const shown = affected\n .slice(0, MAX_COMPONENT_NAMES)\n .map((c) => `${c.name} (${c.status})`);\n const suffix =\n affected.length > MAX_COMPONENT_NAMES\n ? `, +${affected.length - MAX_COMPONENT_NAMES} more`\n : '';\n return `${label} components impacted: ${shown.join(', ')}${suffix}`;\n}\n\nconst READINESS_TIMEOUT_MS = 10_000;\n\nexport async function evaluateWizardReadiness(\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): Promise<WizardReadinessResult> {\n try {\n const health = await Promise.race([\n checkAllExternalServices(),\n new Promise<AllServicesHealth>((resolve) =>\n setTimeout(\n () => resolve(allUnknown('Health check timed out')),\n READINESS_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const reasons: string[] = [];\n\n for (const key of Object.keys(health) as HealthCheckKey[]) {\n const result = health[key];\n const label = SERVICE_LABELS[key];\n\n reasons.push(describeResult(label, result));\n\n if ('degradedOrDownComponents' in result) {\n reasons.push(describeComponents(label, result));\n }\n }\n\n if (getBlockingServiceKeys(health, config).length > 0) {\n return { decision: WizardReadiness.No, health, reasons };\n }\n\n const hasWarnings = Object.values(health).some(\n (h) => h.status !== ServiceHealthStatus.Healthy,\n );\n\n if (hasWarnings) {\n return { decision: WizardReadiness.YesWithWarnings, health, reasons };\n }\n\n return { decision: WizardReadiness.Yes, health, reasons };\n } catch {\n // Health checks must never block the wizard run\n return {\n decision: WizardReadiness.Yes,\n health: allUnknown('Unexpected error'),\n reasons: ['Health check failed unexpectedly — proceeding anyway'],\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Blocking service detection\n// ---------------------------------------------------------------------------\n\n/** Keys that are component-level detail, not top-level services. */\nconst COMPONENT_KEYS: HealthCheckKey[] = [\n 'posthogComponents',\n 'npmComponents',\n 'cloudflareComponents',\n];\n\n/**\n * Get the keys of services that would block a wizard run per the given config.\n */\nexport function getBlockingServiceKeys(\n health: AllServicesHealth,\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): HealthCheckKey[] {\n return (Object.keys(health) as HealthCheckKey[]).filter((key) => {\n if (COMPONENT_KEYS.includes(key)) return false;\n const result = health[key];\n if (\n config.downBlocksRun.includes(key) &&\n result.status === ServiceHealthStatus.Down\n ) {\n return true;\n }\n if (\n (config.degradedBlocksRun ?? []).includes(key) &&\n result.status !== ServiceHealthStatus.Healthy\n ) {\n return true;\n }\n return false;\n });\n}\n\n/** Build an AllServicesHealth where every service is Degraded with the given error. */\nfunction allUnknown(error: string): AllServicesHealth {\n const base: BaseHealthResult = {\n status: ServiceHealthStatus.Degraded,\n error,\n };\n return {\n anthropic: base,\n posthogOverall: base,\n posthogComponents: { ...base },\n github: base,\n npmOverall: base,\n npmComponents: { ...base },\n cloudflareOverall: base,\n cloudflareComponents: { ...base },\n llmGateway: base,\n mcp: base,\n };\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Check if command is a PostHog skill installation from MCP.
3
+ * We control the MCP server, so we only need to verify:
4
+ * 1. It installs to .claude/skills/
5
+ * 2. It downloads from our GitHub releases or localhost (dev)
6
+ *
7
+ * Extracted to its own module to avoid a circular dependency
8
+ * between agent-interface.ts and yara-hooks.ts.
9
+ */
10
+ export declare function isSkillInstallCommand(command: string): boolean;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSkillInstallCommand = isSkillInstallCommand;
4
+ /**
5
+ * Check if command is a PostHog skill installation from MCP.
6
+ * We control the MCP server, so we only need to verify:
7
+ * 1. It installs to .claude/skills/
8
+ * 2. It downloads from our GitHub releases or localhost (dev)
9
+ *
10
+ * Extracted to its own module to avoid a circular dependency
11
+ * between agent-interface.ts and yara-hooks.ts.
12
+ */
13
+ function isSkillInstallCommand(command) {
14
+ if (!command.startsWith('mkdir -p .claude/skills/'))
15
+ return false;
16
+ const urlMatch = command.match(/curl -sL ['"]([^'"]+)['"]/);
17
+ if (!urlMatch)
18
+ return false;
19
+ const url = urlMatch[1];
20
+ return (url.startsWith('https://github.com/PostHog/context-mill/releases/') ||
21
+ /^http:\/\/localhost:\d+\//.test(url));
22
+ }
23
+ //# sourceMappingURL=skill-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-install.js","sourceRoot":"","sources":["../../../src/lib/skill-install.ts"],"names":[],"mappings":";;AASA,sDAWC;AApBD;;;;;;;;GAQG;AACH,SAAgB,qBAAqB,CAAC,OAAe;IACnD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,0BAA0B,CAAC;QAAE,OAAO,KAAK,CAAC;IAElE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,CACL,GAAG,CAAC,UAAU,CAAC,mDAAmD,CAAC;QACnE,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,CACtC,CAAC;AACJ,CAAC","sourcesContent":["/**\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 *\n * Extracted to its own module to avoid a circular dependency\n * between agent-interface.ts and yara-hooks.ts.\n */\nexport function 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/context-mill/releases/') ||\n /^http:\\/\\/localhost:\\d+\\//.test(url)\n );\n}\n"]}
@@ -1 +1 @@
1
- export declare const VERSION = "2.0.2";
1
+ export declare const VERSION = "2.2.0";
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Auto-generated by scripts/generate-version.js — do not edit
5
- exports.VERSION = '2.0.2';
5
+ exports.VERSION = '2.2.0';
6
6
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/lib/version.ts"],"names":[],"mappings":";;;AAAA,8DAA8D;AACjD,QAAA,OAAO,GAAG,OAAO,CAAC","sourcesContent":["// Auto-generated by scripts/generate-version.js — do not edit\nexport const VERSION = '2.0.2';\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/lib/version.ts"],"names":[],"mappings":";;;AAAA,8DAA8D;AACjD,QAAA,OAAO,GAAG,OAAO,CAAC","sourcesContent":["// Auto-generated by scripts/generate-version.js — do not edit\nexport const VERSION = '2.2.0';\n"]}
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import type { Integration } from './constants';
13
13
  import type { FrameworkConfig } from './framework-config';
14
+ import type { WizardReadinessResult } from './health-checks/readiness';
14
15
  export type CloudRegion = 'us' | 'eu';
15
16
  /** Lifecycle phase of the main work (agent run, MCP install, etc.) */
16
17
  export declare enum RunPhase {
@@ -66,6 +67,7 @@ export interface WizardSession {
66
67
  apiKey?: string;
67
68
  menu: boolean;
68
69
  benchmark: boolean;
70
+ yaraReport: boolean;
69
71
  projectId?: number;
70
72
  setupConfirmed: boolean;
71
73
  integration: Integration | null;
@@ -94,10 +96,8 @@ export interface WizardSession {
94
96
  mcpComplete: boolean;
95
97
  mcpOutcome: McpOutcome | null;
96
98
  mcpInstalledClients: string[];
97
- serviceStatus: {
98
- description: string;
99
- statusPageUrl: string;
100
- } | null;
99
+ readinessResult: WizardReadinessResult | null;
100
+ outageDismissed: boolean;
101
101
  settingsOverrideKeys: string[] | null;
102
102
  portConflictProcess: {
103
103
  command: string;
@@ -122,5 +122,6 @@ export declare function buildSession(args: {
122
122
  menu?: boolean;
123
123
  integration?: Integration;
124
124
  benchmark?: boolean;
125
+ yaraReport?: boolean;
125
126
  projectId?: string;
126
127
  }): WizardSession;
@@ -79,6 +79,7 @@ function buildSession(args) {
79
79
  apiKey: args.apiKey,
80
80
  menu: args.menu ?? false,
81
81
  benchmark: args.benchmark ?? false,
82
+ yaraReport: args.yaraReport ?? false,
82
83
  projectId: parseProjectIdArg(args.projectId),
83
84
  setupConfirmed: false,
84
85
  integration: args.integration ?? null,
@@ -95,7 +96,8 @@ function buildSession(args) {
95
96
  mcpInstalledClients: [],
96
97
  loginUrl: null,
97
98
  credentials: null,
98
- serviceStatus: null,
99
+ readinessResult: null,
100
+ outageDismissed: false,
99
101
  settingsOverrideKeys: null,
100
102
  portConflictProcess: null,
101
103
  outroData: null,
@@ -1 +1 @@
1
- {"version":3,"file":"wizard-session.js","sourceRoot":"","sources":["../../../src/lib/wizard-session.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WizardSession — single source of truth for every decision the wizard needs.\n *\n * Populated in layers:\n * CLI args / env vars → populate fields directly\n * Auto-detection → framework, typescript, package manager\n * TUI screens → region, framework disambiguation, etc.\n * OAuth → credentials\n *\n * Business logic reads from the session. Never calls a prompt.\n */\n\nimport type { Integration } from './constants';\nimport type { FrameworkConfig } from './framework-config';\n\nfunction parseProjectIdArg(value: string | undefined): number | undefined {\n if (value === undefined || value === '') return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n > 0 ? n : undefined;\n}\n\nexport type CloudRegion = 'us' | 'eu';\n\n/** Lifecycle phase of the main work (agent run, MCP install, etc.) */\nexport enum RunPhase {\n /** Still gathering input (intro, setup screens) */\n Idle = 'idle',\n /** Main work is in progress */\n Running = 'running',\n /** Main work finished successfully */\n Completed = 'completed',\n /** Main work finished with an error */\n Error = 'error',\n}\n\n/** Features discovered by the feature-discovery subagent */\nexport enum DiscoveredFeature {\n Stripe = 'stripe',\n LLM = 'llm',\n}\n\n/** Additional features the agent can integrate after the main setup */\nexport enum AdditionalFeature {\n LLM = 'llm',\n}\n\n/** Human-readable labels for additional features (used in TUI progress) */\nexport const ADDITIONAL_FEATURE_LABELS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: 'LLM analytics',\n};\n\n/** Agent prompts for each additional feature, injected via the stop hook */\nexport const ADDITIONAL_FEATURE_PROMPTS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: `Now integrate LLM analytics with PostHog. Use the PostHog MCP server to find the appropriate LLM analytics skill, install it, and follow its workflow. PostHog basics are already installed. Update the setup report markdown file when complete with additions from this task. `,\n};\n\n/** Outcome of the MCP server installation step */\nexport enum McpOutcome {\n NoClients = 'no_clients',\n Skipped = 'skipped',\n Installed = 'installed',\n Failed = 'failed',\n}\n\n/** Outcome kind for the outro screen */\nexport enum OutroKind {\n Success = 'success',\n Error = 'error',\n Cancel = 'cancel',\n}\n\nexport interface OutroData {\n kind: OutroKind;\n message?: string;\n changes?: string[];\n docsUrl?: string;\n continueUrl?: string;\n}\n\nexport interface WizardSession {\n // From CLI args\n debug: boolean;\n forceInstall: boolean;\n installDir: string;\n ci: boolean;\n signup: boolean;\n localMcp: boolean;\n apiKey?: string;\n menu: boolean;\n benchmark: boolean;\n projectId?: number;\n\n // From detection + screens\n setupConfirmed: boolean;\n integration: Integration | null;\n frameworkContext: Record<string, unknown>;\n typescript: boolean;\n\n /** Human-readable label for the detected framework variant (e.g., \"Django with Wagtail CMS\") */\n detectedFrameworkLabel: string | null;\n\n /** True once framework detection has run (whether it found something or not) */\n detectionComplete: boolean;\n\n /** Set when the detected framework version is too old for the wizard */\n unsupportedVersion: {\n current: string;\n minimum: string;\n docsUrl: string;\n } | null;\n\n // From OAuth\n credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n } | null;\n\n // Lifecycle\n runPhase: RunPhase;\n loginUrl: string | null;\n\n // Feature discovery\n discoveredFeatures: DiscoveredFeature[];\n llmOptIn: boolean;\n\n // Screen completion\n mcpComplete: boolean;\n mcpOutcome: McpOutcome | null;\n mcpInstalledClients: string[];\n\n // Runtime\n serviceStatus: { description: string; statusPageUrl: string } | null;\n settingsOverrideKeys: string[] | null;\n portConflictProcess: { command: string; pid: string; user: string } | null;\n outroData: OutroData | null;\n\n // Additional features queue (drained via stop hook after main integration)\n additionalFeatureQueue: AdditionalFeature[];\n\n // Resolved framework config (set after integration is known)\n frameworkConfig: FrameworkConfig | null;\n}\n\n/**\n * Build a WizardSession from CLI args, pre-populating whatever is known.\n */\nexport function buildSession(args: {\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n ci?: boolean;\n signup?: boolean;\n localMcp?: boolean;\n apiKey?: string;\n menu?: boolean;\n integration?: Integration;\n benchmark?: boolean;\n projectId?: string;\n}): WizardSession {\n return {\n debug: args.debug ?? false,\n forceInstall: args.forceInstall ?? false,\n installDir: args.installDir ?? process.cwd(),\n ci: args.ci ?? false,\n signup: args.signup ?? false,\n localMcp: args.localMcp ?? false,\n apiKey: args.apiKey,\n menu: args.menu ?? false,\n benchmark: args.benchmark ?? false,\n projectId: parseProjectIdArg(args.projectId),\n\n setupConfirmed: false,\n integration: args.integration ?? null,\n frameworkContext: {},\n typescript: false,\n detectedFrameworkLabel: null,\n detectionComplete: false,\n unsupportedVersion: null,\n\n runPhase: RunPhase.Idle,\n discoveredFeatures: [],\n llmOptIn: false,\n mcpComplete: false,\n mcpOutcome: null,\n mcpInstalledClients: [],\n loginUrl: null,\n credentials: null,\n serviceStatus: null,\n settingsOverrideKeys: null,\n portConflictProcess: null,\n outroData: null,\n additionalFeatureQueue: [],\n frameworkConfig: null,\n };\n}\n"]}
1
+ {"version":3,"file":"wizard-session.js","sourceRoot":"","sources":["../../../src/lib/wizard-session.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WizardSession — single source of truth for every decision the wizard needs.\n *\n * Populated in layers:\n * CLI args / env vars → populate fields directly\n * Auto-detection → framework, typescript, package manager\n * TUI screens → region, framework disambiguation, etc.\n * OAuth → credentials\n *\n * Business logic reads from the session. Never calls a prompt.\n */\n\nimport type { Integration } from './constants';\nimport type { FrameworkConfig } from './framework-config';\nimport type { WizardReadinessResult } from './health-checks/readiness';\n\nfunction parseProjectIdArg(value: string | undefined): number | undefined {\n if (value === undefined || value === '') return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n > 0 ? n : undefined;\n}\n\nexport type CloudRegion = 'us' | 'eu';\n\n/** Lifecycle phase of the main work (agent run, MCP install, etc.) */\nexport enum RunPhase {\n /** Still gathering input (intro, setup screens) */\n Idle = 'idle',\n /** Main work is in progress */\n Running = 'running',\n /** Main work finished successfully */\n Completed = 'completed',\n /** Main work finished with an error */\n Error = 'error',\n}\n\n/** Features discovered by the feature-discovery subagent */\nexport enum DiscoveredFeature {\n Stripe = 'stripe',\n LLM = 'llm',\n}\n\n/** Additional features the agent can integrate after the main setup */\nexport enum AdditionalFeature {\n LLM = 'llm',\n}\n\n/** Human-readable labels for additional features (used in TUI progress) */\nexport const ADDITIONAL_FEATURE_LABELS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: 'LLM analytics',\n};\n\n/** Agent prompts for each additional feature, injected via the stop hook */\nexport const ADDITIONAL_FEATURE_PROMPTS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: `Now integrate LLM analytics with PostHog. Use the PostHog MCP server to find the appropriate LLM analytics skill, install it, and follow its workflow. PostHog basics are already installed. Update the setup report markdown file when complete with additions from this task. `,\n};\n\n/** Outcome of the MCP server installation step */\nexport enum McpOutcome {\n NoClients = 'no_clients',\n Skipped = 'skipped',\n Installed = 'installed',\n Failed = 'failed',\n}\n\n/** Outcome kind for the outro screen */\nexport enum OutroKind {\n Success = 'success',\n Error = 'error',\n Cancel = 'cancel',\n}\n\nexport interface OutroData {\n kind: OutroKind;\n message?: string;\n changes?: string[];\n docsUrl?: string;\n continueUrl?: string;\n}\n\nexport interface WizardSession {\n // From CLI args\n debug: boolean;\n forceInstall: boolean;\n installDir: string;\n ci: boolean;\n signup: boolean;\n localMcp: boolean;\n apiKey?: string;\n menu: boolean;\n benchmark: boolean;\n yaraReport: boolean;\n projectId?: number;\n\n // From detection + screens\n setupConfirmed: boolean;\n integration: Integration | null;\n frameworkContext: Record<string, unknown>;\n typescript: boolean;\n\n /** Human-readable label for the detected framework variant (e.g., \"Django with Wagtail CMS\") */\n detectedFrameworkLabel: string | null;\n\n /** True once framework detection has run (whether it found something or not) */\n detectionComplete: boolean;\n\n /** Set when the detected framework version is too old for the wizard */\n unsupportedVersion: {\n current: string;\n minimum: string;\n docsUrl: string;\n } | null;\n\n // From OAuth\n credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n } | null;\n\n // Lifecycle\n runPhase: RunPhase;\n loginUrl: string | null;\n\n // Feature discovery\n discoveredFeatures: DiscoveredFeature[];\n llmOptIn: boolean;\n\n // Screen completion\n mcpComplete: boolean;\n mcpOutcome: McpOutcome | null;\n mcpInstalledClients: string[];\n\n // Runtime\n readinessResult: WizardReadinessResult | null;\n outageDismissed: boolean;\n settingsOverrideKeys: string[] | null;\n portConflictProcess: { command: string; pid: string; user: string } | null;\n outroData: OutroData | null;\n\n // Additional features queue (drained via stop hook after main integration)\n additionalFeatureQueue: AdditionalFeature[];\n\n // Resolved framework config (set after integration is known)\n frameworkConfig: FrameworkConfig | null;\n}\n\n/**\n * Build a WizardSession from CLI args, pre-populating whatever is known.\n */\nexport function buildSession(args: {\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n ci?: boolean;\n signup?: boolean;\n localMcp?: boolean;\n apiKey?: string;\n menu?: boolean;\n integration?: Integration;\n benchmark?: boolean;\n yaraReport?: boolean;\n projectId?: string;\n}): WizardSession {\n return {\n debug: args.debug ?? false,\n forceInstall: args.forceInstall ?? false,\n installDir: args.installDir ?? process.cwd(),\n ci: args.ci ?? false,\n signup: args.signup ?? false,\n localMcp: args.localMcp ?? false,\n apiKey: args.apiKey,\n menu: args.menu ?? false,\n benchmark: args.benchmark ?? false,\n yaraReport: args.yaraReport ?? false,\n projectId: parseProjectIdArg(args.projectId),\n\n setupConfirmed: false,\n integration: args.integration ?? null,\n frameworkContext: {},\n typescript: false,\n detectedFrameworkLabel: null,\n detectionComplete: false,\n unsupportedVersion: null,\n\n runPhase: RunPhase.Idle,\n discoveredFeatures: [],\n llmOptIn: false,\n mcpComplete: false,\n mcpOutcome: null,\n mcpInstalledClients: [],\n loginUrl: null,\n credentials: null,\n readinessResult: null,\n outageDismissed: false,\n settingsOverrideKeys: null,\n portConflictProcess: null,\n outroData: null,\n additionalFeatureQueue: [],\n frameworkConfig: null,\n };\n}\n"]}
@@ -12,6 +12,8 @@ export interface WizardToolsOptions {
12
12
  workingDirectory: string;
13
13
  /** Framework-specific package manager detector */
14
14
  detectPackageManager: PackageManagerDetector;
15
+ /** Base URL for the skills server (e.g. http://localhost:8765 or GitHub releases URL) */
16
+ skillsBaseUrl: string;
15
17
  }
16
18
  /**
17
19
  * Resolve filePath relative to workingDirectory, rejecting path traversal.
@@ -19,6 +19,7 @@ exports.mergeEnvValues = mergeEnvValues;
19
19
  exports.createWizardToolsServer = createWizardToolsServer;
20
20
  const path_1 = __importDefault(require("path"));
21
21
  const fs_1 = __importDefault(require("fs"));
22
+ const child_process_1 = require("child_process");
22
23
  const zod_1 = require("zod");
23
24
  const debug_1 = require("../utils/debug");
24
25
  // ---------------------------------------------------------------------------
@@ -113,9 +114,31 @@ const SERVER_NAME = 'wizard-tools';
113
114
  * Must be called asynchronously because the SDK is an ESM module loaded via dynamic import.
114
115
  */
115
116
  async function createWizardToolsServer(options) {
116
- const { workingDirectory, detectPackageManager } = options;
117
+ const { workingDirectory, detectPackageManager, skillsBaseUrl } = options;
117
118
  const sdk = await getSDKModule();
118
119
  const { tool, createSdkMcpServer } = sdk;
120
+ let cachedSkillMenu = {};
121
+ let categoryNames = ['integration'];
122
+ try {
123
+ const menuUrl = `${skillsBaseUrl}/skill-menu.json`;
124
+ (0, debug_1.logToFile)(`wizard-tools: pre-fetching skill menu from ${menuUrl}`);
125
+ const resp = await fetch(menuUrl);
126
+ if (resp.ok) {
127
+ const data = (await resp.json());
128
+ cachedSkillMenu = data.categories;
129
+ const keys = Object.keys(cachedSkillMenu);
130
+ if (keys.length > 0) {
131
+ categoryNames = keys;
132
+ }
133
+ (0, debug_1.logToFile)(`wizard-tools: loaded skill menu (${keys.length} categories)`);
134
+ }
135
+ else {
136
+ (0, debug_1.logToFile)(`wizard-tools: skill menu fetch failed: ${resp.status}`);
137
+ }
138
+ }
139
+ catch (err) {
140
+ (0, debug_1.logToFile)(`wizard-tools: skill menu fetch error: ${err.message}`);
141
+ }
119
142
  // -- check_env_keys -------------------------------------------------------
120
143
  const checkEnvKeys = tool('check_env_keys', 'Check which environment variable keys are present or missing in a .env file. Never reveals values.', {
121
144
  filePath: zod_1.z
@@ -200,11 +223,103 @@ async function createWizardToolsServer(options) {
200
223
  ],
201
224
  };
202
225
  });
226
+ // -- load_skill_menu ------------------------------------------------------
227
+ const loadSkillMenu = tool('load_skill_menu', 'Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then use install_skill with the chosen ID.', {
228
+ category: zod_1.z.enum(categoryNames).describe('Skill category'),
229
+ }, (args) => {
230
+ const skills = cachedSkillMenu[args.category];
231
+ if (!skills || skills.length === 0) {
232
+ return {
233
+ content: [
234
+ {
235
+ type: 'text',
236
+ text: `No skills found for category "${args.category}".`,
237
+ },
238
+ ],
239
+ isError: true,
240
+ };
241
+ }
242
+ const menuText = skills.map((s) => `- ${s.id}: ${s.name}`).join('\n');
243
+ (0, debug_1.logToFile)(`load_skill_menu: returning ${skills.length} skills for "${args.category}"`);
244
+ return {
245
+ content: [{ type: 'text', text: menuText }],
246
+ };
247
+ });
248
+ // -- install_skill --------------------------------------------------------
249
+ const installSkill = tool('install_skill', 'Download and install a PostHog skill by ID. Call load_skill_menu first to see available skills. Extracts the skill to .claude/skills/<skillId>/.', {
250
+ skillId: zod_1.z
251
+ .string()
252
+ .describe('Skill ID from the skill menu (e.g., "integration-nextjs-app-router")'),
253
+ }, (args) => {
254
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(args.skillId)) {
255
+ return {
256
+ content: [
257
+ {
258
+ type: 'text',
259
+ text: 'Error: skillId must be lowercase alphanumeric with hyphens.',
260
+ },
261
+ ],
262
+ isError: true,
263
+ };
264
+ }
265
+ // Look up download URL from cached menu
266
+ const allSkills = Object.values(cachedSkillMenu).flat();
267
+ const skill = allSkills.find((s) => s.id === args.skillId);
268
+ if (!skill) {
269
+ return {
270
+ content: [
271
+ {
272
+ type: 'text',
273
+ text: `Error: skill "${args.skillId}" not found. Use load_skill_menu to see available skills.`,
274
+ },
275
+ ],
276
+ isError: true,
277
+ };
278
+ }
279
+ const skillDir = path_1.default.join(workingDirectory, '.claude', 'skills', args.skillId);
280
+ const tmpFile = `/tmp/posthog-skill-${args.skillId}.zip`;
281
+ try {
282
+ fs_1.default.mkdirSync(skillDir, { recursive: true });
283
+ (0, child_process_1.execFileSync)('curl', ['-sL', skill.downloadUrl, '-o', tmpFile], {
284
+ timeout: 30000,
285
+ });
286
+ (0, child_process_1.execFileSync)('unzip', ['-o', tmpFile, '-d', skillDir], {
287
+ timeout: 30000,
288
+ });
289
+ try {
290
+ fs_1.default.unlinkSync(tmpFile);
291
+ }
292
+ catch {
293
+ /* ignore cleanup errors */
294
+ }
295
+ (0, debug_1.logToFile)(`install_skill: installed ${args.skillId} from ${skill.downloadUrl}`);
296
+ return {
297
+ content: [
298
+ {
299
+ type: 'text',
300
+ text: `Skill installed to .claude/skills/${args.skillId}/`,
301
+ },
302
+ ],
303
+ };
304
+ }
305
+ catch (err) {
306
+ (0, debug_1.logToFile)(`install_skill error: ${err.message}`);
307
+ return {
308
+ content: [
309
+ {
310
+ type: 'text',
311
+ text: `Error installing skill: ${err.message}`,
312
+ },
313
+ ],
314
+ isError: true,
315
+ };
316
+ }
317
+ });
203
318
  // -- Assemble server ------------------------------------------------------
204
319
  return createSdkMcpServer({
205
320
  name: SERVER_NAME,
206
321
  version: '1.0.0',
207
- tools: [checkEnvKeys, setEnvValues, detectPM],
322
+ tools: [checkEnvKeys, setEnvValues, detectPM, loadSkillMenu, installSkill],
208
323
  });
209
324
  }
210
325
  /** Tool names exposed by the wizard-tools server, for use in allowedTools */
@@ -212,5 +327,7 @@ exports.WIZARD_TOOL_NAMES = [
212
327
  `${SERVER_NAME}:check_env_keys`,
213
328
  `${SERVER_NAME}:set_env_values`,
214
329
  `${SERVER_NAME}:detect_package_manager`,
330
+ `${SERVER_NAME}:load_skill_menu`,
331
+ `${SERVER_NAME}:install_skill`,
215
332
  ];
216
333
  //# sourceMappingURL=wizard-tools.js.map