@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":"PortConflictScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/PortConflictScreen.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * PortConflictScreen — Modal when another process is blocking the OAuth port.\n *\n * Offers to kill the blocking process and retry, or exit.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport { execSync } from 'node:child_process';\nimport type { WizardStore } from '../store.js';\nimport { ConfirmationInput, Divider } from '../primitives/index.js';\nimport { OAUTH_PORT } from '../../../lib/constants.js';\n\ninterface PortConflictScreenProps {\n store: WizardStore;\n}\n\nexport const PortConflictScreen = ({ store }: PortConflictScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [feedback, setFeedback] = useState<string | null>(null);\n const processInfo = store.session.portConflictProcess;\n\n if (!processInfo) return null;\n\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"#DC9300\"\n paddingX={3}\n paddingY={2}\n width={72}\n >\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color=\"#DC9300\" bold>\n Port {OAUTH_PORT} in use\n </Text>\n </Box>\n\n <Text>Another process is blocking the authentication server:</Text>\n <Box flexDirection=\"column\" marginY={1} paddingLeft={2} gap={0}>\n <Text>\n <Text dimColor>Command </Text>\n <Text bold>{processInfo.command}</Text>\n </Text>\n <Text>\n <Text dimColor>PID </Text>\n <Text bold>{processInfo.pid}</Text>\n </Text>\n <Text>\n <Text dimColor>User </Text>\n <Text bold>{processInfo.user}</Text>\n </Text>\n </Box>\n <Text dimColor>\n Kill this process to continue, or exit and free the port manually.\n </Text>\n\n {feedback && (\n <Box marginTop={1}>\n <Text color=\"yellow\">{feedback}</Text>\n </Box>\n )}\n\n <Box marginY={1}>\n <Divider />\n </Box>\n\n <ConfirmationInput\n message={`Kill process and continue?`}\n confirmLabel=\"Kill & continue [Enter]\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() => {\n try {\n execSync(`lsof -ti :${OAUTH_PORT} | xargs kill`, {\n stdio: 'ignore',\n });\n store.resolvePortConflict();\n } catch {\n setFeedback(\n `Could not kill the process. Try running: lsof -ti :${OAUTH_PORT} | xargs kill`,\n );\n }\n }}\n onCancel={() => process.exit(1)}\n />\n </Box>\n </Box>\n );\n};\n"]}
1
+ {"version":3,"file":"PortConflictScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/PortConflictScreen.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAMvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAE,KAAK,EAA2B,EAAE,EAAE;IACvE,oBAAoB,CAClB,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,EAC3B,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAC1B,CAAC;IAEF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC;IAEtD,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE9B,OAAO,CACL,MAAC,YAAY,IACX,WAAW,EAAC,SAAS,EACrB,KAAK,EAAE,QAAQ,UAAU,SAAS,EAClC,KAAK,EAAE,EAAE,EACT,QAAQ,EAAE,QAAQ,EAClB,MAAM,EACJ,KAAC,iBAAiB,IAChB,OAAO,EAAC,4BAA4B,EACpC,YAAY,EAAC,yBAAyB,EACtC,WAAW,EAAC,YAAY,EACxB,SAAS,EAAE,GAAG,EAAE;gBACd,IAAI,CAAC;oBACH,QAAQ,CAAC,aAAa,UAAU,eAAe,EAAE;wBAC/C,KAAK,EAAE,QAAQ;qBAChB,CAAC,CAAC;oBACH,KAAK,CAAC,mBAAmB,EAAE,CAAC;gBAC9B,CAAC;gBAAC,MAAM,CAAC;oBACP,WAAW,CACT,sDAAsD,UAAU,eAAe,CAChF,CAAC;gBACJ,CAAC;YACH,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAC/B,aAGJ,KAAC,IAAI,yEAA8D,EACnE,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,aAC5D,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,QAAQ,+BAAgB,EAC9B,KAAC,IAAI,IAAC,IAAI,kBAAE,WAAW,CAAC,OAAO,GAAQ,IAClC,EACP,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,QAAQ,2BAAY,EAC1B,KAAC,IAAI,IAAC,IAAI,kBAAE,WAAW,CAAC,GAAG,GAAQ,IAC9B,EACP,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,QAAQ,4BAAa,EAC3B,KAAC,IAAI,IAAC,IAAI,kBAAE,WAAW,CAAC,IAAI,GAAQ,IAC/B,IACH,EACN,KAAC,IAAI,IAAC,QAAQ,yFAEP,IACM,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * PortConflictScreen — Modal when another process is blocking the OAuth port.\n *\n * Offers to kill the blocking process and retry, or exit.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport { execSync } from 'node:child_process';\nimport type { WizardStore } from '../store.js';\nimport { ConfirmationInput, ModalOverlay } from '../primitives/index.js';\nimport { OAUTH_PORT } from '../../../lib/constants.js';\n\ninterface PortConflictScreenProps {\n store: WizardStore;\n}\n\nexport const PortConflictScreen = ({ store }: PortConflictScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [feedback, setFeedback] = useState<string | null>(null);\n const processInfo = store.session.portConflictProcess;\n\n if (!processInfo) return null;\n\n return (\n <ModalOverlay\n borderColor=\"#DC9300\"\n title={`Port ${OAUTH_PORT} in use`}\n width={72}\n feedback={feedback}\n footer={\n <ConfirmationInput\n message=\"Kill process and continue?\"\n confirmLabel=\"Kill & continue [Enter]\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() => {\n try {\n execSync(`lsof -ti :${OAUTH_PORT} | xargs kill`, {\n stdio: 'ignore',\n });\n store.resolvePortConflict();\n } catch {\n setFeedback(\n `Could not kill the process. Try running: lsof -ti :${OAUTH_PORT} | xargs kill`,\n );\n }\n }}\n onCancel={() => process.exit(1)}\n />\n }\n >\n <Text>Another process is blocking the authentication server:</Text>\n <Box flexDirection=\"column\" marginY={1} paddingLeft={2} gap={0}>\n <Text>\n <Text dimColor>Command </Text>\n <Text bold>{processInfo.command}</Text>\n </Text>\n <Text>\n <Text dimColor>PID </Text>\n <Text bold>{processInfo.pid}</Text>\n </Text>\n <Text>\n <Text dimColor>User </Text>\n <Text bold>{processInfo.user}</Text>\n </Text>\n </Box>\n <Text dimColor>\n Kill this process to continue, or exit and free the port manually.\n </Text>\n </ModalOverlay>\n );\n};\n"]}
@@ -1,11 +1,11 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
3
  * SettingsOverrideScreen — Modal when .claude/settings.json contains env overrides
4
4
  * that block the Wizard from reaching the PostHog LLM Gateway.
5
5
  */
6
6
  import { Box, Text } from 'ink';
7
7
  import { useState, useSyncExternalStore } from 'react';
8
- import { ConfirmationInput } from '../primitives/index.js';
8
+ import { ConfirmationInput, ModalOverlay } from '../primitives/index.js';
9
9
  import { Icons } from '../styles.js';
10
10
  export const SettingsOverrideScreen = ({ store, }) => {
11
11
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
@@ -14,11 +14,11 @@ export const SettingsOverrideScreen = ({ store, }) => {
14
14
  if (!keys || keys.length === 0) {
15
15
  return null;
16
16
  }
17
- return (_jsx(Box, { flexDirection: "column", flexGrow: 1, alignItems: "center", justifyContent: "center", children: _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 3, paddingY: 1, width: 64, children: [_jsx(Box, { justifyContent: "center", marginBottom: 1, children: _jsxs(Text, { color: "red", bold: true, children: [Icons.warning, " Settings Conflict"] }) }), _jsxs(Text, { children: ["Your project's ", _jsx(Text, { bold: true, children: ".claude/settings.json" }), " sets:"] }), _jsx(Box, { flexDirection: "column", marginY: 1, paddingLeft: 2, children: keys.map((key) => (_jsxs(Text, { children: [Icons.bullet, ' ', _jsx(Text, { color: "yellow", bold: true, children: key })] }, key))) }), _jsx(Text, { dimColor: true, children: "These overrides prevent the Wizard from reaching the PostHog LLM Gateway. We can back up the file and continue." }), feedback && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "yellow", children: [Icons.warning, " ", feedback] }) })), _jsx(Box, { marginY: 1, children: _jsx(Text, { dimColor: true, children: '─'.repeat(56) }) }), _jsx(ConfirmationInput, { message: "Back up to .wizard-backup and continue?", confirmLabel: "Backup & continue [Enter]", cancelLabel: "Exit [Esc]", onConfirm: () => {
18
- const ok = store.backupAndFixSettingsOverride();
19
- if (!ok) {
20
- setFeedback('Could not back up the settings file.');
21
- }
22
- }, onCancel: () => process.exit(1) })] }) }));
17
+ return (_jsxs(ModalOverlay, { borderColor: "red", title: `${Icons.warning} Settings conflict`, width: 64, feedback: feedback ? `${Icons.warning} ${feedback}` : null, footer: _jsx(ConfirmationInput, { message: "Back up to .wizard-backup and continue?", confirmLabel: "Backup & continue [Enter]", cancelLabel: "Exit [Esc]", onConfirm: () => {
18
+ const ok = store.backupAndFixSettingsOverride();
19
+ if (!ok) {
20
+ setFeedback('Could not back up the settings file.');
21
+ }
22
+ }, onCancel: () => process.exit(1) }), children: [_jsxs(Text, { children: ["Your project's ", _jsx(Text, { bold: true, children: ".claude/settings.json" }), " sets:"] }), _jsx(Box, { flexDirection: "column", marginY: 1, paddingLeft: 2, children: keys.map((key) => (_jsxs(Text, { children: [Icons.bullet, ' ', _jsx(Text, { color: "yellow", bold: true, children: key })] }, key))) }), _jsx(Text, { dimColor: true, children: "These overrides prevent the Wizard from reaching the PostHog LLM Gateway. We can back up the file and continue." })] }));
23
23
  };
24
24
  //# sourceMappingURL=SettingsOverrideScreen.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SettingsOverrideScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/SettingsOverrideScreen.tsx"],"names":[],"mappings":";AAAA;;;GAGG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAMrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EACrC,KAAK,GACuB,EAAE,EAAE;IAChC,oBAAoB,CAClB,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,EAC3B,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAC1B,CAAC;IAEF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC;IAEhD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,KAAC,GAAG,IACF,aAAa,EAAC,QAAQ,EACtB,QAAQ,EAAE,CAAC,EACX,UAAU,EAAC,QAAQ,EACnB,cAAc,EAAC,QAAQ,YAEvB,MAAC,GAAG,IACF,aAAa,EAAC,QAAQ,EACtB,WAAW,EAAC,OAAO,EACnB,WAAW,EAAC,KAAK,EACjB,QAAQ,EAAE,CAAC,EACX,QAAQ,EAAE,CAAC,EACX,KAAK,EAAE,EAAE,aAET,KAAC,GAAG,IAAC,cAAc,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,YAC1C,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,EAAC,IAAI,mBACnB,KAAK,CAAC,OAAO,0BACT,GACH,EAEN,MAAC,IAAI,kCACiB,KAAC,IAAI,IAAC,IAAI,4CAA6B,cACtD,EACP,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,YACnD,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,MAAC,IAAI,eACF,KAAK,CAAC,MAAM,EAAE,GAAG,EAClB,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,kBACtB,GAAG,GACC,KAJE,GAAG,CAKP,CACR,CAAC,GACE,EACN,KAAC,IAAI,IAAC,QAAQ,sIAGP,EAEN,QAAQ,IAAI,CACX,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,aACjB,KAAK,CAAC,OAAO,OAAG,QAAQ,IACpB,GACH,CACP,EAED,KAAC,GAAG,IAAC,OAAO,EAAE,CAAC,YACb,KAAC,IAAI,IAAC,QAAQ,kBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAQ,GAClC,EAEN,KAAC,iBAAiB,IAChB,OAAO,EAAC,yCAAyC,EACjD,YAAY,EAAC,2BAA2B,EACxC,WAAW,EAAC,YAAY,EACxB,SAAS,EAAE,GAAG,EAAE;wBACd,MAAM,EAAE,GAAG,KAAK,CAAC,4BAA4B,EAAE,CAAC;wBAChD,IAAI,CAAC,EAAE,EAAE,CAAC;4BACR,WAAW,CAAC,sCAAsC,CAAC,CAAC;wBACtD,CAAC;oBACH,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAC/B,IACE,GACF,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * SettingsOverrideScreen — Modal when .claude/settings.json contains env overrides\n * that block the Wizard from reaching the PostHog LLM Gateway.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '../store.js';\nimport { ConfirmationInput } from '../primitives/index.js';\nimport { Icons } from '../styles.js';\n\ninterface SettingsOverrideScreenProps {\n store: WizardStore;\n}\n\nexport const SettingsOverrideScreen = ({\n store,\n}: SettingsOverrideScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [feedback, setFeedback] = useState<string | null>(null);\n const keys = store.session.settingsOverrideKeys;\n\n if (!keys || keys.length === 0) {\n return null;\n }\n\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"red\"\n paddingX={3}\n paddingY={1}\n width={64}\n >\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color=\"red\" bold>\n {Icons.warning} Settings Conflict\n </Text>\n </Box>\n\n <Text>\n Your project&apos;s <Text bold>.claude/settings.json</Text> sets:\n </Text>\n <Box flexDirection=\"column\" marginY={1} paddingLeft={2}>\n {keys.map((key) => (\n <Text key={key}>\n {Icons.bullet}{' '}\n <Text color=\"yellow\" bold>\n {key}\n </Text>\n </Text>\n ))}\n </Box>\n <Text dimColor>\n These overrides prevent the Wizard from reaching the PostHog LLM\n Gateway. We can back up the file and continue.\n </Text>\n\n {feedback && (\n <Box marginTop={1}>\n <Text color=\"yellow\">\n {Icons.warning} {feedback}\n </Text>\n </Box>\n )}\n\n <Box marginY={1}>\n <Text dimColor>{'─'.repeat(56)}</Text>\n </Box>\n\n <ConfirmationInput\n message=\"Back up to .wizard-backup and continue?\"\n confirmLabel=\"Backup & continue [Enter]\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() => {\n const ok = store.backupAndFixSettingsOverride();\n if (!ok) {\n setFeedback('Could not back up the settings file.');\n }\n }}\n onCancel={() => process.exit(1)}\n />\n </Box>\n </Box>\n );\n};\n"]}
1
+ {"version":3,"file":"SettingsOverrideScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/SettingsOverrideScreen.tsx"],"names":[],"mappings":";AAAA;;;GAGG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAMrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EACrC,KAAK,GACuB,EAAE,EAAE;IAChC,oBAAoB,CAClB,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,EAC3B,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAC1B,CAAC;IAEF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC;IAEhD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,MAAC,YAAY,IACX,WAAW,EAAC,KAAK,EACjB,KAAK,EAAE,GAAG,KAAK,CAAC,OAAO,oBAAoB,EAC3C,KAAK,EAAE,EAAE,EACT,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,EAC1D,MAAM,EACJ,KAAC,iBAAiB,IAChB,OAAO,EAAC,yCAAyC,EACjD,YAAY,EAAC,2BAA2B,EACxC,WAAW,EAAC,YAAY,EACxB,SAAS,EAAE,GAAG,EAAE;gBACd,MAAM,EAAE,GAAG,KAAK,CAAC,4BAA4B,EAAE,CAAC;gBAChD,IAAI,CAAC,EAAE,EAAE,CAAC;oBACR,WAAW,CAAC,sCAAsC,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAC/B,aAGJ,MAAC,IAAI,kCACiB,KAAC,IAAI,IAAC,IAAI,4CAA6B,cACtD,EACP,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,YACnD,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,MAAC,IAAI,eACF,KAAK,CAAC,MAAM,EAAE,GAAG,EAClB,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,kBACtB,GAAG,GACC,KAJE,GAAG,CAKP,CACR,CAAC,GACE,EACN,KAAC,IAAI,IAAC,QAAQ,sIAGP,IACM,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * SettingsOverrideScreen — Modal when .claude/settings.json contains env overrides\n * that block the Wizard from reaching the PostHog LLM Gateway.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '../store.js';\nimport { ConfirmationInput, ModalOverlay } from '../primitives/index.js';\nimport { Icons } from '../styles.js';\n\ninterface SettingsOverrideScreenProps {\n store: WizardStore;\n}\n\nexport const SettingsOverrideScreen = ({\n store,\n}: SettingsOverrideScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [feedback, setFeedback] = useState<string | null>(null);\n const keys = store.session.settingsOverrideKeys;\n\n if (!keys || keys.length === 0) {\n return null;\n }\n\n return (\n <ModalOverlay\n borderColor=\"red\"\n title={`${Icons.warning} Settings conflict`}\n width={64}\n feedback={feedback ? `${Icons.warning} ${feedback}` : null}\n footer={\n <ConfirmationInput\n message=\"Back up to .wizard-backup and continue?\"\n confirmLabel=\"Backup & continue [Enter]\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() => {\n const ok = store.backupAndFixSettingsOverride();\n if (!ok) {\n setFeedback('Could not back up the settings file.');\n }\n }}\n onCancel={() => process.exit(1)}\n />\n }\n >\n <Text>\n Your project&apos;s <Text bold>.claude/settings.json</Text> sets:\n </Text>\n <Box flexDirection=\"column\" marginY={1} paddingLeft={2}>\n {keys.map((key) => (\n <Text key={key}>\n {Icons.bullet}{' '}\n <Text color=\"yellow\" bold>\n {key}\n </Text>\n </Text>\n ))}\n </Box>\n <Text dimColor>\n These overrides prevent the Wizard from reaching the PostHog LLM\n Gateway. We can back up the file and continue.\n </Text>\n </ModalOverlay>\n );\n};\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * HealthCheckScreen — Flow screen between Intro and Auth.
3
+ *
4
+ * Three states:
5
+ * 1. Checking: spinner while health check runs
6
+ * 2. Healthy: isComplete returns true, router auto-advances to Auth
7
+ * 3. Blocking outage: shows affected services with Continue/Exit
8
+ */
9
+ import type { WizardStore } from '../../store.js';
10
+ interface HealthCheckScreenProps {
11
+ store: WizardStore;
12
+ }
13
+ export declare const HealthCheckScreen: ({ store }: HealthCheckScreenProps) => import("react/jsx-runtime").JSX.Element | null;
14
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * HealthCheckScreen — Flow screen between Intro and Auth.
4
+ *
5
+ * Three states:
6
+ * 1. Checking: spinner while health check runs
7
+ * 2. Healthy: isComplete returns true, router auto-advances to Auth
8
+ * 3. Blocking outage: shows affected services with Continue/Exit
9
+ */
10
+ import { Box, Text } from 'ink';
11
+ import { useSyncExternalStore } from 'react';
12
+ import { ConfirmationInput, LoadingBox, ModalOverlay, } from '../../primitives/index.js';
13
+ import { Icons } from '../../styles.js';
14
+ import { ServiceHealthList } from '../../components/ServiceHealthList.js';
15
+ import { getBlockingServiceKeys } from '../../../../lib/health-checks/readiness.js';
16
+ import { wizardAbort } from '../../../../utils/wizard-abort.js';
17
+ export const HealthCheckScreen = ({ store }) => {
18
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
19
+ const result = store.session.readinessResult;
20
+ // Still checking — show spinner
21
+ if (!result) {
22
+ return (_jsx(Box, { flexDirection: "column", flexGrow: 1, alignItems: "center", justifyContent: "center", children: _jsx(LoadingBox, { message: "Checking service status..." }) }));
23
+ }
24
+ // Healthy or warnings — isComplete returns true, router skips past.
25
+ // This branch only renders for a single frame before advancing.
26
+ const blockingKeys = getBlockingServiceKeys(result.health);
27
+ if (blockingKeys.length === 0)
28
+ return null;
29
+ // Blocking outage — show service list with Continue/Exit
30
+ return (_jsxs(ModalOverlay, { borderColor: "red", title: `${Icons.warning} Ongoing service disruptions`, width: 72, footer: _jsx(ConfirmationInput, { message: "Continue anyway?", confirmLabel: "Continue [Enter]", cancelLabel: "Exit [Esc]", onConfirm: () => store.dismissOutage(), onCancel: () => void wizardAbort({ message: 'Exited due to service outage.' }) }), children: [_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: [_jsx(Text, { color: "red", children: Icons.squareFilled }), _jsx(Text, { dimColor: true, children: " Down " }), _jsx(Text, { color: "#DC9300", children: Icons.squareFilled }), _jsx(Text, { dimColor: true, children: " Degraded" })] }) }), _jsx(ServiceHealthList, { health: result.health, filterKeys: blockingKeys, showHealthy: false })] }), _jsx(Text, { dimColor: true, children: "The wizard may not work reliably while services are affected." })] }));
31
+ };
32
+ //# sourceMappingURL=HealthCheckScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HealthCheckScreen.js","sourceRoot":"","sources":["../../../../../../src/ui/tui/screens/health/HealthCheckScreen.tsx"],"names":[],"mappings":";AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAMhE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAAE,KAAK,EAA0B,EAAE,EAAE;IACrE,oBAAoB,CAClB,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,EAC3B,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAC1B,CAAC;IAEF,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;IAE7C,gCAAgC;IAChC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CACL,KAAC,GAAG,IACF,aAAa,EAAC,QAAQ,EACtB,QAAQ,EAAE,CAAC,EACX,UAAU,EAAC,QAAQ,EACnB,cAAc,EAAC,QAAQ,YAEvB,KAAC,UAAU,IAAC,OAAO,EAAC,4BAA4B,GAAG,GAC/C,CACP,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,gEAAgE;IAChE,MAAM,YAAY,GAAG,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,yDAAyD;IACzD,OAAO,CACL,MAAC,YAAY,IACX,WAAW,EAAC,KAAK,EACjB,KAAK,EAAE,GAAG,KAAK,CAAC,OAAO,8BAA8B,EACrD,KAAK,EAAE,EAAE,EACT,MAAM,EACJ,KAAC,iBAAiB,IAChB,OAAO,EAAC,kBAAkB,EAC1B,YAAY,EAAC,kBAAkB,EAC/B,WAAW,EAAC,YAAY,EACxB,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EACtC,QAAQ,EAAE,GAAG,EAAE,CACb,KAAK,WAAW,CAAC,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,GAEhE,aAGJ,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACzC,KAAC,GAAG,IAAC,YAAY,EAAE,CAAC,YAClB,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,YAAE,KAAK,CAAC,YAAY,GAAQ,EAC7C,KAAC,IAAI,IAAC,QAAQ,6BAAc,EAC5B,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,YAAE,KAAK,CAAC,YAAY,GAAQ,EACjD,KAAC,IAAI,IAAC,QAAQ,gCAAiB,IAC1B,GACH,EAEN,KAAC,iBAAiB,IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EACrB,UAAU,EAAE,YAAY,EACxB,WAAW,EAAE,KAAK,GAClB,IACE,EAEN,KAAC,IAAI,IAAC,QAAQ,oFAEP,IACM,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * HealthCheckScreen — Flow screen between Intro and Auth.\n *\n * Three states:\n * 1. Checking: spinner while health check runs\n * 2. Healthy: isComplete returns true, router auto-advances to Auth\n * 3. Blocking outage: shows affected services with Continue/Exit\n */\n\nimport { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '../../store.js';\nimport {\n ConfirmationInput,\n LoadingBox,\n ModalOverlay,\n} from '../../primitives/index.js';\nimport { Icons } from '../../styles.js';\nimport { ServiceHealthList } from '../../components/ServiceHealthList.js';\nimport { getBlockingServiceKeys } from '../../../../lib/health-checks/readiness.js';\nimport { wizardAbort } from '../../../../utils/wizard-abort.js';\n\ninterface HealthCheckScreenProps {\n store: WizardStore;\n}\n\nexport const HealthCheckScreen = ({ store }: HealthCheckScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const result = store.session.readinessResult;\n\n // Still checking — show spinner\n if (!result) {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <LoadingBox message=\"Checking service status...\" />\n </Box>\n );\n }\n\n // Healthy or warnings — isComplete returns true, router skips past.\n // This branch only renders for a single frame before advancing.\n const blockingKeys = getBlockingServiceKeys(result.health);\n if (blockingKeys.length === 0) return null;\n\n // Blocking outage — show service list with Continue/Exit\n return (\n <ModalOverlay\n borderColor=\"red\"\n title={`${Icons.warning} Ongoing service disruptions`}\n width={72}\n footer={\n <ConfirmationInput\n message=\"Continue anyway?\"\n confirmLabel=\"Continue [Enter]\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() => store.dismissOutage()}\n onCancel={() =>\n void wizardAbort({ message: 'Exited due to service outage.' })\n }\n />\n }\n >\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box marginBottom={1}>\n <Text>\n <Text color=\"red\">{Icons.squareFilled}</Text>\n <Text dimColor> Down </Text>\n <Text color=\"#DC9300\">{Icons.squareFilled}</Text>\n <Text dimColor> Degraded</Text>\n </Text>\n </Box>\n\n <ServiceHealthList\n health={result.health}\n filterKeys={blockingKeys}\n showHealthy={false}\n />\n </Box>\n\n <Text dimColor>\n The wizard may not work reliably while services are affected.\n </Text>\n </ModalOverlay>\n );\n};\n"]}
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Navigation is delegated to WizardRouter.
6
6
  * The active screen is derived from session state — not imperatively set.
7
- * Overlays (outage, etc.) are the only imperative navigation.
7
+ * Overlays (settings-override, port-conflict) are the only imperative navigation.
8
8
  *
9
9
  * All session mutations that affect screen resolution go through
10
10
  * explicit setters so emitChange() is always called.
@@ -52,7 +52,18 @@ export declare class WizardStore {
52
52
  private _backupAndFixSettings;
53
53
  /** Blocks OAuth flow until the port-conflict overlay is dismissed. */
54
54
  private _resolvePortConflict;
55
+ /**
56
+ * Resolves when the health-check screen is done — either auto-advanced
57
+ * (healthy) or user-dismissed (outage). bin.ts awaits this before runWizard().
58
+ */
59
+ private _resolveHealthGate;
60
+ readonly healthGateComplete: Promise<void>;
55
61
  constructor(flow?: Flow);
62
+ /**
63
+ * Kick off the health check. Stores the result and resolves the
64
+ * health gate if non-blocking.
65
+ */
66
+ private _initHealthCheck;
56
67
  get session(): WizardSession;
57
68
  set session(value: WizardSession);
58
69
  get statusMessages(): string[];
@@ -74,10 +85,9 @@ export declare class WizardStore {
74
85
  docsUrl: string;
75
86
  }): void;
76
87
  setLoginUrl(url: string | null): void;
77
- setServiceStatus(status: {
78
- description: string;
79
- statusPageUrl: string;
80
- } | null): void;
88
+ setReadinessResult(result: import('../../lib/health-checks/readiness.js').WizardReadinessResult | null): void;
89
+ /** User dismissed the blocking outage screen. Unblocks bin.ts. */
90
+ dismissOutage(): void;
81
91
  /**
82
92
  * Push the settings-override overlay and return a promise that blocks
83
93
  * until the user dismisses it via backupAndFixSettingsOverride().
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Navigation is delegated to WizardRouter.
6
6
  * The active screen is derived from session state — not imperatively set.
7
- * Overlays (outage, etc.) are the only imperative navigation.
7
+ * Overlays (settings-override, port-conflict) are the only imperative navigation.
8
8
  *
9
9
  * All session mutations that affect screen resolution go through
10
10
  * explicit setters so emitChange() is always called.
@@ -14,6 +14,7 @@ import { TaskStatus } from '../wizard-ui.js';
14
14
  import { AdditionalFeature, McpOutcome, RunPhase, buildSession, } from '../../lib/wizard-session.js';
15
15
  import { WizardRouter, Screen, Overlay, Flow, } from './router.js';
16
16
  import { analytics, sessionProperties } from '../../utils/analytics.js';
17
+ import { evaluateWizardReadiness, WizardReadiness, } from '../../lib/health-checks/readiness.js';
17
18
  export { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };
18
19
  export class WizardStore {
19
20
  // ── Internal nanostore atoms ─────────────────────────────────────
@@ -45,8 +46,45 @@ export class WizardStore {
45
46
  _backupAndFixSettings = null;
46
47
  /** Blocks OAuth flow until the port-conflict overlay is dismissed. */
47
48
  _resolvePortConflict = null;
49
+ /**
50
+ * Resolves when the health-check screen is done — either auto-advanced
51
+ * (healthy) or user-dismissed (outage). bin.ts awaits this before runWizard().
52
+ */
53
+ _resolveHealthGate;
54
+ healthGateComplete = new Promise((resolve) => {
55
+ this._resolveHealthGate = resolve;
56
+ });
48
57
  constructor(flow = Flow.Wizard) {
49
58
  this.router = new WizardRouter(flow);
59
+ // Fire health check immediately for Wizard flow so results arrive
60
+ // while the user is still on IntroScreen.
61
+ if (flow === Flow.Wizard) {
62
+ this._initHealthCheck();
63
+ }
64
+ else {
65
+ this._resolveHealthGate();
66
+ }
67
+ }
68
+ /**
69
+ * Kick off the health check. Stores the result and resolves the
70
+ * health gate if non-blocking.
71
+ */
72
+ _initHealthCheck() {
73
+ evaluateWizardReadiness()
74
+ .then((readiness) => {
75
+ this.setReadinessResult(readiness);
76
+ if (readiness.decision !== WizardReadiness.No) {
77
+ this._resolveHealthGate();
78
+ }
79
+ })
80
+ .catch(() => {
81
+ this.setReadinessResult({
82
+ decision: WizardReadiness.Yes,
83
+ health: {},
84
+ reasons: [],
85
+ });
86
+ this._resolveHealthGate();
87
+ });
50
88
  }
51
89
  // ── State accessors (read from atoms) ────────────────────────────
52
90
  get session() {
@@ -120,8 +158,14 @@ export class WizardStore {
120
158
  this.$session.setKey('loginUrl', url);
121
159
  this.emitChange();
122
160
  }
123
- setServiceStatus(status) {
124
- this.$session.setKey('serviceStatus', status);
161
+ setReadinessResult(result) {
162
+ this.$session.setKey('readinessResult', result);
163
+ this.emitChange();
164
+ }
165
+ /** User dismissed the blocking outage screen. Unblocks bin.ts. */
166
+ dismissOutage() {
167
+ this.$session.setKey('outageDismissed', true);
168
+ this._resolveHealthGate();
125
169
  this.emitChange();
126
170
  }
127
171
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/ui/tui/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WizardStore — Nanostore-backed reactive store for the TUI.\n * React components subscribe via useSyncExternalStore.\n *\n * Navigation is delegated to WizardRouter.\n * The active screen is derived from session state — not imperatively set.\n * Overlays (outage, etc.) are the only imperative navigation.\n *\n * All session mutations that affect screen resolution go through\n * explicit setters so emitChange() is always called.\n */\n\nimport { atom, map } from 'nanostores';\nimport { TaskStatus } from '../wizard-ui.js';\nimport {\n type WizardSession,\n type OutroData,\n type DiscoveredFeature,\n AdditionalFeature,\n McpOutcome,\n RunPhase,\n buildSession,\n} from '../../lib/wizard-session.js';\nimport {\n WizardRouter,\n type ScreenName,\n Screen,\n Overlay,\n Flow,\n} from './router.js';\nimport { analytics, sessionProperties } from '../../utils/analytics.js';\n\nexport { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };\nexport type { ScreenName, OutroData, WizardSession };\n\nexport interface TaskItem {\n label: string;\n activeForm?: string;\n status: TaskStatus;\n /** Legacy compat */\n done: boolean;\n}\n\nexport interface PlannedEvent {\n name: string;\n description: string;\n}\n\nexport class WizardStore {\n // ── Internal nanostore atoms ─────────────────────────────────────\n private $session = map<WizardSession>(buildSession({}));\n private $statusMessages = atom<string[]>([]);\n private $statusExpanded = atom(false);\n private $tasks = atom<TaskItem[]>([]);\n private $eventPlan = atom<PlannedEvent[]>([]);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /**\n * Setup promise — IntroScreen resolves this when the user confirms.\n * bin.ts awaits it before calling runWizard.\n */\n private _resolveSetup!: () => void;\n readonly setupComplete: Promise<void> = new Promise((resolve) => {\n this._resolveSetup = resolve;\n });\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n constructor(flow: Flow = Flow.Wizard) {\n this.router = new WizardRouter(flow);\n }\n\n // ── State accessors (read from atoms) ────────────────────────────\n\n get session(): WizardSession {\n return this.$session.get();\n }\n\n set session(value: WizardSession) {\n this.$session.set(value);\n }\n\n get statusMessages(): string[] {\n return this.$statusMessages.get();\n }\n\n get tasks(): TaskItem[] {\n return this.$tasks.get();\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.$eventPlan.get();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n // ── Session setters ─────────────────────────────────────────────\n // Every setter that affects screen resolution calls emitChange().\n // Business logic calls these instead of mutating session directly.\n\n /** Unblocks bin.ts via the setupComplete promise. */\n completeSetup(): void {\n this.$session.setKey('setupConfirmed', true);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this._resolveSetup();\n this.emitChange();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.$session.setKey('runPhase', phase);\n this.emitChange();\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.$session.setKey('credentials', credentials);\n analytics.wizardCapture('auth complete', {\n project_id: credentials?.projectId,\n });\n this.emitChange();\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.$session.setKey('integration', integration);\n this.$session.setKey('frameworkConfig', config);\n this.$session.setKey('unsupportedVersion', null);\n this.emitChange();\n }\n\n setDetectionComplete(): void {\n this.$session.setKey('detectionComplete', true);\n this.emitChange();\n }\n\n setDetectedFramework(label: string): void {\n this.$session.setKey('detectedFrameworkLabel', label);\n this.emitChange();\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.$session.setKey('unsupportedVersion', info);\n this.emitChange();\n }\n\n setLoginUrl(url: string | null): void {\n this.$session.setKey('loginUrl', url);\n this.emitChange();\n }\n\n setServiceStatus(\n status: { description: string; statusPageUrl: string } | null,\n ): void {\n this.$session.setKey('serviceStatus', status);\n this.emitChange();\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n keys: string[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n this.$session.setKey('settingsOverrideKeys', keys);\n this._backupAndFixSettings = backupAndFix;\n this.pushOverlay(Overlay.SettingsOverride);\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user kills the blocking process or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void> {\n this.$session.setKey('portConflictProcess', processInfo);\n this.pushOverlay(Overlay.PortConflict);\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay after the user kills the process. */\n resolvePortConflict(): void {\n this.$session.setKey('portConflictProcess', null);\n this.popOverlay();\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.$session.setKey('settingsOverrideKeys', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n if (!this.session.discoveredFeatures.includes(feature)) {\n this.session.discoveredFeatures.push(feature);\n this.emitChange();\n }\n }\n\n /**\n * Enable an additional feature: enqueue it for the stop hook\n * and set any feature-specific session flags.\n */\n enableFeature(feature: AdditionalFeature): void {\n if (!this.session.additionalFeatureQueue.includes(feature)) {\n this.session.additionalFeatureQueue.push(feature);\n }\n // Feature-specific flags\n if (feature === AdditionalFeature.LLM) {\n this.session.llmOptIn = true;\n }\n analytics.wizardCapture('feature enabled', { feature });\n this.emitChange();\n }\n\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n ): void {\n this.$session.setKey('mcpComplete', true);\n this.$session.setKey('mcpOutcome', outcome);\n this.$session.setKey('mcpInstalledClients', installedClients);\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setOutroData(data: OutroData): void {\n this.$session.setKey('outroData', data);\n this.emitChange();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n const ctx = { ...this.$session.get().frameworkContext, [key]: value };\n this.$session.setKey('frameworkContext', ctx);\n this.emitChange();\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this.session);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Screen transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this.session);\n const prev = this._lastScreen;\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n const msgs = this.$statusMessages.get();\n // Skip consecutive duplicate messages\n if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;\n this.$statusMessages.set([...msgs, message]);\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.$tasks.set(tasks);\n this.emitChange();\n }\n\n updateTask(index: number, done: boolean): void {\n const tasks = this.$tasks.get();\n if (tasks[index]) {\n const updated = [...tasks];\n updated[index] = {\n ...updated[index],\n done,\n status: done ? TaskStatus.Completed : TaskStatus.Pending,\n };\n this.$tasks.set(updated);\n this.emitChange();\n }\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.$eventPlan.set(events);\n this.emitChange();\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const incoming = todos.map((t) => ({\n label: t.content,\n activeForm: t.activeForm,\n status: (t.status as TaskStatus) || TaskStatus.Pending,\n done: t.status === TaskStatus.Completed,\n }));\n\n const incomingLabels = new Set(incoming.map((t) => t.label));\n\n const retained = this.$tasks\n .get()\n .filter((t) => t.done && !incomingLabels.has(t.label));\n\n this.$tasks.set([...retained, ...incoming]);\n this.emitChange();\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/ui/tui/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WizardStore — Nanostore-backed reactive store for the TUI.\n * React components subscribe via useSyncExternalStore.\n *\n * Navigation is delegated to WizardRouter.\n * The active screen is derived from session state — not imperatively set.\n * Overlays (settings-override, port-conflict) are the only imperative navigation.\n *\n * All session mutations that affect screen resolution go through\n * explicit setters so emitChange() is always called.\n */\n\nimport { atom, map } from 'nanostores';\nimport { TaskStatus } from '../wizard-ui.js';\nimport {\n type WizardSession,\n type OutroData,\n type DiscoveredFeature,\n AdditionalFeature,\n McpOutcome,\n RunPhase,\n buildSession,\n} from '../../lib/wizard-session.js';\nimport {\n WizardRouter,\n type ScreenName,\n Screen,\n Overlay,\n Flow,\n} from './router.js';\nimport { analytics, sessionProperties } from '../../utils/analytics.js';\nimport {\n evaluateWizardReadiness,\n WizardReadiness,\n} from '../../lib/health-checks/readiness.js';\n\nexport { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };\nexport type { ScreenName, OutroData, WizardSession };\n\nexport interface TaskItem {\n label: string;\n activeForm?: string;\n status: TaskStatus;\n /** Legacy compat */\n done: boolean;\n}\n\nexport interface PlannedEvent {\n name: string;\n description: string;\n}\n\nexport class WizardStore {\n // ── Internal nanostore atoms ─────────────────────────────────────\n private $session = map<WizardSession>(buildSession({}));\n private $statusMessages = atom<string[]>([]);\n private $statusExpanded = atom(false);\n private $tasks = atom<TaskItem[]>([]);\n private $eventPlan = atom<PlannedEvent[]>([]);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /**\n * Setup promise — IntroScreen resolves this when the user confirms.\n * bin.ts awaits it before calling runWizard.\n */\n private _resolveSetup!: () => void;\n readonly setupComplete: Promise<void> = new Promise((resolve) => {\n this._resolveSetup = resolve;\n });\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n /**\n * Resolves when the health-check screen is done — either auto-advanced\n * (healthy) or user-dismissed (outage). bin.ts awaits this before runWizard().\n */\n private _resolveHealthGate!: () => void;\n readonly healthGateComplete: Promise<void> = new Promise((resolve) => {\n this._resolveHealthGate = resolve;\n });\n\n constructor(flow: Flow = Flow.Wizard) {\n this.router = new WizardRouter(flow);\n\n // Fire health check immediately for Wizard flow so results arrive\n // while the user is still on IntroScreen.\n if (flow === Flow.Wizard) {\n this._initHealthCheck();\n } else {\n this._resolveHealthGate();\n }\n }\n\n /**\n * Kick off the health check. Stores the result and resolves the\n * health gate if non-blocking.\n */\n private _initHealthCheck(): void {\n evaluateWizardReadiness()\n .then((readiness) => {\n this.setReadinessResult(readiness);\n if (readiness.decision !== WizardReadiness.No) {\n this._resolveHealthGate();\n }\n })\n .catch(() => {\n this.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n this._resolveHealthGate();\n });\n }\n\n // ── State accessors (read from atoms) ────────────────────────────\n\n get session(): WizardSession {\n return this.$session.get();\n }\n\n set session(value: WizardSession) {\n this.$session.set(value);\n }\n\n get statusMessages(): string[] {\n return this.$statusMessages.get();\n }\n\n get tasks(): TaskItem[] {\n return this.$tasks.get();\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.$eventPlan.get();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n // ── Session setters ─────────────────────────────────────────────\n // Every setter that affects screen resolution calls emitChange().\n // Business logic calls these instead of mutating session directly.\n\n /** Unblocks bin.ts via the setupComplete promise. */\n completeSetup(): void {\n this.$session.setKey('setupConfirmed', true);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this._resolveSetup();\n this.emitChange();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.$session.setKey('runPhase', phase);\n this.emitChange();\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.$session.setKey('credentials', credentials);\n analytics.wizardCapture('auth complete', {\n project_id: credentials?.projectId,\n });\n this.emitChange();\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.$session.setKey('integration', integration);\n this.$session.setKey('frameworkConfig', config);\n this.$session.setKey('unsupportedVersion', null);\n this.emitChange();\n }\n\n setDetectionComplete(): void {\n this.$session.setKey('detectionComplete', true);\n this.emitChange();\n }\n\n setDetectedFramework(label: string): void {\n this.$session.setKey('detectedFrameworkLabel', label);\n this.emitChange();\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.$session.setKey('unsupportedVersion', info);\n this.emitChange();\n }\n\n setLoginUrl(url: string | null): void {\n this.$session.setKey('loginUrl', url);\n this.emitChange();\n }\n\n setReadinessResult(\n result:\n | import('../../lib/health-checks/readiness.js').WizardReadinessResult\n | null,\n ): void {\n this.$session.setKey('readinessResult', result);\n this.emitChange();\n }\n\n /** User dismissed the blocking outage screen. Unblocks bin.ts. */\n dismissOutage(): void {\n this.$session.setKey('outageDismissed', true);\n this._resolveHealthGate();\n this.emitChange();\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n keys: string[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n this.$session.setKey('settingsOverrideKeys', keys);\n this._backupAndFixSettings = backupAndFix;\n this.pushOverlay(Overlay.SettingsOverride);\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user kills the blocking process or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void> {\n this.$session.setKey('portConflictProcess', processInfo);\n this.pushOverlay(Overlay.PortConflict);\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay after the user kills the process. */\n resolvePortConflict(): void {\n this.$session.setKey('portConflictProcess', null);\n this.popOverlay();\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.$session.setKey('settingsOverrideKeys', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n if (!this.session.discoveredFeatures.includes(feature)) {\n this.session.discoveredFeatures.push(feature);\n this.emitChange();\n }\n }\n\n /**\n * Enable an additional feature: enqueue it for the stop hook\n * and set any feature-specific session flags.\n */\n enableFeature(feature: AdditionalFeature): void {\n if (!this.session.additionalFeatureQueue.includes(feature)) {\n this.session.additionalFeatureQueue.push(feature);\n }\n // Feature-specific flags\n if (feature === AdditionalFeature.LLM) {\n this.session.llmOptIn = true;\n }\n analytics.wizardCapture('feature enabled', { feature });\n this.emitChange();\n }\n\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n ): void {\n this.$session.setKey('mcpComplete', true);\n this.$session.setKey('mcpOutcome', outcome);\n this.$session.setKey('mcpInstalledClients', installedClients);\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setOutroData(data: OutroData): void {\n this.$session.setKey('outroData', data);\n this.emitChange();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n const ctx = { ...this.$session.get().frameworkContext, [key]: value };\n this.$session.setKey('frameworkContext', ctx);\n this.emitChange();\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this.session);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Screen transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this.session);\n const prev = this._lastScreen;\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n const msgs = this.$statusMessages.get();\n // Skip consecutive duplicate messages\n if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;\n this.$statusMessages.set([...msgs, message]);\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.$tasks.set(tasks);\n this.emitChange();\n }\n\n updateTask(index: number, done: boolean): void {\n const tasks = this.$tasks.get();\n if (tasks[index]) {\n const updated = [...tasks];\n updated[index] = {\n ...updated[index],\n done,\n status: done ? TaskStatus.Completed : TaskStatus.Pending,\n };\n this.$tasks.set(updated);\n this.emitChange();\n }\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.$eventPlan.set(events);\n this.emitChange();\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const incoming = todos.map((t) => ({\n label: t.content,\n activeForm: t.activeForm,\n status: (t.status as TaskStatus) || TaskStatus.Pending,\n done: t.status === TaskStatus.Completed,\n }));\n\n const incomingLabels = new Set(incoming.map((t) => t.label));\n\n const retained = this.$tasks\n .get()\n .filter((t) => t.done && !incomingLabels.has(t.label));\n\n this.$tasks.set([...retained, ...incoming]);\n this.emitChange();\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n"]}
@@ -40,11 +40,10 @@ export interface WizardUI {
40
40
  host: string;
41
41
  projectId: number;
42
42
  }): void;
43
- /** Show service degradation (pushes outage overlay in TUI). */
44
- showServiceStatus(data: {
45
- description: string;
46
- statusPageUrl: string;
47
- }): void;
43
+ /** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */
44
+ showBlockingOutage(result: import('../lib/health-checks/readiness.js').WizardReadinessResult): Promise<void>;
45
+ /** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */
46
+ setReadinessWarnings(result: import('../lib/health-checks/readiness.js').WizardReadinessResult): void;
48
47
  /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */
49
48
  showPortConflict(processInfo: {
50
49
  command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"wizard-ui.js","sourceRoot":"","sources":["../../../src/ui/wizard-ui.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,iCAAmB,CAAA;IACnB,wCAA0B,CAAA;IAC1B,qCAAuB,CAAA;AACzB,CAAC,EAJW,UAAU,0BAAV,UAAU,QAIrB","sourcesContent":["/**\n * WizardUI — abstraction layer for all user-facing operations.\n *\n * Business logic calls `getUI()` instead of importing the store directly.\n * Implementations: InkUI (TUI), LoggingUI (CI).\n *\n * No prompt methods — the TUI screens own all user input.\n * Session-mutating methods trigger reactive screen resolution in the TUI.\n */\n\nexport enum TaskStatus {\n Pending = 'pending',\n InProgress = 'in_progress',\n Completed = 'completed',\n}\n\nexport interface SpinnerHandle {\n start(message?: string): void;\n stop(message?: string): void;\n message(msg?: string): void;\n}\n\nexport interface WizardUI {\n // ── Lifecycle messages ────────────────────────────────────────────\n intro(message: string): void;\n outro(message: string): void;\n cancel(message: string): void;\n\n // ── Logging ───────────────────────────────────────────────────────\n log: {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n };\n\n note(message: string): void;\n pushStatus(message: string): void;\n\n // ── Spinner ───────────────────────────────────────────────────────\n spinner(): SpinnerHandle;\n\n // ── Session state (triggers reactive screen resolution in TUI) ────\n /** Signal that the main work (agent run) has started. */\n startRun(): void;\n\n /** Store OAuth/API credentials. Resolves past AuthScreen in TUI. */\n setCredentials(credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void;\n\n /** Show service degradation (pushes outage overlay in TUI). */\n showServiceStatus(data: { description: string; statusPageUrl: string }): void;\n\n /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void>;\n\n /** Warn that .claude/settings.json overrides blocking env vars (pushes blocking overlay in TUI). */\n showSettingsOverride(\n keys: string[],\n backupAndFix: () => boolean,\n ): Promise<void>;\n\n // ── Display state ──────────────────────────────────────────────────\n /** Set the detected framework label (e.g., \"Django with Wagtail CMS\") */\n setDetectedFramework(label: string): void;\n\n /** Register a callback to run when the TUI transitions onto the given screen. */\n onEnterScreen(screen: string, fn: () => void): void;\n\n setLoginUrl(url: string | null): void;\n\n // ── Todo tracking from SDK TodoWrite events ───────────────────────\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void;\n\n // ── Event plan from .posthog-events.json ────────────────────\n setEventPlan(events: Array<{ name: string; description: string }>): void;\n}\n"]}
1
+ {"version":3,"file":"wizard-ui.js","sourceRoot":"","sources":["../../../src/ui/wizard-ui.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,iCAAmB,CAAA;IACnB,wCAA0B,CAAA;IAC1B,qCAAuB,CAAA;AACzB,CAAC,EAJW,UAAU,0BAAV,UAAU,QAIrB","sourcesContent":["/**\n * WizardUI — abstraction layer for all user-facing operations.\n *\n * Business logic calls `getUI()` instead of importing the store directly.\n * Implementations: InkUI (TUI), LoggingUI (CI).\n *\n * No prompt methods — the TUI screens own all user input.\n * Session-mutating methods trigger reactive screen resolution in the TUI.\n */\n\nexport enum TaskStatus {\n Pending = 'pending',\n InProgress = 'in_progress',\n Completed = 'completed',\n}\n\nexport interface SpinnerHandle {\n start(message?: string): void;\n stop(message?: string): void;\n message(msg?: string): void;\n}\n\nexport interface WizardUI {\n // ── Lifecycle messages ────────────────────────────────────────────\n intro(message: string): void;\n outro(message: string): void;\n cancel(message: string): void;\n\n // ── Logging ───────────────────────────────────────────────────────\n log: {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n };\n\n note(message: string): void;\n pushStatus(message: string): void;\n\n // ── Spinner ───────────────────────────────────────────────────────\n spinner(): SpinnerHandle;\n\n // ── Session state (triggers reactive screen resolution in TUI) ────\n /** Signal that the main work (agent run) has started. */\n startRun(): void;\n\n /** Store OAuth/API credentials. Resolves past AuthScreen in TUI. */\n setCredentials(credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void;\n\n /** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */\n showBlockingOutage(\n result: import('../lib/health-checks/readiness.js').WizardReadinessResult,\n ): Promise<void>;\n\n /** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */\n setReadinessWarnings(\n result: import('../lib/health-checks/readiness.js').WizardReadinessResult,\n ): void;\n\n /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void>;\n\n /** Warn that .claude/settings.json overrides blocking env vars (pushes blocking overlay in TUI). */\n showSettingsOverride(\n keys: string[],\n backupAndFix: () => boolean,\n ): Promise<void>;\n\n // ── Display state ──────────────────────────────────────────────────\n /** Set the detected framework label (e.g., \"Django with Wagtail CMS\") */\n setDetectedFramework(label: string): void;\n\n /** Register a callback to run when the TUI transitions onto the given screen. */\n onEnterScreen(screen: string, fn: () => void): void;\n\n setLoginUrl(url: string | null): void;\n\n // ── Todo tracking from SDK TodoWrite events ───────────────────────\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void;\n\n // ── Event plan from .posthog-events.json ────────────────────\n setEventPlan(events: Array<{ name: string; description: string }>): void;\n}\n"]}
@@ -61,7 +61,8 @@ jest.mock('../../ui', () => ({
61
61
  pushStatus: jest.fn(),
62
62
  syncTodos: jest.fn(),
63
63
  setLoginUrl: jest.fn(),
64
- showServiceStatus: jest.fn(),
64
+ showBlockingOutage: jest.fn(),
65
+ setReadinessWarnings: jest.fn(),
65
66
  showSettingsOverride: jest.fn(),
66
67
  startRun: jest.fn(),
67
68
  note: jest.fn(),
@@ -1 +1 @@
1
- {"version":3,"file":"setup-utils.test.js","sourceRoot":"","sources":["../../../../src/utils/__tests__/setup-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { installPackage } from '../setup-utils';\n\nimport * as ChildProcess from 'node:child_process';\nimport type { PackageManager } from '../package-manager';\n\njest.mock('node:child_process', () => ({\n __esModule: true,\n ...jest.requireActual('node:child_process'),\n}));\n\njest.mock('../../ui', () => ({\n getUI: jest.fn().mockReturnValue({\n log: {\n info: jest.fn(),\n success: jest.fn(),\n warn: jest.fn(),\n error: jest.fn(),\n step: jest.fn(),\n },\n cancel: jest.fn(),\n outro: jest.fn(),\n intro: jest.fn(),\n spinner: jest.fn().mockImplementation(() => ({\n start: jest.fn(),\n stop: jest.fn(),\n message: jest.fn(),\n })),\n setDetectedFramework: jest.fn(),\n setCredentials: jest.fn(),\n pushStatus: jest.fn(),\n syncTodos: jest.fn(),\n setLoginUrl: jest.fn(),\n showServiceStatus: jest.fn(),\n showSettingsOverride: jest.fn(),\n startRun: jest.fn(),\n note: jest.fn(),\n }),\n}));\n\ndescribe.skip('installPackage', () => {\n afterEach(() => {\n jest.clearAllMocks();\n });\n\n it('force-installs a package if the forceInstall flag is set', async () => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'npm install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: jest.fn(),\n addOverride: jest.fn(),\n };\n\n const execSpy = jest\n .spyOn(ChildProcess, 'exec')\n // @ts-expect-error - don't care about the return value\n .mockImplementationOnce((cmd, cb) => {\n if (cb) {\n // @ts-expect-error - don't care about the options value\n cb(null, '', '');\n }\n });\n\n await installPackage({\n alreadyInstalled: false,\n packageName: 'posthog-js',\n packageNameDisplayLabel: 'posthog-js',\n forceInstall: true,\n packageManager: packageManagerMock,\n installDir: process.cwd(),\n });\n\n expect(execSpy).toHaveBeenCalledWith(\n 'npm install posthog-js --force',\n expect.any(Function),\n );\n });\n\n it.each([false, undefined])(\n \"doesn't force-install a package if the forceInstall flag is %s\",\n async (flag) => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'npm install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: jest.fn(),\n addOverride: jest.fn(),\n };\n\n const execSpy = jest\n .spyOn(ChildProcess, 'exec')\n // @ts-expect-error - don't care about the return value\n .mockImplementationOnce((cmd, cb) => {\n if (cb) {\n // @ts-expect-error - don't care about the options value\n cb(null, '', '');\n }\n });\n\n await installPackage({\n alreadyInstalled: false,\n packageName: 'posthog-js',\n packageNameDisplayLabel: 'posthog-js',\n forceInstall: flag,\n packageManager: packageManagerMock,\n installDir: process.cwd(),\n });\n\n expect(execSpy).toHaveBeenCalledWith(\n 'npm install posthog-js ',\n expect.any(Function),\n );\n },\n );\n});\n"]}
1
+ {"version":3,"file":"setup-utils.test.js","sourceRoot":"","sources":["../../../../src/utils/__tests__/setup-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { installPackage } from '../setup-utils';\n\nimport * as ChildProcess from 'node:child_process';\nimport type { PackageManager } from '../package-manager';\n\njest.mock('node:child_process', () => ({\n __esModule: true,\n ...jest.requireActual('node:child_process'),\n}));\n\njest.mock('../../ui', () => ({\n getUI: jest.fn().mockReturnValue({\n log: {\n info: jest.fn(),\n success: jest.fn(),\n warn: jest.fn(),\n error: jest.fn(),\n step: jest.fn(),\n },\n cancel: jest.fn(),\n outro: jest.fn(),\n intro: jest.fn(),\n spinner: jest.fn().mockImplementation(() => ({\n start: jest.fn(),\n stop: jest.fn(),\n message: jest.fn(),\n })),\n setDetectedFramework: jest.fn(),\n setCredentials: jest.fn(),\n pushStatus: jest.fn(),\n syncTodos: jest.fn(),\n setLoginUrl: jest.fn(),\n showBlockingOutage: jest.fn(),\n setReadinessWarnings: jest.fn(),\n showSettingsOverride: jest.fn(),\n startRun: jest.fn(),\n note: jest.fn(),\n }),\n}));\n\ndescribe.skip('installPackage', () => {\n afterEach(() => {\n jest.clearAllMocks();\n });\n\n it('force-installs a package if the forceInstall flag is set', async () => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'npm install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: jest.fn(),\n addOverride: jest.fn(),\n };\n\n const execSpy = jest\n .spyOn(ChildProcess, 'exec')\n // @ts-expect-error - don't care about the return value\n .mockImplementationOnce((cmd, cb) => {\n if (cb) {\n // @ts-expect-error - don't care about the options value\n cb(null, '', '');\n }\n });\n\n await installPackage({\n alreadyInstalled: false,\n packageName: 'posthog-js',\n packageNameDisplayLabel: 'posthog-js',\n forceInstall: true,\n packageManager: packageManagerMock,\n installDir: process.cwd(),\n });\n\n expect(execSpy).toHaveBeenCalledWith(\n 'npm install posthog-js --force',\n expect.any(Function),\n );\n });\n\n it.each([false, undefined])(\n \"doesn't force-install a package if the forceInstall flag is %s\",\n async (flag) => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'npm install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: jest.fn(),\n addOverride: jest.fn(),\n };\n\n const execSpy = jest\n .spyOn(ChildProcess, 'exec')\n // @ts-expect-error - don't care about the return value\n .mockImplementationOnce((cmd, cb) => {\n if (cb) {\n // @ts-expect-error - don't care about the options value\n cb(null, '', '');\n }\n });\n\n await installPackage({\n alreadyInstalled: false,\n packageName: 'posthog-js',\n packageNameDisplayLabel: 'posthog-js',\n forceInstall: flag,\n packageManager: packageManagerMock,\n installDir: process.cwd(),\n });\n\n expect(execSpy).toHaveBeenCalledWith(\n 'npm install posthog-js ',\n expect.any(Function),\n );\n },\n );\n});\n"]}
@@ -1,5 +1,17 @@
1
1
  Never hallucinate an API key. Instead, always use the API key populated in the .env file.
2
2
 
3
+ 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.
4
+
5
+ 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.
6
+
7
+ 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.
8
+
9
+ 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.
10
+
11
+ 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.
12
+
13
+ Do not spawn subagents unless explicitly instructed to do so.
14
+
3
15
  # Feature flags
4
16
 
5
17
  A given feature flag should be used in as few places as possible. Do not increase the risk of undefined behavior by scattering the same feature flag across multiple areas of code. If the same feature flag needs to be introduced at multiple callsites, flag this for the developer to inspect carefully.
@@ -56,6 +56,15 @@ export type WizardOptions = {
56
56
  * and writes detailed usage data to /tmp/posthog-wizard-benchmark.json.
57
57
  */
58
58
  benchmark: boolean;
59
+ /**
60
+ * Cloud region for the PostHog instance (US or EU).
61
+ * When not provided, the user will be prompted to select one.
62
+ */
63
+ cloudRegion?: CloudRegion;
64
+ /**
65
+ * Whether to print a YARA scanner summary after the agent run.
66
+ */
67
+ yaraReport: boolean;
59
68
  };
60
69
  export interface Feature {
61
70
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/types.ts"],"names":[],"mappings":"","sourcesContent":["export type PostHogProjectData = Record<string, unknown>;\n\nexport type PreselectedProject = {\n project: PostHogProjectData;\n authToken: string;\n};\n\nexport type WizardOptions = {\n /**\n * Whether to enable debug mode.\n */\n debug: boolean;\n\n /**\n * Whether to force install the SDK package to continue with the installation in case\n * any package manager checks are failing (e.g. peer dependency versions).\n *\n * Use with caution and only if you know what you're doing.\n *\n * Does not apply to all wizard flows (currently NPM only)\n */\n forceInstall: boolean;\n\n /**\n * The directory to run the wizard in.\n */\n installDir: string;\n\n /**\n * Whether to select the default option for all questions automatically.\n */\n default: boolean;\n\n /**\n * Whether to create a new PostHog account during setup.\n */\n signup: boolean;\n\n /**\n * Whether to use the local MCP server at http://localhost:8787/mcp\n */\n localMcp: boolean;\n\n /**\n * CI mode - non-interactive execution\n */\n ci: boolean;\n\n /**\n * Personal API key (phx_xxx) - used for LLM gateway auth, skips OAuth\n */\n apiKey?: string;\n\n /**\n * PostHog project ID. When set (e.g. in CI with --project-id), the wizard uses this project\n * instead of the default from the API key or OAuth.\n */\n projectId?: number;\n\n /**\n * Whether to show the menu for manual integration selection instead of auto-detecting.\n */\n menu: boolean;\n\n /**\n * Whether to run in benchmark mode with per-phase token tracking.\n * When enabled, the wizard runs each workflow phase as a separate agent call\n * and writes detailed usage data to /tmp/posthog-wizard-benchmark.json.\n */\n benchmark: boolean;\n};\n\nexport interface Feature {\n id: string;\n prompt: string;\n enabledHint?: string;\n disabledHint?: string;\n}\n\nexport type FileChange = {\n filePath: string;\n oldContent?: string;\n newContent: string;\n};\n\nexport type CloudRegion = 'us' | 'eu';\n\nexport type AIModel =\n | 'gpt-5-mini'\n | 'o4-mini'\n | 'gemini-2.5-flash'\n | 'gemini-2.5-pro';\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/types.ts"],"names":[],"mappings":"","sourcesContent":["export type PostHogProjectData = Record<string, unknown>;\n\nexport type PreselectedProject = {\n project: PostHogProjectData;\n authToken: string;\n};\n\nexport type WizardOptions = {\n /**\n * Whether to enable debug mode.\n */\n debug: boolean;\n\n /**\n * Whether to force install the SDK package to continue with the installation in case\n * any package manager checks are failing (e.g. peer dependency versions).\n *\n * Use with caution and only if you know what you're doing.\n *\n * Does not apply to all wizard flows (currently NPM only)\n */\n forceInstall: boolean;\n\n /**\n * The directory to run the wizard in.\n */\n installDir: string;\n\n /**\n * Whether to select the default option for all questions automatically.\n */\n default: boolean;\n\n /**\n * Whether to create a new PostHog account during setup.\n */\n signup: boolean;\n\n /**\n * Whether to use the local MCP server at http://localhost:8787/mcp\n */\n localMcp: boolean;\n\n /**\n * CI mode - non-interactive execution\n */\n ci: boolean;\n\n /**\n * Personal API key (phx_xxx) - used for LLM gateway auth, skips OAuth\n */\n apiKey?: string;\n\n /**\n * PostHog project ID. When set (e.g. in CI with --project-id), the wizard uses this project\n * instead of the default from the API key or OAuth.\n */\n projectId?: number;\n\n /**\n * Whether to show the menu for manual integration selection instead of auto-detecting.\n */\n menu: boolean;\n\n /**\n * Whether to run in benchmark mode with per-phase token tracking.\n * When enabled, the wizard runs each workflow phase as a separate agent call\n * and writes detailed usage data to /tmp/posthog-wizard-benchmark.json.\n */\n benchmark: boolean;\n\n /**\n * Cloud region for the PostHog instance (US or EU).\n * When not provided, the user will be prompted to select one.\n */\n cloudRegion?: CloudRegion;\n\n /**\n * Whether to print a YARA scanner summary after the agent run.\n */\n yaraReport: boolean;\n};\n\nexport interface Feature {\n id: string;\n prompt: string;\n enabledHint?: string;\n disabledHint?: string;\n}\n\nexport type FileChange = {\n filePath: string;\n oldContent?: string;\n newContent: string;\n};\n\nexport type CloudRegion = 'us' | 'eu';\n\nexport type AIModel =\n | 'gpt-5-mini'\n | 'o4-mini'\n | 'gemini-2.5-flash'\n | 'gemini-2.5-pro';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/wizard",
3
- "version": "2.0.2",
3
+ "version": "2.2.0",
4
4
  "homepage": "https://github.com/PostHog/wizard",
5
5
  "repository": "https://github.com/PostHog/wizard",
6
6
  "description": "The PostHog wizard helps you to configure your project",
@@ -32,7 +32,7 @@
32
32
  "definition": "dist/index.d.ts"
33
33
  },
34
34
  "dependencies": {
35
- "@anthropic-ai/claude-agent-sdk": "0.2.7",
35
+ "@anthropic-ai/claude-agent-sdk": "0.2.73",
36
36
  "@inkjs/ui": "^2.0.0",
37
37
  "@langchain/core": "^0.3.40",
38
38
  "axios": "1.7.4",
@@ -1,10 +0,0 @@
1
- /**
2
- * OutageScreen — Shown when Claude/Anthropic services are degraded.
3
- * Reads session.serviceStatus and provides a ConfirmationInput to continue or exit.
4
- */
5
- import type { WizardStore } from '../store.js';
6
- interface OutageScreenProps {
7
- store: WizardStore;
8
- }
9
- export declare const OutageScreen: ({ store }: OutageScreenProps) => import("react/jsx-runtime").JSX.Element | null;
10
- export {};
@@ -1,17 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * OutageScreen — Shown when Claude/Anthropic services are degraded.
4
- * Reads session.serviceStatus and provides a ConfirmationInput to continue or exit.
5
- */
6
- import { Box, Text } from 'ink';
7
- import { useSyncExternalStore } from 'react';
8
- import { ConfirmationInput } from '../primitives/index.js';
9
- export const OutageScreen = ({ store }) => {
10
- useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
11
- const serviceStatus = store.session.serviceStatus;
12
- if (!serviceStatus) {
13
- return null;
14
- }
15
- return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { color: "yellow", bold: true, children: ['\u26A0', " Claude/Anthropic services are experiencing issues."] }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [_jsx(Text, { color: "yellow", children: "Status:" }), " ", serviceStatus.description] }), _jsxs(Text, { children: [_jsx(Text, { color: "yellow", children: "Status page:" }), ' ', _jsx(Text, { color: "cyan", children: serviceStatus.statusPageUrl })] }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "The wizard may not work reliably while services are affected." })] }), _jsx(ConfirmationInput, { message: "Continue anyway?", onConfirm: () => store.popOverlay(), onCancel: () => process.exit(0) })] }));
16
- };
17
- //# sourceMappingURL=OutageScreen.js.map