@posthog/wizard 2.2.0 → 2.4.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.
- package/dist/src/lib/__tests__/agent-interface.test.js +22 -0
- package/dist/src/lib/__tests__/agent-interface.test.js.map +1 -1
- package/dist/src/lib/agent-interface.d.ts +20 -2
- package/dist/src/lib/agent-interface.js +97 -14
- package/dist/src/lib/agent-interface.js.map +1 -1
- package/dist/src/lib/agent-runner.js +21 -9
- package/dist/src/lib/agent-runner.js.map +1 -1
- package/dist/src/lib/api.d.ts +4 -4
- package/dist/src/lib/constants.d.ts +1 -1
- package/dist/src/lib/health-checks/__tests__/health-checks.test.js +11 -4
- package/dist/src/lib/health-checks/__tests__/health-checks.test.js.map +1 -1
- package/dist/src/lib/health-checks/endpoints.d.ts +1 -0
- package/dist/src/lib/health-checks/endpoints.js +3 -1
- package/dist/src/lib/health-checks/endpoints.js.map +1 -1
- package/dist/src/lib/health-checks/index.d.ts +1 -1
- package/dist/src/lib/health-checks/index.js +2 -1
- package/dist/src/lib/health-checks/index.js.map +1 -1
- package/dist/src/lib/health-checks/readiness.js +12 -3
- package/dist/src/lib/health-checks/readiness.js.map +1 -1
- package/dist/src/lib/health-checks/types.d.ts +1 -0
- package/dist/src/lib/health-checks/types.js.map +1 -1
- package/dist/src/lib/version.d.ts +1 -1
- package/dist/src/lib/version.js +1 -1
- package/dist/src/lib/version.js.map +1 -1
- package/dist/src/lib/wizard-session.d.ts +2 -0
- package/dist/src/lib/wizard-session.js +1 -0
- package/dist/src/lib/wizard-session.js.map +1 -1
- package/dist/src/lib/wizard-tools.d.ts +22 -0
- package/dist/src/lib/wizard-tools.js +71 -39
- package/dist/src/lib/wizard-tools.js.map +1 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/zed.d.ts +6 -6
- package/dist/src/ui/logging-ui.d.ts +3 -1
- package/dist/src/ui/logging-ui.js +6 -6
- package/dist/src/ui/logging-ui.js.map +1 -1
- package/dist/src/ui/tui/ink-ui.d.ts +3 -1
- package/dist/src/ui/tui/ink-ui.js +5 -2
- package/dist/src/ui/tui/ink-ui.js.map +1 -1
- package/dist/src/ui/tui/playground/demos/HealthCheckDemo.js +1 -0
- package/dist/src/ui/tui/playground/demos/HealthCheckDemo.js.map +1 -1
- package/dist/src/ui/tui/router.d.ts +3 -1
- package/dist/src/ui/tui/router.js +2 -0
- package/dist/src/ui/tui/router.js.map +1 -1
- package/dist/src/ui/tui/screen-registry.js +4 -0
- package/dist/src/ui/tui/screen-registry.js.map +1 -1
- package/dist/src/ui/tui/screens/AuthErrorScreen.d.ts +7 -0
- package/dist/src/ui/tui/screens/AuthErrorScreen.js +16 -0
- package/dist/src/ui/tui/screens/AuthErrorScreen.js.map +1 -0
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.d.ts +13 -0
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.js +32 -0
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.js.map +1 -0
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.d.ts +0 -4
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.js +13 -7
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.js.map +1 -1
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.js +50 -5
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.js.map +1 -1
- package/dist/src/ui/tui/store.d.ts +4 -1
- package/dist/src/ui/tui/store.js +16 -3
- package/dist/src/ui/tui/store.js.map +1 -1
- package/dist/src/ui/wizard-ui.d.ts +4 -2
- package/dist/src/ui/wizard-ui.js.map +1 -1
- package/dist/src/utils/__tests__/semver.test.js +45 -3
- package/dist/src/utils/__tests__/semver.test.js.map +1 -1
- package/dist/src/utils/semver.js +25 -0
- package/dist/src/utils/semver.js.map +1 -1
- package/package.json +1 -1
|
@@ -19,7 +19,9 @@ export { Screen, Flow };
|
|
|
19
19
|
export var Overlay;
|
|
20
20
|
(function (Overlay) {
|
|
21
21
|
Overlay["SettingsOverride"] = "settings-override";
|
|
22
|
+
Overlay["ManagedSettings"] = "managed-settings";
|
|
22
23
|
Overlay["PortConflict"] = "port-conflict";
|
|
24
|
+
Overlay["AuthError"] = "auth-error";
|
|
23
25
|
})(Overlay || (Overlay = {}));
|
|
24
26
|
// ── Router ────────────────────────────────────────────────────────────
|
|
25
27
|
export class WizardRouter {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../../src/ui/tui/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAC;AAEjE,gEAAgE;AAChE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAGxB,yEAAyE;AAEzE,+CAA+C;AAC/C,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../../src/ui/tui/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAC;AAEjE,gEAAgE;AAChE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAGxB,yEAAyE;AAEzE,+CAA+C;AAC/C,MAAM,CAAN,IAAY,OAKX;AALD,WAAY,OAAO;IACjB,iDAAsC,CAAA;IACtC,+CAAoC,CAAA;IACpC,yCAA8B,CAAA;IAC9B,mCAAwB,CAAA;AAC1B,CAAC,EALW,OAAO,KAAP,OAAO,QAKlB;AAKD,yEAAyE;AAEzE,MAAM,OAAO,YAAY;IACf,IAAI,CAAc;IAClB,QAAQ,CAAO;IACf,QAAQ,GAAc,EAAE,CAAC;IAEjC,YAAY,WAAiB,IAAI,CAAC,MAAM;QACtC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,OAAsB;QAC5B,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;gBAAE,SAAS;YACjD,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC5D,OAAO,KAAK,CAAC,MAAM,CAAC;QACtB,CAAC;QAED,sDAAsD;QACtD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAChD,CAAC;IAED,oDAAoD;IACpD,IAAI,YAAY;QACd,uDAAuD;QACvD,uEAAuE;QACvE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,mCAAmC;IACnC,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,8CAA8C;IAC9C,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAClC,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,OAAgB;QAC1B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,cAAc,GAA0B,IAAI,CAAC;IAErD,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,6DAA6D;IAC7D,aAAa,CAAC,GAA0B;QACtC,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC;IAC5B,CAAC;CACF","sourcesContent":["/**\n * WizardRouter — declarative flow pipelines + overlay stack.\n *\n * Two layers:\n * Flow cursor — linear pipeline of screens, advanced with next()\n * Overlay stack — interrupts (outage, auth-expired, etc.) that push/pop\n *\n * The visible screen is: top of overlay stack if non-empty, otherwise the flow cursor.\n *\n * Adding a flow screen = append to a pipeline array.\n * Adding an overlay = call pushOverlay() from anywhere.\n * No switch statements, no hardcoded transitions in business logic.\n */\n\nimport type { WizardSession } from '../../lib/wizard-session.js';\nimport { FLOWS, Screen, Flow, type FlowEntry } from './flows.js';\n\n// Re-export so existing imports from './router.js' keep working\nexport { Screen, Flow };\nexport type { FlowEntry };\n\n// ── Screen name taxonomy ──────────────────────────────────────────────\n\n/** Screens that interrupt flows as overlays */\nexport enum Overlay {\n SettingsOverride = 'settings-override',\n ManagedSettings = 'managed-settings',\n PortConflict = 'port-conflict',\n AuthError = 'auth-error',\n}\n\n/** Union of all screen names */\nexport type ScreenName = Screen | Overlay;\n\n// ── Router ────────────────────────────────────────────────────────────\n\nexport class WizardRouter {\n private flow: FlowEntry[];\n private flowName: Flow;\n private overlays: Overlay[] = [];\n\n constructor(flowName: Flow = Flow.Wizard) {\n this.flowName = flowName;\n this.flow = FLOWS[flowName];\n }\n\n /**\n * Resolve which screen should be active based on session state.\n * Walks the flow pipeline, skipping hidden entries and completed entries,\n * returns the first incomplete screen.\n */\n resolve(session: WizardSession): ScreenName {\n if (this.overlays.length > 0) {\n return this.overlays[this.overlays.length - 1];\n }\n\n for (const entry of this.flow) {\n if (entry.show && !entry.show(session)) continue;\n if (entry.isComplete && entry.isComplete(session)) continue;\n return entry.screen;\n }\n\n // All entries complete — show the last screen (outro)\n return this.flow[this.flow.length - 1].screen;\n }\n\n /** The screen that should be rendered right now. */\n get activeScreen(): ScreenName {\n // Overlays take priority — resolve() handles this too,\n // but activeScreen is called before session is available in some paths\n if (this.overlays.length > 0) {\n return this.overlays[this.overlays.length - 1];\n }\n return this.flow[0].screen;\n }\n\n /** The name of the active flow. */\n get activeFlow(): Flow {\n return this.flowName;\n }\n\n /** Whether an overlay is currently active. */\n get hasOverlay(): boolean {\n return this.overlays.length > 0;\n }\n\n /**\n * Push an overlay that interrupts the current flow.\n * The flow resumes when the overlay is dismissed via popOverlay().\n */\n pushOverlay(overlay: Overlay): void {\n this.overlays.push(overlay);\n }\n\n /**\n * Dismiss the topmost overlay. The flow screen underneath resumes.\n */\n popOverlay(): void {\n this.overlays.pop();\n }\n\n /**\n * Direction hint for screen transitions.\n */\n private _lastDirection: 'push' | 'pop' | null = null;\n\n get lastNavDirection(): 'push' | 'pop' | null {\n return this._lastDirection;\n }\n\n /** @internal — called by store wrapper to track direction */\n _setDirection(dir: 'push' | 'pop' | null): void {\n this._lastDirection = dir;\n }\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Screen, Overlay } from './router.js';
|
|
3
3
|
import { HealthCheckScreen } from './screens/health/HealthCheckScreen.js';
|
|
4
4
|
import { SettingsOverrideScreen } from './screens/SettingsOverrideScreen.js';
|
|
5
|
+
import { ManagedSettingsScreen } from './screens/ManagedSettingsScreen.js';
|
|
5
6
|
import { PortConflictScreen } from './screens/PortConflictScreen.js';
|
|
6
7
|
import { IntroScreen } from './screens/IntroScreen.js';
|
|
7
8
|
import { SetupScreen } from './screens/SetupScreen.js';
|
|
@@ -9,6 +10,7 @@ import { AuthScreen } from './screens/AuthScreen.js';
|
|
|
9
10
|
import { RunScreen } from './screens/RunScreen.js';
|
|
10
11
|
import { McpScreen } from './screens/McpScreen.js';
|
|
11
12
|
import { OutroScreen } from './screens/OutroScreen.js';
|
|
13
|
+
import { AuthErrorScreen } from './screens/AuthErrorScreen.js';
|
|
12
14
|
import { createMcpInstaller } from './services/mcp-installer.js';
|
|
13
15
|
export function createServices() {
|
|
14
16
|
return {
|
|
@@ -19,7 +21,9 @@ export function createScreens(store, services) {
|
|
|
19
21
|
return {
|
|
20
22
|
// Overlays
|
|
21
23
|
[Overlay.SettingsOverride]: _jsx(SettingsOverrideScreen, { store: store }),
|
|
24
|
+
[Overlay.ManagedSettings]: _jsx(ManagedSettingsScreen, { store: store }),
|
|
22
25
|
[Overlay.PortConflict]: _jsx(PortConflictScreen, { store: store }),
|
|
26
|
+
[Overlay.AuthError]: _jsx(AuthErrorScreen, {}),
|
|
23
27
|
// Wizard flow
|
|
24
28
|
[Screen.Intro]: _jsx(IntroScreen, { store: store }),
|
|
25
29
|
[Screen.HealthCheck]: _jsx(HealthCheckScreen, { store: store }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen-registry.js","sourceRoot":"","sources":["../../../../src/ui/tui/screen-registry.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAOjE,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,YAAY,EAAE,kBAAkB,EAAE;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAkB,EAClB,QAAwB;IAExB,OAAO;QACL,WAAW;QACX,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAC,sBAAsB,IAAC,KAAK,EAAE,KAAK,GAAI;QACpE,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,KAAC,kBAAkB,IAAC,KAAK,EAAE,KAAK,GAAI;
|
|
1
|
+
{"version":3,"file":"screen-registry.js","sourceRoot":"","sources":["../../../../src/ui/tui/screen-registry.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAOjE,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,YAAY,EAAE,kBAAkB,EAAE;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAkB,EAClB,QAAwB;IAExB,OAAO;QACL,WAAW;QACX,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAC,sBAAsB,IAAC,KAAK,EAAE,KAAK,GAAI;QACpE,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,KAAC,qBAAqB,IAAC,KAAK,EAAE,KAAK,GAAI;QAClE,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,KAAC,kBAAkB,IAAC,KAAK,EAAE,KAAK,GAAI;QAC5D,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAC,eAAe,KAAG;QAExC,cAAc;QACd,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,GAAI;QAC7C,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,KAAC,iBAAiB,IAAC,KAAK,EAAE,KAAK,GAAI;QACzD,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,GAAI;QAC7C,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI;QAC3C,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,GAAI;QACzC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,YAAY,GAAI;QAC3E,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,GAAI;QAE7C,uBAAuB;QACvB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACf,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,YAAY,EAAE,UAAU,SAAG,CACzE;QACD,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAClB,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,QAAQ,CAAC,YAAY,EAChC,IAAI,EAAC,QAAQ,EACb,UAAU,SACV,CACH;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Screen registry — maps screen names to React components.\n *\n * Adding a new screen:\n * 1. Create the component in screens/\n * 2. Add an entry here\n * 3. Add the screen name to the router flow (router.ts)\n *\n * App.tsx never needs to change.\n */\n\nimport type { ReactNode } from 'react';\nimport type { WizardStore } from './store.js';\nimport { Screen, Overlay, type ScreenName } from './router.js';\n\nimport { HealthCheckScreen } from './screens/health/HealthCheckScreen.js';\nimport { SettingsOverrideScreen } from './screens/SettingsOverrideScreen.js';\nimport { ManagedSettingsScreen } from './screens/ManagedSettingsScreen.js';\nimport { PortConflictScreen } from './screens/PortConflictScreen.js';\nimport { IntroScreen } from './screens/IntroScreen.js';\nimport { SetupScreen } from './screens/SetupScreen.js';\nimport { AuthScreen } from './screens/AuthScreen.js';\nimport { RunScreen } from './screens/RunScreen.js';\nimport { McpScreen } from './screens/McpScreen.js';\nimport { OutroScreen } from './screens/OutroScreen.js';\nimport { AuthErrorScreen } from './screens/AuthErrorScreen.js';\nimport { createMcpInstaller } from './services/mcp-installer.js';\nimport type { McpInstaller } from './services/mcp-installer.js';\n\nexport interface ScreenServices {\n mcpInstaller: McpInstaller;\n}\n\nexport function createServices(): ScreenServices {\n return {\n mcpInstaller: createMcpInstaller(),\n };\n}\n\nexport function createScreens(\n store: WizardStore,\n services: ScreenServices,\n): Record<ScreenName, ReactNode> {\n return {\n // Overlays\n [Overlay.SettingsOverride]: <SettingsOverrideScreen store={store} />,\n [Overlay.ManagedSettings]: <ManagedSettingsScreen store={store} />,\n [Overlay.PortConflict]: <PortConflictScreen store={store} />,\n [Overlay.AuthError]: <AuthErrorScreen />,\n\n // Wizard flow\n [Screen.Intro]: <IntroScreen store={store} />,\n [Screen.HealthCheck]: <HealthCheckScreen store={store} />,\n [Screen.Setup]: <SetupScreen store={store} />,\n [Screen.Auth]: <AuthScreen store={store} />,\n [Screen.Run]: <RunScreen store={store} />,\n [Screen.Mcp]: <McpScreen store={store} installer={services.mcpInstaller} />,\n [Screen.Outro]: <OutroScreen store={store} />,\n\n // Standalone MCP flows\n [Screen.McpAdd]: (\n <McpScreen store={store} installer={services.mcpInstaller} standalone />\n ),\n [Screen.McpRemove]: (\n <McpScreen\n store={store}\n installer={services.mcpInstaller}\n mode=\"remove\"\n standalone\n />\n ),\n };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuthErrorScreen — Shown when the Anthropic API returns a 401.
|
|
3
|
+
*
|
|
4
|
+
* Claude Code's own auth can conflict with the wizard's OAuth token.
|
|
5
|
+
* This overlay tells the user to log out of Claude Code and retry.
|
|
6
|
+
*/
|
|
7
|
+
export declare const AuthErrorScreen: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* AuthErrorScreen — Shown when the Anthropic API returns a 401.
|
|
4
|
+
*
|
|
5
|
+
* Claude Code's own auth can conflict with the wizard's OAuth token.
|
|
6
|
+
* This overlay tells the user to log out of Claude Code and retry.
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Text, useInput } from 'ink';
|
|
9
|
+
import { Colors } from '../styles.js';
|
|
10
|
+
export const AuthErrorScreen = () => {
|
|
11
|
+
useInput(() => {
|
|
12
|
+
process.exit(1);
|
|
13
|
+
});
|
|
14
|
+
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Text, { color: "red", bold: true, children: ['\u2718', " Authentication error"] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Text, { children: "The Wizard couldn't connect to the PostHog LLM Gateway. If you use Claude Code, its credentials might conflict with the Wizard." }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Try logging out of Claude Code temporarily and re-running the Wizard by running:" }) }), _jsx(Box, { flexDirection: "column", marginTop: 1, paddingLeft: 2, children: _jsx(Text, { color: "cyan", children: "claude auth logout" }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: Colors.muted, children: "Press any key to exit" }) })] }));
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=AuthErrorScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthErrorScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/AuthErrorScreen.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE;IAClC,QAAQ,CAAC,GAAG,EAAE;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aACrC,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,EAAC,IAAI,mBACnB,QAAQ,6BACJ,EAEP,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,YACtC,KAAC,IAAI,kJAIE,GACH,EAEN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,QAAQ,uGAGP,GACH,EAEN,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,YACtD,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,mCAA0B,GACxC,EAEN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,KAAK,sCAA8B,GACnD,IACF,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * AuthErrorScreen — Shown when the Anthropic API returns a 401.\n *\n * Claude Code's own auth can conflict with the wizard's OAuth token.\n * This overlay tells the user to log out of Claude Code and retry.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { Colors } from '../styles.js';\n\nexport const AuthErrorScreen = () => {\n useInput(() => {\n process.exit(1);\n });\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text color=\"red\" bold>\n {'\\u2718'} Authentication error\n </Text>\n\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n The Wizard couldn't connect to the PostHog LLM Gateway. If\n you use Claude Code, its credentials might conflict with the\n Wizard.\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>\n Try logging out of Claude Code temporarily and re-running the Wizard\n by running:\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={2}>\n <Text color=\"cyan\">claude auth logout</Text>\n </Box>\n\n <Box marginTop={1}>\n <Text color={Colors.muted}>Press any key to exit</Text>\n </Box>\n </Box>\n );\n};\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ManagedSettingsScreen — Modal when IT/org-managed settings contain overrides
|
|
3
|
+
* that block the Wizard from reaching the PostHog LLM Gateway.
|
|
4
|
+
*
|
|
5
|
+
* Unlike SettingsOverrideScreen, the wizard cannot back up or modify these files.
|
|
6
|
+
* The user must contact their IT administrator to resolve the conflict.
|
|
7
|
+
*/
|
|
8
|
+
import type { WizardStore } from '../store.js';
|
|
9
|
+
interface ManagedSettingsScreenProps {
|
|
10
|
+
store: WizardStore;
|
|
11
|
+
}
|
|
12
|
+
export declare const ManagedSettingsScreen: ({ store, }: ManagedSettingsScreenProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ManagedSettingsScreen — Modal when IT/org-managed settings contain overrides
|
|
4
|
+
* that block the Wizard from reaching the PostHog LLM Gateway.
|
|
5
|
+
*
|
|
6
|
+
* Unlike SettingsOverrideScreen, the wizard cannot back up or modify these files.
|
|
7
|
+
* The user must contact their IT administrator to resolve the conflict.
|
|
8
|
+
*/
|
|
9
|
+
import { Box, Text } from 'ink';
|
|
10
|
+
import { useSyncExternalStore } from 'react';
|
|
11
|
+
import { ConfirmationInput, ModalOverlay } from '../primitives/index.js';
|
|
12
|
+
import { Icons } from '../styles.js';
|
|
13
|
+
function sourceLabel(source) {
|
|
14
|
+
switch (source) {
|
|
15
|
+
case 'managed':
|
|
16
|
+
return 'Managed settings (IT/org-managed)';
|
|
17
|
+
case 'project':
|
|
18
|
+
return '.claude/settings.json';
|
|
19
|
+
default:
|
|
20
|
+
return source;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const ManagedSettingsScreen = ({ store, }) => {
|
|
24
|
+
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
25
|
+
const conflicts = store.session.settingsConflicts;
|
|
26
|
+
const readOnlyConflicts = conflicts?.filter((c) => !c.writable);
|
|
27
|
+
if (!readOnlyConflicts || readOnlyConflicts.length === 0) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return (_jsxs(ModalOverlay, { borderColor: "red", title: `${Icons.warning} Organization settings conflict`, width: 68, footer: _jsx(ConfirmationInput, { message: "Contact your IT administrator to resolve this.", confirmLabel: "", cancelLabel: "Exit [Esc]", onConfirm: () => process.exit(1), onCancel: () => process.exit(1) }), children: [_jsx(Text, { dimColor: true, children: "Your organization's managed settings contain overrides that prevent the Wizard from reaching the PostHog LLM Gateway." }), readOnlyConflicts.map((conflict) => (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, children: sourceLabel(conflict.source) }), _jsx(Box, { flexDirection: "column", paddingLeft: 2, children: conflict.keys.map((key) => (_jsxs(Text, { children: [Icons.bullet, ' ', _jsx(Text, { color: "yellow", bold: true, children: key })] }, key))) })] }, conflict.source))), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Try running \"claude auth logout\" or contact your IT administrator to resolve this." }) })] }));
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=ManagedSettingsScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManagedSettingsScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/ManagedSettingsScreen.tsx"],"names":[],"mappings":";AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGrC,SAAS,WAAW,CAAC,MAAkC;IACrD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,mCAAmC,CAAC;QAC7C,KAAK,SAAS;YACZ,OAAO,uBAAuB,CAAC;QACjC;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC;AAMD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,KAAK,GACsB,EAAE,EAAE;IAC/B,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,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC;IAClD,MAAM,iBAAiB,GAAG,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEhE,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,MAAC,YAAY,IACX,WAAW,EAAC,KAAK,EACjB,KAAK,EAAE,GAAG,KAAK,CAAC,OAAO,iCAAiC,EACxD,KAAK,EAAE,EAAE,EACT,MAAM,EACJ,KAAC,iBAAiB,IAChB,OAAO,EAAC,gDAAgD,EACxD,YAAY,EAAC,EAAE,EACf,WAAW,EAAC,YAAY,EACxB,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAC/B,aAGJ,KAAC,IAAI,IAAC,QAAQ,4IAGP,EACN,iBAAiB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CACnC,MAAC,GAAG,IAAuB,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,aAC5D,KAAC,IAAI,IAAC,IAAI,kBAAE,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAQ,EAChD,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAE,CAAC,YACvC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC1B,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,KAXE,QAAQ,CAAC,MAAM,CAYnB,CACP,CAAC,EACF,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,QAAQ,2GAGP,GACH,IACO,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * ManagedSettingsScreen — Modal when IT/org-managed settings contain overrides\n * that block the Wizard from reaching the PostHog LLM Gateway.\n *\n * Unlike SettingsOverrideScreen, the wizard cannot back up or modify these files.\n * The user must contact their IT administrator to resolve the conflict.\n */\n\nimport { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '../store.js';\nimport { ConfirmationInput, ModalOverlay } from '../primitives/index.js';\nimport { Icons } from '../styles.js';\nimport type { SettingsConflict } from '../../../lib/agent-interface.js';\n\nfunction sourceLabel(source: SettingsConflict['source']): string {\n switch (source) {\n case 'managed':\n return 'Managed settings (IT/org-managed)';\n case 'project':\n return '.claude/settings.json';\n default:\n return source;\n }\n}\n\ninterface ManagedSettingsScreenProps {\n store: WizardStore;\n}\n\nexport const ManagedSettingsScreen = ({\n store,\n}: ManagedSettingsScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const conflicts = store.session.settingsConflicts;\n const readOnlyConflicts = conflicts?.filter((c) => !c.writable);\n\n if (!readOnlyConflicts || readOnlyConflicts.length === 0) {\n return null;\n }\n\n return (\n <ModalOverlay\n borderColor=\"red\"\n title={`${Icons.warning} Organization settings conflict`}\n width={68}\n footer={\n <ConfirmationInput\n message=\"Contact your IT administrator to resolve this.\"\n confirmLabel=\"\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() => process.exit(1)}\n onCancel={() => process.exit(1)}\n />\n }\n >\n <Text dimColor>\n Your organization's managed settings contain overrides that prevent\n the Wizard from reaching the PostHog LLM Gateway.\n </Text>\n {readOnlyConflicts.map((conflict) => (\n <Box key={conflict.source} flexDirection=\"column\" marginTop={1}>\n <Text bold>{sourceLabel(conflict.source)}</Text>\n <Box flexDirection=\"column\" paddingLeft={2}>\n {conflict.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 </Box>\n ))}\n <Box marginTop={1}>\n <Text dimColor>\n Try running \"claude auth logout\" or contact your IT administrator to\n resolve this.\n </Text>\n </Box>\n </ModalOverlay>\n );\n};\n"]}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SettingsOverrideScreen — Modal when .claude/settings.json contains env overrides
|
|
3
|
-
* that block the Wizard from reaching the PostHog LLM Gateway.
|
|
4
|
-
*/
|
|
5
1
|
import type { WizardStore } from '../store.js';
|
|
6
2
|
interface SettingsOverrideScreenProps {
|
|
7
3
|
store: WizardStore;
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* SettingsOverrideScreen — Modal when .claude/settings.json contains env overrides
|
|
4
|
-
* that block the Wizard from reaching the PostHog LLM Gateway.
|
|
5
|
-
*/
|
|
6
2
|
import { Box, Text } from 'ink';
|
|
7
3
|
import { useState, useSyncExternalStore } from 'react';
|
|
8
4
|
import { ConfirmationInput, ModalOverlay } from '../primitives/index.js';
|
|
9
5
|
import { Icons } from '../styles.js';
|
|
6
|
+
function sourcePath(source) {
|
|
7
|
+
switch (source) {
|
|
8
|
+
case 'project':
|
|
9
|
+
return '.claude/settings.json';
|
|
10
|
+
case 'managed':
|
|
11
|
+
return '/Library/Application Support/ClaudeCode/managed-settings.json';
|
|
12
|
+
default:
|
|
13
|
+
return source;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
10
16
|
export const SettingsOverrideScreen = ({ store, }) => {
|
|
11
17
|
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
12
18
|
const [feedback, setFeedback] = useState(null);
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
19
|
+
const conflicts = store.session.settingsConflicts?.filter((c) => c.writable);
|
|
20
|
+
if (!conflicts || conflicts.length === 0) {
|
|
15
21
|
return null;
|
|
16
22
|
}
|
|
17
23
|
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: () => {
|
|
@@ -19,6 +25,6 @@ export const SettingsOverrideScreen = ({ store, }) => {
|
|
|
19
25
|
if (!ok) {
|
|
20
26
|
setFeedback('Could not back up the settings file.');
|
|
21
27
|
}
|
|
22
|
-
}, onCancel: () => process.exit(1) }), children: [_jsxs(Text, { children: ["Your
|
|
28
|
+
}, onCancel: () => process.exit(1) }), children: [conflicts.map((conflict) => (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { children: ["Your settings file at", ' ', _jsx(Text, { bold: true, children: sourcePath(conflict.source) }), " sets:"] }), _jsx(Box, { flexDirection: "column", paddingLeft: 2, children: conflict.keys.map((key) => (_jsxs(Text, { children: [Icons.bullet, ' ', _jsx(Text, { color: "yellow", bold: true, children: key })] }, key))) })] }, conflict.source))), _jsx(Text, { dimColor: true, children: "These settings override credentials and prevent the Wizard from reaching the PostHog LLM Gateway. We can back up the file and continue." })] }));
|
|
23
29
|
};
|
|
24
30
|
//# sourceMappingURL=SettingsOverrideScreen.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsOverrideScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/SettingsOverrideScreen.tsx"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"SettingsOverrideScreen.js","sourceRoot":"","sources":["../../../../../src/ui/tui/screens/SettingsOverrideScreen.tsx"],"names":[],"mappings":";AAAA,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;AAGrC,SAAS,UAAU,CAAC,MAA8B;IAChD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,uBAAuB,CAAC;QACjC,KAAK,SAAS;YACZ,OAAO,+DAA+D,CAAC;QACzE;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC;AAMD,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,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE7E,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzC,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,aAGH,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAC3B,MAAC,GAAG,IAAuB,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aAC/D,MAAC,IAAI,wCACmB,GAAG,EACzB,KAAC,IAAI,IAAC,IAAI,kBAAE,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAQ,cAC1C,EACP,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAE,CAAC,YACvC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC1B,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,KAdE,QAAQ,CAAC,MAAM,CAenB,CACP,CAAC,EACF,KAAC,IAAI,IAAC,QAAQ,8JAGP,IACM,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { 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';\nimport type { SettingsConflictSource } from '../../../lib/agent-interface.js';\n\nfunction sourcePath(source: SettingsConflictSource): string {\n switch (source) {\n case 'project':\n return '.claude/settings.json';\n case 'managed':\n return '/Library/Application Support/ClaudeCode/managed-settings.json';\n default:\n return source;\n }\n}\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 conflicts = store.session.settingsConflicts?.filter((c) => c.writable);\n\n if (!conflicts || conflicts.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 {conflicts.map((conflict) => (\n <Box key={conflict.source} flexDirection=\"column\" marginBottom={1}>\n <Text>\n Your settings file at{' '}\n <Text bold>{sourcePath(conflict.source)}</Text> sets:\n </Text>\n <Box flexDirection=\"column\" paddingLeft={2}>\n {conflict.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 </Box>\n ))}\n <Text dimColor>\n These settings override credentials and prevent the Wizard from reaching\n the PostHog LLM Gateway. We can back up the file and continue.\n </Text>\n </ModalOverlay>\n );\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* HealthCheckScreen — Flow screen between Intro and Auth.
|
|
4
4
|
*
|
|
@@ -7,16 +7,30 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
* 2. Healthy: isComplete returns true, router auto-advances to Auth
|
|
8
8
|
* 3. Blocking outage: shows affected services with Continue/Exit
|
|
9
9
|
*/
|
|
10
|
-
import { Box, Text } from 'ink';
|
|
11
|
-
import { useSyncExternalStore } from 'react';
|
|
10
|
+
import { Box, Text, useInput } from 'ink';
|
|
11
|
+
import { useState, useSyncExternalStore } from 'react';
|
|
12
12
|
import { ConfirmationInput, LoadingBox, ModalOverlay, } from '../../primitives/index.js';
|
|
13
|
-
import { Icons } from '../../styles.js';
|
|
13
|
+
import { Colors, Icons } from '../../styles.js';
|
|
14
14
|
import { ServiceHealthList } from '../../components/ServiceHealthList.js';
|
|
15
15
|
import { getBlockingServiceKeys } from '../../../../lib/health-checks/readiness.js';
|
|
16
|
+
import { ServiceHealthStatus } from '../../../../lib/health-checks/types.js';
|
|
16
17
|
import { wizardAbort } from '../../../../utils/wizard-abort.js';
|
|
18
|
+
import { fetchSkillMenu, downloadSkill } from '../../../../lib/wizard-tools.js';
|
|
19
|
+
const EXAMPLE_PROMPT = 'Integrate PostHog into this project using the skill files in .posthog/skills/. Read SKILL.md first, then follow the numbered workflow files in order.';
|
|
20
|
+
const SkillsDownloadedScreen = () => {
|
|
21
|
+
useInput(() => {
|
|
22
|
+
process.exit(0);
|
|
23
|
+
});
|
|
24
|
+
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Text, { color: "green", bold: true, children: [Icons.check, " Skills downloaded to .posthog/skills/"] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { children: "You can continue setup with another agent using this prompt:" }), _jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsx(Text, { color: "cyan", children: EXAMPLE_PROMPT }) })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: Colors.muted, children: "Press any key to exit" }) })] }));
|
|
25
|
+
};
|
|
17
26
|
export const HealthCheckScreen = ({ store }) => {
|
|
18
27
|
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
28
|
+
const [downloaded, setDownloaded] = useState(false);
|
|
29
|
+
const [downloading, setDownloading] = useState(false);
|
|
19
30
|
const result = store.session.readinessResult;
|
|
31
|
+
if (downloaded) {
|
|
32
|
+
return _jsx(SkillsDownloadedScreen, {});
|
|
33
|
+
}
|
|
20
34
|
// Still checking — show spinner
|
|
21
35
|
if (!result) {
|
|
22
36
|
return (_jsx(Box, { flexDirection: "column", flexGrow: 1, alignItems: "center", justifyContent: "center", children: _jsx(LoadingBox, { message: "Checking service status..." }) }));
|
|
@@ -26,7 +40,38 @@ export const HealthCheckScreen = ({ store }) => {
|
|
|
26
40
|
const blockingKeys = getBlockingServiceKeys(result.health);
|
|
27
41
|
if (blockingKeys.length === 0)
|
|
28
42
|
return null;
|
|
43
|
+
const isGithubReleasesDown = blockingKeys.includes('githubReleases');
|
|
44
|
+
const canDownloadSkills = result.health.githubReleases.status === ServiceHealthStatus.Healthy;
|
|
45
|
+
const integration = store.session.integration;
|
|
46
|
+
const title = `Ongoing service disruptions`;
|
|
47
|
+
const docsUrl = store.session.frameworkConfig?.metadata.docsUrl;
|
|
48
|
+
const description = isGithubReleasesDown
|
|
49
|
+
? "The Wizard can't download necessary skills from GitHub Releases right now."
|
|
50
|
+
: 'The Wizard may not work reliably while services are affected.';
|
|
51
|
+
const handleDownloadAndExit = async () => {
|
|
52
|
+
if (downloading)
|
|
53
|
+
return;
|
|
54
|
+
setDownloading(true);
|
|
55
|
+
const skillsBaseUrl = 'https://github.com/PostHog/context-mill/releases/latest/download';
|
|
56
|
+
const menu = await fetchSkillMenu(skillsBaseUrl);
|
|
57
|
+
if (menu) {
|
|
58
|
+
const prefix = `integration-${integration}`;
|
|
59
|
+
const skills = (menu.categories['integration'] ?? []).filter((s) => s.id.startsWith(prefix));
|
|
60
|
+
for (const skill of skills) {
|
|
61
|
+
downloadSkill(skill, store.session.installDir, '.posthog/skills');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
setDownloaded(true);
|
|
65
|
+
};
|
|
66
|
+
const handleCancel = canDownloadSkills && !isGithubReleasesDown
|
|
67
|
+
? () => void handleDownloadAndExit()
|
|
68
|
+
: () => void wizardAbort({ message: 'Exited due to service outage.' });
|
|
69
|
+
const cancelLabel = canDownloadSkills && !isGithubReleasesDown
|
|
70
|
+
? downloading
|
|
71
|
+
? 'Downloading...'
|
|
72
|
+
: 'Download skills & Exit [Esc]'
|
|
73
|
+
: 'Exit [Esc]';
|
|
29
74
|
// Blocking outage — show service list with Continue/Exit
|
|
30
|
-
return (_jsxs(ModalOverlay, { borderColor: "red", title:
|
|
75
|
+
return (_jsxs(ModalOverlay, { borderColor: "red", title: title, width: 72, footer: isGithubReleasesDown ? (_jsx(ConfirmationInput, { message: "", confirmLabel: "", cancelLabel: "Exit [Esc]", onConfirm: () => void wizardAbort({ message: 'Exited due to service outage.' }), onCancel: () => void wizardAbort({ message: 'Exited due to service outage.' }) })) : (_jsx(ConfirmationInput, { message: "Continue anyway?", confirmLabel: "Continue [Enter]", cancelLabel: cancelLabel, onConfirm: () => store.dismissOutage(), onCancel: handleCancel })), 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: description }), isGithubReleasesDown && docsUrl && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: ["Set up manually: ", _jsx(Text, { color: "cyan", children: docsUrl })] }) })), canDownloadSkills && !isGithubReleasesDown && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "You can still download the PostHog integration skills and continue with another agent." }) }))] }));
|
|
31
76
|
};
|
|
32
77
|
//# sourceMappingURL=HealthCheckScreen.js.map
|
|
@@ -1 +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"]}
|
|
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,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAMhF,MAAM,cAAc,GAClB,uJAAuJ,CAAC;AAE1J,MAAM,sBAAsB,GAAG,GAAG,EAAE;IAClC,QAAQ,CAAC,GAAG,EAAE;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aACrC,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,IAAI,mBACrB,KAAK,CAAC,KAAK,8CACP,EAEP,MAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aACvC,KAAC,IAAI,+EAEE,EACP,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,YAC/B,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAE,cAAc,GAAQ,GACtC,IACF,EAEN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,KAAK,sCAA8B,GACnD,IACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,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,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEtD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;IAE7C,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,KAAC,sBAAsB,KAAG,CAAC;IACpC,CAAC;IAED,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,MAAM,oBAAoB,GAAG,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACrE,MAAM,iBAAiB,GACrB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,mBAAmB,CAAC,OAAO,CAAC;IACtE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;IAE9C,MAAM,KAAK,GAAG,6BAA6B,CAAC;IAE5C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,OAAO,CAAC;IAChE,MAAM,WAAW,GAAG,oBAAoB;QACtC,CAAC,CAAC,4EAA4E;QAC9E,CAAC,CAAC,+DAA+D,CAAC;IAEpE,MAAM,qBAAqB,GAAG,KAAK,IAAI,EAAE;QACvC,IAAI,WAAW;YAAE,OAAO;QACxB,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,aAAa,GACjB,kEAAkE,CAAC;QACrE,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,MAAM,GAAG,eAAe,WAAW,EAAE,CAAC;YAC5C,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACjE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CACxB,CAAC;YACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QACD,aAAa,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,YAAY,GAChB,iBAAiB,IAAI,CAAC,oBAAoB;QACxC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,qBAAqB,EAAE;QACpC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,WAAW,CAAC,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,CAAC;IAE3E,MAAM,WAAW,GACf,iBAAiB,IAAI,CAAC,oBAAoB;QACxC,CAAC,CAAC,WAAW;YACX,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,8BAA8B;QAClC,CAAC,CAAC,YAAY,CAAC;IAEnB,yDAAyD;IACzD,OAAO,CACL,MAAC,YAAY,IACX,WAAW,EAAC,KAAK,EACjB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,EAAE,EACT,MAAM,EACJ,oBAAoB,CAAC,CAAC,CAAC,CACrB,KAAC,iBAAiB,IAChB,OAAO,EAAC,EAAE,EACV,YAAY,EAAC,EAAE,EACf,WAAW,EAAC,YAAY,EACxB,SAAS,EAAE,GAAG,EAAE,CACd,KAAK,WAAW,CAAC,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,EAEhE,QAAQ,EAAE,GAAG,EAAE,CACb,KAAK,WAAW,CAAC,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,GAEhE,CACH,CAAC,CAAC,CAAC,CACF,KAAC,iBAAiB,IAChB,OAAO,EAAC,kBAAkB,EAC1B,YAAY,EAAC,kBAAkB,EAC/B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EACtC,QAAQ,EAAE,YAAY,GACtB,CACH,aAGH,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,kBAAE,WAAW,GAAQ,EAElC,oBAAoB,IAAI,OAAO,IAAI,CAClC,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,MAAC,IAAI,oCACc,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAE,OAAO,GAAQ,IAC/C,GACH,CACP,EAEA,iBAAiB,IAAI,CAAC,oBAAoB,IAAI,CAC7C,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,yGAGE,GACH,CACP,IACY,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, useInput } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '../../store.js';\nimport {\n ConfirmationInput,\n LoadingBox,\n ModalOverlay,\n} from '../../primitives/index.js';\nimport { Colors, Icons } from '../../styles.js';\nimport { ServiceHealthList } from '../../components/ServiceHealthList.js';\nimport { getBlockingServiceKeys } from '../../../../lib/health-checks/readiness.js';\nimport { ServiceHealthStatus } from '../../../../lib/health-checks/types.js';\nimport { wizardAbort } from '../../../../utils/wizard-abort.js';\nimport { fetchSkillMenu, downloadSkill } from '../../../../lib/wizard-tools.js';\n\ninterface HealthCheckScreenProps {\n store: WizardStore;\n}\n\nconst EXAMPLE_PROMPT =\n 'Integrate PostHog into this project using the skill files in .posthog/skills/. Read SKILL.md first, then follow the numbered workflow files in order.';\n\nconst SkillsDownloadedScreen = () => {\n useInput(() => {\n process.exit(0);\n });\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text color=\"green\" bold>\n {Icons.check} Skills downloaded to .posthog/skills/\n </Text>\n\n <Box marginTop={1} flexDirection=\"column\">\n <Text>\n You can continue setup with another agent using this prompt:\n </Text>\n <Box marginTop={1} paddingLeft={2}>\n <Text color=\"cyan\">{EXAMPLE_PROMPT}</Text>\n </Box>\n </Box>\n\n <Box marginTop={1}>\n <Text color={Colors.muted}>Press any key to exit</Text>\n </Box>\n </Box>\n );\n};\n\nexport const HealthCheckScreen = ({ store }: HealthCheckScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [downloaded, setDownloaded] = useState(false);\n const [downloading, setDownloading] = useState(false);\n\n const result = store.session.readinessResult;\n\n if (downloaded) {\n return <SkillsDownloadedScreen />;\n }\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 const isGithubReleasesDown = blockingKeys.includes('githubReleases');\n const canDownloadSkills =\n result.health.githubReleases.status === ServiceHealthStatus.Healthy;\n const integration = store.session.integration;\n\n const title = `Ongoing service disruptions`;\n\n const docsUrl = store.session.frameworkConfig?.metadata.docsUrl;\n const description = isGithubReleasesDown\n ? \"The Wizard can't download necessary skills from GitHub Releases right now.\"\n : 'The Wizard may not work reliably while services are affected.';\n\n const handleDownloadAndExit = async () => {\n if (downloading) return;\n setDownloading(true);\n const skillsBaseUrl =\n 'https://github.com/PostHog/context-mill/releases/latest/download';\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (menu) {\n const prefix = `integration-${integration}`;\n const skills = (menu.categories['integration'] ?? []).filter((s) =>\n s.id.startsWith(prefix),\n );\n for (const skill of skills) {\n downloadSkill(skill, store.session.installDir, '.posthog/skills');\n }\n }\n setDownloaded(true);\n };\n\n const handleCancel =\n canDownloadSkills && !isGithubReleasesDown\n ? () => void handleDownloadAndExit()\n : () => void wizardAbort({ message: 'Exited due to service outage.' });\n\n const cancelLabel =\n canDownloadSkills && !isGithubReleasesDown\n ? downloading\n ? 'Downloading...'\n : 'Download skills & Exit [Esc]'\n : 'Exit [Esc]';\n\n // Blocking outage — show service list with Continue/Exit\n return (\n <ModalOverlay\n borderColor=\"red\"\n title={title}\n width={72}\n footer={\n isGithubReleasesDown ? (\n <ConfirmationInput\n message=\"\"\n confirmLabel=\"\"\n cancelLabel=\"Exit [Esc]\"\n onConfirm={() =>\n void wizardAbort({ message: 'Exited due to service outage.' })\n }\n onCancel={() =>\n void wizardAbort({ message: 'Exited due to service outage.' })\n }\n />\n ) : (\n <ConfirmationInput\n message=\"Continue anyway?\"\n confirmLabel=\"Continue [Enter]\"\n cancelLabel={cancelLabel}\n onConfirm={() => store.dismissOutage()}\n onCancel={handleCancel}\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>{description}</Text>\n\n {isGithubReleasesDown && docsUrl && (\n <Box marginTop={1}>\n <Text>\n Set up manually: <Text color=\"cyan\">{docsUrl}</Text>\n </Text>\n </Box>\n )}\n\n {canDownloadSkills && !isGithubReleasesDown && (\n <Box marginTop={1}>\n <Text>\n You can still download the PostHog integration skills and continue\n with another agent.\n </Text>\n </Box>\n )}\n </ModalOverlay>\n );\n};\n"]}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { TaskStatus } from '../wizard-ui.js';
|
|
13
13
|
import { type WizardSession, type OutroData, type DiscoveredFeature, AdditionalFeature, McpOutcome, RunPhase } from '../../lib/wizard-session.js';
|
|
14
|
+
import type { SettingsConflict } from '../../lib/agent-interface.js';
|
|
14
15
|
import { WizardRouter, type ScreenName, Screen, Overlay, Flow } from './router.js';
|
|
15
16
|
export { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };
|
|
16
17
|
export type { ScreenName, OutroData, WizardSession };
|
|
@@ -92,7 +93,7 @@ export declare class WizardStore {
|
|
|
92
93
|
* Push the settings-override overlay and return a promise that blocks
|
|
93
94
|
* until the user dismisses it via backupAndFixSettingsOverride().
|
|
94
95
|
*/
|
|
95
|
-
showSettingsOverride(
|
|
96
|
+
showSettingsOverride(conflicts: SettingsConflict[], backupAndFix: () => boolean): Promise<void>;
|
|
96
97
|
/**
|
|
97
98
|
* Push the port-conflict overlay and return a promise that blocks
|
|
98
99
|
* until the user kills the blocking process or exits.
|
|
@@ -108,6 +109,8 @@ export declare class WizardStore {
|
|
|
108
109
|
* Back up .claude/settings.json. Dismisses the overlay on success.
|
|
109
110
|
*/
|
|
110
111
|
backupAndFixSettingsOverride(): boolean;
|
|
112
|
+
/** Push the auth-error overlay (no dismiss — user must exit). */
|
|
113
|
+
showAuthError(): void;
|
|
111
114
|
addDiscoveredFeature(feature: DiscoveredFeature): void;
|
|
112
115
|
/**
|
|
113
116
|
* Enable an additional feature: enqueue it for the stop hook
|
package/dist/src/ui/tui/store.js
CHANGED
|
@@ -172,10 +172,18 @@ export class WizardStore {
|
|
|
172
172
|
* Push the settings-override overlay and return a promise that blocks
|
|
173
173
|
* until the user dismisses it via backupAndFixSettingsOverride().
|
|
174
174
|
*/
|
|
175
|
-
showSettingsOverride(
|
|
176
|
-
|
|
175
|
+
showSettingsOverride(conflicts, backupAndFix) {
|
|
176
|
+
const allKeys = conflicts.flatMap((c) => c.keys);
|
|
177
|
+
this.$session.setKey('settingsOverrideKeys', allKeys);
|
|
178
|
+
this.$session.setKey('settingsConflicts', conflicts);
|
|
177
179
|
this._backupAndFixSettings = backupAndFix;
|
|
178
|
-
|
|
180
|
+
const hasReadOnly = conflicts.some((c) => !c.writable);
|
|
181
|
+
if (hasReadOnly) {
|
|
182
|
+
this.pushOverlay(Overlay.ManagedSettings);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
this.pushOverlay(Overlay.SettingsOverride);
|
|
186
|
+
}
|
|
179
187
|
return new Promise((resolve) => {
|
|
180
188
|
this._resolveSettingsOverride = resolve;
|
|
181
189
|
});
|
|
@@ -205,6 +213,7 @@ export class WizardStore {
|
|
|
205
213
|
const ok = this._backupAndFixSettings?.() ?? false;
|
|
206
214
|
if (ok) {
|
|
207
215
|
this.$session.setKey('settingsOverrideKeys', null);
|
|
216
|
+
this.$session.setKey('settingsConflicts', null);
|
|
208
217
|
this.popOverlay();
|
|
209
218
|
this._resolveSettingsOverride?.();
|
|
210
219
|
this._resolveSettingsOverride = null;
|
|
@@ -212,6 +221,10 @@ export class WizardStore {
|
|
|
212
221
|
}
|
|
213
222
|
return ok;
|
|
214
223
|
}
|
|
224
|
+
/** Push the auth-error overlay (no dismiss — user must exit). */
|
|
225
|
+
showAuthError() {
|
|
226
|
+
this.pushOverlay(Overlay.AuthError);
|
|
227
|
+
}
|
|
215
228
|
addDiscoveredFeature(feature) {
|
|
216
229
|
if (!this.session.discoveredFeatures.includes(feature)) {
|
|
217
230
|
this.session.discoveredFeatures.push(feature);
|
|
@@ -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 (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"]}
|
|
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 type { SettingsConflict } from '../../lib/agent-interface.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 conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n const allKeys = conflicts.flatMap((c) => c.keys);\n this.$session.setKey('settingsOverrideKeys', allKeys);\n this.$session.setKey('settingsConflicts', conflicts);\n this._backupAndFixSettings = backupAndFix;\n\n const hasReadOnly = conflicts.some((c) => !c.writable);\n if (hasReadOnly) {\n this.pushOverlay(Overlay.ManagedSettings);\n } else {\n this.pushOverlay(Overlay.SettingsOverride);\n }\n\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.$session.setKey('settingsConflicts', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n /** Push the auth-error overlay (no dismiss — user must exit). */\n showAuthError(): void {\n this.pushOverlay(Overlay.AuthError);\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"]}
|