@posthog/wizard 2.9.0 → 2.10.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/README.md +40 -0
- package/dist/McpScreen-BmHapIaP.js +3357 -0
- package/dist/McpScreen-BmHapIaP.js.map +1 -0
- package/dist/add-mcp-server-to-clients-DZtISNrs.js +455 -0
- package/dist/add-mcp-server-to-clients-DZtISNrs.js.map +1 -0
- package/dist/agent-runner-CGwrcr57.js +1112 -0
- package/dist/agent-runner-CGwrcr57.js.map +1 -0
- package/dist/agent-skill-BVjJqol6.js +59 -0
- package/dist/agent-skill-BVjJqol6.js.map +1 -0
- package/dist/analytics-C4jO5Qda.js +207 -0
- package/dist/analytics-C4jO5Qda.js.map +1 -0
- package/dist/analytics-CpjaBpx6.js +2 -0
- package/dist/bin.d.ts +1 -2
- package/dist/bin.js +635 -524
- package/dist/bin.js.map +1 -1
- package/dist/craft-pre-release.sh +10 -0
- package/dist/debug-CIyf0ZGx.js +2 -0
- package/dist/debug-CyJ_3dTP.js +201 -0
- package/dist/debug-CyJ_3dTP.js.map +1 -0
- package/dist/defaults-DoVkE0gW.js +234 -0
- package/dist/defaults-DoVkE0gW.js.map +1 -0
- package/dist/detection-CkLpxBCD.js +122 -0
- package/dist/detection-CkLpxBCD.js.map +1 -0
- package/dist/env-api-key-K8TdTDII.js +20 -0
- package/dist/env-api-key-K8TdTDII.js.map +1 -0
- package/dist/file-utils-BWneZy6p.js +38 -0
- package/dist/file-utils-BWneZy6p.js.map +1 -0
- package/dist/generate-version.cjs +11 -0
- package/dist/package-json-BQgl5C3Z.js +2 -0
- package/dist/package-json-Ctq6LSl8.js +25 -0
- package/dist/package-json-Ctq6LSl8.js.map +1 -0
- package/dist/package-manager-nUQ-ebjr.js +222 -0
- package/dist/package-manager-nUQ-ebjr.js.map +1 -0
- package/dist/posthog-integration-BzxdDK4z.js +230 -0
- package/dist/posthog-integration-BzxdDK4z.js.map +1 -0
- package/dist/readiness-Dn7eq8NE.js +2156 -0
- package/dist/readiness-Dn7eq8NE.js.map +1 -0
- package/dist/registry-s55_iuJT.js +2922 -0
- package/dist/registry-s55_iuJT.js.map +1 -0
- package/dist/rolldown-runtime-B_-DWIq7.js +15 -0
- package/dist/router-D5A1Sb4p.js +141 -0
- package/dist/router-D5A1Sb4p.js.map +1 -0
- package/dist/setup-utils-CdDnllRW.js +928 -0
- package/dist/setup-utils-CdDnllRW.js.map +1 -0
- package/dist/smoke-test-ci.sh +165 -0
- package/dist/start-playground-B8qCLu7U.js +1005 -0
- package/dist/start-playground-B8qCLu7U.js.map +1 -0
- package/dist/start-tui-PygiIyNC.js +1887 -0
- package/dist/start-tui-PygiIyNC.js.map +1 -0
- package/dist/steps-CySv8XdD.js +146 -0
- package/dist/steps-CySv8XdD.js.map +1 -0
- package/dist/telemetry-Ct_GGkSO.js +13 -0
- package/dist/telemetry-Ct_GGkSO.js.map +1 -0
- package/dist/wizard-abort-7HUIsqv1.js +39 -0
- package/dist/wizard-abort-7HUIsqv1.js.map +1 -0
- package/dist/wizard-abort-Dhjb2o08.js +2 -0
- package/dist/wizard-session-Db6R023m.js +62 -0
- package/dist/wizard-session-Db6R023m.js.map +1 -0
- package/dist/wizard-session-y7nf6aKH.js +2 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +16 -8
- package/dist/src/__tests__/cli.test.d.ts +0 -1
- package/dist/src/__tests__/cli.test.js +0 -256
- package/dist/src/__tests__/cli.test.js.map +0 -1
- package/dist/src/__tests__/package-json.test.d.ts +0 -1
- package/dist/src/__tests__/package-json.test.js +0 -173
- package/dist/src/__tests__/package-json.test.js.map +0 -1
- package/dist/src/__tests__/wizard-abort.test.d.ts +0 -1
- package/dist/src/__tests__/wizard-abort.test.js +0 -148
- package/dist/src/__tests__/wizard-abort.test.js.map +0 -1
- package/dist/src/frameworks/android/android-wizard-agent.d.ts +0 -6
- package/dist/src/frameworks/android/android-wizard-agent.js +0 -142
- package/dist/src/frameworks/android/android-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/android/utils.d.ts +0 -11
- package/dist/src/frameworks/android/utils.js +0 -97
- package/dist/src/frameworks/android/utils.js.map +0 -1
- package/dist/src/frameworks/angular/angular-wizard-agent.d.ts +0 -4
- package/dist/src/frameworks/angular/angular-wizard-agent.js +0 -65
- package/dist/src/frameworks/angular/angular-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/angular/utils.d.ts +0 -4
- package/dist/src/frameworks/angular/utils.js +0 -9
- package/dist/src/frameworks/angular/utils.js.map +0 -1
- package/dist/src/frameworks/astro/astro-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/astro/astro-wizard-agent.js +0 -102
- package/dist/src/frameworks/astro/astro-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/astro/utils.d.ts +0 -14
- package/dist/src/frameworks/astro/utils.js +0 -114
- package/dist/src/frameworks/astro/utils.js.map +0 -1
- package/dist/src/frameworks/django/django-wizard-agent.d.ts +0 -8
- package/dist/src/frameworks/django/django-wizard-agent.js +0 -173
- package/dist/src/frameworks/django/django-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/django/utils.d.ts +0 -31
- package/dist/src/frameworks/django/utils.js +0 -306
- package/dist/src/frameworks/django/utils.js.map +0 -1
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.d.ts +0 -5
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.js +0 -191
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/fastapi/utils.d.ts +0 -26
- package/dist/src/frameworks/fastapi/utils.js +0 -258
- package/dist/src/frameworks/fastapi/utils.js.map +0 -1
- package/dist/src/frameworks/flask/flask-wizard-agent.d.ts +0 -8
- package/dist/src/frameworks/flask/flask-wizard-agent.js +0 -179
- package/dist/src/frameworks/flask/flask-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/flask/utils.d.ts +0 -28
- package/dist/src/frameworks/flask/utils.js +0 -344
- package/dist/src/frameworks/flask/utils.js.map +0 -1
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.d.ts +0 -4
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.js +0 -61
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.d.ts +0 -3
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.js +0 -152
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/javascript-web/utils.d.ts +0 -28
- package/dist/src/frameworks/javascript-web/utils.js +0 -147
- package/dist/src/frameworks/javascript-web/utils.js.map +0 -1
- package/dist/src/frameworks/laravel/laravel-wizard-agent.d.ts +0 -10
- package/dist/src/frameworks/laravel/laravel-wizard-agent.js +0 -182
- package/dist/src/frameworks/laravel/laravel-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/laravel/utils.d.ts +0 -38
- package/dist/src/frameworks/laravel/utils.js +0 -238
- package/dist/src/frameworks/laravel/utils.js.map +0 -1
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js +0 -94
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/nextjs/utils.d.ts +0 -12
- package/dist/src/frameworks/nextjs/utils.js +0 -52
- package/dist/src/frameworks/nextjs/utils.js.map +0 -1
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.d.ts +0 -6
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.js +0 -77
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/python/python-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/python/python-wizard-agent.js +0 -195
- package/dist/src/frameworks/python/python-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/python/utils.d.ts +0 -28
- package/dist/src/frameworks/python/utils.js +0 -147
- package/dist/src/frameworks/python/utils.js.map +0 -1
- package/dist/src/frameworks/rails/rails-wizard-agent.d.ts +0 -8
- package/dist/src/frameworks/rails/rails-wizard-agent.js +0 -90
- package/dist/src/frameworks/rails/rails-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/rails/utils.d.ts +0 -37
- package/dist/src/frameworks/rails/utils.js +0 -187
- package/dist/src/frameworks/rails/utils.js.map +0 -1
- package/dist/src/frameworks/react-native/react-native-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js +0 -89
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/react-native/utils.d.ts +0 -8
- package/dist/src/frameworks/react-native/utils.js +0 -28
- package/dist/src/frameworks/react-native/utils.js.map +0 -1
- package/dist/src/frameworks/react-router/react-router-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js +0 -94
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/react-router/utils.d.ts +0 -13
- package/dist/src/frameworks/react-router/utils.js +0 -161
- package/dist/src/frameworks/react-router/utils.js.map +0 -1
- package/dist/src/frameworks/ruby/ruby-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/ruby/ruby-wizard-agent.js +0 -113
- package/dist/src/frameworks/ruby/ruby-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/ruby/utils.d.ts +0 -25
- package/dist/src/frameworks/ruby/utils.js +0 -158
- package/dist/src/frameworks/ruby/utils.js.map +0 -1
- package/dist/src/frameworks/svelte/svelte-wizard-agent.d.ts +0 -4
- package/dist/src/frameworks/svelte/svelte-wizard-agent.js +0 -61
- package/dist/src/frameworks/svelte/svelte-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/swift/swift-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/swift/swift-wizard-agent.js +0 -143
- package/dist/src/frameworks/swift/swift-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/swift/utils.d.ts +0 -8
- package/dist/src/frameworks/swift/utils.js +0 -105
- package/dist/src/frameworks/swift/utils.js.map +0 -1
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.d.ts +0 -7
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.js +0 -96
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/tanstack-router/utils.d.ts +0 -11
- package/dist/src/frameworks/tanstack-router/utils.js +0 -149
- package/dist/src/frameworks/tanstack-router/utils.js.map +0 -1
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.d.ts +0 -4
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.js +0 -64
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.js.map +0 -1
- package/dist/src/frameworks/tanstack-start/utils.d.ts +0 -4
- package/dist/src/frameworks/tanstack-start/utils.js +0 -9
- package/dist/src/frameworks/tanstack-start/utils.js.map +0 -1
- package/dist/src/frameworks/vue/vue-wizard-agent.d.ts +0 -4
- package/dist/src/frameworks/vue/vue-wizard-agent.js +0 -62
- package/dist/src/frameworks/vue/vue-wizard-agent.js.map +0 -1
- package/dist/src/lib/__tests__/agent-interface.test.d.ts +0 -1
- package/dist/src/lib/__tests__/agent-interface.test.js +0 -317
- package/dist/src/lib/__tests__/agent-interface.test.js.map +0 -1
- package/dist/src/lib/__tests__/cloudflare-detection.test.d.ts +0 -1
- package/dist/src/lib/__tests__/cloudflare-detection.test.js +0 -119
- package/dist/src/lib/__tests__/cloudflare-detection.test.js.map +0 -1
- package/dist/src/lib/__tests__/wizard-tools.test.d.ts +0 -1
- package/dist/src/lib/__tests__/wizard-tools.test.js +0 -200
- package/dist/src/lib/__tests__/wizard-tools.test.js.map +0 -1
- package/dist/src/lib/__tests__/yara-hooks.test.d.ts +0 -1
- package/dist/src/lib/__tests__/yara-hooks.test.js +0 -432
- package/dist/src/lib/__tests__/yara-hooks.test.js.map +0 -1
- package/dist/src/lib/__tests__/yara-scanner.test.d.ts +0 -1
- package/dist/src/lib/__tests__/yara-scanner.test.js +0 -613
- package/dist/src/lib/__tests__/yara-scanner.test.js.map +0 -1
- package/dist/src/lib/agent/__tests__/agent-prompt.test.d.ts +0 -1
- package/dist/src/lib/agent/__tests__/agent-prompt.test.js +0 -57
- package/dist/src/lib/agent/__tests__/agent-prompt.test.js.map +0 -1
- package/dist/src/lib/agent/agent-interface.d.ts +0 -171
- package/dist/src/lib/agent/agent-interface.js +0 -1082
- package/dist/src/lib/agent/agent-interface.js.map +0 -1
- package/dist/src/lib/agent/agent-prompt.d.ts +0 -23
- package/dist/src/lib/agent/agent-prompt.js +0 -47
- package/dist/src/lib/agent/agent-prompt.js.map +0 -1
- package/dist/src/lib/agent/agent-runner.d.ts +0 -78
- package/dist/src/lib/agent/agent-runner.js +0 -323
- package/dist/src/lib/agent/agent-runner.js.map +0 -1
- package/dist/src/lib/agent/commandments.d.ts +0 -1
- package/dist/src/lib/agent/commandments.js +0 -26
- package/dist/src/lib/agent/commandments.js.map +0 -1
- package/dist/src/lib/api.d.ts +0 -75
- package/dist/src/lib/api.js +0 -105
- package/dist/src/lib/api.js.map +0 -1
- package/dist/src/lib/cloudflare-detection.d.ts +0 -14
- package/dist/src/lib/cloudflare-detection.js +0 -74
- package/dist/src/lib/cloudflare-detection.js.map +0 -1
- package/dist/src/lib/constants.d.ts +0 -74
- package/dist/src/lib/constants.js +0 -98
- package/dist/src/lib/constants.js.map +0 -1
- package/dist/src/lib/detection/__tests__/context.test.d.ts +0 -1
- package/dist/src/lib/detection/__tests__/context.test.js +0 -72
- package/dist/src/lib/detection/__tests__/context.test.js.map +0 -1
- package/dist/src/lib/detection/__tests__/features.test.d.ts +0 -1
- package/dist/src/lib/detection/__tests__/features.test.js +0 -75
- package/dist/src/lib/detection/__tests__/features.test.js.map +0 -1
- package/dist/src/lib/detection/__tests__/package-manager.test.d.ts +0 -1
- package/dist/src/lib/detection/__tests__/package-manager.test.js +0 -195
- package/dist/src/lib/detection/__tests__/package-manager.test.js.map +0 -1
- package/dist/src/lib/detection/context.d.ts +0 -31
- package/dist/src/lib/detection/context.js +0 -92
- package/dist/src/lib/detection/context.js.map +0 -1
- package/dist/src/lib/detection/features.d.ts +0 -16
- package/dist/src/lib/detection/features.js +0 -56
- package/dist/src/lib/detection/features.js.map +0 -1
- package/dist/src/lib/detection/framework.d.ts +0 -14
- package/dist/src/lib/detection/framework.js +0 -35
- package/dist/src/lib/detection/framework.js.map +0 -1
- package/dist/src/lib/detection/index.d.ts +0 -3
- package/dist/src/lib/detection/index.js +0 -11
- package/dist/src/lib/detection/index.js.map +0 -1
- package/dist/src/lib/detection/package-manager.d.ts +0 -37
- package/dist/src/lib/detection/package-manager.js +0 -183
- package/dist/src/lib/detection/package-manager.js.map +0 -1
- package/dist/src/lib/framework-config.d.ts +0 -175
- package/dist/src/lib/framework-config.js +0 -22
- package/dist/src/lib/framework-config.js.map +0 -1
- package/dist/src/lib/health-checks/__tests__/health-checks.test.d.ts +0 -18
- package/dist/src/lib/health-checks/__tests__/health-checks.test.js +0 -759
- package/dist/src/lib/health-checks/__tests__/health-checks.test.js.map +0 -1
- package/dist/src/lib/health-checks/endpoints.d.ts +0 -4
- package/dist/src/lib/health-checks/endpoints.js +0 -49
- package/dist/src/lib/health-checks/endpoints.js.map +0 -1
- package/dist/src/lib/health-checks/index.d.ts +0 -4
- package/dist/src/lib/health-checks/index.js +0 -24
- package/dist/src/lib/health-checks/index.js.map +0 -1
- package/dist/src/lib/health-checks/readiness.d.ts +0 -29
- package/dist/src/lib/health-checks/readiness.js +0 -188
- package/dist/src/lib/health-checks/readiness.js.map +0 -1
- package/dist/src/lib/health-checks/statuspage.d.ts +0 -9
- package/dist/src/lib/health-checks/statuspage.js +0 -105
- package/dist/src/lib/health-checks/statuspage.js.map +0 -1
- package/dist/src/lib/health-checks/types.d.ts +0 -32
- package/dist/src/lib/health-checks/types.js +0 -10
- package/dist/src/lib/health-checks/types.js.map +0 -1
- package/dist/src/lib/helper-functions.d.ts +0 -1
- package/dist/src/lib/helper-functions.js +0 -6
- package/dist/src/lib/helper-functions.js.map +0 -1
- package/dist/src/lib/middleware/benchmark.d.ts +0 -54
- package/dist/src/lib/middleware/benchmark.js +0 -45
- package/dist/src/lib/middleware/benchmark.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/cache-tracker.d.ts +0 -44
- package/dist/src/lib/middleware/benchmarks/cache-tracker.js +0 -81
- package/dist/src/lib/middleware/benchmarks/cache-tracker.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.d.ts +0 -29
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.js +0 -60
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/context-size-tracker.d.ts +0 -26
- package/dist/src/lib/middleware/benchmarks/context-size-tracker.js +0 -56
- package/dist/src/lib/middleware/benchmarks/context-size-tracker.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/cost-tracker.d.ts +0 -16
- package/dist/src/lib/middleware/benchmarks/cost-tracker.js +0 -76
- package/dist/src/lib/middleware/benchmarks/cost-tracker.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/duration-tracker.d.ts +0 -20
- package/dist/src/lib/middleware/benchmarks/duration-tracker.js +0 -40
- package/dist/src/lib/middleware/benchmarks/duration-tracker.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/index.d.ts +0 -9
- package/dist/src/lib/middleware/benchmarks/index.js +0 -60
- package/dist/src/lib/middleware/benchmarks/index.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/json-writer.d.ts +0 -15
- package/dist/src/lib/middleware/benchmarks/json-writer.js +0 -144
- package/dist/src/lib/middleware/benchmarks/json-writer.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/summary.d.ts +0 -9
- package/dist/src/lib/middleware/benchmarks/summary.js +0 -102
- package/dist/src/lib/middleware/benchmarks/summary.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/token-tracker.d.ts +0 -40
- package/dist/src/lib/middleware/benchmarks/token-tracker.js +0 -77
- package/dist/src/lib/middleware/benchmarks/token-tracker.js.map +0 -1
- package/dist/src/lib/middleware/benchmarks/turn-counter.d.ts +0 -34
- package/dist/src/lib/middleware/benchmarks/turn-counter.js +0 -59
- package/dist/src/lib/middleware/benchmarks/turn-counter.js.map +0 -1
- package/dist/src/lib/middleware/config.d.ts +0 -24
- package/dist/src/lib/middleware/config.js +0 -78
- package/dist/src/lib/middleware/config.js.map +0 -1
- package/dist/src/lib/middleware/index.d.ts +0 -11
- package/dist/src/lib/middleware/index.js +0 -18
- package/dist/src/lib/middleware/index.js.map +0 -1
- package/dist/src/lib/middleware/phase-detector.d.ts +0 -7
- package/dist/src/lib/middleware/phase-detector.js +0 -64
- package/dist/src/lib/middleware/phase-detector.js.map +0 -1
- package/dist/src/lib/middleware/pipeline.d.ts +0 -29
- package/dist/src/lib/middleware/pipeline.js +0 -82
- package/dist/src/lib/middleware/pipeline.js.map +0 -1
- package/dist/src/lib/middleware/types.d.ts +0 -40
- package/dist/src/lib/middleware/types.js +0 -9
- package/dist/src/lib/middleware/types.js.map +0 -1
- package/dist/src/lib/registry.d.ts +0 -3
- package/dist/src/lib/registry.js +0 -49
- package/dist/src/lib/registry.js.map +0 -1
- package/dist/src/lib/safe-tools.d.ts +0 -2
- package/dist/src/lib/safe-tools.js +0 -215
- package/dist/src/lib/safe-tools.js.map +0 -1
- package/dist/src/lib/skill-install.d.ts +0 -10
- package/dist/src/lib/skill-install.js +0 -23
- package/dist/src/lib/skill-install.js.map +0 -1
- package/dist/src/lib/version.d.ts +0 -1
- package/dist/src/lib/version.js +0 -6
- package/dist/src/lib/version.js.map +0 -1
- package/dist/src/lib/wizard-session.d.ts +0 -146
- package/dist/src/lib/wizard-session.js +0 -116
- package/dist/src/lib/wizard-session.js.map +0 -1
- package/dist/src/lib/wizard-tools.d.ts +0 -91
- package/dist/src/lib/wizard-tools.js +0 -389
- package/dist/src/lib/wizard-tools.js.map +0 -1
- package/dist/src/lib/workflows/__tests__/agent-skill.test.d.ts +0 -1
- package/dist/src/lib/workflows/__tests__/agent-skill.test.js +0 -66
- package/dist/src/lib/workflows/__tests__/agent-skill.test.js.map +0 -1
- package/dist/src/lib/workflows/__tests__/revenue-analytics-detect.test.d.ts +0 -1
- package/dist/src/lib/workflows/__tests__/revenue-analytics-detect.test.js +0 -101
- package/dist/src/lib/workflows/__tests__/revenue-analytics-detect.test.js.map +0 -1
- package/dist/src/lib/workflows/__tests__/workflow-registry.test.d.ts +0 -1
- package/dist/src/lib/workflows/__tests__/workflow-registry.test.js +0 -32
- package/dist/src/lib/workflows/__tests__/workflow-registry.test.js.map +0 -1
- package/dist/src/lib/workflows/__tests__/workflow-step.test.d.ts +0 -1
- package/dist/src/lib/workflows/__tests__/workflow-step.test.js +0 -54
- package/dist/src/lib/workflows/__tests__/workflow-step.test.js.map +0 -1
- package/dist/src/lib/workflows/agent-skill/index.d.ts +0 -44
- package/dist/src/lib/workflows/agent-skill/index.js +0 -47
- package/dist/src/lib/workflows/agent-skill/index.js.map +0 -1
- package/dist/src/lib/workflows/agent-skill/steps.d.ts +0 -8
- package/dist/src/lib/workflows/agent-skill/steps.js +0 -32
- package/dist/src/lib/workflows/agent-skill/steps.js.map +0 -1
- package/dist/src/lib/workflows/posthog-integration/detect.d.ts +0 -12
- package/dist/src/lib/workflows/posthog-integration/detect.js +0 -57
- package/dist/src/lib/workflows/posthog-integration/detect.js.map +0 -1
- package/dist/src/lib/workflows/posthog-integration/index.d.ts +0 -3
- package/dist/src/lib/workflows/posthog-integration/index.js +0 -152
- package/dist/src/lib/workflows/posthog-integration/index.js.map +0 -1
- package/dist/src/lib/workflows/posthog-integration/steps.d.ts +0 -9
- package/dist/src/lib/workflows/posthog-integration/steps.js +0 -100
- package/dist/src/lib/workflows/posthog-integration/steps.js.map +0 -1
- package/dist/src/lib/workflows/revenue-analytics/detect.d.ts +0 -40
- package/dist/src/lib/workflows/revenue-analytics/detect.js +0 -156
- package/dist/src/lib/workflows/revenue-analytics/detect.js.map +0 -1
- package/dist/src/lib/workflows/revenue-analytics/index.d.ts +0 -4
- package/dist/src/lib/workflows/revenue-analytics/index.js +0 -30
- package/dist/src/lib/workflows/revenue-analytics/index.js.map +0 -1
- package/dist/src/lib/workflows/revenue-analytics/steps.d.ts +0 -8
- package/dist/src/lib/workflows/revenue-analytics/steps.js +0 -48
- package/dist/src/lib/workflows/revenue-analytics/steps.js.map +0 -1
- package/dist/src/lib/workflows/workflow-registry.d.ts +0 -18
- package/dist/src/lib/workflows/workflow-registry.js +0 -32
- package/dist/src/lib/workflows/workflow-registry.js.map +0 -1
- package/dist/src/lib/workflows/workflow-step.d.ts +0 -126
- package/dist/src/lib/workflows/workflow-step.js +0 -28
- package/dist/src/lib/workflows/workflow-step.js.map +0 -1
- package/dist/src/lib/yara-hooks.d.ts +0 -44
- package/dist/src/lib/yara-hooks.js +0 -377
- package/dist/src/lib/yara-hooks.js.map +0 -1
- package/dist/src/lib/yara-scanner.d.ts +0 -61
- package/dist/src/lib/yara-scanner.js +0 -328
- package/dist/src/lib/yara-scanner.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/MCPClient.d.ts +0 -30
- package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js +0 -138
- package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.d.ts +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.js +0 -72
- package/dist/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.d.ts +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.js +0 -341
- package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/claude.test.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/codex.test.d.ts +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/codex.test.js +0 -108
- package/dist/src/steps/add-mcp-server-to-clients/clients/__tests__/codex.test.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.d.ts +0 -89
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js +0 -169
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude.d.ts +0 -80
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude.js +0 -64
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/codex.d.ts +0 -88
- package/dist/src/steps/add-mcp-server-to-clients/clients/codex.js +0 -76
- package/dist/src/steps/add-mcp-server-to-clients/clients/codex.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.d.ts +0 -84
- package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js +0 -61
- package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.d.ts +0 -92
- package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.js +0 -101
- package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/clients/zed.d.ts +0 -110
- package/dist/src/steps/add-mcp-server-to-clients/clients/zed.js +0 -102
- package/dist/src/steps/add-mcp-server-to-clients/clients/zed.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/defaults.d.ts +0 -119
- package/dist/src/steps/add-mcp-server-to-clients/defaults.js +0 -239
- package/dist/src/steps/add-mcp-server-to-clients/defaults.js.map +0 -1
- package/dist/src/steps/add-mcp-server-to-clients/index.d.ts +0 -23
- package/dist/src/steps/add-mcp-server-to-clients/index.js +0 -111
- package/dist/src/steps/add-mcp-server-to-clients/index.js.map +0 -1
- package/dist/src/steps/add-or-update-environment-variables.d.ts +0 -10
- package/dist/src/steps/add-or-update-environment-variables.js +0 -188
- package/dist/src/steps/add-or-update-environment-variables.js.map +0 -1
- package/dist/src/steps/index.d.ts +0 -4
- package/dist/src/steps/index.js +0 -21
- package/dist/src/steps/index.js.map +0 -1
- package/dist/src/steps/run-prettier.d.ts +0 -5
- package/dist/src/steps/run-prettier.js +0 -91
- package/dist/src/steps/run-prettier.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.d.ts +0 -11
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.js +0 -12
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/index.d.ts +0 -6
- package/dist/src/steps/upload-environment-variables/index.js +0 -38
- package/dist/src/steps/upload-environment-variables/index.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/providers/__tests__/vercel.test.d.ts +0 -1
- package/dist/src/steps/upload-environment-variables/providers/__tests__/vercel.test.js +0 -117
- package/dist/src/steps/upload-environment-variables/providers/__tests__/vercel.test.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/providers/vercel.d.ts +0 -15
- package/dist/src/steps/upload-environment-variables/providers/vercel.js +0 -142
- package/dist/src/steps/upload-environment-variables/providers/vercel.js.map +0 -1
- package/dist/src/telemetry.d.ts +0 -2
- package/dist/src/telemetry.js +0 -13
- package/dist/src/telemetry.js.map +0 -1
- package/dist/src/ui/index.d.ts +0 -8
- package/dist/src/ui/index.js +0 -17
- package/dist/src/ui/index.js.map +0 -1
- package/dist/src/ui/logging-ui.d.ts +0 -52
- package/dist/src/ui/logging-ui.js +0 -121
- package/dist/src/ui/logging-ui.js.map +0 -1
- package/dist/src/ui/tui/App.d.ts +0 -6
- package/dist/src/ui/tui/App.js +0 -10
- package/dist/src/ui/tui/App.js.map +0 -1
- package/dist/src/ui/tui/__tests__/flows.test.d.ts +0 -1
- package/dist/src/ui/tui/__tests__/flows.test.js +0 -115
- package/dist/src/ui/tui/__tests__/flows.test.js.map +0 -1
- package/dist/src/ui/tui/__tests__/layout-helpers.test.d.ts +0 -1
- package/dist/src/ui/tui/__tests__/layout-helpers.test.js +0 -68
- package/dist/src/ui/tui/__tests__/layout-helpers.test.js.map +0 -1
- package/dist/src/ui/tui/__tests__/router.test.d.ts +0 -1
- package/dist/src/ui/tui/__tests__/router.test.js +0 -87
- package/dist/src/ui/tui/__tests__/router.test.js.map +0 -1
- package/dist/src/ui/tui/__tests__/store.test.d.ts +0 -1
- package/dist/src/ui/tui/__tests__/store.test.js +0 -889
- package/dist/src/ui/tui/__tests__/store.test.js.map +0 -1
- package/dist/src/ui/tui/components/LearnCard.d.ts +0 -10
- package/dist/src/ui/tui/components/LearnCard.js +0 -217
- package/dist/src/ui/tui/components/LearnCard.js.map +0 -1
- package/dist/src/ui/tui/components/ServiceHealthList.d.ts +0 -15
- package/dist/src/ui/tui/components/ServiceHealthList.js +0 -57
- package/dist/src/ui/tui/components/ServiceHealthList.js.map +0 -1
- package/dist/src/ui/tui/components/TipsCard.d.ts +0 -9
- package/dist/src/ui/tui/components/TipsCard.js +0 -55
- package/dist/src/ui/tui/components/TipsCard.js.map +0 -1
- package/dist/src/ui/tui/components/TitleBar.d.ts +0 -6
- package/dist/src/ui/tui/components/TitleBar.js +0 -17
- package/dist/src/ui/tui/components/TitleBar.js.map +0 -1
- package/dist/src/ui/tui/flows.d.ts +0 -51
- package/dist/src/ui/tui/flows.js +0 -75
- package/dist/src/ui/tui/flows.js.map +0 -1
- package/dist/src/ui/tui/hooks/useStdoutDimensions.d.ts +0 -9
- package/dist/src/ui/tui/hooks/useStdoutDimensions.js +0 -37
- package/dist/src/ui/tui/hooks/useStdoutDimensions.js.map +0 -1
- package/dist/src/ui/tui/ink-ui.d.ts +0 -58
- package/dist/src/ui/tui/ink-ui.js +0 -125
- package/dist/src/ui/tui/ink-ui.js.map +0 -1
- package/dist/src/ui/tui/package.json +0 -1
- package/dist/src/ui/tui/playground/PlaygroundApp.d.ts +0 -12
- package/dist/src/ui/tui/playground/PlaygroundApp.js +0 -44
- package/dist/src/ui/tui/playground/PlaygroundApp.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/HealthCheckDemo.d.ts +0 -11
- package/dist/src/ui/tui/playground/demos/HealthCheckDemo.js +0 -57
- package/dist/src/ui/tui/playground/demos/HealthCheckDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/InputDemo.d.ts +0 -4
- package/dist/src/ui/tui/playground/demos/InputDemo.js +0 -53
- package/dist/src/ui/tui/playground/demos/InputDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/LayoutDemo.d.ts +0 -5
- package/dist/src/ui/tui/playground/demos/LayoutDemo.js +0 -25
- package/dist/src/ui/tui/playground/demos/LayoutDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/LogDemo.d.ts +0 -5
- package/dist/src/ui/tui/playground/demos/LogDemo.js +0 -53
- package/dist/src/ui/tui/playground/demos/LogDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/ModalDemo.d.ts +0 -6
- package/dist/src/ui/tui/playground/demos/ModalDemo.js +0 -13
- package/dist/src/ui/tui/playground/demos/ModalDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/ProgressDemo.d.ts +0 -5
- package/dist/src/ui/tui/playground/demos/ProgressDemo.js +0 -58
- package/dist/src/ui/tui/playground/demos/ProgressDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/RunScreenDemo.d.ts +0 -11
- package/dist/src/ui/tui/playground/demos/RunScreenDemo.js +0 -159
- package/dist/src/ui/tui/playground/demos/RunScreenDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/demos/WelcomeDemo.d.ts +0 -9
- package/dist/src/ui/tui/playground/demos/WelcomeDemo.js +0 -15
- package/dist/src/ui/tui/playground/demos/WelcomeDemo.js.map +0 -1
- package/dist/src/ui/tui/playground/start-playground.d.ts +0 -4
- package/dist/src/ui/tui/playground/start-playground.js +0 -24
- package/dist/src/ui/tui/playground/start-playground.js.map +0 -1
- package/dist/src/ui/tui/primitives/CardLayout.d.ts +0 -12
- package/dist/src/ui/tui/primitives/CardLayout.js +0 -10
- package/dist/src/ui/tui/primitives/CardLayout.js.map +0 -1
- package/dist/src/ui/tui/primitives/ConfirmationInput.d.ts +0 -13
- package/dist/src/ui/tui/primitives/ConfirmationInput.js +0 -35
- package/dist/src/ui/tui/primitives/ConfirmationInput.js.map +0 -1
- package/dist/src/ui/tui/primitives/ContentSequencer.d.ts +0 -42
- package/dist/src/ui/tui/primitives/ContentSequencer.js +0 -137
- package/dist/src/ui/tui/primitives/ContentSequencer.js.map +0 -1
- package/dist/src/ui/tui/primitives/DissolveTransition.d.ts +0 -21
- package/dist/src/ui/tui/primitives/DissolveTransition.js +0 -149
- package/dist/src/ui/tui/primitives/DissolveTransition.js.map +0 -1
- package/dist/src/ui/tui/primitives/Divider.d.ts +0 -6
- package/dist/src/ui/tui/primitives/Divider.js +0 -15
- package/dist/src/ui/tui/primitives/Divider.js.map +0 -1
- package/dist/src/ui/tui/primitives/EventPlanViewer.d.ts +0 -9
- package/dist/src/ui/tui/primitives/EventPlanViewer.js +0 -9
- package/dist/src/ui/tui/primitives/EventPlanViewer.js.map +0 -1
- package/dist/src/ui/tui/primitives/GroupedPickerMenu.d.ts +0 -23
- package/dist/src/ui/tui/primitives/GroupedPickerMenu.js +0 -182
- package/dist/src/ui/tui/primitives/GroupedPickerMenu.js.map +0 -1
- package/dist/src/ui/tui/primitives/HNViewer.d.ts +0 -7
- package/dist/src/ui/tui/primitives/HNViewer.js +0 -63
- package/dist/src/ui/tui/primitives/HNViewer.js.map +0 -1
- package/dist/src/ui/tui/primitives/LinesBlock.d.ts +0 -16
- package/dist/src/ui/tui/primitives/LinesBlock.js +0 -37
- package/dist/src/ui/tui/primitives/LinesBlock.js.map +0 -1
- package/dist/src/ui/tui/primitives/LoadingBox.d.ts +0 -8
- package/dist/src/ui/tui/primitives/LoadingBox.js +0 -10
- package/dist/src/ui/tui/primitives/LoadingBox.js.map +0 -1
- package/dist/src/ui/tui/primitives/LogViewer.d.ts +0 -11
- package/dist/src/ui/tui/primitives/LogViewer.js +0 -55
- package/dist/src/ui/tui/primitives/LogViewer.js.map +0 -1
- package/dist/src/ui/tui/primitives/ModalOverlay.d.ts +0 -25
- package/dist/src/ui/tui/primitives/ModalOverlay.js +0 -7
- package/dist/src/ui/tui/primitives/ModalOverlay.js.map +0 -1
- package/dist/src/ui/tui/primitives/NodeBlock.d.ts +0 -13
- package/dist/src/ui/tui/primitives/NodeBlock.js +0 -17
- package/dist/src/ui/tui/primitives/NodeBlock.js.map +0 -1
- package/dist/src/ui/tui/primitives/PickerMenu.d.ts +0 -20
- package/dist/src/ui/tui/primitives/PickerMenu.js +0 -143
- package/dist/src/ui/tui/primitives/PickerMenu.js.map +0 -1
- package/dist/src/ui/tui/primitives/ProgressList.d.ts +0 -17
- package/dist/src/ui/tui/primitives/ProgressList.js +0 -32
- package/dist/src/ui/tui/primitives/ProgressList.js.map +0 -1
- package/dist/src/ui/tui/primitives/PromptLabel.d.ts +0 -11
- package/dist/src/ui/tui/primitives/PromptLabel.js +0 -13
- package/dist/src/ui/tui/primitives/PromptLabel.js.map +0 -1
- package/dist/src/ui/tui/primitives/ScreenContainer.d.ts +0 -16
- package/dist/src/ui/tui/primitives/ScreenContainer.js +0 -36
- package/dist/src/ui/tui/primitives/ScreenContainer.js.map +0 -1
- package/dist/src/ui/tui/primitives/ScreenErrorBoundary.d.ts +0 -22
- package/dist/src/ui/tui/primitives/ScreenErrorBoundary.js +0 -35
- package/dist/src/ui/tui/primitives/ScreenErrorBoundary.js.map +0 -1
- package/dist/src/ui/tui/primitives/SplitView.d.ts +0 -11
- package/dist/src/ui/tui/primitives/SplitView.js +0 -9
- package/dist/src/ui/tui/primitives/SplitView.js.map +0 -1
- package/dist/src/ui/tui/primitives/TabContainer.d.ts +0 -23
- package/dist/src/ui/tui/primitives/TabContainer.js +0 -45
- package/dist/src/ui/tui/primitives/TabContainer.js.map +0 -1
- package/dist/src/ui/tui/primitives/TextBlock.d.ts +0 -41
- package/dist/src/ui/tui/primitives/TextBlock.js +0 -144
- package/dist/src/ui/tui/primitives/TextBlock.js.map +0 -1
- package/dist/src/ui/tui/primitives/content-types.d.ts +0 -37
- package/dist/src/ui/tui/primitives/content-types.js +0 -19
- package/dist/src/ui/tui/primitives/content-types.js.map +0 -1
- package/dist/src/ui/tui/primitives/index.d.ts +0 -27
- package/dist/src/ui/tui/primitives/index.js +0 -24
- package/dist/src/ui/tui/primitives/index.js.map +0 -1
- package/dist/src/ui/tui/primitives/layout-helpers.d.ts +0 -36
- package/dist/src/ui/tui/primitives/layout-helpers.js +0 -95
- package/dist/src/ui/tui/primitives/layout-helpers.js.map +0 -1
- package/dist/src/ui/tui/primitives/text-helpers.d.ts +0 -10
- package/dist/src/ui/tui/primitives/text-helpers.js +0 -43
- package/dist/src/ui/tui/primitives/text-helpers.js.map +0 -1
- package/dist/src/ui/tui/router.d.ts +0 -58
- package/dist/src/ui/tui/router.js +0 -96
- package/dist/src/ui/tui/router.js.map +0 -1
- package/dist/src/ui/tui/screen-registry.d.ts +0 -19
- package/dist/src/ui/tui/screen-registry.js +0 -44
- package/dist/src/ui/tui/screen-registry.js.map +0 -1
- package/dist/src/ui/tui/screens/AuthErrorScreen.d.ts +0 -7
- package/dist/src/ui/tui/screens/AuthErrorScreen.js +0 -16
- package/dist/src/ui/tui/screens/AuthErrorScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/AuthScreen.d.ts +0 -13
- package/dist/src/ui/tui/screens/AuthScreen.js +0 -20
- package/dist/src/ui/tui/screens/AuthScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/IntroScreen.d.ts +0 -16
- package/dist/src/ui/tui/screens/IntroScreen.js +0 -79
- package/dist/src/ui/tui/screens/IntroScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.d.ts +0 -13
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.js +0 -32
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/McpScreen.d.ts +0 -24
- package/dist/src/ui/tui/screens/McpScreen.js +0 -127
- package/dist/src/ui/tui/screens/McpScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/OutroScreen.d.ts +0 -11
- package/dist/src/ui/tui/screens/OutroScreen.js +0 -22
- package/dist/src/ui/tui/screens/OutroScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/PortConflictScreen.d.ts +0 -11
- package/dist/src/ui/tui/screens/PortConflictScreen.js +0 -30
- package/dist/src/ui/tui/screens/PortConflictScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/RevenueIntroScreen.d.ts +0 -16
- package/dist/src/ui/tui/screens/RevenueIntroScreen.js +0 -64
- package/dist/src/ui/tui/screens/RevenueIntroScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/RunScreen.d.ts +0 -16
- package/dist/src/ui/tui/screens/RunScreen.js +0 -73
- package/dist/src/ui/tui/screens/RunScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.d.ts +0 -6
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.js +0 -30
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/SetupScreen.d.ts +0 -13
- package/dist/src/ui/tui/screens/SetupScreen.js +0 -74
- package/dist/src/ui/tui/screens/SetupScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/SkillsScreen.d.ts +0 -14
- package/dist/src/ui/tui/screens/SkillsScreen.js +0 -71
- package/dist/src/ui/tui/screens/SkillsScreen.js.map +0 -1
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.d.ts +0 -14
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.js +0 -77
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.js.map +0 -1
- package/dist/src/ui/tui/services/mcp-installer.d.ts +0 -21
- package/dist/src/ui/tui/services/mcp-installer.js +0 -58
- package/dist/src/ui/tui/services/mcp-installer.js.map +0 -1
- package/dist/src/ui/tui/start-tui.d.ts +0 -9
- package/dist/src/ui/tui/start-tui.js +0 -41
- package/dist/src/ui/tui/start-tui.js.map +0 -1
- package/dist/src/ui/tui/store.d.ts +0 -190
- package/dist/src/ui/tui/store.js +0 -472
- package/dist/src/ui/tui/store.js.map +0 -1
- package/dist/src/ui/tui/styles.d.ts +0 -32
- package/dist/src/ui/tui/styles.js +0 -35
- package/dist/src/ui/tui/styles.js.map +0 -1
- package/dist/src/ui/wizard-ui.d.ts +0 -81
- package/dist/src/ui/wizard-ui.js +0 -19
- package/dist/src/ui/wizard-ui.js.map +0 -1
- package/dist/src/utils/__tests__/analytics.test.d.ts +0 -1
- package/dist/src/utils/__tests__/analytics.test.js +0 -136
- package/dist/src/utils/__tests__/analytics.test.js.map +0 -1
- package/dist/src/utils/__tests__/provisioning.test.d.ts +0 -1
- package/dist/src/utils/__tests__/provisioning.test.js +0 -192
- package/dist/src/utils/__tests__/provisioning.test.js.map +0 -1
- package/dist/src/utils/__tests__/semver.test.d.ts +0 -1
- package/dist/src/utils/__tests__/semver.test.js +0 -159
- package/dist/src/utils/__tests__/semver.test.js.map +0 -1
- package/dist/src/utils/__tests__/setup-utils.test.d.ts +0 -1
- package/dist/src/utils/__tests__/setup-utils.test.js +0 -138
- package/dist/src/utils/__tests__/setup-utils.test.js.map +0 -1
- package/dist/src/utils/analytics.d.ts +0 -33
- package/dist/src/utils/analytics.js +0 -137
- package/dist/src/utils/analytics.js.map +0 -1
- package/dist/src/utils/anthropic-status.d.ts +0 -17
- package/dist/src/utils/anthropic-status.js +0 -49
- package/dist/src/utils/anthropic-status.js.map +0 -1
- package/dist/src/utils/bash.d.ts +0 -2
- package/dist/src/utils/bash.js +0 -54
- package/dist/src/utils/bash.js.map +0 -1
- package/dist/src/utils/custom-headers.d.ts +0 -9
- package/dist/src/utils/custom-headers.js +0 -24
- package/dist/src/utils/custom-headers.js.map +0 -1
- package/dist/src/utils/debug.d.ts +0 -29
- package/dist/src/utils/debug.js +0 -87
- package/dist/src/utils/debug.js.map +0 -1
- package/dist/src/utils/env-api-key.d.ts +0 -5
- package/dist/src/utils/env-api-key.js +0 -57
- package/dist/src/utils/env-api-key.js.map +0 -1
- package/dist/src/utils/environment.d.ts +0 -4
- package/dist/src/utils/environment.js +0 -77
- package/dist/src/utils/environment.js.map +0 -1
- package/dist/src/utils/file-utils.d.ts +0 -10
- package/dist/src/utils/file-utils.js +0 -49
- package/dist/src/utils/file-utils.js.map +0 -1
- package/dist/src/utils/logging.d.ts +0 -9
- package/dist/src/utils/logging.js +0 -47
- package/dist/src/utils/logging.js.map +0 -1
- package/dist/src/utils/oauth.d.ts +0 -33
- package/dist/src/utils/oauth.js +0 -288
- package/dist/src/utils/oauth.js.map +0 -1
- package/dist/src/utils/package-json.d.ts +0 -30
- package/dist/src/utils/package-json.js +0 -47
- package/dist/src/utils/package-json.js.map +0 -1
- package/dist/src/utils/package-manager.d.ts +0 -21
- package/dist/src/utils/package-manager.js +0 -210
- package/dist/src/utils/package-manager.js.map +0 -1
- package/dist/src/utils/provisioning.d.ts +0 -25
- package/dist/src/utils/provisioning.js +0 -191
- package/dist/src/utils/provisioning.js.map +0 -1
- package/dist/src/utils/rules/astro-rules.md +0 -44
- package/dist/src/utils/rules/next-rules.md +0 -9
- package/dist/src/utils/rules/react-native-rules.md +0 -7
- package/dist/src/utils/rules/react-rules.md +0 -7
- package/dist/src/utils/rules/svelte-rules.md +0 -7
- package/dist/src/utils/rules/universal.md +0 -32
- package/dist/src/utils/semver.d.ts +0 -21
- package/dist/src/utils/semver.js +0 -87
- package/dist/src/utils/semver.js.map +0 -1
- package/dist/src/utils/setup-utils.d.ts +0 -79
- package/dist/src/utils/setup-utils.js +0 -406
- package/dist/src/utils/setup-utils.js.map +0 -1
- package/dist/src/utils/string.d.ts +0 -1
- package/dist/src/utils/string.js +0 -9
- package/dist/src/utils/string.js.map +0 -1
- package/dist/src/utils/types.d.ts +0 -85
- package/dist/src/utils/types.js +0 -3
- package/dist/src/utils/types.js.map +0 -1
- package/dist/src/utils/urls.d.ts +0 -7
- package/dist/src/utils/urls.js +0 -78
- package/dist/src/utils/urls.js.map +0 -1
- package/dist/src/utils/vendor/is-unicorn-supported.d.ts +0 -1
- package/dist/src/utils/vendor/is-unicorn-supported.js +0 -24
- package/dist/src/utils/vendor/is-unicorn-supported.js.map +0 -1
- package/dist/src/utils/wizard-abort.d.ts +0 -16
- package/dist/src/utils/wizard-abort.js +0 -59
- package/dist/src/utils/wizard-abort.js.map +0 -1
|
@@ -0,0 +1,2156 @@
|
|
|
1
|
+
import { n as __require } from "./rolldown-runtime-B_-DWIq7.js";
|
|
2
|
+
import { a as getLogFilePath, c as getUI, o as initLogFile, r as debug, s as logToFile } from "./debug-CyJ_3dTP.js";
|
|
3
|
+
import { C as WIZARD_VARIANT_FLAG_KEY, S as WIZARD_VARIANTS, b as WIZARD_REMARK_EVENT_NAME, h as POSTHOG_PROPERTY_HEADER_PREFIX, n as analytics, p as POSTHOG_FLAG_HEADER_PREFIX, v as REMOTE_SKILLS_BASE_URL, x as WIZARD_USER_AGENT } from "./analytics-C4jO5Qda.js";
|
|
4
|
+
import { o as getLlmGatewayUrlFromHost } from "./setup-utils-CdDnllRW.js";
|
|
5
|
+
import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-Db6R023m.js";
|
|
6
|
+
import { n as registerCleanup, r as wizardAbort, t as WizardError } from "./wizard-abort-7HUIsqv1.js";
|
|
7
|
+
import * as fs$1 from "fs";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import fg from "fast-glob";
|
|
12
|
+
import { execFileSync } from "child_process";
|
|
13
|
+
//#region src/utils/custom-headers.ts
|
|
14
|
+
/**
|
|
15
|
+
* Builds a list of custom headers for ANTHROPIC_CUSTOM_HEADERS.
|
|
16
|
+
*/
|
|
17
|
+
function createCustomHeaders() {
|
|
18
|
+
const entries = [];
|
|
19
|
+
return {
|
|
20
|
+
add(key, value) {
|
|
21
|
+
const name = key.startsWith("x-") || key.startsWith("X-") ? key : `X-${key}`;
|
|
22
|
+
entries.push({
|
|
23
|
+
key: name,
|
|
24
|
+
value
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
addFlag(flagKey, variant) {
|
|
28
|
+
const headerName = POSTHOG_FLAG_HEADER_PREFIX + flagKey.toUpperCase();
|
|
29
|
+
entries.push({
|
|
30
|
+
key: headerName,
|
|
31
|
+
value: variant
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
encode() {
|
|
35
|
+
return entries.map(({ key, value }) => `${key}: ${value}`).join("\n");
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/lib/safe-tools.ts
|
|
41
|
+
const LINTING_TOOLS = [
|
|
42
|
+
"codespell",
|
|
43
|
+
"cspell",
|
|
44
|
+
"git-diff-check",
|
|
45
|
+
"gitleaks",
|
|
46
|
+
"trufflehog",
|
|
47
|
+
"asl-validator",
|
|
48
|
+
"ansible-lint",
|
|
49
|
+
"pmd",
|
|
50
|
+
"biome",
|
|
51
|
+
"cfn-lint",
|
|
52
|
+
"cfnlint",
|
|
53
|
+
"checkov",
|
|
54
|
+
"trivy",
|
|
55
|
+
"test-aztemplate",
|
|
56
|
+
"shellcheck",
|
|
57
|
+
"shfmt",
|
|
58
|
+
"buildifier",
|
|
59
|
+
"cpplint",
|
|
60
|
+
"clang-format",
|
|
61
|
+
"clang-tidy",
|
|
62
|
+
"cmake-format",
|
|
63
|
+
"iwyu",
|
|
64
|
+
"pragma-once",
|
|
65
|
+
"dotnet-format",
|
|
66
|
+
"circleci",
|
|
67
|
+
"clj-kondo",
|
|
68
|
+
"coffeelint",
|
|
69
|
+
"commitlint",
|
|
70
|
+
"jscpd",
|
|
71
|
+
"stylelint",
|
|
72
|
+
"prettier",
|
|
73
|
+
"cue-fmt",
|
|
74
|
+
"dart",
|
|
75
|
+
"hadolint",
|
|
76
|
+
"dotenv-linter",
|
|
77
|
+
"editorconfig-checker",
|
|
78
|
+
"actionlint",
|
|
79
|
+
"zizmor",
|
|
80
|
+
"gofmt",
|
|
81
|
+
"gofumpt",
|
|
82
|
+
"goimports",
|
|
83
|
+
"gokart",
|
|
84
|
+
"golangci-lint",
|
|
85
|
+
"golines",
|
|
86
|
+
"semgrep",
|
|
87
|
+
"goreleaser",
|
|
88
|
+
"graphql-schema-linter",
|
|
89
|
+
"npm-groovy-lint",
|
|
90
|
+
"haml-lint",
|
|
91
|
+
"htmlhint",
|
|
92
|
+
"djlint",
|
|
93
|
+
"checkstyle",
|
|
94
|
+
"google-java-format",
|
|
95
|
+
"eslint",
|
|
96
|
+
"next lint",
|
|
97
|
+
"deno",
|
|
98
|
+
"rome",
|
|
99
|
+
"eslint-plugin-jsonc",
|
|
100
|
+
"eslint-plugin-json",
|
|
101
|
+
"eslint-plugin-jsx-a11y",
|
|
102
|
+
"eslint-plugin-react",
|
|
103
|
+
"nbqa",
|
|
104
|
+
"detekt",
|
|
105
|
+
"ktlint",
|
|
106
|
+
"kubeconform",
|
|
107
|
+
"kube-linter",
|
|
108
|
+
"chktex",
|
|
109
|
+
"luacheck",
|
|
110
|
+
"stylua",
|
|
111
|
+
"markdownlint",
|
|
112
|
+
"markdownlint-cli2",
|
|
113
|
+
"markdown-link-check",
|
|
114
|
+
"markdown-table-prettify",
|
|
115
|
+
"remark-lint",
|
|
116
|
+
"textlint",
|
|
117
|
+
"vale",
|
|
118
|
+
"nixpkgs-fmt",
|
|
119
|
+
"spectral",
|
|
120
|
+
"sort-package-json",
|
|
121
|
+
"perlcritic",
|
|
122
|
+
"perltidy",
|
|
123
|
+
"php-cs-fixer",
|
|
124
|
+
"phpcs",
|
|
125
|
+
"phpstan",
|
|
126
|
+
"psalm",
|
|
127
|
+
"oxipng",
|
|
128
|
+
"psscriptanalyzer",
|
|
129
|
+
"prisma",
|
|
130
|
+
"protolint",
|
|
131
|
+
"buf",
|
|
132
|
+
"pylint",
|
|
133
|
+
"flake8",
|
|
134
|
+
"isort",
|
|
135
|
+
"ruff",
|
|
136
|
+
"black",
|
|
137
|
+
"autopep8",
|
|
138
|
+
"bandit",
|
|
139
|
+
"mypy",
|
|
140
|
+
"pyright",
|
|
141
|
+
"sourcery",
|
|
142
|
+
"yapf",
|
|
143
|
+
"lintr",
|
|
144
|
+
"opa",
|
|
145
|
+
"regal",
|
|
146
|
+
"rubocop",
|
|
147
|
+
"brakeman",
|
|
148
|
+
"rufo",
|
|
149
|
+
"standardrb",
|
|
150
|
+
"clippy",
|
|
151
|
+
"rustfmt",
|
|
152
|
+
"scalafmt",
|
|
153
|
+
"osv-scanner",
|
|
154
|
+
"terrascan",
|
|
155
|
+
"tfsec",
|
|
156
|
+
"snakemake --lint",
|
|
157
|
+
"snakefmt",
|
|
158
|
+
"sqlfluff",
|
|
159
|
+
"sql-formatter",
|
|
160
|
+
"sqlfmt",
|
|
161
|
+
"squawk",
|
|
162
|
+
"svgo",
|
|
163
|
+
"stringslint",
|
|
164
|
+
"swiftformat",
|
|
165
|
+
"swiftlint",
|
|
166
|
+
"tflint",
|
|
167
|
+
"terraform",
|
|
168
|
+
"tofu",
|
|
169
|
+
"terragrunt",
|
|
170
|
+
"txtpbfmt",
|
|
171
|
+
"taplo",
|
|
172
|
+
"eslint-plugin-vue",
|
|
173
|
+
"xmllint",
|
|
174
|
+
"yamllint"
|
|
175
|
+
];
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/lib/wizard-tools.ts
|
|
178
|
+
/**
|
|
179
|
+
* Unified in-process MCP server for the PostHog wizard.
|
|
180
|
+
*
|
|
181
|
+
* Provides tools that run locally (secret values never leave the machine):
|
|
182
|
+
* - check_env_keys: Check which env var keys exist in a .env file
|
|
183
|
+
* - set_env_values: Create/update env vars in a .env file
|
|
184
|
+
* - detect_package_manager: Detect the project's package manager(s)
|
|
185
|
+
*/
|
|
186
|
+
let _sdkModule$1 = null;
|
|
187
|
+
async function getSDKModule$1() {
|
|
188
|
+
if (!_sdkModule$1) _sdkModule$1 = await import("@anthropic-ai/claude-agent-sdk");
|
|
189
|
+
return _sdkModule$1;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Fetch the skill menu from the skills server.
|
|
193
|
+
* Returns parsed data on success, `null` on failure.
|
|
194
|
+
*/
|
|
195
|
+
async function fetchSkillMenu(skillsBaseUrl) {
|
|
196
|
+
try {
|
|
197
|
+
const menuUrl = `${skillsBaseUrl}/skill-menu.json`;
|
|
198
|
+
logToFile(`fetchSkillMenu: fetching from ${menuUrl}`);
|
|
199
|
+
const resp = await fetch(menuUrl);
|
|
200
|
+
if (resp.ok) {
|
|
201
|
+
const data = await resp.json();
|
|
202
|
+
logToFile(`fetchSkillMenu: loaded (${Object.keys(data.categories).length} categories)`);
|
|
203
|
+
return data;
|
|
204
|
+
}
|
|
205
|
+
logToFile(`fetchSkillMenu: failed with HTTP ${resp.status}`);
|
|
206
|
+
return null;
|
|
207
|
+
} catch (err) {
|
|
208
|
+
logToFile(`fetchSkillMenu: error: ${err.message}`);
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Download and extract a skill.
|
|
214
|
+
* By default installs to `<installDir>/.claude/skills/<id>/`.
|
|
215
|
+
* Pass `skillsRoot` to override the base directory (e.g. `.posthog/skills`).
|
|
216
|
+
*/
|
|
217
|
+
function downloadSkill(skillEntry, installDir, skillsRoot) {
|
|
218
|
+
const skillDir = skillsRoot ? path.join(installDir, skillsRoot, skillEntry.id) : path.join(installDir, ".claude", "skills", skillEntry.id);
|
|
219
|
+
const tmpFile = `/tmp/posthog-skill-${skillEntry.id}.zip`;
|
|
220
|
+
try {
|
|
221
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
222
|
+
execFileSync("curl", [
|
|
223
|
+
"-sL",
|
|
224
|
+
skillEntry.downloadUrl,
|
|
225
|
+
"-o",
|
|
226
|
+
tmpFile
|
|
227
|
+
], { timeout: 3e4 });
|
|
228
|
+
execFileSync("unzip", [
|
|
229
|
+
"-o",
|
|
230
|
+
tmpFile,
|
|
231
|
+
"-d",
|
|
232
|
+
skillDir
|
|
233
|
+
], { timeout: 3e4 });
|
|
234
|
+
try {
|
|
235
|
+
fs.unlinkSync(tmpFile);
|
|
236
|
+
} catch {}
|
|
237
|
+
logToFile(`downloadSkill: installed ${skillEntry.id} from ${skillEntry.downloadUrl}`);
|
|
238
|
+
return { success: true };
|
|
239
|
+
} catch (err) {
|
|
240
|
+
logToFile(`downloadSkill: error: ${err.message}`);
|
|
241
|
+
return {
|
|
242
|
+
success: false,
|
|
243
|
+
error: err.message
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* High-level "install a skill by ID" helper. Fetches the skill menu,
|
|
249
|
+
* finds the skill, downloads and extracts it. Workflows should use this
|
|
250
|
+
* instead of composing fetchSkillMenu + downloadSkill themselves.
|
|
251
|
+
*/
|
|
252
|
+
async function installSkillById(skillId, installDir, skillsBaseUrl, skillsRoot) {
|
|
253
|
+
const menu = await fetchSkillMenu(skillsBaseUrl);
|
|
254
|
+
if (!menu) return { kind: "menu-fetch-failed" };
|
|
255
|
+
const skill = Object.values(menu.categories).flat().find((s) => s.id === skillId);
|
|
256
|
+
if (!skill) return {
|
|
257
|
+
kind: "skill-not-found",
|
|
258
|
+
skillId
|
|
259
|
+
};
|
|
260
|
+
const result = downloadSkill(skill, installDir, skillsRoot);
|
|
261
|
+
if (!result.success) return {
|
|
262
|
+
kind: "download-failed",
|
|
263
|
+
message: result.error ?? "unknown"
|
|
264
|
+
};
|
|
265
|
+
return {
|
|
266
|
+
kind: "ok",
|
|
267
|
+
path: skillsRoot ? `${skillsRoot}/${skillId}` : `.claude/skills/${skillId}`
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Resolve filePath relative to workingDirectory, rejecting path traversal.
|
|
272
|
+
*/
|
|
273
|
+
function resolveEnvPath(workingDirectory, filePath) {
|
|
274
|
+
const resolved = path.resolve(workingDirectory, filePath);
|
|
275
|
+
if (!resolved.startsWith(workingDirectory + path.sep) && resolved !== workingDirectory) throw new Error(`Path traversal rejected: "${filePath}" resolves outside working directory`);
|
|
276
|
+
return resolved;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Ensure the given env file basename is covered by .gitignore in the working directory.
|
|
280
|
+
* Creates .gitignore if it doesn't exist; appends the entry if missing.
|
|
281
|
+
*/
|
|
282
|
+
function ensureGitignoreCoverage(workingDirectory, envFileName) {
|
|
283
|
+
const gitignorePath = path.join(workingDirectory, ".gitignore");
|
|
284
|
+
if (fs.existsSync(gitignorePath)) {
|
|
285
|
+
const content = fs.readFileSync(gitignorePath, "utf8");
|
|
286
|
+
if (content.split("\n").some((line) => line.trim() === envFileName)) return;
|
|
287
|
+
const newContent = content.endsWith("\n") ? `${content}${envFileName}\n` : `${content}\n${envFileName}\n`;
|
|
288
|
+
fs.writeFileSync(gitignorePath, newContent, "utf8");
|
|
289
|
+
} else fs.writeFileSync(gitignorePath, `${envFileName}\n`, "utf8");
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Parse a .env file's content and return the set of defined key names.
|
|
293
|
+
*/
|
|
294
|
+
function parseEnvKeys(content) {
|
|
295
|
+
const keys = /* @__PURE__ */ new Set();
|
|
296
|
+
for (const line of content.split("\n")) {
|
|
297
|
+
const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/);
|
|
298
|
+
if (match) keys.add(match[1]);
|
|
299
|
+
}
|
|
300
|
+
return keys;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Merge key-value pairs into existing .env content.
|
|
304
|
+
* Updates existing keys in-place, appends new keys at the end.
|
|
305
|
+
*/
|
|
306
|
+
function mergeEnvValues(content, values) {
|
|
307
|
+
let result = content;
|
|
308
|
+
const updatedKeys = /* @__PURE__ */ new Set();
|
|
309
|
+
for (const [key, value] of Object.entries(values)) {
|
|
310
|
+
const regex = new RegExp(`^(\\s*${key}\\s*=).*$`, "m");
|
|
311
|
+
if (regex.test(result)) {
|
|
312
|
+
result = result.replace(regex, `$1${value}`);
|
|
313
|
+
updatedKeys.add(key);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const newKeys = Object.entries(values).filter(([key]) => !updatedKeys.has(key));
|
|
317
|
+
if (newKeys.length > 0) {
|
|
318
|
+
if (result.length > 0 && !result.endsWith("\n")) result += "\n";
|
|
319
|
+
for (const [key, value] of newKeys) result += `${key}=${value}\n`;
|
|
320
|
+
}
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
const SERVER_NAME = "wizard-tools";
|
|
324
|
+
/**
|
|
325
|
+
* Create the unified in-process MCP server with all wizard tools.
|
|
326
|
+
* Must be called asynchronously because the SDK is an ESM module loaded via dynamic import.
|
|
327
|
+
*/
|
|
328
|
+
async function createWizardToolsServer(options) {
|
|
329
|
+
const { workingDirectory, detectPackageManager, skillsBaseUrl } = options;
|
|
330
|
+
const { tool, createSdkMcpServer } = await getSDKModule$1();
|
|
331
|
+
let cachedSkillMenu = {};
|
|
332
|
+
let categoryNames = ["integration"];
|
|
333
|
+
const menu = await fetchSkillMenu(skillsBaseUrl);
|
|
334
|
+
if (menu) cachedSkillMenu = menu.categories;
|
|
335
|
+
const keys = Object.keys(cachedSkillMenu);
|
|
336
|
+
if (keys.length > 0) categoryNames = keys;
|
|
337
|
+
return createSdkMcpServer({
|
|
338
|
+
name: SERVER_NAME,
|
|
339
|
+
version: "1.0.0",
|
|
340
|
+
tools: [
|
|
341
|
+
tool("check_env_keys", "Check which environment variable keys are present or missing in a .env file. Never reveals values.", {
|
|
342
|
+
filePath: z.string().describe("Path to the .env file, relative to the project root"),
|
|
343
|
+
keys: z.array(z.string()).describe("Environment variable key names to check")
|
|
344
|
+
}, (args) => {
|
|
345
|
+
const resolved = resolveEnvPath(workingDirectory, args.filePath);
|
|
346
|
+
logToFile(`check_env_keys: ${resolved}, keys: ${args.keys.join(", ")}`);
|
|
347
|
+
const existingKeys = fs.existsSync(resolved) ? parseEnvKeys(fs.readFileSync(resolved, "utf8")) : /* @__PURE__ */ new Set();
|
|
348
|
+
const results = {};
|
|
349
|
+
for (const key of args.keys) results[key] = existingKeys.has(key) ? "present" : "missing";
|
|
350
|
+
return { content: [{
|
|
351
|
+
type: "text",
|
|
352
|
+
text: JSON.stringify(results, null, 2)
|
|
353
|
+
}] };
|
|
354
|
+
}),
|
|
355
|
+
tool("set_env_values", "Create or update environment variable keys in a .env file. Creates the file if it does not exist. Ensures .gitignore coverage.", {
|
|
356
|
+
filePath: z.string().describe("Path to the .env file, relative to the project root"),
|
|
357
|
+
values: z.record(z.string(), z.string()).describe("Key-value pairs to set")
|
|
358
|
+
}, (args) => {
|
|
359
|
+
const forbidden = Object.keys(args.values).find((k) => k.toUpperCase() === "POSTHOG_KEY");
|
|
360
|
+
if (forbidden) return {
|
|
361
|
+
content: [{
|
|
362
|
+
type: "text",
|
|
363
|
+
text: `Error: "${forbidden}" is not a valid PostHog env var name. Use the project-specific key name from your framework's integration guide (e.g. NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN).`
|
|
364
|
+
}],
|
|
365
|
+
isError: true
|
|
366
|
+
};
|
|
367
|
+
const resolved = resolveEnvPath(workingDirectory, args.filePath);
|
|
368
|
+
logToFile(`set_env_values: ${resolved}, keys: ${Object.keys(args.values).join(", ")}`);
|
|
369
|
+
const content = mergeEnvValues(fs.existsSync(resolved) ? fs.readFileSync(resolved, "utf8") : "", args.values);
|
|
370
|
+
const dir = path.dirname(resolved);
|
|
371
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
372
|
+
fs.writeFileSync(resolved, content, "utf8");
|
|
373
|
+
ensureGitignoreCoverage(workingDirectory, path.basename(resolved));
|
|
374
|
+
return { content: [{
|
|
375
|
+
type: "text",
|
|
376
|
+
text: `Updated ${Object.keys(args.values).length} key(s) in ${args.filePath}`
|
|
377
|
+
}] };
|
|
378
|
+
}),
|
|
379
|
+
tool("detect_package_manager", "Detect which package manager(s) the project uses. Returns the name, install command, and run command for each detected package manager. Call this before running any install commands.", {}, async () => {
|
|
380
|
+
logToFile(`detect_package_manager: scanning ${workingDirectory}`);
|
|
381
|
+
const result = await detectPackageManager(workingDirectory);
|
|
382
|
+
logToFile(`detect_package_manager: detected ${result.detected.length} package manager(s)`);
|
|
383
|
+
return { content: [{
|
|
384
|
+
type: "text",
|
|
385
|
+
text: JSON.stringify(result, null, 2)
|
|
386
|
+
}] };
|
|
387
|
+
}),
|
|
388
|
+
tool("load_skill_menu", "Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then use install_skill with the chosen ID.", { category: z.enum(categoryNames).describe("Skill category") }, (args) => {
|
|
389
|
+
const skills = cachedSkillMenu[args.category];
|
|
390
|
+
if (!skills || skills.length === 0) return {
|
|
391
|
+
content: [{
|
|
392
|
+
type: "text",
|
|
393
|
+
text: `No skills found for category "${args.category}".`
|
|
394
|
+
}],
|
|
395
|
+
isError: true
|
|
396
|
+
};
|
|
397
|
+
const menuText = skills.map((s) => `- ${s.id}: ${s.name}`).join("\n");
|
|
398
|
+
logToFile(`load_skill_menu: returning ${skills.length} skills for "${args.category}"`);
|
|
399
|
+
return { content: [{
|
|
400
|
+
type: "text",
|
|
401
|
+
text: menuText
|
|
402
|
+
}] };
|
|
403
|
+
}),
|
|
404
|
+
tool("install_skill", "Download and install a PostHog skill by ID. Call load_skill_menu first to see available skills. Extracts the skill to .claude/skills/<skillId>/.", { skillId: z.string().describe("Skill ID from the skill menu (e.g., \"integration-nextjs-app-router\")") }, (args) => {
|
|
405
|
+
if (!/^[a-z0-9][a-z0-9_-]*$/.test(args.skillId)) return {
|
|
406
|
+
content: [{
|
|
407
|
+
type: "text",
|
|
408
|
+
text: "Error: skillId must be lowercase alphanumeric with hyphens."
|
|
409
|
+
}],
|
|
410
|
+
isError: true
|
|
411
|
+
};
|
|
412
|
+
const skill = Object.values(cachedSkillMenu).flat().find((s) => s.id === args.skillId);
|
|
413
|
+
if (!skill) return {
|
|
414
|
+
content: [{
|
|
415
|
+
type: "text",
|
|
416
|
+
text: `Error: skill "${args.skillId}" not found. Use load_skill_menu to see available skills.`
|
|
417
|
+
}],
|
|
418
|
+
isError: true
|
|
419
|
+
};
|
|
420
|
+
const result = downloadSkill(skill, workingDirectory);
|
|
421
|
+
if (result.success) return { content: [{
|
|
422
|
+
type: "text",
|
|
423
|
+
text: `Skill installed to .claude/skills/${args.skillId}/`
|
|
424
|
+
}] };
|
|
425
|
+
else return {
|
|
426
|
+
content: [{
|
|
427
|
+
type: "text",
|
|
428
|
+
text: `Error installing skill: ${result.error}`
|
|
429
|
+
}],
|
|
430
|
+
isError: true
|
|
431
|
+
};
|
|
432
|
+
})
|
|
433
|
+
]
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/** Tool names exposed by the wizard-tools server, for use in allowedTools */
|
|
437
|
+
const WIZARD_TOOL_NAMES = [
|
|
438
|
+
`${SERVER_NAME}:check_env_keys`,
|
|
439
|
+
`${SERVER_NAME}:set_env_values`,
|
|
440
|
+
`${SERVER_NAME}:detect_package_manager`,
|
|
441
|
+
`${SERVER_NAME}:load_skill_menu`,
|
|
442
|
+
`${SERVER_NAME}:install_skill`
|
|
443
|
+
];
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region src/lib/yara-scanner.ts
|
|
446
|
+
const POST_WRITE_EDIT = [{
|
|
447
|
+
phase: "PostToolUse",
|
|
448
|
+
tool: "Write"
|
|
449
|
+
}, {
|
|
450
|
+
phase: "PostToolUse",
|
|
451
|
+
tool: "Edit"
|
|
452
|
+
}];
|
|
453
|
+
const POST_READ_GREP = [{
|
|
454
|
+
phase: "PostToolUse",
|
|
455
|
+
tool: "Read"
|
|
456
|
+
}, {
|
|
457
|
+
phase: "PostToolUse",
|
|
458
|
+
tool: "Grep"
|
|
459
|
+
}];
|
|
460
|
+
const PRE_BASH = [{
|
|
461
|
+
phase: "PreToolUse",
|
|
462
|
+
tool: "Bash"
|
|
463
|
+
}];
|
|
464
|
+
const RULES = [
|
|
465
|
+
{
|
|
466
|
+
name: "pii_in_capture_call",
|
|
467
|
+
description: "Detects PII fields passed to posthog.capture() — violates 'NEVER send PII in capture()' commandment",
|
|
468
|
+
severity: "high",
|
|
469
|
+
category: "posthog_pii",
|
|
470
|
+
appliesTo: POST_WRITE_EDIT,
|
|
471
|
+
patterns: [
|
|
472
|
+
/\.capture\s*\([^)]{0,200}email/i,
|
|
473
|
+
/\.capture\s*\([^)]{0,200}phone/i,
|
|
474
|
+
/\.capture\s*\([^)]{0,200}full[_\s]?name/i,
|
|
475
|
+
/\.capture\s*\([^)]{0,200}first[_\s]?name/i,
|
|
476
|
+
/\.capture\s*\([^)]{0,200}last[_\s]?name/i,
|
|
477
|
+
/\.capture\s*\([^)]{0,200}(street|mailing|home|billing)[_\s]?address/i,
|
|
478
|
+
/\.capture\s*\([^)]{0,200}(ssn|social[_\s]?security)/i,
|
|
479
|
+
/\.capture\s*\([^)]{0,200}(date[_\s]?of[_\s]?birth|dob|birthday)/i,
|
|
480
|
+
/\.capture\s*\([^)]{0,200}\$ip/,
|
|
481
|
+
/\.identify\s*\([^)]{0,200}(ssn|social[_\s]?security)/i,
|
|
482
|
+
/\.identify\s*\([^)]{0,200}(card[_\s]?number|cvv|credit[_\s]?card)/i,
|
|
483
|
+
/\.identify\s*\([^)]{0,200}(date[_\s]?of[_\s]?birth|dob|birthday)/i,
|
|
484
|
+
/\.identify\s*\([^)]{0,200}(street|mailing|home|billing)[_\s]?address/i,
|
|
485
|
+
/\$set[^}]{0,200}email/i,
|
|
486
|
+
/\$set[^}]{0,200}phone/i
|
|
487
|
+
]
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
name: "hardcoded_posthog_key",
|
|
491
|
+
description: "Detects hardcoded PostHog API keys in source — violates 'use environment variables' commandment",
|
|
492
|
+
severity: "high",
|
|
493
|
+
category: "posthog_hardcoded_key",
|
|
494
|
+
appliesTo: POST_WRITE_EDIT,
|
|
495
|
+
patterns: [
|
|
496
|
+
/phc_[a-zA-Z0-9]{20,}/,
|
|
497
|
+
/phx_[a-zA-Z0-9]{20,}/,
|
|
498
|
+
/apiKey\s*[:=]\s*['"][a-zA-Z0-9_]{20,}['"]/,
|
|
499
|
+
/api_key\s*[:=]\s*['"][a-zA-Z0-9_]{20,}['"]/,
|
|
500
|
+
/POSTHOG_PROJECT_TOKEN\s*[:=]\s*['"][a-zA-Z0-9_]{20,}['"]/
|
|
501
|
+
]
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: "autocapture_disabled",
|
|
505
|
+
description: "Detects agent disabling autocapture — violates 'don't disable autocapture' commandment",
|
|
506
|
+
severity: "medium",
|
|
507
|
+
category: "posthog_autocapture",
|
|
508
|
+
appliesTo: POST_WRITE_EDIT,
|
|
509
|
+
patterns: [
|
|
510
|
+
/autocapture\s*:\s*false/,
|
|
511
|
+
/autocapture\s*:\s*'false'/,
|
|
512
|
+
/autocapture\s*:\s*"false"/,
|
|
513
|
+
/autocapture\s*=\s*False/,
|
|
514
|
+
/disable_autocapture\s*[:=]\s*(true|True|1)/
|
|
515
|
+
]
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
name: "hardcoded_posthog_host",
|
|
519
|
+
description: "Detects hardcoded PostHog host URLs in source — should use environment variables",
|
|
520
|
+
severity: "high",
|
|
521
|
+
category: "posthog_hardcoded_key",
|
|
522
|
+
appliesTo: POST_WRITE_EDIT,
|
|
523
|
+
patterns: [/['"]https:\/\/(us|eu)\.i\.posthog\.com['"]/]
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
name: "session_recording_disabled",
|
|
527
|
+
description: "Detects agent disabling session recording",
|
|
528
|
+
severity: "medium",
|
|
529
|
+
category: "posthog_config",
|
|
530
|
+
appliesTo: POST_WRITE_EDIT,
|
|
531
|
+
patterns: [/disable_session_recording\s*:\s*true/i, /disable_session_recording\s*=\s*True/]
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
name: "opt_out_capturing",
|
|
535
|
+
description: "Detects agent opting out of PostHog capturing entirely",
|
|
536
|
+
severity: "medium",
|
|
537
|
+
category: "posthog_config",
|
|
538
|
+
appliesTo: POST_WRITE_EDIT,
|
|
539
|
+
patterns: [/opt_out_capturing\s*[:=]\s*(true|True|1)/i, /opted_out\s*[:=]\s*(true|True|1)/i]
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: "prompt_injection_wizard_override",
|
|
543
|
+
description: "Detects classic prompt injection attempting to override agent instructions",
|
|
544
|
+
severity: "critical",
|
|
545
|
+
category: "prompt_injection",
|
|
546
|
+
appliesTo: POST_READ_GREP,
|
|
547
|
+
patterns: [
|
|
548
|
+
/ignore previous instructions/i,
|
|
549
|
+
/disregard all/i,
|
|
550
|
+
/forget your instructions/i,
|
|
551
|
+
/override your rules/i,
|
|
552
|
+
/act as a different/i,
|
|
553
|
+
/new instructions:/i
|
|
554
|
+
]
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
name: "prompt_injection_wizard_specific",
|
|
558
|
+
description: "Detects wizard-specific manipulation or tool abuse attempts in project files",
|
|
559
|
+
severity: "medium",
|
|
560
|
+
category: "prompt_injection",
|
|
561
|
+
appliesTo: POST_READ_GREP,
|
|
562
|
+
patterns: [
|
|
563
|
+
/skip posthog/i,
|
|
564
|
+
/do not install posthog/i,
|
|
565
|
+
/remove posthog/i,
|
|
566
|
+
/uninstall posthog/i,
|
|
567
|
+
/delete the posthog/i,
|
|
568
|
+
/run the following command/i,
|
|
569
|
+
/execute this shell command/i,
|
|
570
|
+
/you are now a\s/i
|
|
571
|
+
]
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
name: "prompt_injection_base64",
|
|
575
|
+
description: "Detects suspicious base64-encoded blocks in file content that may contain obfuscated prompt injection",
|
|
576
|
+
severity: "critical",
|
|
577
|
+
category: "prompt_injection",
|
|
578
|
+
appliesTo: POST_READ_GREP,
|
|
579
|
+
patterns: [/(?:\/\/|#|\/\*)\s*[A-Za-z0-9+/]{100,}={0,2}/]
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
name: "secret_exfiltration_via_command",
|
|
583
|
+
description: "Detects shell commands attempting to exfiltrate secrets or credentials",
|
|
584
|
+
severity: "critical",
|
|
585
|
+
category: "exfiltration",
|
|
586
|
+
appliesTo: PRE_BASH,
|
|
587
|
+
patterns: [
|
|
588
|
+
/curl\s+.*\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,
|
|
589
|
+
/wget\s+.*\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)/i,
|
|
590
|
+
/(\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD)|\.env|credentials)\S*.*\|\s*curl/i,
|
|
591
|
+
/(\$\{?[A-Z_]*(KEY|TOKEN|SECRET|PASSWORD)|\.env|credentials)\S*.*\|\s*wget/i,
|
|
592
|
+
/\|\s*nc\s/,
|
|
593
|
+
/\|\s*netcat\s/,
|
|
594
|
+
/base64.*\|\s*(curl|wget|nc\s)/i,
|
|
595
|
+
/cat\s+.*\.env.*\|\s*(curl|wget)/,
|
|
596
|
+
/curl.*phc_[a-zA-Z0-9]/,
|
|
597
|
+
/wget.*phc_[a-zA-Z0-9]/
|
|
598
|
+
]
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
name: "destructive_rm",
|
|
602
|
+
description: "Detects rm -rf or rm -r commands that could mass-delete files",
|
|
603
|
+
severity: "critical",
|
|
604
|
+
category: "filesystem_safety",
|
|
605
|
+
appliesTo: PRE_BASH,
|
|
606
|
+
patterns: [
|
|
607
|
+
/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r)\b/,
|
|
608
|
+
/\brm\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*r[a-zA-Z]*\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*f\b/,
|
|
609
|
+
/\brm\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*f[a-zA-Z]*\s+(-[a-zA-Z]*\s+)*-[a-zA-Z]*r\b/
|
|
610
|
+
]
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: "git_force_push",
|
|
614
|
+
description: "Detects git push --force which can overwrite remote history",
|
|
615
|
+
severity: "critical",
|
|
616
|
+
category: "filesystem_safety",
|
|
617
|
+
appliesTo: PRE_BASH,
|
|
618
|
+
patterns: [/git\s+push\s+.*--force/, /git\s+push\s+.*-f\b/]
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
name: "git_reset_hard",
|
|
622
|
+
description: "Detects git reset --hard which discards all uncommitted changes",
|
|
623
|
+
severity: "critical",
|
|
624
|
+
category: "filesystem_safety",
|
|
625
|
+
appliesTo: PRE_BASH,
|
|
626
|
+
patterns: [/git\s+reset\s+--hard/]
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
name: "wrong_posthog_package",
|
|
630
|
+
description: "Detects installing the wrong PostHog npm package — should be posthog-js or posthog-node",
|
|
631
|
+
severity: "high",
|
|
632
|
+
category: "supply_chain",
|
|
633
|
+
appliesTo: PRE_BASH,
|
|
634
|
+
patterns: [
|
|
635
|
+
/npm\s+install\s+(?:--save\s+|--save-dev\s+|-[SD]\s+)*posthog(?!\s*-)/,
|
|
636
|
+
/pnpm\s+(?:add|install)\s+(?:--save\s+|--save-dev\s+|-[SD]\s+)*posthog(?!\s*-)/,
|
|
637
|
+
/yarn\s+add\s+(?:--dev\s+|-D\s+)*posthog(?!\s*-)/,
|
|
638
|
+
/bun\s+(?:add|install)\s+(?:--dev\s+|-[dD]\s+)*posthog(?!\s*-)/
|
|
639
|
+
]
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
name: "npm_install_global",
|
|
643
|
+
description: "Detects global npm installs — should never install packages globally",
|
|
644
|
+
severity: "high",
|
|
645
|
+
category: "supply_chain",
|
|
646
|
+
appliesTo: PRE_BASH,
|
|
647
|
+
patterns: [/npm\s+install\s+-g\b/, /npm\s+install\s+--global\b/]
|
|
648
|
+
}
|
|
649
|
+
];
|
|
650
|
+
/** Maximum content length to scan (100 KB). Inputs beyond this are truncated. */
|
|
651
|
+
const MAX_SCAN_LENGTH = 1e5;
|
|
652
|
+
/**
|
|
653
|
+
* Scan content against rules applicable to a given hook phase and tool.
|
|
654
|
+
* Returns all matching rules (one match per rule, first pattern wins).
|
|
655
|
+
*/
|
|
656
|
+
function scan(content, phase, tool) {
|
|
657
|
+
const scanContent = content.length > MAX_SCAN_LENGTH ? content.slice(0, MAX_SCAN_LENGTH) : content;
|
|
658
|
+
const applicableRules = RULES.filter((r) => r.appliesTo.some((a) => a.phase === phase && a.tool === tool));
|
|
659
|
+
const matches = [];
|
|
660
|
+
for (const rule of applicableRules) for (const pattern of rule.patterns) {
|
|
661
|
+
const match = pattern.exec(scanContent);
|
|
662
|
+
if (match) {
|
|
663
|
+
matches.push({
|
|
664
|
+
rule,
|
|
665
|
+
matchedText: match[0],
|
|
666
|
+
offset: match.index
|
|
667
|
+
});
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return matches.length > 0 ? {
|
|
672
|
+
matched: true,
|
|
673
|
+
matches
|
|
674
|
+
} : { matched: false };
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Scan all files in a skill directory for prompt injection.
|
|
678
|
+
* Used for context-mill scanning after skill installation.
|
|
679
|
+
*/
|
|
680
|
+
function scanSkillDirectory(files) {
|
|
681
|
+
const allMatches = [];
|
|
682
|
+
for (const file of files) {
|
|
683
|
+
const result = scan(file.content, "PostToolUse", "Read");
|
|
684
|
+
if (result.matched) allMatches.push(...result.matches);
|
|
685
|
+
}
|
|
686
|
+
return allMatches.length > 0 ? {
|
|
687
|
+
matched: true,
|
|
688
|
+
matches: allMatches
|
|
689
|
+
} : { matched: false };
|
|
690
|
+
}
|
|
691
|
+
//#endregion
|
|
692
|
+
//#region src/lib/skill-install.ts
|
|
693
|
+
/**
|
|
694
|
+
* Check if command is a PostHog skill installation from MCP.
|
|
695
|
+
* We control the MCP server, so we only need to verify:
|
|
696
|
+
* 1. It installs to .claude/skills/
|
|
697
|
+
* 2. It downloads from our GitHub releases or localhost (dev)
|
|
698
|
+
*
|
|
699
|
+
* Extracted to its own module to avoid a circular dependency
|
|
700
|
+
* between agent-interface.ts and yara-hooks.ts.
|
|
701
|
+
*/
|
|
702
|
+
function isSkillInstallCommand(command) {
|
|
703
|
+
if (!command.startsWith("mkdir -p .claude/skills/")) return false;
|
|
704
|
+
const urlMatch = command.match(/curl -sL ['"]([^'"]+)['"]/);
|
|
705
|
+
if (!urlMatch) return false;
|
|
706
|
+
const url = urlMatch[1];
|
|
707
|
+
return url.startsWith("https://github.com/PostHog/context-mill/releases/") || /^http:\/\/localhost:\d+\//.test(url);
|
|
708
|
+
}
|
|
709
|
+
//#endregion
|
|
710
|
+
//#region src/lib/yara-hooks.ts
|
|
711
|
+
/**
|
|
712
|
+
* YARA hook wiring for the Claude Agent SDK.
|
|
713
|
+
*
|
|
714
|
+
* Creates PreToolUse and PostToolUse hook callback arrays that
|
|
715
|
+
* integrate the YARA scanner into the wizard's agent loop. These
|
|
716
|
+
* hooks are registered in the SDK's query() options alongside the
|
|
717
|
+
* existing Stop hook.
|
|
718
|
+
*
|
|
719
|
+
* PreToolUse hooks block dangerous commands before execution.
|
|
720
|
+
* PostToolUse hooks detect violations in written code and prompt
|
|
721
|
+
* injection in read content, and scan context-mill skill downloads.
|
|
722
|
+
*/
|
|
723
|
+
let scanCount = 0;
|
|
724
|
+
const scanViolations = [];
|
|
725
|
+
function recordScan() {
|
|
726
|
+
scanCount++;
|
|
727
|
+
}
|
|
728
|
+
function recordViolation(entry) {
|
|
729
|
+
scanViolations.push(entry);
|
|
730
|
+
}
|
|
731
|
+
/** Format the scan report summary. Returns null if no scans occurred */
|
|
732
|
+
function formatScanReport() {
|
|
733
|
+
if (scanCount === 0) return null;
|
|
734
|
+
const lines = ["", "— YARA Scanner Summary —"];
|
|
735
|
+
const violationCount = scanViolations.length;
|
|
736
|
+
const cleanCount = scanCount - violationCount;
|
|
737
|
+
lines.push(`✓ ${scanCount} tool calls scanned, ${violationCount} violation${violationCount !== 1 ? "s" : ""} detected`);
|
|
738
|
+
if (violationCount > 0) {
|
|
739
|
+
lines.push("");
|
|
740
|
+
for (const v of scanViolations) {
|
|
741
|
+
const tag = v.action.toUpperCase();
|
|
742
|
+
lines.push(` [${tag}] ${v.rule} (${v.severity.toUpperCase()}) — ${v.phase}:${v.tool}`);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if (cleanCount > 0) {
|
|
746
|
+
lines.push("");
|
|
747
|
+
lines.push(`No violations: ✓ ${cleanCount} clean scan${cleanCount !== 1 ? "s" : ""}`);
|
|
748
|
+
}
|
|
749
|
+
lines.push("");
|
|
750
|
+
return lines.join("\n");
|
|
751
|
+
}
|
|
752
|
+
const YARA_REPORT_PATH = "/tmp/posthog-wizard-yara-report.json";
|
|
753
|
+
/** Write the scan report to a JSON file. Returns the file path, or null if no scans occurred. */
|
|
754
|
+
function writeScanReport() {
|
|
755
|
+
if (scanCount === 0) return null;
|
|
756
|
+
const report = {
|
|
757
|
+
summary: {
|
|
758
|
+
totalScans: scanCount,
|
|
759
|
+
violations: scanViolations.length,
|
|
760
|
+
clean: scanCount - scanViolations.length
|
|
761
|
+
},
|
|
762
|
+
violations: scanViolations
|
|
763
|
+
};
|
|
764
|
+
try {
|
|
765
|
+
fs.writeFileSync(YARA_REPORT_PATH, JSON.stringify(report, null, 2));
|
|
766
|
+
} catch (err) {
|
|
767
|
+
logToFile("[YARA] Failed to write scan report:", err);
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
770
|
+
return YARA_REPORT_PATH;
|
|
771
|
+
}
|
|
772
|
+
/** Timeout for synchronous scan hooks (PreToolUse, PostToolUse Write/Edit/Read) */
|
|
773
|
+
const HOOK_TIMEOUT_MS = 60;
|
|
774
|
+
/** Timeout for skill install hook (involves filesystem I/O) */
|
|
775
|
+
const SKILL_SCAN_HOOK_TIMEOUT_MS = 120;
|
|
776
|
+
function logYaraMatch(phase, tool, match, action) {
|
|
777
|
+
logToFile(`[YARA] ${phase}:${tool} [${action.toUpperCase()}] rule "${match.rule.name}" (severity: ${match.rule.severity}, category: ${match.rule.category})\n Description: ${match.rule.description}\n Matched text: "${match.matchedText.substring(0, 200)}"`);
|
|
778
|
+
analytics.wizardCapture("yara rule matched", {
|
|
779
|
+
rule: match.rule.name,
|
|
780
|
+
severity: match.rule.severity,
|
|
781
|
+
category: match.rule.category,
|
|
782
|
+
action,
|
|
783
|
+
phase,
|
|
784
|
+
tool
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
const SEVERITY_RANK = {
|
|
788
|
+
critical: 4,
|
|
789
|
+
high: 3,
|
|
790
|
+
medium: 2,
|
|
791
|
+
low: 1
|
|
792
|
+
};
|
|
793
|
+
/** Return the highest-severity match from a list of matches. */
|
|
794
|
+
function highestSeverityMatch(matches) {
|
|
795
|
+
return matches.reduce((worst, m) => (SEVERITY_RANK[m.rule.severity] ?? 0) > (SEVERITY_RANK[worst.rule.severity] ?? 0) ? m : worst);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Create PreToolUse hook matchers for YARA scanning.
|
|
799
|
+
* Scans Bash commands before execution for exfiltration,
|
|
800
|
+
* destructive operations, and supply chain violations.
|
|
801
|
+
*/
|
|
802
|
+
function createPreToolUseYaraHooks() {
|
|
803
|
+
return [{
|
|
804
|
+
hooks: [(input) => {
|
|
805
|
+
try {
|
|
806
|
+
if (input.tool_name !== "Bash") return Promise.resolve({});
|
|
807
|
+
const toolInput = input.tool_input;
|
|
808
|
+
const command = typeof toolInput?.command === "string" ? toolInput.command : "";
|
|
809
|
+
if (!command) return Promise.resolve({});
|
|
810
|
+
recordScan();
|
|
811
|
+
const result = scan(command, "PreToolUse", "Bash");
|
|
812
|
+
if (!result.matched) return Promise.resolve({});
|
|
813
|
+
const match = highestSeverityMatch(result.matches);
|
|
814
|
+
logYaraMatch("PreToolUse", "Bash", match, "blocked");
|
|
815
|
+
recordViolation({
|
|
816
|
+
rule: match.rule.name,
|
|
817
|
+
severity: match.rule.severity,
|
|
818
|
+
action: "blocked",
|
|
819
|
+
phase: "PreToolUse",
|
|
820
|
+
tool: "Bash"
|
|
821
|
+
});
|
|
822
|
+
return Promise.resolve({
|
|
823
|
+
decision: "block",
|
|
824
|
+
reason: `[YARA] ${match.rule.name}: ${match.rule.description}. Command blocked for security.`
|
|
825
|
+
});
|
|
826
|
+
} catch (error) {
|
|
827
|
+
logToFile("[YARA] PreToolUse hook error:", error);
|
|
828
|
+
return Promise.resolve({
|
|
829
|
+
decision: "block",
|
|
830
|
+
reason: "[YARA] Scanner error — command blocked as a precaution."
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}],
|
|
834
|
+
timeout: HOOK_TIMEOUT_MS
|
|
835
|
+
}];
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Create PostToolUse hook matchers for YARA scanning.
|
|
839
|
+
*
|
|
840
|
+
* Three matchers:
|
|
841
|
+
* 1. Write/Edit — scan written content for PII, secrets, config violations
|
|
842
|
+
* 2. Read/Grep — scan read content for prompt injection
|
|
843
|
+
* 3. Bash (skill install) — scan downloaded skill files for poisoned content
|
|
844
|
+
*/
|
|
845
|
+
function createPostToolUseYaraHooks() {
|
|
846
|
+
return [
|
|
847
|
+
{
|
|
848
|
+
hooks: [(input) => {
|
|
849
|
+
try {
|
|
850
|
+
const toolName = input.tool_name;
|
|
851
|
+
if (toolName !== "Write" && toolName !== "Edit") return Promise.resolve({});
|
|
852
|
+
const toolInput = input.tool_input;
|
|
853
|
+
const content = toolName === "Write" ? toolInput?.content ?? "" : toolInput?.new_str ?? "";
|
|
854
|
+
if (!content) return Promise.resolve({});
|
|
855
|
+
recordScan();
|
|
856
|
+
const tool = toolName;
|
|
857
|
+
const result = scan(content, "PostToolUse", tool);
|
|
858
|
+
if (!result.matched) return Promise.resolve({});
|
|
859
|
+
const match = highestSeverityMatch(result.matches);
|
|
860
|
+
logYaraMatch("PostToolUse", tool, match, "reverted");
|
|
861
|
+
recordViolation({
|
|
862
|
+
rule: match.rule.name,
|
|
863
|
+
severity: match.rule.severity,
|
|
864
|
+
action: "reverted",
|
|
865
|
+
phase: "PostToolUse",
|
|
866
|
+
tool
|
|
867
|
+
});
|
|
868
|
+
return Promise.resolve({ hookSpecificOutput: {
|
|
869
|
+
hookEventName: "PostToolUse",
|
|
870
|
+
additionalContext: `[YARA VIOLATION] ${match.rule.name}: ${match.rule.description}. You MUST revert this change immediately. The content you just wrote violates security policy.`
|
|
871
|
+
} });
|
|
872
|
+
} catch (error) {
|
|
873
|
+
logToFile("[YARA] PostToolUse Write/Edit hook error:", error);
|
|
874
|
+
return Promise.resolve({ hookSpecificOutput: {
|
|
875
|
+
hookEventName: "PostToolUse",
|
|
876
|
+
additionalContext: "[YARA] Scanner error — you MUST revert this change as a precaution."
|
|
877
|
+
} });
|
|
878
|
+
}
|
|
879
|
+
}],
|
|
880
|
+
timeout: HOOK_TIMEOUT_MS
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
hooks: [(input) => {
|
|
884
|
+
try {
|
|
885
|
+
const toolName = input.tool_name;
|
|
886
|
+
if (toolName !== "Read" && toolName !== "Grep") return Promise.resolve({});
|
|
887
|
+
const toolResponse = input.tool_response;
|
|
888
|
+
const content = typeof toolResponse === "string" ? toolResponse : JSON.stringify(toolResponse ?? "");
|
|
889
|
+
if (!content) return Promise.resolve({});
|
|
890
|
+
recordScan();
|
|
891
|
+
const tool = toolName;
|
|
892
|
+
const result = scan(content, "PostToolUse", tool);
|
|
893
|
+
if (!result.matched) return Promise.resolve({});
|
|
894
|
+
const match = highestSeverityMatch(result.matches);
|
|
895
|
+
if (match.rule.severity === "critical") {
|
|
896
|
+
logYaraMatch("PostToolUse", tool, match, "aborted");
|
|
897
|
+
recordViolation({
|
|
898
|
+
rule: match.rule.name,
|
|
899
|
+
severity: match.rule.severity,
|
|
900
|
+
action: "aborted",
|
|
901
|
+
phase: "PostToolUse",
|
|
902
|
+
tool
|
|
903
|
+
});
|
|
904
|
+
return Promise.resolve({ stopReason: `[YARA CRITICAL] ${match.rule.name}: Prompt injection detected in file content. Agent context is potentially poisoned. Session terminated for safety.` });
|
|
905
|
+
}
|
|
906
|
+
logYaraMatch("PostToolUse", tool, match, "warned");
|
|
907
|
+
recordViolation({
|
|
908
|
+
rule: match.rule.name,
|
|
909
|
+
severity: match.rule.severity,
|
|
910
|
+
action: "warned",
|
|
911
|
+
phase: "PostToolUse",
|
|
912
|
+
tool
|
|
913
|
+
});
|
|
914
|
+
return Promise.resolve({ hookSpecificOutput: {
|
|
915
|
+
hookEventName: "PostToolUse",
|
|
916
|
+
additionalContext: `[YARA WARNING] ${match.rule.name}: ${match.rule.description}`
|
|
917
|
+
} });
|
|
918
|
+
} catch (error) {
|
|
919
|
+
logToFile("[YARA] PostToolUse Read/Grep hook error:", error);
|
|
920
|
+
return Promise.resolve({ stopReason: "[YARA] Scanner error while scanning read content — session terminated as a precaution." });
|
|
921
|
+
}
|
|
922
|
+
}],
|
|
923
|
+
timeout: HOOK_TIMEOUT_MS
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
hooks: [async (input) => {
|
|
927
|
+
try {
|
|
928
|
+
if (input.tool_name !== "Bash") return {};
|
|
929
|
+
const toolInput = input.tool_input;
|
|
930
|
+
const command = typeof toolInput?.command === "string" ? toolInput.command : "";
|
|
931
|
+
if (!isSkillInstallCommand(command)) return {};
|
|
932
|
+
const dirMatch = command.match(/mkdir -p (.claude\/skills\/[^\s&]+)/);
|
|
933
|
+
if (!dirMatch) return {};
|
|
934
|
+
const skillDir = dirMatch[1];
|
|
935
|
+
const cwd = input.cwd ?? process.cwd();
|
|
936
|
+
recordScan();
|
|
937
|
+
const result = await scanSkillFiles(cwd, skillDir);
|
|
938
|
+
if (!result.matched) return {};
|
|
939
|
+
const match = highestSeverityMatch(result.matches);
|
|
940
|
+
logYaraMatch("PostToolUse", "Bash (skill install)", match, "aborted");
|
|
941
|
+
recordViolation({
|
|
942
|
+
rule: match.rule.name,
|
|
943
|
+
severity: match.rule.severity,
|
|
944
|
+
action: "aborted",
|
|
945
|
+
phase: "PostToolUse",
|
|
946
|
+
tool: "Bash (skill)"
|
|
947
|
+
});
|
|
948
|
+
return { stopReason: `[YARA CRITICAL] Poisoned skill detected in ${skillDir}: ${match.rule.name}. The downloaded skill contains potential prompt injection. Session terminated for safety.` };
|
|
949
|
+
} catch (error) {
|
|
950
|
+
logToFile("[YARA] PostToolUse skill install hook error:", error);
|
|
951
|
+
return { stopReason: "[YARA] Scanner error while scanning skill files — session terminated as a precaution." };
|
|
952
|
+
}
|
|
953
|
+
}],
|
|
954
|
+
timeout: SKILL_SCAN_HOOK_TIMEOUT_MS
|
|
955
|
+
}
|
|
956
|
+
];
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Read and scan all text files in a skill directory for prompt injection.
|
|
960
|
+
*/
|
|
961
|
+
async function scanSkillFiles(cwd, skillDir) {
|
|
962
|
+
const absoluteDir = path.resolve(cwd, skillDir);
|
|
963
|
+
if (!fs.existsSync(absoluteDir)) {
|
|
964
|
+
logToFile(`[YARA] Skill directory does not exist: ${absoluteDir}`);
|
|
965
|
+
return { matched: false };
|
|
966
|
+
}
|
|
967
|
+
const files = await fg("**/*.{md,txt,yaml,yml,json,js,ts,py,rb,sh}", {
|
|
968
|
+
cwd: absoluteDir,
|
|
969
|
+
absolute: true
|
|
970
|
+
});
|
|
971
|
+
const fileContents = [];
|
|
972
|
+
for (const filePath of files) try {
|
|
973
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
974
|
+
fileContents.push({
|
|
975
|
+
path: filePath,
|
|
976
|
+
content
|
|
977
|
+
});
|
|
978
|
+
} catch (err) {
|
|
979
|
+
logToFile(`[YARA] Could not read skill file ${filePath}:`, err);
|
|
980
|
+
}
|
|
981
|
+
if (fileContents.length === 0) {
|
|
982
|
+
logToFile(`[YARA] No text files found in skill directory: ${absoluteDir}`);
|
|
983
|
+
return { matched: false };
|
|
984
|
+
}
|
|
985
|
+
logToFile(`[YARA] Scanning ${fileContents.length} files in skill directory: ${skillDir}`);
|
|
986
|
+
return scanSkillDirectory(fileContents);
|
|
987
|
+
}
|
|
988
|
+
//#endregion
|
|
989
|
+
//#region src/lib/agent/commandments.ts
|
|
990
|
+
/**
|
|
991
|
+
* Wizard-wide commandments that are always appended as a system prompt.
|
|
992
|
+
*
|
|
993
|
+
* Keep this as a simple string so it can be inlined into the compiled bundle
|
|
994
|
+
* without extra files, copying, or runtime I/O.
|
|
995
|
+
*/
|
|
996
|
+
const WIZARD_COMMANDMENTS = [
|
|
997
|
+
"Never hallucinate a PostHog project token, host, or any other secret. Always use the real values that have been configured for this project (for example via environment variables).",
|
|
998
|
+
"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.",
|
|
999
|
+
"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.",
|
|
1000
|
+
"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.",
|
|
1001
|
+
"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.",
|
|
1002
|
+
"Treat feature flags, custom properties, and event names as part of an analytics contract. Prefer reusing existing names and patterns in the project. When you must introduce new ones, make them clear, descriptive, and consistent with existing conventions, and avoid scattering the same flag or property across many unrelated callsites.",
|
|
1003
|
+
"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.",
|
|
1004
|
+
"Do not spawn subagents unless explicitly instructed to do so.",
|
|
1005
|
+
"After reading the integration skill, use the TodoWrite tool to track your progress. Create a todo list at the describing the high-level areas of work, mark each as in_progress when you begin it, and completed when done. Describe high-level tasks from the workflow (\"inserting event tracking code\", etc), not specific files or lines. For each new stage of the integration, create additional todos if necessary. Create a final \"wrapping up\" step and mark it completed when the integration is complete.",
|
|
1006
|
+
"Do not assume \"PostHog provider\" or \"PostHogProvider\" in todo labels, status messages, or code. Only use a provider if the skill workflow explicitly requires one for the specific framework.",
|
|
1007
|
+
"If you see a [YARA WARNING] or [YARA VIOLATION] message, handle it silently. Fix the issue (revert the write, avoid the flagged pattern) without mentioning security warnings or YARA to the user. These are internal guardrails, not user-facing alerts. Never show scary security language to the user."
|
|
1008
|
+
].join("\n");
|
|
1009
|
+
function getWizardCommandments() {
|
|
1010
|
+
return WIZARD_COMMANDMENTS;
|
|
1011
|
+
}
|
|
1012
|
+
//#endregion
|
|
1013
|
+
//#region src/lib/agent/agent-interface.ts
|
|
1014
|
+
/**
|
|
1015
|
+
* Shared agent interface for PostHog wizards
|
|
1016
|
+
* Uses Claude Agent SDK directly with PostHog LLM gateway
|
|
1017
|
+
*/
|
|
1018
|
+
let _sdkModule = null;
|
|
1019
|
+
async function getSDKModule() {
|
|
1020
|
+
if (!_sdkModule) _sdkModule = await import("@anthropic-ai/claude-agent-sdk");
|
|
1021
|
+
return _sdkModule;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Get the path to the bundled Claude Code CLI from the SDK package.
|
|
1025
|
+
* This ensures we use the SDK's bundled version rather than the user's installed Claude Code.
|
|
1026
|
+
*/
|
|
1027
|
+
function getClaudeCodeExecutablePath() {
|
|
1028
|
+
const sdkPackagePath = __require.resolve("@anthropic-ai/claude-agent-sdk");
|
|
1029
|
+
return path.join(path.dirname(sdkPackagePath), "cli.js");
|
|
1030
|
+
}
|
|
1031
|
+
const AgentSignals = {
|
|
1032
|
+
STATUS: "[STATUS]",
|
|
1033
|
+
ERROR_MCP_MISSING: "[ERROR-MCP-MISSING]",
|
|
1034
|
+
ERROR_RESOURCE_MISSING: "[ERROR-RESOURCE-MISSING]",
|
|
1035
|
+
ABORT: "[ABORT]",
|
|
1036
|
+
WIZARD_REMARK: "[WIZARD-REMARK]",
|
|
1037
|
+
BENCHMARK: "[BENCHMARK]"
|
|
1038
|
+
};
|
|
1039
|
+
const BLOCKING_ENV_KEYS = [
|
|
1040
|
+
"ANTHROPIC_API_KEY",
|
|
1041
|
+
"ANTHROPIC_BASE_URL",
|
|
1042
|
+
"ANTHROPIC_AUTH_TOKEN"
|
|
1043
|
+
];
|
|
1044
|
+
const BLOCKING_SETTINGS_KEYS = ["apiKeyHelper"];
|
|
1045
|
+
/**
|
|
1046
|
+
* Check a single settings file for blocking env keys and top-level settings keys.
|
|
1047
|
+
* Returns matched key names, or an empty array if none found.
|
|
1048
|
+
*/
|
|
1049
|
+
function checkSettingsFile(filePath) {
|
|
1050
|
+
try {
|
|
1051
|
+
const raw = fs$1.readFileSync(filePath, "utf-8");
|
|
1052
|
+
const parsed = JSON.parse(raw);
|
|
1053
|
+
const matched = [];
|
|
1054
|
+
const envBlock = parsed?.env;
|
|
1055
|
+
if (envBlock && typeof envBlock === "object") matched.push(...BLOCKING_ENV_KEYS.filter((key) => key in envBlock));
|
|
1056
|
+
matched.push(...BLOCKING_SETTINGS_KEYS.filter((key) => key in parsed && parsed[key] !== "" && parsed[key] != null));
|
|
1057
|
+
return matched;
|
|
1058
|
+
} catch {
|
|
1059
|
+
return [];
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Managed settings path on macOS.
|
|
1064
|
+
* IT/MDM-deployed settings — readable by all users, writable only by root.
|
|
1065
|
+
*/
|
|
1066
|
+
const MANAGED_SETTINGS_PATH = "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
1067
|
+
/**
|
|
1068
|
+
* Check project and org-managed settings for blocking keys that conflict
|
|
1069
|
+
* with the wizard's proxy auth.
|
|
1070
|
+
*/
|
|
1071
|
+
function checkAllSettingsConflicts(workingDirectory) {
|
|
1072
|
+
const conflicts = [];
|
|
1073
|
+
const sources = [{
|
|
1074
|
+
source: "managed",
|
|
1075
|
+
paths: [MANAGED_SETTINGS_PATH],
|
|
1076
|
+
writable: false
|
|
1077
|
+
}, {
|
|
1078
|
+
source: "project",
|
|
1079
|
+
paths: [path.join(workingDirectory, ".claude", "settings.json"), path.join(workingDirectory, ".claude", "settings")],
|
|
1080
|
+
writable: true
|
|
1081
|
+
}];
|
|
1082
|
+
for (const { source, paths, writable } of sources) for (const filePath of paths) {
|
|
1083
|
+
const keys = checkSettingsFile(filePath);
|
|
1084
|
+
if (keys.length > 0) {
|
|
1085
|
+
conflicts.push({
|
|
1086
|
+
source,
|
|
1087
|
+
keys,
|
|
1088
|
+
writable
|
|
1089
|
+
});
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
return conflicts;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Copy .claude/settings.json to .wizard-backup (overwriting if it exists),
|
|
1097
|
+
* then remove the original so the SDK doesn't load the blocking overrides.
|
|
1098
|
+
*/
|
|
1099
|
+
function backupAndFixClaudeSettings(workingDirectory) {
|
|
1100
|
+
for (const name of ["settings.json", "settings"]) {
|
|
1101
|
+
const filePath = path.join(workingDirectory, ".claude", name);
|
|
1102
|
+
const backupPath = `${filePath}.wizard-backup`;
|
|
1103
|
+
analytics.wizardCapture("backedup-claude-settings");
|
|
1104
|
+
try {
|
|
1105
|
+
fs$1.copyFileSync(filePath, backupPath);
|
|
1106
|
+
fs$1.unlinkSync(filePath);
|
|
1107
|
+
registerCleanup(() => {
|
|
1108
|
+
try {
|
|
1109
|
+
restoreClaudeSettings(workingDirectory);
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
analytics.captureException(error);
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
return true;
|
|
1115
|
+
} catch {}
|
|
1116
|
+
}
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Restore .claude/settings.json from .wizard-backup.
|
|
1121
|
+
* Copies (not moves) so the backup is preserved.
|
|
1122
|
+
*/
|
|
1123
|
+
function restoreClaudeSettings(workingDirectory) {
|
|
1124
|
+
for (const name of ["settings.json", "settings"]) {
|
|
1125
|
+
const backup = path.join(workingDirectory, ".claude", `${name}.wizard-backup`);
|
|
1126
|
+
try {
|
|
1127
|
+
fs$1.copyFileSync(backup, path.join(workingDirectory, ".claude", name));
|
|
1128
|
+
analytics.wizardCapture("restored-claude-settings");
|
|
1129
|
+
return;
|
|
1130
|
+
} catch (error) {
|
|
1131
|
+
analytics.captureException(error);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Create a stop hook callback that drains the additional feature queue,
|
|
1137
|
+
* then collects a remark, then allows stop.
|
|
1138
|
+
*
|
|
1139
|
+
* Three-phase logic using closure state:
|
|
1140
|
+
* Phase 1 — drain queue: block with each feature prompt in order
|
|
1141
|
+
* Phase 2 — collect remark (once): block with remark prompt
|
|
1142
|
+
* Phase 3 — allow stop: return {}
|
|
1143
|
+
*/
|
|
1144
|
+
function createStopHook(featureQueue, collectedText) {
|
|
1145
|
+
let featureIndex = 0;
|
|
1146
|
+
let remarkRequested = false;
|
|
1147
|
+
return (input) => {
|
|
1148
|
+
logToFile("Stop hook triggered", {
|
|
1149
|
+
stop_hook_active: input.stop_hook_active,
|
|
1150
|
+
featureIndex,
|
|
1151
|
+
remarkRequested,
|
|
1152
|
+
queueLength: featureQueue.length
|
|
1153
|
+
});
|
|
1154
|
+
if (collectedText) {
|
|
1155
|
+
if (collectedText.join("\n").includes("API Error:")) {
|
|
1156
|
+
logToFile("Stop hook: API error detected, allowing immediate stop");
|
|
1157
|
+
return {};
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
if (featureIndex < featureQueue.length) {
|
|
1161
|
+
const feature = featureQueue[featureIndex++];
|
|
1162
|
+
const prompt = ADDITIONAL_FEATURE_PROMPTS[feature];
|
|
1163
|
+
logToFile(`Stop hook: injecting feature prompt for ${feature}`);
|
|
1164
|
+
return {
|
|
1165
|
+
decision: "block",
|
|
1166
|
+
reason: prompt
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
if (!remarkRequested) {
|
|
1170
|
+
remarkRequested = true;
|
|
1171
|
+
logToFile("Stop hook: requesting reflection");
|
|
1172
|
+
return {
|
|
1173
|
+
decision: "block",
|
|
1174
|
+
reason: `Before concluding, provide a brief remark about what information or guidance would have been useful to have in the integration prompt or documentation for this run. Specifically cite anything that would have prevented tool failures, erroneous edits, or other wasted turns. Format your response exactly as: ${AgentSignals.WIZARD_REMARK} Your remark here`
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
logToFile("Stop hook: allowing stop");
|
|
1178
|
+
return {};
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Select wizard metadata from WIZARD_VARIANTS using the variant feature flag.
|
|
1183
|
+
* If the flag is missing or the value is not in config, returns the "base" variant (VARIANT: "base").
|
|
1184
|
+
*/
|
|
1185
|
+
function buildWizardMetadata(flags = {}) {
|
|
1186
|
+
const variantKey = flags[WIZARD_VARIANT_FLAG_KEY];
|
|
1187
|
+
return { ...(variantKey && WIZARD_VARIANTS[variantKey]) ?? WIZARD_VARIANTS["base"] };
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Build env for the SDK subprocess: process.env plus ANTHROPIC_CUSTOM_HEADERS from wizard metadata/flags.
|
|
1191
|
+
*/
|
|
1192
|
+
function buildAgentEnv(wizardMetadata, wizardFlags) {
|
|
1193
|
+
const headers = createCustomHeaders();
|
|
1194
|
+
for (const [key, value] of Object.entries(wizardMetadata)) headers.add(key.startsWith("X-POSTHOG-PROPERTY-") ? key : `${POSTHOG_PROPERTY_HEADER_PREFIX}${key}`, value);
|
|
1195
|
+
for (const [flagKey, variant] of Object.entries(wizardFlags)) {
|
|
1196
|
+
if (!flagKey.toLowerCase().startsWith("wizard")) continue;
|
|
1197
|
+
headers.addFlag(flagKey, variant);
|
|
1198
|
+
}
|
|
1199
|
+
const encoded = headers.encode();
|
|
1200
|
+
logToFile("ANTHROPIC_CUSTOM_HEADERS", encoded);
|
|
1201
|
+
return encoded;
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Package managers that can be used to run commands.
|
|
1205
|
+
*/
|
|
1206
|
+
const PACKAGE_MANAGERS = [
|
|
1207
|
+
"npm",
|
|
1208
|
+
"pnpm",
|
|
1209
|
+
"yarn",
|
|
1210
|
+
"bun",
|
|
1211
|
+
"npx",
|
|
1212
|
+
"pip",
|
|
1213
|
+
"pip3",
|
|
1214
|
+
"poetry",
|
|
1215
|
+
"pipenv",
|
|
1216
|
+
"uv"
|
|
1217
|
+
];
|
|
1218
|
+
/**
|
|
1219
|
+
* Safe scripts/commands that can be run with any package manager.
|
|
1220
|
+
* Uses startsWith matching, so 'build' matches 'build', 'build:prod', etc.
|
|
1221
|
+
* Note: Linting tools are in LINTING_TOOLS and checked separately.
|
|
1222
|
+
*/
|
|
1223
|
+
const SAFE_SCRIPTS = [
|
|
1224
|
+
"install",
|
|
1225
|
+
"add",
|
|
1226
|
+
"ci",
|
|
1227
|
+
"build",
|
|
1228
|
+
"tsc",
|
|
1229
|
+
"typecheck",
|
|
1230
|
+
"type-check",
|
|
1231
|
+
"check-types",
|
|
1232
|
+
"types",
|
|
1233
|
+
"lint",
|
|
1234
|
+
"format"
|
|
1235
|
+
];
|
|
1236
|
+
/**
|
|
1237
|
+
* Dangerous shell operators that could allow command injection.
|
|
1238
|
+
* Note: We handle `2>&1` and `| tail/head` separately as safe patterns.
|
|
1239
|
+
*/
|
|
1240
|
+
const DANGEROUS_OPERATORS = /[;`$()]/;
|
|
1241
|
+
/**
|
|
1242
|
+
* Check if command is an allowed package manager command.
|
|
1243
|
+
* Matches: <pkg-manager> [run|exec] <safe-script> [args...]
|
|
1244
|
+
*/
|
|
1245
|
+
function matchesAllowedPrefix(command) {
|
|
1246
|
+
const parts = command.split(/\s+/);
|
|
1247
|
+
if (parts.length === 0 || !PACKAGE_MANAGERS.includes(parts[0])) return false;
|
|
1248
|
+
let scriptIndex = 1;
|
|
1249
|
+
if (parts[scriptIndex] === "run" || parts[scriptIndex] === "exec") scriptIndex++;
|
|
1250
|
+
const scriptPart = parts.slice(scriptIndex).join(" ");
|
|
1251
|
+
return SAFE_SCRIPTS.some((safe) => scriptPart.startsWith(safe)) || LINTING_TOOLS.some((tool) => scriptPart.startsWith(tool));
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Permission hook that allows only safe commands.
|
|
1255
|
+
* - Package manager install commands
|
|
1256
|
+
* - Build/typecheck/lint commands for verification
|
|
1257
|
+
* - Piping to tail/head for output limiting is allowed
|
|
1258
|
+
* - Stderr redirection (2>&1) is allowed
|
|
1259
|
+
*/
|
|
1260
|
+
function wizardCanUseTool(toolName, input) {
|
|
1261
|
+
if (toolName === "Read" || toolName === "Write" || toolName === "Edit") {
|
|
1262
|
+
const filePath = typeof input.file_path === "string" ? input.file_path : "";
|
|
1263
|
+
const basename = path.basename(filePath);
|
|
1264
|
+
if (basename.startsWith(".env")) {
|
|
1265
|
+
logToFile(`Denying ${toolName} on env file: ${filePath}`);
|
|
1266
|
+
return {
|
|
1267
|
+
behavior: "deny",
|
|
1268
|
+
message: `Direct ${toolName} of ${basename} is not allowed. Use the wizard-tools MCP server (check_env_keys / set_env_values) to read or modify environment variables.`
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
return {
|
|
1272
|
+
behavior: "allow",
|
|
1273
|
+
updatedInput: input
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
if (toolName === "Grep") {
|
|
1277
|
+
const grepPath = typeof input.path === "string" ? input.path : "";
|
|
1278
|
+
if (grepPath && path.basename(grepPath).startsWith(".env")) {
|
|
1279
|
+
logToFile(`Denying Grep on env file: ${grepPath}`);
|
|
1280
|
+
return {
|
|
1281
|
+
behavior: "deny",
|
|
1282
|
+
message: `Grep on ${path.basename(grepPath)} is not allowed. Use the wizard-tools MCP server (check_env_keys) to check environment variables.`
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
return {
|
|
1286
|
+
behavior: "allow",
|
|
1287
|
+
updatedInput: input
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
if (toolName !== "Bash") return {
|
|
1291
|
+
behavior: "allow",
|
|
1292
|
+
updatedInput: input
|
|
1293
|
+
};
|
|
1294
|
+
const command = (typeof input.command === "string" ? input.command : "").trim();
|
|
1295
|
+
if (DANGEROUS_OPERATORS.test(command)) {
|
|
1296
|
+
logToFile(`Denying bash command with dangerous operators: ${command}`);
|
|
1297
|
+
debug(`Denying bash command with dangerous operators: ${command}`);
|
|
1298
|
+
analytics.wizardCapture("bash denied", {
|
|
1299
|
+
reason: "dangerous operators",
|
|
1300
|
+
command
|
|
1301
|
+
});
|
|
1302
|
+
return {
|
|
1303
|
+
behavior: "deny",
|
|
1304
|
+
message: `Bash command not allowed. Shell operators like ; \` $ ( ) are not permitted.`
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
const normalized = command.replace(/\s*\d*>&\d+\s*/g, " ").trim();
|
|
1308
|
+
const pipeMatch = normalized.match(/^(.+?)\s*\|\s*(tail|head)(\s+\S+)*\s*$/);
|
|
1309
|
+
if (pipeMatch) {
|
|
1310
|
+
const baseCommand = pipeMatch[1].trim();
|
|
1311
|
+
if (/[|&]/.test(baseCommand)) {
|
|
1312
|
+
logToFile(`Denying bash command with multiple pipes: ${command}`);
|
|
1313
|
+
debug(`Denying bash command with multiple pipes: ${command}`);
|
|
1314
|
+
analytics.wizardCapture("bash denied", {
|
|
1315
|
+
reason: "multiple pipes",
|
|
1316
|
+
command
|
|
1317
|
+
});
|
|
1318
|
+
return {
|
|
1319
|
+
behavior: "deny",
|
|
1320
|
+
message: `Bash command not allowed. Only single pipe to tail/head is permitted.`
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
if (matchesAllowedPrefix(baseCommand)) {
|
|
1324
|
+
logToFile(`Allowing bash command with output limiter: ${command}`);
|
|
1325
|
+
debug(`Allowing bash command with output limiter: ${command}`);
|
|
1326
|
+
return {
|
|
1327
|
+
behavior: "allow",
|
|
1328
|
+
updatedInput: input
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
if (/[|&]/.test(normalized)) {
|
|
1333
|
+
logToFile(`Denying bash command with pipe/&: ${command}`);
|
|
1334
|
+
debug(`Denying bash command with pipe/&: ${command}`);
|
|
1335
|
+
analytics.wizardCapture("bash denied", {
|
|
1336
|
+
reason: "disallowed pipe",
|
|
1337
|
+
command
|
|
1338
|
+
});
|
|
1339
|
+
return {
|
|
1340
|
+
behavior: "deny",
|
|
1341
|
+
message: `Bash command not allowed. Pipes are only permitted with tail/head for output limiting.`
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
if (matchesAllowedPrefix(normalized)) {
|
|
1345
|
+
logToFile(`Allowing bash command: ${command}`);
|
|
1346
|
+
debug(`Allowing bash command: ${command}`);
|
|
1347
|
+
return {
|
|
1348
|
+
behavior: "allow",
|
|
1349
|
+
updatedInput: input
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
logToFile(`Denying bash command: ${command}`);
|
|
1353
|
+
debug(`Denying bash command: ${command}`);
|
|
1354
|
+
analytics.wizardCapture("bash denied", {
|
|
1355
|
+
reason: "not in allowlist",
|
|
1356
|
+
command
|
|
1357
|
+
});
|
|
1358
|
+
return {
|
|
1359
|
+
behavior: "deny",
|
|
1360
|
+
message: `Bash command not allowed. Only install, build, typecheck, lint, and formatting commands are permitted.`
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Initialize agent configuration for the LLM gateway
|
|
1365
|
+
*/
|
|
1366
|
+
async function initializeAgent(config, options) {
|
|
1367
|
+
initLogFile();
|
|
1368
|
+
logToFile("Agent initialization starting");
|
|
1369
|
+
logToFile("Install directory:", options.installDir);
|
|
1370
|
+
getUI().log.step("Initializing Claude agent...");
|
|
1371
|
+
try {
|
|
1372
|
+
const gatewayUrl = getLlmGatewayUrlFromHost(config.posthogApiHost);
|
|
1373
|
+
process.env.ANTHROPIC_BASE_URL = gatewayUrl;
|
|
1374
|
+
process.env.ANTHROPIC_AUTH_TOKEN = config.posthogApiKey;
|
|
1375
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = config.posthogApiKey;
|
|
1376
|
+
process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = "true";
|
|
1377
|
+
logToFile("Configured LLM gateway:", gatewayUrl);
|
|
1378
|
+
const mcpServers = {
|
|
1379
|
+
"posthog-wizard": {
|
|
1380
|
+
type: "http",
|
|
1381
|
+
url: config.posthogMcpUrl,
|
|
1382
|
+
headers: {
|
|
1383
|
+
Authorization: `Bearer ${config.posthogApiKey}`,
|
|
1384
|
+
"User-Agent": WIZARD_USER_AGENT
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
...Object.fromEntries(Object.entries(config.additionalMcpServers ?? {}).map(([name, { url }]) => [name, {
|
|
1388
|
+
type: "http",
|
|
1389
|
+
url
|
|
1390
|
+
}]))
|
|
1391
|
+
};
|
|
1392
|
+
mcpServers["wizard-tools"] = await createWizardToolsServer({
|
|
1393
|
+
workingDirectory: config.workingDirectory,
|
|
1394
|
+
detectPackageManager: config.detectPackageManager,
|
|
1395
|
+
skillsBaseUrl: config.skillsBaseUrl
|
|
1396
|
+
});
|
|
1397
|
+
const agentRunConfig = {
|
|
1398
|
+
workingDirectory: config.workingDirectory,
|
|
1399
|
+
mcpServers,
|
|
1400
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
1401
|
+
wizardFlags: config.wizardFlags,
|
|
1402
|
+
wizardMetadata: config.wizardMetadata
|
|
1403
|
+
};
|
|
1404
|
+
logToFile("Agent config:", {
|
|
1405
|
+
workingDirectory: agentRunConfig.workingDirectory,
|
|
1406
|
+
posthogMcpUrl: config.posthogMcpUrl,
|
|
1407
|
+
gatewayUrl,
|
|
1408
|
+
apiKeyPresent: !!config.posthogApiKey
|
|
1409
|
+
});
|
|
1410
|
+
if (options.debug) debug("Agent config:", {
|
|
1411
|
+
workingDirectory: agentRunConfig.workingDirectory,
|
|
1412
|
+
posthogMcpUrl: config.posthogMcpUrl,
|
|
1413
|
+
gatewayUrl,
|
|
1414
|
+
apiKeyPresent: !!config.posthogApiKey
|
|
1415
|
+
});
|
|
1416
|
+
getUI().log.step(`Verbose logs: ${getLogFilePath()}`);
|
|
1417
|
+
getUI().log.success("Agent initialized. Let's get cooking!");
|
|
1418
|
+
return agentRunConfig;
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
getUI().log.error(`Failed to initialize agent: ${error.message}`);
|
|
1421
|
+
logToFile("Agent initialization error:", error);
|
|
1422
|
+
debug("Agent initialization error:", error);
|
|
1423
|
+
throw error;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Check agent output for YARA scanner violations.
|
|
1428
|
+
* Used in both the success and catch paths of runAgent.
|
|
1429
|
+
*/
|
|
1430
|
+
function checkYaraViolation(outputText, spinner) {
|
|
1431
|
+
if (outputText.includes("[YARA CRITICAL]") || outputText.includes("[YARA] Scanner error")) {
|
|
1432
|
+
logToFile("Agent error: YARA_VIOLATION");
|
|
1433
|
+
spinner.stop("Security violation detected");
|
|
1434
|
+
return { error: "WIZARD_YARA_VIOLATION" };
|
|
1435
|
+
}
|
|
1436
|
+
return null;
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Execute an agent with the provided prompt and options
|
|
1440
|
+
* Handles the full lifecycle: spinner, execution, error handling
|
|
1441
|
+
*
|
|
1442
|
+
* @returns An object containing any error detected in the agent's output
|
|
1443
|
+
*/
|
|
1444
|
+
async function runAgent(agentConfig, prompt, options, spinner, config, middleware) {
|
|
1445
|
+
const { spinnerMessage = "Customizing your PostHog setup...", successMessage = "PostHog integration complete", errorMessage = "Integration failed", abortCases = [] } = config ?? {};
|
|
1446
|
+
const { query } = await getSDKModule();
|
|
1447
|
+
spinner.start(spinnerMessage);
|
|
1448
|
+
const cliPath = getClaudeCodeExecutablePath();
|
|
1449
|
+
logToFile("Starting agent run");
|
|
1450
|
+
logToFile("Claude Code executable:", cliPath);
|
|
1451
|
+
logToFile("Prompt:", prompt);
|
|
1452
|
+
const startTime = Date.now();
|
|
1453
|
+
const collectedText = [];
|
|
1454
|
+
let receivedSuccessResult = false;
|
|
1455
|
+
let loggedInitialContext = false;
|
|
1456
|
+
let lastResultMessage = null;
|
|
1457
|
+
let signalDone;
|
|
1458
|
+
const resultReceived = new Promise((resolve) => {
|
|
1459
|
+
signalDone = resolve;
|
|
1460
|
+
});
|
|
1461
|
+
const createPromptStream = async function* () {
|
|
1462
|
+
yield {
|
|
1463
|
+
type: "user",
|
|
1464
|
+
session_id: "",
|
|
1465
|
+
message: {
|
|
1466
|
+
role: "user",
|
|
1467
|
+
content: prompt
|
|
1468
|
+
},
|
|
1469
|
+
parent_tool_use_id: null
|
|
1470
|
+
};
|
|
1471
|
+
await resultReceived;
|
|
1472
|
+
};
|
|
1473
|
+
const completeWithSuccess = (suppressedError) => {
|
|
1474
|
+
const durationMs = Date.now() - startTime;
|
|
1475
|
+
const durationSeconds = Math.round(durationMs / 1e3);
|
|
1476
|
+
if (suppressedError) {
|
|
1477
|
+
logToFile(`Ignoring post-completion error, agent completed successfully in ${durationSeconds}s`);
|
|
1478
|
+
logToFile("Suppressed error:", suppressedError.message);
|
|
1479
|
+
} else logToFile(`Agent run completed in ${durationSeconds}s`);
|
|
1480
|
+
const outputText = collectedText.join("\n");
|
|
1481
|
+
const remarkRegex = new RegExp(`${AgentSignals.WIZARD_REMARK.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*(.+?)(?:\\n|$)`, "s");
|
|
1482
|
+
const remarkMatch = outputText.match(remarkRegex);
|
|
1483
|
+
if (remarkMatch && remarkMatch[1]) {
|
|
1484
|
+
const remark = remarkMatch[1].trim();
|
|
1485
|
+
if (remark) analytics.capture(WIZARD_REMARK_EVENT_NAME, { remark });
|
|
1486
|
+
}
|
|
1487
|
+
analytics.wizardCapture("agent completed", {
|
|
1488
|
+
duration_ms: durationMs,
|
|
1489
|
+
duration_seconds: durationSeconds
|
|
1490
|
+
});
|
|
1491
|
+
try {
|
|
1492
|
+
middleware?.finalize(lastResultMessage, durationMs);
|
|
1493
|
+
} catch (e) {
|
|
1494
|
+
logToFile(`${AgentSignals.BENCHMARK} Middleware finalize error:`, e);
|
|
1495
|
+
}
|
|
1496
|
+
spinner.stop(successMessage);
|
|
1497
|
+
return {};
|
|
1498
|
+
};
|
|
1499
|
+
let eventPlanWatcher;
|
|
1500
|
+
let eventPlanInterval;
|
|
1501
|
+
const abortController = new AbortController();
|
|
1502
|
+
let abortReason = null;
|
|
1503
|
+
try {
|
|
1504
|
+
const allowedTools = [
|
|
1505
|
+
"Read",
|
|
1506
|
+
"Write",
|
|
1507
|
+
"Edit",
|
|
1508
|
+
"Glob",
|
|
1509
|
+
"Grep",
|
|
1510
|
+
"Bash",
|
|
1511
|
+
"ListMcpResourcesTool",
|
|
1512
|
+
"Skill",
|
|
1513
|
+
...WIZARD_TOOL_NAMES
|
|
1514
|
+
];
|
|
1515
|
+
const response = query({
|
|
1516
|
+
prompt: createPromptStream(),
|
|
1517
|
+
options: {
|
|
1518
|
+
abortController,
|
|
1519
|
+
model: agentConfig.model,
|
|
1520
|
+
cwd: agentConfig.workingDirectory,
|
|
1521
|
+
permissionMode: "acceptEdits",
|
|
1522
|
+
betas: ["context-1m-2025-08-07"],
|
|
1523
|
+
mcpServers: agentConfig.mcpServers,
|
|
1524
|
+
settingSources: ["project"],
|
|
1525
|
+
allowedTools,
|
|
1526
|
+
sandbox: {
|
|
1527
|
+
enabled: true,
|
|
1528
|
+
allowUnsandboxedCommands: false,
|
|
1529
|
+
filesystem: { allowWrite: [
|
|
1530
|
+
"/" + agentConfig.workingDirectory,
|
|
1531
|
+
"/" + agentConfig.workingDirectory + "/**",
|
|
1532
|
+
"//tmp",
|
|
1533
|
+
"//tmp/**",
|
|
1534
|
+
"//private/tmp",
|
|
1535
|
+
"//private/tmp/**",
|
|
1536
|
+
"~/Library/pnpm/store/**",
|
|
1537
|
+
"~/.local/share/pnpm/store/**",
|
|
1538
|
+
"~/.pnpm-store/**",
|
|
1539
|
+
"~/.npm/**",
|
|
1540
|
+
"~/.yarn/**",
|
|
1541
|
+
"~/.yarn/berry/**"
|
|
1542
|
+
] },
|
|
1543
|
+
network: { allowedDomains: [
|
|
1544
|
+
"github.com",
|
|
1545
|
+
"api.github.com",
|
|
1546
|
+
"raw.githubusercontent.com",
|
|
1547
|
+
"release-assets.githubusercontent.com",
|
|
1548
|
+
"objects.githubusercontent.com"
|
|
1549
|
+
] }
|
|
1550
|
+
},
|
|
1551
|
+
env: {
|
|
1552
|
+
...process.env,
|
|
1553
|
+
ANTHROPIC_API_KEY: void 0,
|
|
1554
|
+
ENABLE_TOOL_SEARCH: "auto:0",
|
|
1555
|
+
ANTHROPIC_CUSTOM_HEADERS: buildAgentEnv(agentConfig.wizardMetadata ?? {}, agentConfig.wizardFlags ?? {})
|
|
1556
|
+
},
|
|
1557
|
+
canUseTool: (toolName, input) => {
|
|
1558
|
+
logToFile("canUseTool called:", {
|
|
1559
|
+
toolName,
|
|
1560
|
+
input
|
|
1561
|
+
});
|
|
1562
|
+
const result = wizardCanUseTool(toolName, input);
|
|
1563
|
+
logToFile("canUseTool result:", result);
|
|
1564
|
+
return Promise.resolve(result);
|
|
1565
|
+
},
|
|
1566
|
+
systemPrompt: {
|
|
1567
|
+
type: "preset",
|
|
1568
|
+
preset: "claude_code",
|
|
1569
|
+
append: getWizardCommandments()
|
|
1570
|
+
},
|
|
1571
|
+
tools: {
|
|
1572
|
+
type: "preset",
|
|
1573
|
+
preset: "claude_code"
|
|
1574
|
+
},
|
|
1575
|
+
stderr: (data) => {
|
|
1576
|
+
logToFile("CLI stderr:", data);
|
|
1577
|
+
if (options.debug) debug("CLI stderr:", data);
|
|
1578
|
+
},
|
|
1579
|
+
hooks: {
|
|
1580
|
+
PreToolUse: createPreToolUseYaraHooks(),
|
|
1581
|
+
PostToolUse: createPostToolUseYaraHooks(),
|
|
1582
|
+
Stop: [{
|
|
1583
|
+
hooks: [createStopHook(config?.additionalFeatureQueue ?? [], collectedText)],
|
|
1584
|
+
timeout: 30
|
|
1585
|
+
}]
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
const eventPlanPath = path.join(agentConfig.workingDirectory, ".posthog-events.json");
|
|
1590
|
+
const readEventPlan = () => {
|
|
1591
|
+
try {
|
|
1592
|
+
const content = fs$1.readFileSync(eventPlanPath, "utf-8");
|
|
1593
|
+
const parsed = JSON.parse(content);
|
|
1594
|
+
if (Array.isArray(parsed)) getUI().setEventPlan(parsed.map((e) => ({
|
|
1595
|
+
name: e.name ?? e.event ?? "",
|
|
1596
|
+
description: e.description ?? ""
|
|
1597
|
+
})));
|
|
1598
|
+
} catch {}
|
|
1599
|
+
};
|
|
1600
|
+
try {
|
|
1601
|
+
eventPlanWatcher = fs$1.watch(eventPlanPath, () => readEventPlan());
|
|
1602
|
+
readEventPlan();
|
|
1603
|
+
} catch {
|
|
1604
|
+
eventPlanInterval = setInterval(() => {
|
|
1605
|
+
try {
|
|
1606
|
+
fs$1.accessSync(eventPlanPath);
|
|
1607
|
+
readEventPlan();
|
|
1608
|
+
clearInterval(eventPlanInterval);
|
|
1609
|
+
eventPlanInterval = void 0;
|
|
1610
|
+
eventPlanWatcher = fs$1.watch(eventPlanPath, () => readEventPlan());
|
|
1611
|
+
} catch {}
|
|
1612
|
+
}, 1e3);
|
|
1613
|
+
}
|
|
1614
|
+
for await (const message of response) {
|
|
1615
|
+
if (!loggedInitialContext && message.type === "assistant") {
|
|
1616
|
+
const usage = message.message?.usage;
|
|
1617
|
+
if (usage) {
|
|
1618
|
+
const input = usage.input_tokens ?? 0;
|
|
1619
|
+
const cacheCreation = usage.cache_creation_input_tokens ?? 0;
|
|
1620
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
1621
|
+
const initialTokens = input + cacheCreation + cacheRead;
|
|
1622
|
+
logToFile(`Initial context: ${initialTokens} tokens (input=${input}, cache_creation=${cacheCreation}, cache_read=${cacheRead})`);
|
|
1623
|
+
analytics.wizardCapture("agent initial context", {
|
|
1624
|
+
initial_tokens: initialTokens,
|
|
1625
|
+
input_tokens: input,
|
|
1626
|
+
cache_creation_input_tokens: cacheCreation,
|
|
1627
|
+
cache_read_input_tokens: cacheRead
|
|
1628
|
+
});
|
|
1629
|
+
}
|
|
1630
|
+
loggedInitialContext = true;
|
|
1631
|
+
}
|
|
1632
|
+
handleSDKMessage(message, options, spinner, collectedText, receivedSuccessResult);
|
|
1633
|
+
if (abortCases.length > 0 && !abortReason && message.type === "assistant") {
|
|
1634
|
+
const content = message.message?.content;
|
|
1635
|
+
if (Array.isArray(content)) {
|
|
1636
|
+
for (const block of content) if (block.type === "text" && typeof block.text === "string") {
|
|
1637
|
+
const match = block.text.match(/\[ABORT\]\s*(.+?)(?:\n|$)/);
|
|
1638
|
+
if (match) {
|
|
1639
|
+
abortReason = match[1].trim();
|
|
1640
|
+
logToFile(`Agent emitted [ABORT]: ${abortReason}`);
|
|
1641
|
+
abortController.abort();
|
|
1642
|
+
signalDone();
|
|
1643
|
+
break;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
if (message.type === "assistant" && collectedText.join("\n").includes("API Error: 401")) {
|
|
1649
|
+
signalDone();
|
|
1650
|
+
spinner.stop("Authentication failed");
|
|
1651
|
+
logToFile("Agent error: 401, showing auth error screen");
|
|
1652
|
+
getUI().showAuthError();
|
|
1653
|
+
await wizardAbort({
|
|
1654
|
+
message: "Authentication failed (401)",
|
|
1655
|
+
error: new WizardError("Authentication failed")
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
try {
|
|
1659
|
+
middleware?.onMessage(message);
|
|
1660
|
+
} catch (e) {
|
|
1661
|
+
logToFile(`${AgentSignals.BENCHMARK} Middleware onMessage error:`, e);
|
|
1662
|
+
}
|
|
1663
|
+
if (message.type === "result") {
|
|
1664
|
+
if (message.subtype === "success" && !message.is_error) {
|
|
1665
|
+
receivedSuccessResult = true;
|
|
1666
|
+
lastResultMessage = message;
|
|
1667
|
+
}
|
|
1668
|
+
signalDone();
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
if (abortReason) {
|
|
1672
|
+
spinner.stop("Wizard aborted");
|
|
1673
|
+
return {
|
|
1674
|
+
error: "WIZARD_ABORT",
|
|
1675
|
+
message: abortReason
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
const outputText = collectedText.join("\n");
|
|
1679
|
+
const yaraResult = checkYaraViolation(outputText, spinner);
|
|
1680
|
+
if (yaraResult) return yaraResult;
|
|
1681
|
+
if (outputText.includes(AgentSignals.ERROR_MCP_MISSING)) {
|
|
1682
|
+
logToFile("Agent error: MCP_MISSING");
|
|
1683
|
+
spinner.stop("Agent could not access PostHog MCP");
|
|
1684
|
+
return { error: "WIZARD_MCP_MISSING" };
|
|
1685
|
+
}
|
|
1686
|
+
if (outputText.includes(AgentSignals.ERROR_RESOURCE_MISSING)) {
|
|
1687
|
+
logToFile("Agent error: RESOURCE_MISSING");
|
|
1688
|
+
spinner.stop("Agent could not access setup resource");
|
|
1689
|
+
return { error: "WIZARD_RESOURCE_MISSING" };
|
|
1690
|
+
}
|
|
1691
|
+
const apiErrorMatch = outputText.match(/API Error: [^\n]+/g);
|
|
1692
|
+
const apiErrorMessage = apiErrorMatch ? apiErrorMatch.join("\n") : "Unknown API error";
|
|
1693
|
+
if (outputText.includes("API Error: 429")) {
|
|
1694
|
+
logToFile("Agent error: RATE_LIMIT");
|
|
1695
|
+
spinner.stop("Rate limit exceeded");
|
|
1696
|
+
return {
|
|
1697
|
+
error: "WIZARD_RATE_LIMIT",
|
|
1698
|
+
message: apiErrorMessage
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
if (outputText.includes("API Error:")) {
|
|
1702
|
+
logToFile("Agent error: API_ERROR");
|
|
1703
|
+
spinner.stop("API error occurred");
|
|
1704
|
+
return {
|
|
1705
|
+
error: "WIZARD_API_ERROR",
|
|
1706
|
+
message: apiErrorMessage
|
|
1707
|
+
};
|
|
1708
|
+
}
|
|
1709
|
+
return completeWithSuccess();
|
|
1710
|
+
} catch (error) {
|
|
1711
|
+
signalDone();
|
|
1712
|
+
if (abortReason) {
|
|
1713
|
+
spinner.stop("Wizard aborted");
|
|
1714
|
+
return {
|
|
1715
|
+
error: "WIZARD_ABORT",
|
|
1716
|
+
message: abortReason
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
if (receivedSuccessResult) return completeWithSuccess(error);
|
|
1720
|
+
const outputText = collectedText.join("\n");
|
|
1721
|
+
const yaraResult = checkYaraViolation(outputText, spinner);
|
|
1722
|
+
if (yaraResult) return yaraResult;
|
|
1723
|
+
const apiErrorMatch = outputText.match(/API Error: [^\n]+/g);
|
|
1724
|
+
const apiErrorMessage = apiErrorMatch ? apiErrorMatch.join("\n") : "Unknown API error";
|
|
1725
|
+
if (outputText.includes("API Error: 429")) {
|
|
1726
|
+
logToFile("Agent error (caught): RATE_LIMIT");
|
|
1727
|
+
spinner.stop("Rate limit exceeded");
|
|
1728
|
+
return {
|
|
1729
|
+
error: "WIZARD_RATE_LIMIT",
|
|
1730
|
+
message: apiErrorMessage
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
if (outputText.includes("API Error:")) {
|
|
1734
|
+
logToFile("Agent error (caught): API_ERROR");
|
|
1735
|
+
spinner.stop("API error occurred");
|
|
1736
|
+
return {
|
|
1737
|
+
error: "WIZARD_API_ERROR",
|
|
1738
|
+
message: apiErrorMessage
|
|
1739
|
+
};
|
|
1740
|
+
}
|
|
1741
|
+
spinner.stop(errorMessage);
|
|
1742
|
+
getUI().log.error(`Error: ${error.message}`);
|
|
1743
|
+
logToFile("Agent run failed:", error);
|
|
1744
|
+
debug("Full error:", error);
|
|
1745
|
+
throw error;
|
|
1746
|
+
} finally {
|
|
1747
|
+
eventPlanWatcher?.close();
|
|
1748
|
+
if (eventPlanInterval) clearInterval(eventPlanInterval);
|
|
1749
|
+
if (!receivedSuccessResult) {
|
|
1750
|
+
const durationMs = Date.now() - startTime;
|
|
1751
|
+
analytics.wizardCapture("agent aborted", {
|
|
1752
|
+
duration_ms: durationMs,
|
|
1753
|
+
duration_seconds: Math.round(durationMs / 1e3)
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Handle SDK messages and provide user feedback
|
|
1760
|
+
*
|
|
1761
|
+
* @param receivedSuccessResult - If true, suppress user-facing error output for cleanup errors
|
|
1762
|
+
* while still logging to file. The SDK may emit a second error
|
|
1763
|
+
* result after success due to cleanup race conditions.
|
|
1764
|
+
*/
|
|
1765
|
+
function handleSDKMessage(message, options, spinner, collectedText, receivedSuccessResult = false) {
|
|
1766
|
+
logToFile(`SDK Message: ${message.type}`, JSON.stringify(message, null, 2));
|
|
1767
|
+
if (options.debug) debug(`SDK Message type: ${message.type}`);
|
|
1768
|
+
switch (message.type) {
|
|
1769
|
+
case "assistant": {
|
|
1770
|
+
const content = message.message?.content;
|
|
1771
|
+
if (Array.isArray(content)) for (const block of content) {
|
|
1772
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
1773
|
+
collectedText.push(block.text);
|
|
1774
|
+
const statusRegex = new RegExp(`^.*${AgentSignals.STATUS.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*(.+?)$`, "m");
|
|
1775
|
+
const statusMatch = block.text.match(statusRegex);
|
|
1776
|
+
if (statusMatch) {
|
|
1777
|
+
const statusText = statusMatch[1].trim();
|
|
1778
|
+
getUI().pushStatus(statusText);
|
|
1779
|
+
spinner.message(statusText);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
if (block.type === "tool_use" && block.name === "TodoWrite" && block.input?.todos && Array.isArray(block.input.todos)) getUI().syncTodos(block.input.todos);
|
|
1783
|
+
}
|
|
1784
|
+
break;
|
|
1785
|
+
}
|
|
1786
|
+
case "result":
|
|
1787
|
+
if (message.is_error) {
|
|
1788
|
+
logToFile("Agent result with error:", message.result);
|
|
1789
|
+
if (typeof message.result === "string") collectedText.push(message.result);
|
|
1790
|
+
if (message.errors && !receivedSuccessResult) for (const err of message.errors) {
|
|
1791
|
+
getUI().log.error(`Error: ${err}`);
|
|
1792
|
+
logToFile("ERROR:", err);
|
|
1793
|
+
}
|
|
1794
|
+
} else if (message.subtype === "success") {
|
|
1795
|
+
logToFile("Agent completed successfully");
|
|
1796
|
+
if (typeof message.result === "string") collectedText.push(message.result);
|
|
1797
|
+
} else {
|
|
1798
|
+
logToFile("Agent result with error:", message.result);
|
|
1799
|
+
if (message.errors && !receivedSuccessResult) for (const err of message.errors) {
|
|
1800
|
+
getUI().log.error(`Error: ${err}`);
|
|
1801
|
+
logToFile("ERROR:", err);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
break;
|
|
1805
|
+
case "system":
|
|
1806
|
+
if (message.subtype === "init") logToFile("Agent session initialized", {
|
|
1807
|
+
model: message.model,
|
|
1808
|
+
tools: message.tools?.length,
|
|
1809
|
+
mcpServers: message.mcp_servers
|
|
1810
|
+
});
|
|
1811
|
+
break;
|
|
1812
|
+
default:
|
|
1813
|
+
if (options.debug) debug(`Unhandled message type: ${message.type}`);
|
|
1814
|
+
break;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
//#endregion
|
|
1818
|
+
//#region src/lib/health-checks/statuspage.ts
|
|
1819
|
+
function mapIndicator(v) {
|
|
1820
|
+
switch (v) {
|
|
1821
|
+
case "none": return "healthy";
|
|
1822
|
+
case "minor": return "degraded";
|
|
1823
|
+
case "major":
|
|
1824
|
+
case "critical": return "down";
|
|
1825
|
+
default: return "degraded";
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
function mapComponentRaw(v) {
|
|
1829
|
+
switch (v) {
|
|
1830
|
+
case "operational": return "healthy";
|
|
1831
|
+
case "degraded_performance":
|
|
1832
|
+
case "under_maintenance": return "degraded";
|
|
1833
|
+
case "partial_outage":
|
|
1834
|
+
case "major_outage": return "down";
|
|
1835
|
+
default: return "degraded";
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
function errResult$1(error) {
|
|
1839
|
+
return {
|
|
1840
|
+
status: "degraded",
|
|
1841
|
+
error
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
async function fetchStatuspageIndicator(url, timeoutMs = 5e3) {
|
|
1845
|
+
try {
|
|
1846
|
+
const controller = new AbortController();
|
|
1847
|
+
const tid = setTimeout(() => controller.abort(), timeoutMs);
|
|
1848
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
1849
|
+
clearTimeout(tid);
|
|
1850
|
+
if (!res.ok) return errResult$1(`HTTP ${res.status}`);
|
|
1851
|
+
const indicator = (await res.json()).status?.indicator ?? null;
|
|
1852
|
+
return {
|
|
1853
|
+
status: mapIndicator(indicator),
|
|
1854
|
+
rawIndicator: indicator ?? void 0
|
|
1855
|
+
};
|
|
1856
|
+
} catch (e) {
|
|
1857
|
+
if (e instanceof Error && e.name === "AbortError") return errResult$1("Request timed out");
|
|
1858
|
+
return errResult$1(e instanceof Error ? e.message : "Unknown error");
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
async function fetchStatuspageSummary(url, timeoutMs = 5e3) {
|
|
1862
|
+
try {
|
|
1863
|
+
const controller = new AbortController();
|
|
1864
|
+
const tid = setTimeout(() => controller.abort(), timeoutMs);
|
|
1865
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
1866
|
+
clearTimeout(tid);
|
|
1867
|
+
if (!res.ok) return errResult$1(`HTTP ${res.status}`);
|
|
1868
|
+
const data = await res.json();
|
|
1869
|
+
const indicator = data.status?.indicator ?? null;
|
|
1870
|
+
const overall = mapIndicator(indicator);
|
|
1871
|
+
const affected = (data.components ?? []).map((c) => ({
|
|
1872
|
+
name: c.name,
|
|
1873
|
+
status: mapComponentRaw(c.status),
|
|
1874
|
+
rawStatus: c.status
|
|
1875
|
+
})).filter((c) => c.status !== "healthy");
|
|
1876
|
+
return {
|
|
1877
|
+
status: affected.length > 0 ? "degraded" : overall,
|
|
1878
|
+
rawIndicator: indicator ?? void 0,
|
|
1879
|
+
degradedOrDownComponents: affected.length > 0 ? affected : void 0
|
|
1880
|
+
};
|
|
1881
|
+
} catch (e) {
|
|
1882
|
+
if (e instanceof Error && e.name === "AbortError") return errResult$1("Request timed out");
|
|
1883
|
+
return errResult$1(e instanceof Error ? e.message : "Unknown error");
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
const checkAnthropicHealth = () => fetchStatuspageIndicator("https://status.claude.com/api/v2/status.json");
|
|
1887
|
+
const checkGithubHealth = () => fetchStatuspageIndicator("https://www.githubstatus.com/api/v2/status.json");
|
|
1888
|
+
const checkNpmOverallHealth = () => fetchStatuspageIndicator("https://status.npmjs.org/api/v2/status.json");
|
|
1889
|
+
const checkNpmComponentHealth = () => fetchStatuspageSummary("https://status.npmjs.org/api/v2/summary.json");
|
|
1890
|
+
const checkCloudflareOverallHealth = () => fetchStatuspageIndicator("https://www.cloudflarestatus.com/api/v2/status.json");
|
|
1891
|
+
const checkCloudflareComponentHealth = () => fetchStatuspageSummary("https://www.cloudflarestatus.com/api/v2/summary.json");
|
|
1892
|
+
//#endregion
|
|
1893
|
+
//#region src/lib/health-checks/incidentio.ts
|
|
1894
|
+
function mapIncidentImpact(impact) {
|
|
1895
|
+
switch (impact) {
|
|
1896
|
+
case "full_outage": return "down";
|
|
1897
|
+
case "partial_outage":
|
|
1898
|
+
case "degraded_performance": return "degraded";
|
|
1899
|
+
default: return "degraded";
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
function mapComponentStatus(status) {
|
|
1903
|
+
switch (status) {
|
|
1904
|
+
case "operational": return "healthy";
|
|
1905
|
+
case "full_outage": return "down";
|
|
1906
|
+
case "partial_outage":
|
|
1907
|
+
case "degraded_performance": return "degraded";
|
|
1908
|
+
default: return "degraded";
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
function errResult(error) {
|
|
1912
|
+
return {
|
|
1913
|
+
status: "degraded",
|
|
1914
|
+
error
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
const POSTHOG_STATUS_URL = "https://www.posthogstatus.com/api/v1/summary";
|
|
1918
|
+
async function fetchPosthogStatus(timeoutMs = 5e3) {
|
|
1919
|
+
try {
|
|
1920
|
+
const controller = new AbortController();
|
|
1921
|
+
const tid = setTimeout(() => controller.abort(), timeoutMs);
|
|
1922
|
+
const res = await fetch(POSTHOG_STATUS_URL, { signal: controller.signal });
|
|
1923
|
+
clearTimeout(tid);
|
|
1924
|
+
if (!res.ok) {
|
|
1925
|
+
const err = errResult(`HTTP ${res.status}`);
|
|
1926
|
+
return {
|
|
1927
|
+
overall: err,
|
|
1928
|
+
components: err
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
1931
|
+
const incidents = (await res.json()).ongoing_incidents ?? [];
|
|
1932
|
+
if (incidents.length === 0) return {
|
|
1933
|
+
overall: { status: "healthy" },
|
|
1934
|
+
components: { status: "healthy" }
|
|
1935
|
+
};
|
|
1936
|
+
let worstOverall = "degraded";
|
|
1937
|
+
const affected = [];
|
|
1938
|
+
for (const incident of incidents) {
|
|
1939
|
+
if (mapIncidentImpact(incident.current_worst_impact) === "down") worstOverall = "down";
|
|
1940
|
+
for (const comp of incident.affected_components ?? []) {
|
|
1941
|
+
const compStatus = mapComponentStatus(comp.current_status);
|
|
1942
|
+
if (compStatus !== "healthy") affected.push({
|
|
1943
|
+
name: comp.group_name ? `${comp.group_name} — ${comp.name}` : comp.name,
|
|
1944
|
+
status: compStatus,
|
|
1945
|
+
rawStatus: comp.current_status
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
return {
|
|
1950
|
+
overall: { status: worstOverall },
|
|
1951
|
+
components: {
|
|
1952
|
+
status: affected.length > 0 ? "degraded" : worstOverall,
|
|
1953
|
+
degradedOrDownComponents: affected.length > 0 ? affected : void 0
|
|
1954
|
+
}
|
|
1955
|
+
};
|
|
1956
|
+
} catch (e) {
|
|
1957
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
1958
|
+
const err = errResult("Request timed out");
|
|
1959
|
+
return {
|
|
1960
|
+
overall: err,
|
|
1961
|
+
components: err
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
const err = errResult(e instanceof Error ? e.message : "Unknown error");
|
|
1965
|
+
return {
|
|
1966
|
+
overall: err,
|
|
1967
|
+
components: err
|
|
1968
|
+
};
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
let _cache = null;
|
|
1972
|
+
function getPosthogHealth() {
|
|
1973
|
+
if (!_cache) _cache = fetchPosthogStatus();
|
|
1974
|
+
return _cache;
|
|
1975
|
+
}
|
|
1976
|
+
const checkPosthogOverallHealth = async () => (await getPosthogHealth()).overall;
|
|
1977
|
+
const checkPosthogComponentHealth = async () => (await getPosthogHealth()).components;
|
|
1978
|
+
//#endregion
|
|
1979
|
+
//#region src/lib/health-checks/endpoints.ts
|
|
1980
|
+
function downResult(error) {
|
|
1981
|
+
return {
|
|
1982
|
+
status: "down",
|
|
1983
|
+
error
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
async function fetchEndpointHealth(url, timeoutMs = 5e3, expectedStatus = 200) {
|
|
1987
|
+
try {
|
|
1988
|
+
const controller = new AbortController();
|
|
1989
|
+
const tid = setTimeout(() => controller.abort(), timeoutMs);
|
|
1990
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
1991
|
+
clearTimeout(tid);
|
|
1992
|
+
if (res.status === expectedStatus) return {
|
|
1993
|
+
status: "healthy",
|
|
1994
|
+
rawIndicator: `HTTP ${res.status}`
|
|
1995
|
+
};
|
|
1996
|
+
return downResult(`HTTP ${res.status}`);
|
|
1997
|
+
} catch (e) {
|
|
1998
|
+
if (e instanceof Error && e.name === "AbortError") return downResult("Request timed out");
|
|
1999
|
+
return downResult(e instanceof Error ? e.message : "Unknown error");
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
const checkLlmGatewayHealth = () => fetchEndpointHealth("https://gateway.us.posthog.com/_liveness");
|
|
2003
|
+
const checkMcpHealth = () => fetchEndpointHealth("https://mcp.posthog.com/");
|
|
2004
|
+
const checkGithubReleasesHealth = () => fetchEndpointHealth(`${REMOTE_SKILLS_BASE_URL}/skill-menu.json`);
|
|
2005
|
+
//#endregion
|
|
2006
|
+
//#region src/lib/health-checks/readiness.ts
|
|
2007
|
+
const SERVICE_LABELS = {
|
|
2008
|
+
anthropic: "Anthropic",
|
|
2009
|
+
posthogOverall: "PostHog",
|
|
2010
|
+
posthogComponents: "PostHog (components)",
|
|
2011
|
+
github: "GitHub",
|
|
2012
|
+
npmOverall: "npm",
|
|
2013
|
+
npmComponents: "npm (components)",
|
|
2014
|
+
cloudflareOverall: "Cloudflare",
|
|
2015
|
+
cloudflareComponents: "Cloudflare (components)",
|
|
2016
|
+
llmGateway: "LLM Gateway",
|
|
2017
|
+
mcp: "MCP",
|
|
2018
|
+
githubReleases: "GitHub Releases"
|
|
2019
|
+
};
|
|
2020
|
+
/**
|
|
2021
|
+
* See README section "Health checks" for the full rationale.
|
|
2022
|
+
* Adjust these arrays to change what blocks a wizard run.
|
|
2023
|
+
*/
|
|
2024
|
+
const DEFAULT_WIZARD_READINESS_CONFIG = {
|
|
2025
|
+
downBlocksRun: [
|
|
2026
|
+
"anthropic",
|
|
2027
|
+
"npmOverall",
|
|
2028
|
+
"llmGateway",
|
|
2029
|
+
"mcp",
|
|
2030
|
+
"githubReleases"
|
|
2031
|
+
],
|
|
2032
|
+
degradedBlocksRun: ["anthropic"]
|
|
2033
|
+
};
|
|
2034
|
+
async function checkAllExternalServices() {
|
|
2035
|
+
const [anthropic, posthogOverall, posthogComponents, github, npmOverall, npmComponents, cloudflareOverall, cloudflareComponents, llmGateway, mcp, githubReleases] = await Promise.all([
|
|
2036
|
+
checkAnthropicHealth(),
|
|
2037
|
+
checkPosthogOverallHealth(),
|
|
2038
|
+
checkPosthogComponentHealth(),
|
|
2039
|
+
checkGithubHealth(),
|
|
2040
|
+
checkNpmOverallHealth(),
|
|
2041
|
+
checkNpmComponentHealth(),
|
|
2042
|
+
checkCloudflareOverallHealth(),
|
|
2043
|
+
checkCloudflareComponentHealth(),
|
|
2044
|
+
checkLlmGatewayHealth(),
|
|
2045
|
+
checkMcpHealth(),
|
|
2046
|
+
checkGithubReleasesHealth()
|
|
2047
|
+
]);
|
|
2048
|
+
return {
|
|
2049
|
+
anthropic,
|
|
2050
|
+
posthogOverall,
|
|
2051
|
+
posthogComponents,
|
|
2052
|
+
github,
|
|
2053
|
+
npmOverall,
|
|
2054
|
+
npmComponents,
|
|
2055
|
+
cloudflareOverall,
|
|
2056
|
+
cloudflareComponents,
|
|
2057
|
+
llmGateway,
|
|
2058
|
+
mcp,
|
|
2059
|
+
githubReleases
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
function describeResult(label, h) {
|
|
2063
|
+
const parts = [`${label}: ${h.status}`];
|
|
2064
|
+
if (h.rawIndicator) parts.push(`indicator=${h.rawIndicator}`);
|
|
2065
|
+
if (h.error) parts.push(h.error);
|
|
2066
|
+
return parts.join(" — ");
|
|
2067
|
+
}
|
|
2068
|
+
const MAX_COMPONENT_NAMES = 8;
|
|
2069
|
+
function describeComponents(label, h) {
|
|
2070
|
+
const affected = h.degradedOrDownComponents;
|
|
2071
|
+
if (!affected || affected.length === 0) return `${label} components: all operational`;
|
|
2072
|
+
const shown = affected.slice(0, MAX_COMPONENT_NAMES).map((c) => `${c.name} (${c.status})`);
|
|
2073
|
+
const suffix = affected.length > MAX_COMPONENT_NAMES ? `, +${affected.length - MAX_COMPONENT_NAMES} more` : "";
|
|
2074
|
+
return `${label} components impacted: ${shown.join(", ")}${suffix}`;
|
|
2075
|
+
}
|
|
2076
|
+
const READINESS_TIMEOUT_MS = 1e4;
|
|
2077
|
+
async function evaluateWizardReadiness(config = DEFAULT_WIZARD_READINESS_CONFIG) {
|
|
2078
|
+
try {
|
|
2079
|
+
const health = await Promise.race([checkAllExternalServices(), new Promise((resolve) => setTimeout(() => resolve(allUnknown("Health check timed out")), READINESS_TIMEOUT_MS))]);
|
|
2080
|
+
const reasons = [];
|
|
2081
|
+
for (const key of Object.keys(health)) {
|
|
2082
|
+
const result = health[key];
|
|
2083
|
+
const label = SERVICE_LABELS[key];
|
|
2084
|
+
reasons.push(describeResult(label, result));
|
|
2085
|
+
if ("degradedOrDownComponents" in result) reasons.push(describeComponents(label, result));
|
|
2086
|
+
}
|
|
2087
|
+
const blockingKeys = getBlockingServiceKeys(health, config);
|
|
2088
|
+
if (blockingKeys.length > 0) {
|
|
2089
|
+
logToFile(`[health-checks] blocked by: ${blockingKeys.join(", ")}`);
|
|
2090
|
+
return {
|
|
2091
|
+
decision: "no",
|
|
2092
|
+
health,
|
|
2093
|
+
reasons
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
if (Object.values(health).some((h) => h.status !== "healthy")) return {
|
|
2097
|
+
decision: "yes_with_warnings",
|
|
2098
|
+
health,
|
|
2099
|
+
reasons
|
|
2100
|
+
};
|
|
2101
|
+
return {
|
|
2102
|
+
decision: "yes",
|
|
2103
|
+
health,
|
|
2104
|
+
reasons
|
|
2105
|
+
};
|
|
2106
|
+
} catch (err) {
|
|
2107
|
+
logToFile(`[health-checks] error: ${err instanceof Error ? err.message : err}`);
|
|
2108
|
+
return {
|
|
2109
|
+
decision: "yes",
|
|
2110
|
+
health: allUnknown("Unexpected error"),
|
|
2111
|
+
reasons: ["Health check failed unexpectedly — proceeding anyway"]
|
|
2112
|
+
};
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
/** Keys that are component-level detail, not top-level services. */
|
|
2116
|
+
const COMPONENT_KEYS = [
|
|
2117
|
+
"posthogComponents",
|
|
2118
|
+
"npmComponents",
|
|
2119
|
+
"cloudflareComponents"
|
|
2120
|
+
];
|
|
2121
|
+
/**
|
|
2122
|
+
* Get the keys of services that would block a wizard run per the given config.
|
|
2123
|
+
*/
|
|
2124
|
+
function getBlockingServiceKeys(health, config = DEFAULT_WIZARD_READINESS_CONFIG) {
|
|
2125
|
+
return Object.keys(health).filter((key) => {
|
|
2126
|
+
if (COMPONENT_KEYS.includes(key)) return false;
|
|
2127
|
+
const result = health[key];
|
|
2128
|
+
if (config.downBlocksRun.includes(key) && result.status === "down") return true;
|
|
2129
|
+
if ((config.degradedBlocksRun ?? []).includes(key) && result.status !== "healthy") return true;
|
|
2130
|
+
return false;
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
/** Build an AllServicesHealth where every service is Degraded with the given error. */
|
|
2134
|
+
function allUnknown(error) {
|
|
2135
|
+
const base = {
|
|
2136
|
+
status: "degraded",
|
|
2137
|
+
error
|
|
2138
|
+
};
|
|
2139
|
+
return {
|
|
2140
|
+
anthropic: base,
|
|
2141
|
+
posthogOverall: base,
|
|
2142
|
+
posthogComponents: { ...base },
|
|
2143
|
+
github: base,
|
|
2144
|
+
npmOverall: base,
|
|
2145
|
+
npmComponents: { ...base },
|
|
2146
|
+
cloudflareOverall: base,
|
|
2147
|
+
cloudflareComponents: { ...base },
|
|
2148
|
+
llmGateway: base,
|
|
2149
|
+
mcp: base,
|
|
2150
|
+
githubReleases: base
|
|
2151
|
+
};
|
|
2152
|
+
}
|
|
2153
|
+
//#endregion
|
|
2154
|
+
export { backupAndFixClaudeSettings as a, initializeAgent as c, formatScanReport as d, writeScanReport as f, installSkillById as h, AgentSignals as i, restoreClaudeSettings as l, fetchSkillMenu as m, evaluateWizardReadiness as n, buildWizardMetadata as o, downloadSkill as p, getBlockingServiceKeys as r, checkAllSettingsConflicts as s, SERVICE_LABELS as t, runAgent as u };
|
|
2155
|
+
|
|
2156
|
+
//# sourceMappingURL=readiness-Dn7eq8NE.js.map
|