@posthog/wizard 2.79.1 → 2.80.1
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 +187 -57
- package/dist/{PickerMenu-dG5DQCZA.js → PickerMenu-BGGeYqd-.js} +112 -12
- package/dist/PickerMenu-BGGeYqd-.js.map +1 -0
- package/dist/README.md +9 -6
- package/dist/{agent-interface-FkbaBJwz.js → agent-interface-CemBvTAA.js} +130 -324
- package/dist/agent-interface-CemBvTAA.js.map +1 -0
- package/dist/{agent-prompt-loader-D0weQ-7k.js → agent-prompt-loader-DPnj6SwU.js} +6 -5
- package/dist/agent-prompt-loader-DPnj6SwU.js.map +1 -0
- package/dist/analytics-B3ROGuIr.js +2 -0
- package/dist/analytics-D21z3E5l.js +732 -0
- package/dist/analytics-D21z3E5l.js.map +1 -0
- package/dist/{api-CrbCIQOz.js → api-DtGIqQ2U.js} +2 -3
- package/dist/api-DtGIqQ2U.js.map +1 -0
- package/dist/api-IhROOQNv.js +2 -0
- package/dist/api-key-login-OEntFvu5.js +2 -0
- package/dist/api-key-login-h3E2G3zu.js +55 -0
- package/dist/api-key-login-h3E2G3zu.js.map +1 -0
- package/dist/bin.js +2 -2
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-vAq-T-K7.js → bounded-fs-CAsuF6al.js} +3 -3
- package/dist/{bounded-fs-vAq-T-K7.js.map → bounded-fs-CAsuF6al.js.map} +1 -1
- package/dist/{ci-install-COcV8SY2.js → ci-install-CEYE02t-.js} +22 -26
- package/dist/ci-install-CEYE02t-.js.map +1 -0
- package/dist/console-log-O828zyiq.js +32 -0
- package/dist/console-log-O828zyiq.js.map +1 -0
- package/dist/{debug-kAHwWGg7.js → debug-BfQPD2Hg.js} +18 -52
- package/dist/debug-BfQPD2Hg.js.map +1 -0
- package/dist/{defaults-a9TelDhJ.js → defaults-DDVl3tKN.js} +2 -51
- package/dist/defaults-DDVl3tKN.js.map +1 -0
- package/dist/{emit-BSetXzDV.js → emit-RfAewcWv.js} +1 -1
- package/dist/{emit-BSetXzDV.js.map → emit-RfAewcWv.js.map} +1 -1
- package/dist/{errors-C2domSkK.js → errors-CHrJzAZb.js} +4 -4
- package/dist/{errors-C2domSkK.js.map → errors-CHrJzAZb.js.map} +1 -1
- package/dist/family-picker-BKs-tTyu.js +46 -0
- package/dist/family-picker-BKs-tTyu.js.map +1 -0
- package/dist/{gateway-C9-GlLO9.js → gateway-D3gIlR6b.js} +122 -11
- package/dist/gateway-D3gIlR6b.js.map +1 -0
- package/dist/headless-BJjhP0SI.js +10 -0
- package/dist/headless-BJjhP0SI.js.map +1 -0
- package/dist/headless-DIX68UUA.js +3 -0
- package/dist/host-resolution-D8GhEVoX.js +114 -0
- package/dist/host-resolution-D8GhEVoX.js.map +1 -0
- package/dist/install-Bw8tvDvS.js +2 -0
- package/dist/{add-mcp-server-to-clients-DIaTRWMY.js → install-paPCzPHI.js} +34 -100
- package/dist/install-paPCzPHI.js.map +1 -0
- package/dist/interactive-tdxZKWax.js +11 -0
- package/dist/interactive-tdxZKWax.js.map +1 -0
- package/dist/{telemetry-B7zJdRmA.js → links-Cyj6v8kg.js} +4 -13
- package/dist/links-Cyj6v8kg.js.map +1 -0
- package/dist/{main-CgKxbwMP.js → main-0p-YxUNa.js} +233 -490
- package/dist/main-0p-YxUNa.js.map +1 -0
- package/dist/{mcp-DnAyW0-w.js → mcp-D3Z5MXhA.js} +3 -4
- package/dist/{mcp-DnAyW0-w.js.map → mcp-D3Z5MXhA.js.map} +1 -1
- package/dist/mcp-install-smoke-test.ts +2 -2
- package/dist/{mcp-prompt-streaming-DDWQ-FCA.js → mcp-prompt-streaming-COVbWnHt.js} +12 -12
- package/dist/mcp-prompt-streaming-COVbWnHt.js.map +1 -0
- package/dist/mode-label-DB3ol_sj.js +9 -0
- package/dist/mode-label-DB3ol_sj.js.map +1 -0
- package/dist/{models-WcwUnSKb.js → models-D1SnCzvl.js} +2 -2
- package/dist/{models-WcwUnSKb.js.map → models-D1SnCzvl.js.map} +1 -1
- package/dist/non-interactive-DxRBc73O.js +18 -0
- package/dist/non-interactive-DxRBc73O.js.map +1 -0
- package/dist/{oauth-session-DYM2Hrl2.js → oauth-session-Dde79Ycm.js} +3 -3
- package/dist/{oauth-session-DYM2Hrl2.js.map → oauth-session-Dde79Ycm.js.map} +1 -1
- package/dist/{orchestrator-tools-DbgNBFGA.js → orchestrator-tools-BSNhzzkT.js} +3 -3
- package/dist/{orchestrator-tools-DbgNBFGA.js.map → orchestrator-tools-BSNhzzkT.js.map} +1 -1
- package/dist/{package-json-Atg34fa4.js → package-json-2UrhE6kP.js} +1 -1
- package/dist/{package-json-Atg34fa4.js.map → package-json-2UrhE6kP.js.map} +1 -1
- package/dist/package-json-Dblip2_X.js +2 -0
- package/dist/package-manager-BRXlXo0p.js +105 -0
- package/dist/package-manager-BRXlXo0p.js.map +1 -0
- package/dist/{pi-8KsYsPmM.js → pi-cM_4Gd_9.js} +19 -20
- package/dist/pi-cM_4Gd_9.js.map +1 -0
- package/dist/playground-DTKy0XHT.js +12 -0
- package/dist/playground-DTKy0XHT.js.map +1 -0
- package/dist/posthog-integration-bwHwE87a.js +10291 -0
- package/dist/posthog-integration-bwHwE87a.js.map +1 -0
- package/dist/programs-BhtyA3lE.js +3 -0
- package/dist/programs-SeT1qNik.js +5348 -0
- package/dist/programs-SeT1qNik.js.map +1 -0
- package/dist/provisioning-BcXfeCMc.js +2 -0
- package/dist/{provisioning-Bo2NRxFz.js → provisioning-JbJtq7hq.js} +5 -67
- package/dist/provisioning-JbJtq7hq.js.map +1 -0
- package/dist/{queue-tools-C8mXOh7e.js → queue-tools-BIZSJyt6.js} +7 -9
- package/dist/queue-tools-BIZSJyt6.js.map +1 -0
- package/dist/results-DtKICAdz.js +55 -0
- package/dist/results-DtKICAdz.js.map +1 -0
- package/dist/run-CDurA5tO.js +248 -0
- package/dist/run-CDurA5tO.js.map +1 -0
- package/dist/run-DDCvLILJ.js +246 -0
- package/dist/run-DDCvLILJ.js.map +1 -0
- package/dist/run-tool-CTq9OOdT.js +2 -0
- package/dist/run-tool-DML8JJvt.js +2420 -0
- package/dist/run-tool-DML8JJvt.js.map +1 -0
- package/dist/runners-Dhu4pZTN.js +253 -0
- package/dist/runners-Dhu4pZTN.js.map +1 -0
- package/dist/{security-C71pkwqH.js → security-DEH8Rn0_.js} +5 -5
- package/dist/security-DEH8Rn0_.js.map +1 -0
- package/dist/setup-utils-C5-WM-hS.js +118 -0
- package/dist/setup-utils-C5-WM-hS.js.map +1 -0
- package/dist/smoke-test.sh +1 -1
- package/dist/{playground-BlYRBMj7.js → start-playground-DL4mVEUx.js} +63 -54
- package/dist/start-playground-DL4mVEUx.js.map +1 -0
- package/dist/{subagent-D1TrTchE.js → subagent-CnFvAq6E.js} +3 -3
- package/dist/{subagent-D1TrTchE.js.map → subagent-CnFvAq6E.js.map} +1 -1
- package/dist/{task-DqRlQBfs.js → task-BOScSm4W.js} +17 -18
- package/dist/task-BOScSm4W.js.map +1 -0
- package/dist/{tasks-ChWufsdO.js → tasks-BfJhVky2.js} +1 -1
- package/dist/tasks-BfJhVky2.js.map +1 -0
- package/dist/telemetry-CP4rGicd.js +13 -0
- package/dist/telemetry-CP4rGicd.js.map +1 -0
- package/dist/terminal-J3OD3dN0.js +16162 -0
- package/dist/terminal-J3OD3dN0.js.map +1 -0
- package/dist/tools-CCMV3DmB.js +544 -0
- package/dist/tools-CCMV3DmB.js.map +1 -0
- package/dist/{tools-CkJ2y9Wt.js → tools-Cz8tDptL.js} +9 -9
- package/dist/tools-Cz8tDptL.js.map +1 -0
- package/dist/tui-BUZ2PWqN.js +2 -0
- package/dist/tui-Csf7VJxt.js +25 -0
- package/dist/tui-Csf7VJxt.js.map +1 -0
- package/dist/{steps-BPcg3_3Q.js → upload-step-CEacB2RV.js} +17 -19
- package/dist/upload-step-CEacB2RV.js.map +1 -0
- package/dist/urls-BDELGZHq.js +67 -0
- package/dist/urls-BDELGZHq.js.map +1 -0
- package/dist/warlock-smoke-test.ts +1 -2
- package/dist/{wizard-abort-BPdv07np.js → wizard-abort-D3-75KyV.js} +41 -32
- package/dist/wizard-abort-D3-75KyV.js.map +1 -0
- package/dist/yara-hooks-CZ1tKxy_.js +2 -0
- package/dist/{yara-hooks-BnxejtXK.js → yara-hooks-D8YDyX7o.js} +283 -21
- package/dist/yara-hooks-D8YDyX7o.js.map +1 -0
- package/package.json +7 -8
- package/dist/PickerMenu-dG5DQCZA.js.map +0 -1
- package/dist/add-mcp-server-to-clients-DIaTRWMY.js.map +0 -1
- package/dist/add-mcp-server-to-clients-artmN7mz.js +0 -2
- package/dist/agent-BEjARD2a.js +0 -6
- package/dist/agent-BWFhuLgo.js +0 -3178
- package/dist/agent-BWFhuLgo.js.map +0 -1
- package/dist/agent-interface-FkbaBJwz.js.map +0 -1
- package/dist/agent-prompt-loader-D0weQ-7k.js.map +0 -1
- package/dist/analytics-DFtbRjYh.js +0 -2
- package/dist/analytics-DXK1gc12.js +0 -301
- package/dist/analytics-DXK1gc12.js.map +0 -1
- package/dist/api-Cm9UtKZh.js +0 -2
- package/dist/api-CrbCIQOz.js.map +0 -1
- package/dist/check-screens.tsx +0 -190
- package/dist/ci-install-COcV8SY2.js.map +0 -1
- package/dist/constants-DHCBSfnx.js +0 -260
- package/dist/constants-DHCBSfnx.js.map +0 -1
- package/dist/debug-BuYHGr6_.js +0 -2
- package/dist/debug-kAHwWGg7.js.map +0 -1
- package/dist/defaults-a9TelDhJ.js.map +0 -1
- package/dist/endpoints-BVMYm9F4.js +0 -108
- package/dist/endpoints-BVMYm9F4.js.map +0 -1
- package/dist/env-api-key-BP-NFFXt.js +0 -17
- package/dist/env-api-key-BP-NFFXt.js.map +0 -1
- package/dist/env-api-key-CaWEDj_9.js +0 -2
- package/dist/environment-BATlQxcQ.js +0 -39
- package/dist/environment-BATlQxcQ.js.map +0 -1
- package/dist/environment-CwD8OPYj.js +0 -2
- package/dist/file-C5JMsyR1.js +0 -2
- package/dist/file-DcRKycV8.js +0 -60
- package/dist/file-DcRKycV8.js.map +0 -1
- package/dist/file-watcher-Brq2nnHV.js +0 -123
- package/dist/file-watcher-Brq2nnHV.js.map +0 -1
- package/dist/gateway-C9-GlLO9.js.map +0 -1
- package/dist/headless-ui-CqI2gXlD.js +0 -44
- package/dist/headless-ui-CqI2gXlD.js.map +0 -1
- package/dist/interactive-B_Ti_CsS.js +0 -11
- package/dist/interactive-B_Ti_CsS.js.map +0 -1
- package/dist/local-dev-McsurOC-.js +0 -135
- package/dist/local-dev-McsurOC-.js.map +0 -1
- package/dist/logging-ui-Dza4D0MK.js +0 -226
- package/dist/logging-ui-Dza4D0MK.js.map +0 -1
- package/dist/main-CgKxbwMP.js.map +0 -1
- package/dist/mcp-prompt-streaming-DDWQ-FCA.js.map +0 -1
- package/dist/mint-failure-u8xQKNOn.js +0 -6392
- package/dist/mint-failure-u8xQKNOn.js.map +0 -1
- package/dist/non-interactive-DyVC1AGc.js +0 -18
- package/dist/non-interactive-DyVC1AGc.js.map +0 -1
- package/dist/package-json-D8Ga03tK.js +0 -2
- package/dist/pi-8KsYsPmM.js.map +0 -1
- package/dist/playground-BlYRBMj7.js.map +0 -1
- package/dist/posthog-Bt0Aplb8.js +0 -124
- package/dist/posthog-Bt0Aplb8.js.map +0 -1
- package/dist/posthog-CUgCEhH0.js +0 -2
- package/dist/provisioning-Bo2NRxFz.js.map +0 -1
- package/dist/provisioning-OGFGlzf7.js +0 -2
- package/dist/queue-tools-C8mXOh7e.js.map +0 -1
- package/dist/registry-C06e_x-p.js +0 -2
- package/dist/registry-CD5RQt38.js +0 -3464
- package/dist/registry-CD5RQt38.js.map +0 -1
- package/dist/run-agent-legacy-ChacZImU.js +0 -2
- package/dist/run-agent-legacy-DOlM6DQu.js +0 -3540
- package/dist/run-agent-legacy-DOlM6DQu.js.map +0 -1
- package/dist/runners-ov3EXF1n.js +0 -834
- package/dist/runners-ov3EXF1n.js.map +0 -1
- package/dist/security-C71pkwqH.js.map +0 -1
- package/dist/setup-utils-B26Lf2yF.js +0 -1512
- package/dist/setup-utils-B26Lf2yF.js.map +0 -1
- package/dist/setup-utils-CVS86NYR.js +0 -2
- package/dist/start-tui-Bo2L0bar.js +0 -6962
- package/dist/start-tui-Bo2L0bar.js.map +0 -1
- package/dist/steps-BPcg3_3Q.js.map +0 -1
- package/dist/store-BTzcvRGT.js +0 -992
- package/dist/store-BTzcvRGT.js.map +0 -1
- package/dist/store-BpqySPXm.js +0 -5
- package/dist/task-DqRlQBfs.js.map +0 -1
- package/dist/task-stream-Bw6JaLCX.js +0 -363
- package/dist/task-stream-Bw6JaLCX.js.map +0 -1
- package/dist/tasks-ChWufsdO.js.map +0 -1
- package/dist/telemetry-B7zJdRmA.js.map +0 -1
- package/dist/terminal-zgkEfoCL.js +0 -7196
- package/dist/terminal-zgkEfoCL.js.map +0 -1
- package/dist/tools-CkJ2y9Wt.js.map +0 -1
- package/dist/ui-Q6-RvERF.js +0 -15
- package/dist/ui-Q6-RvERF.js.map +0 -1
- package/dist/version-CHhJjz_H.js +0 -6
- package/dist/version-CHhJjz_H.js.map +0 -1
- package/dist/wizard-abort-BPdv07np.js.map +0 -1
- package/dist/wizard-abort-Br1qMDNa.js +0 -3
- package/dist/wizard-session-2w4Ru-Wz.js +0 -131
- package/dist/wizard-session-2w4Ru-Wz.js.map +0 -1
- package/dist/wizard-session-DGaUHOF3.js +0 -2
- package/dist/wizard-ui-DVqrYaOM.js +0 -16
- package/dist/wizard-ui-DVqrYaOM.js.map +0 -1
- package/dist/yara-hooks-BnxejtXK.js.map +0 -1
- package/dist/yara-hooks-DSuExwb4.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-D3gIlR6b.js","names":[],"sources":["../src/shared/health-checks/endpoints.ts","../src/agent/gateway-session.ts","../src/agent/signals.ts","../src/agent/runner/harness/pi/gateway.ts"],"sourcesContent":["import { AWS_SKILLS_BASE_URL, GITHUB_SKILLS_BASE_URL } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport { ServiceHealthStatus, type BaseHealthResult } from './types';\n\n// Direct gateway and skill-origin checks distinguish HTTP failures from connection failures.\n\nfunction noConnectionResult(error: string, attempts: number): BaseHealthResult {\n return {\n status: ServiceHealthStatus.NoConnection,\n error,\n rawIndicator: attempts > 1 ? `attempts=${attempts}` : undefined,\n };\n}\n\nfunction downResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Down, error };\n}\n\n// Backoffs sized to cover typical wifi flakiness — a single dropped\n// packet recovers via the 500ms retry; a wifi access point reconnect\n// or wifi↔LTE handoff (2-5s) is caught by the 2000ms retry. Tighter\n// schedules miss multi-second blips because all retries land in the\n// same dead window.\nconst RETRY_BACKOFFS_MS = [500, 2000];\n\nasync function attemptFetch(\n url: string,\n timeoutMs: number,\n redirect: 'follow' | 'manual' | 'error',\n): Promise<\n | { kind: 'response'; res: Response }\n | { kind: 'error'; error: Error; timedOut: boolean }\n> {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal, redirect });\n clearTimeout(tid);\n return { kind: 'response', res };\n } catch (e) {\n clearTimeout(tid);\n const err = e instanceof Error ? e : new Error('Unknown error');\n return { kind: 'error', error: err, timedOut: err.name === 'AbortError' };\n }\n}\n\n// Exported so tests can pin the retry/taxonomy machinery directly.\nexport async function fetchEndpointHealth(\n url: string,\n timeoutMs = 5000,\n isExpectedStatus: (status: number) => boolean = (s) => s === 200,\n redirect: 'follow' | 'manual' | 'error' = 'follow',\n): Promise<BaseHealthResult> {\n // Total attempts = 1 initial + RETRY_BACKOFFS_MS.length retries. Both\n // unexpected HTTP statuses (4xx/5xx) and network errors trigger a retry:\n // transient 5xx and Cloudflare edge blips often recover on a retry, and\n // even nominally deterministic 4xx can be transient (CDN propagation\n // lag after a release, token rotation, rate-limit window resets). GETs\n // are idempotent so retrying is safe.\n //\n // Final status if every attempt fails:\n // - At least one HTTP response observed → `Down` (server-side evidence)\n // - Only network errors observed → `NoConnection`\n let lastHttpStatus: number | null = null;\n let lastError = 'Unknown error';\n let attempts = 0;\n\n for (let i = 0; i <= RETRY_BACKOFFS_MS.length; i++) {\n if (i > 0) {\n const wait = RETRY_BACKOFFS_MS[i - 1];\n logToFile(\n `[health-checks] retry ${i}/${RETRY_BACKOFFS_MS.length} for ${url} in ${wait}ms (last: ${lastError})`,\n );\n await new Promise((r) => setTimeout(r, wait));\n }\n attempts++;\n\n const outcome = await attemptFetch(url, timeoutMs, redirect);\n\n if (outcome.kind === 'response') {\n const res = outcome.res;\n if (isExpectedStatus(res.status)) {\n const result: BaseHealthResult = {\n status: ServiceHealthStatus.Healthy,\n rawIndicator:\n attempts > 1\n ? `HTTP ${res.status} (attempts=${attempts})`\n : `HTTP ${res.status}`,\n };\n logToFile(\n `[health-checks] GET ${url} -> ${result.status}` +\n ` (${result.rawIndicator})`,\n );\n return result;\n }\n lastHttpStatus = res.status;\n lastError = `HTTP ${res.status}`;\n continue;\n }\n\n lastError = outcome.timedOut\n ? `Request timed out after ${timeoutMs}ms`\n : outcome.error.message;\n }\n\n const result =\n lastHttpStatus !== null\n ? downResult(`HTTP ${lastHttpStatus} (attempts=${attempts})`)\n : noConnectionResult(lastError, attempts);\n logToFile(\n `[health-checks] GET ${url} -> ${result.status}` +\n ` (attempts=${attempts}, ${result.error})`,\n );\n return result;\n}\n\nexport const checkLlmGatewayHealth = (\n gatewayUrl: string,\n): Promise<BaseHealthResult> =>\n fetchEndpointHealth(new URL('/readyz', gatewayUrl).href);\n\n/**\n * Skills are published to two origins under the same filenames and\n * `fetchWithRetry` fails over between them, so the run is only blocked when\n * neither answers. Probed in parallel — sequential probes would double the\n * worst case past `READINESS_TIMEOUT_MS`.\n */\nexport const checkSkillsOriginHealth = async (): Promise<BaseHealthResult> => {\n const [github, aws] = await Promise.all([\n fetchEndpointHealth(`${GITHUB_SKILLS_BASE_URL}/skill-menu.json`),\n fetchEndpointHealth(`${AWS_SKILLS_BASE_URL}/skill-menu.json`),\n ]);\n return combineOriginHealth(github, aws);\n};\n\n/**\n * Mirrors `fetchWithRetry`: a download tries GitHub, then AWS, so the run is\n * only blocked when neither origin answers. Whichever failure the probes saw,\n * one origin serving means skills are reachable.\n */\nfunction combineOriginHealth(\n github: BaseHealthResult,\n aws: BaseHealthResult,\n): BaseHealthResult {\n if (github.status === ServiceHealthStatus.Healthy) {\n // Naming the dead origin makes a one-sided outage legible in the log and\n // in the readiness reasons, where the status alone reads as \"fine\".\n return aws.status === ServiceHealthStatus.Healthy\n ? github\n : withIndicatorSuffix(github, 'aws unavailable');\n }\n\n if (aws.status === ServiceHealthStatus.Healthy) {\n return withIndicatorSuffix(aws, 'via aws, github unavailable');\n }\n\n const error = `github: ${github.error ?? 'unknown'} | aws: ${\n aws.error ?? 'unknown'\n }`;\n const confirmedDown =\n github.status === ServiceHealthStatus.Down ||\n aws.status === ServiceHealthStatus.Down;\n return {\n status: confirmedDown\n ? ServiceHealthStatus.Down\n : ServiceHealthStatus.NoConnection,\n error,\n // Keeps the `attempts=N` the blocked-readiness analytics parses.\n rawIndicator: github.rawIndicator ?? aws.rawIndicator,\n };\n}\n\nfunction withIndicatorSuffix(\n result: BaseHealthResult,\n suffix: string,\n): BaseHealthResult {\n return {\n ...result,\n rawIndicator: result.rawIndicator\n ? `${result.rawIndicator} (${suffix})`\n : suffix,\n };\n}\n","/**\n * Gateway auth for a wizard run: a `phe_` scoped token the backend mints, with\n * pinned attribution, a spend cap and an expiry.\n *\n * Every mint failure throws: a silent downgrade would spend uncapped,\n * unattributed money to hide an outage.\n */\n\nimport { logToFile } from '@utils/debug';\nimport { analytics } from '@utils/analytics';\nimport { ErrorCodes, WizardError } from '@shared/errors';\nimport type { GatewayCredential } from '@shared/api';\nimport type { HostResolution } from '@shared/host-resolution';\nimport { oauthLoginKey } from '@shared/oauth-session';\nimport { checkLlmGatewayHealth } from '@shared/health-checks/endpoints';\nimport { ServiceHealthStatus } from '@shared/health-checks/types';\nimport { IS_PRODUCTION_BUILD } from '@env';\n\nexport interface GatewayAuth {\n /** Base URL for model calls (no `/v1`; transports append their route). */\n gatewayUrl: string;\n /** Gateway bearer, minted normally or supplied directly by CI. */\n token: string;\n /** Team verified by the mint, or explicitly supplied for CI attribution. */\n teamId?: number;\n /**\n * Instant past which a 401 on this bearer is age rather than a bad\n * credential: the cache re-mints past it, and a session still holding the\n * old bearer may re-mint once. Before it the mint has to be trusted.\n */\n refreshAtMs: number;\n}\n\ninterface CachedAuth {\n key: string;\n auth: GatewayAuth;\n /** Re-resolve once past this instant. */\n staleAtMs: number;\n}\n\nlet cached: CachedAuth | null = null;\n/**\n * Shared so concurrent callers mint once. The orchestrator starts every runnable\n * task at once, and each would otherwise take its own token and its own cap.\n */\nlet inFlight: { key: string; promise: Promise<GatewayAuth> } | null = null;\nlet ciAuth: GatewayAuth | null = null;\n\n// Snapshot CI supplies a gateway bearer without minting or re-minting.\nexport function configureGatewayCredentialsForCI(\n token: string,\n projectId: number,\n gatewayUrl: string,\n): void {\n if (IS_PRODUCTION_BUILD)\n throw new Error('CI gateway auth requires a non-production build');\n if (!token.trim() || !Number.isSafeInteger(projectId) || projectId <= 0) {\n throw new Error('CI gateway auth requires a token and valid project ID');\n }\n if (\n !/^https?:\\/\\//.test(gatewayUrl) ||\n !isTrustedGatewayUrl(gatewayUrl, '')\n ) {\n throw new Error('CI gateway auth requires a trusted gateway origin');\n }\n resetGatewaySession();\n ciAuth = {\n token: token.trim(),\n teamId: projectId,\n gatewayUrl: gatewayUrl.replace(/\\/+$/, ''),\n refreshAtMs: Infinity,\n };\n}\n\n/** Use this run's pre-issued gateway token, or mint when it has none; the keyed mint cache stays. */\nexport function useRunGatewayCredential(\n gateway: GatewayCredential | undefined,\n projectId: number,\n): void {\n if (gateway) {\n configureGatewayCredentialsForCI(gateway.token, projectId, gateway.url);\n return;\n }\n ciAuth = null;\n}\n\n/**\n * Adoption floor. The anthropic subprocess holds its credential until a 401\n * forces a re-mint, so a token below this would churn mints.\n */\nconst MIN_USABLE_TTL_MS = 2 * 60 * 1000;\n/** Re-resolve at this fraction of the token's life, leaving a usable remainder. */\nconst REFRESH_AT_FRACTION = 0.8;\n// Exceeds the backend's own 10s gateway timeout: a slow mint that lands after the\n// CLI hangs up spends a daily mint and orphans a live token.\nconst MINT_TIMEOUT_MS = 20_000;\n/** Longer than any refusal the mint writes; a body past this is not a message. */\nconst MAX_REFUSAL_DETAIL_LENGTH = 500;\n/** Outcomes are short snake_case labels; anything longer is not one. */\nconst MAX_REFUSAL_OUTCOME_LENGTH = 64;\n\n/** Resolve this run's gateway auth, minting and re-minting near expiry. */\nexport async function gatewayAuth(\n host: HostResolution,\n accessToken: string,\n program: string | undefined,\n): Promise<GatewayAuth> {\n if (ciAuth) return ciAuth;\n // Keyed by program: a token pins `wizard:<program>`, so reusing one across\n // programs bills the wrong budget. Keyed by login rather than OAuth token:\n // the token rotates mid-run, and each new one would spend a weekly mint.\n const key = `${host.apiHost}\\n${oauthLoginKey(accessToken)}\\n${\n program ?? ''\n }`;\n if (cached && cached.key === key && Date.now() < cached.staleAtMs) {\n return cached.auth;\n }\n if (inFlight && inFlight.key === key) return inFlight.promise;\n const promise = resolveGatewayAuth(host, accessToken, key, program);\n inFlight = { key, promise };\n try {\n return await promise;\n } finally {\n if (inFlight?.promise === promise) inFlight = null;\n }\n}\n\nasync function resolveGatewayAuth(\n host: HostResolution,\n accessToken: string,\n key: string,\n program: string | undefined,\n): Promise<GatewayAuth> {\n if (!program) {\n // Every run has one; absent means a caller was not wired, and the spend would\n // be unattributable.\n logToFile('[gateway] run has no program id; failing the run');\n throw new GatewayMintFailed(\n 'this run has no program to attribute its spend to',\n );\n }\n const minted = await mintGatewayToken(host, accessToken, program);\n const health = await checkLlmGatewayHealth(minted.gatewayUrl);\n if (health.status !== ServiceHealthStatus.Healthy) {\n throw new WizardError(\n 'The PostHog AI gateway is unavailable. Please try again later.',\n undefined,\n ErrorCodes.EnvServiceOutage,\n );\n }\n const expiresAtMs = Date.parse(minted.expiresAt);\n const ttlMs = expiresAtMs - Date.now();\n if (!Number.isFinite(expiresAtMs) || ttlMs < MIN_USABLE_TTL_MS) {\n // Expired, unreadable, or too short to serve a session. Adopting it would\n // 401 mid-run, and downgrading would spend the rest of the run uncapped.\n logToFile(\n `[gateway] mint returned a token with ${ttlMs}ms of life; failing the run`,\n );\n throw new GatewayMintFailed(\n `the PostHog gateway issued a token with ${ttlMs}ms of life`,\n );\n }\n const staleAtMs = Date.now() + ttlMs * REFRESH_AT_FRACTION;\n // Only failures are logged otherwise, so a successful run leaves no\n // local trace. Never log the token itself.\n logToFile(\n `[gateway] minted a scoped token: program=${program} team=${\n minted.teamId ?? 'unknown'\n } ttl=${Math.round(ttlMs / 1000)}s url=${minted.gatewayUrl}`,\n );\n const auth: GatewayAuth = {\n gatewayUrl: minted.gatewayUrl,\n token: minted.token,\n teamId: minted.teamId,\n refreshAtMs: staleAtMs,\n };\n cached = { key, auth, staleAtMs };\n return auth;\n}\n\n/** Test hook: drop the cached auth so the next call re-resolves. */\nexport function resetGatewaySession(): void {\n cached = null;\n inFlight = null;\n ciAuth = null;\n}\n\n/** Whether a 401 on this bearer may be age (past its refresh instant) rather than a bad credential. */\nexport function isPastRefresh(auth: GatewayAuth, now = Date.now()): boolean {\n return now >= auth.refreshAtMs;\n}\n\n/**\n * Whether a server-supplied origin may receive a bearer and prompt content:\n * https (loopback excepted), and either a current cloud gateway or the host the run\n * authenticated against.\n */\nexport function isTrustedGatewayUrl(value: string, apiHost: string): boolean {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return false;\n }\n // Consumers append routes to this value, so anything beyond an origin\n // (path, query, fragment, userinfo) would build a malformed endpoint.\n if (\n url.pathname !== '/' ||\n url.search ||\n url.hash ||\n url.username ||\n url.password\n ) {\n return false;\n }\n const localhost =\n url.hostname === 'localhost' ||\n url.hostname === '127.0.0.1' ||\n url.hostname === 'host.docker.internal';\n // Loopback is the dev gateway, and is the one case allowed over http.\n if (localhost) return true;\n if (url.protocol !== 'https:') return false;\n if (url.hostname.endsWith('.posthog.com')) {\n return (\n url.origin === 'https://ai-gateway.us.posthog.com' ||\n url.origin === 'https://ai-gateway.eu.posthog.com'\n );\n }\n try {\n return url.hostname === new URL(apiHost).hostname;\n } catch {\n return false;\n }\n}\n\ninterface MintedToken {\n token: string;\n expiresAt: string;\n gatewayUrl: string;\n teamId?: number;\n}\n\n/**\n * A deliberate refusal from the mint endpoint, as opposed to the mint being\n * unavailable. Thrown so the run stops instead of proceeding without the\n * controls the refusal was enforcing. A WizardError, so the runners print its\n * message as-is and `wizardAbort` resolves its code.\n */\nexport class GatewayMintRefused extends WizardError {\n readonly status: number;\n /** The backend's refusal outcome (`blocked`, `throttled`, ...), when it sent one. */\n readonly outcome?: string;\n\n constructor(status: number, message: string, outcome?: string) {\n super(message, { status, outcome }, ErrorCodes.GatewayMintRefused);\n this.name = 'GatewayMintRefused';\n this.status = status;\n this.outcome = outcome;\n }\n}\n\n/**\n * The mint could not produce a usable credential: unreachable, a 5xx, or a\n * response the client cannot use.\n */\nexport class GatewayMintFailed extends WizardError {\n constructor(message: string) {\n super(message, undefined, ErrorCodes.GatewayMintFailed);\n this.name = 'GatewayMintFailed';\n }\n}\n\n/**\n * Whether a mint status means \"refused this run\" rather than \"not available\".\n * 429 the daily run limit, 403 revoked project access, 400 a login covering\n * more than one project, 401 a credential the mint does not accept, 404 an\n * instance without the mint endpoint.\n */\nfunction isMintRefusal(status: number): boolean {\n return (\n status === 400 ||\n status === 401 ||\n status === 403 ||\n status === 404 ||\n status === 429\n );\n}\n\ninterface MintRefusal {\n detail?: string;\n outcome?: string;\n}\n\n/**\n * The server's own reason for a refusal, when it sent one. DRF answers every\n * refusal as `{\"detail\": \"...\", \"code\": \"<outcome>\"}`; the blocklist's detail\n * names the contact address, which the fixed messages below cannot. `code` is\n * the backend's own label for the refusal (`outcome` on older backends) and\n * rides the client event.\n */\nfunction cleanRefusalText(value: unknown): string {\n if (typeof value !== 'string') return '';\n // Not because the server sends escapes, but because this string is printed\n // straight to a terminal: sanitizing at the boundary means no later message\n // can move the cursor or repaint the screen.\n // eslint-disable-next-line no-control-regex\n return value.replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, ' ').trim();\n}\n\nasync function readRefusal(resp: Response): Promise<MintRefusal> {\n try {\n const body = (await resp.json()) as {\n detail?: unknown;\n code?: unknown;\n outcome?: unknown;\n };\n const detail = cleanRefusalText(body?.detail);\n // The DRF handler flattens a dict detail, so the outcome rides as `code`.\n // A `code` that cleans to nothing does not shadow a usable `outcome`.\n const outcome =\n cleanRefusalText(body?.code) || cleanRefusalText(body?.outcome);\n return {\n detail:\n detail.length > 0 && detail.length <= MAX_REFUSAL_DETAIL_LENGTH\n ? detail\n : undefined,\n outcome:\n outcome.length > 0 && outcome.length <= MAX_REFUSAL_OUTCOME_LENGTH\n ? outcome\n : undefined,\n };\n } catch {\n return {};\n }\n}\n\nfunction mintRefusalMessage(status: number, detail?: string): string {\n if (detail) return detail;\n switch (status) {\n case 429:\n return 'This wizard program has used its daily run limit. Try again tomorrow.';\n case 403:\n return 'Your access to this project has changed. Re-authenticate and try again.';\n case 400:\n // The only 400 the mint answers is the exactly-one-project check.\n return 'Your PostHog login must cover exactly one project. Re-authenticate and try again.';\n case 401:\n return 'PostHog did not accept this login. Re-authenticate with `npx @posthog/wizard@latest`.';\n case 404:\n return 'This PostHog instance does not issue gateway tokens. Upgrade with `npx @posthog/wizard@latest` and try again.';\n default:\n return 'The PostHog gateway refused this run.';\n }\n}\n\nasync function mintGatewayToken(\n host: HostResolution,\n accessToken: string,\n program: string,\n): Promise<MintedToken> {\n try {\n const resp = await fetch(`${host.apiHost}/api/wizard/gateway_token/`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n // The flag tells the server this build reads a refusal, so it may answer\n // with the reason. A build that omits it gets a 404, which is its signal\n // to fall back to the legacy gateway.\n body: JSON.stringify({ program, reads_refusal_reason: true }),\n signal: AbortSignal.timeout(MINT_TIMEOUT_MS),\n });\n if (!resp.ok) {\n if (isMintRefusal(resp.status)) {\n const refusal = await readRefusal(resp);\n logToFile(\n `[gateway] mint refused with HTTP ${resp.status} (${\n refusal.outcome ?? 'no outcome'\n }); failing the run`,\n );\n // The terminal denial event for this run. The backend's own event has\n // no run id, so this is what joins a refusal to the session.\n analytics.wizardCapture('gateway mint refused', {\n status: resp.status,\n outcome: refusal.outcome,\n program,\n });\n throw new GatewayMintRefused(\n resp.status,\n mintRefusalMessage(resp.status, refusal.detail),\n refusal.outcome,\n );\n }\n logToFile(\n `[gateway] mint failed with HTTP ${resp.status}; failing the run`,\n );\n throw new GatewayMintFailed(\n `the PostHog gateway could not issue a token (HTTP ${resp.status})`,\n );\n }\n const body = (await resp.json()) as {\n token?: string;\n expires_at?: string;\n gateway_url?: string;\n team_id?: number;\n };\n // Checked one at a time, not in a loop, so each clause narrows the optional\n // field for the return below and each names itself in the failure.\n if (!body.token) {\n logToFile('[gateway] mint response omitted token; failing the run');\n throw new GatewayMintFailed('mint response omitted token');\n }\n if (!body.expires_at) {\n logToFile('[gateway] mint response omitted expires_at; failing the run');\n throw new GatewayMintFailed('mint response omitted expires_at');\n }\n if (!body.gateway_url) {\n logToFile('[gateway] mint response omitted gateway_url; failing the run');\n throw new GatewayMintFailed('mint response omitted gateway_url');\n }\n if (!isTrustedGatewayUrl(body.gateway_url, host.apiHost)) {\n logToFile(\n '[gateway] mint returned an untrusted gateway url; failing the run',\n );\n throw new GatewayMintFailed('mint returned an untrusted gateway url');\n }\n const gatewayUrl = new URL(body.gateway_url);\n if (\n ['localhost', '127.0.0.1'].includes(new URL(host.apiHost).hostname) &&\n gatewayUrl.hostname === 'host.docker.internal'\n ) {\n gatewayUrl.hostname = 'localhost';\n }\n return {\n token: body.token,\n expiresAt: body.expires_at,\n gatewayUrl: gatewayUrl.origin,\n teamId: body.team_id,\n };\n } catch (e) {\n // Decisions and failures both pass through: this catch exists for transport\n // errors, and folding the others into it would lose the reason.\n if (e instanceof GatewayMintRefused || e instanceof GatewayMintFailed)\n throw e;\n logToFile(\n `[gateway] mint transport failure (${String(e)}); failing the run`,\n );\n throw new GatewayMintFailed(\n `could not reach the PostHog gateway (${String(e)})`,\n );\n }\n}\n\n/**\n * The v2 run-metadata carrier: one JSON blob for the `X-PostHog-Properties`\n * header. Plain keys only, since the gateway strips `$`-prefixed keys as reserved,\n * so feature-flag variants land as `wizard_flag_<key>` instead of the legacy\n * `$feature/<key>` (dashboards keying on `$feature/wizard-*` read the new key\n * post-cutover).\n */\nexport function buildWizardPropertiesBlob(\n wizardMetadata: Record<string, string>,\n wizardFlags: Record<string, string>,\n teamId?: number,\n): string {\n // The gateway pins `$ai_product` to `wizard:<program>`, and rejects a legacy\n // product override on a scoped token, so the unprefixed key every cost and\n // error consumer reads is only present if this blob declares it.\n const props: Record<string, string | number> = { ai_product: 'wizard' };\n if (teamId !== undefined) props.team_id = teamId;\n for (const [key, value] of Object.entries(wizardMetadata)) {\n props[stripPropertyPrefix(key)] = value;\n }\n for (const [flagKey, variant] of Object.entries(wizardFlags)) {\n if (!flagKey.toLowerCase().startsWith('wizard')) continue;\n props[`wizard_flag_${flagKey.toLowerCase()}`] = variant;\n }\n return JSON.stringify(props);\n}\n\nconst LEGACY_PROPERTY_PREFIX = 'X-POSTHOG-PROPERTY-';\n\nfunction stripPropertyPrefix(key: string): string {\n return key.toUpperCase().startsWith(LEGACY_PROPERTY_PREFIX)\n ? key.slice(LEGACY_PROPERTY_PREFIX.length).toLowerCase()\n : key;\n}\n","/**\n * Agent signal vocabulary — the marker strings the agent emits and the error\n * taxonomy the runner returns. Kept as a dependency-free leaf module so both\n * `agent-interface.ts` and `output-signals.ts` can import it without a cycle.\n */\n\nexport const AgentSignals = {\n /** Signal emitted when the agent reports progress to the user */\n STATUS: '[STATUS]',\n /** Signal emitted when the agent cannot access the PostHog MCP server */\n ERROR_MCP_MISSING: '[ERROR-MCP-MISSING]',\n /** Signal emitted when the agent cannot access the setup resource */\n ERROR_RESOURCE_MISSING: '[ERROR-RESOURCE-MISSING]',\n /**\n * Signal emitted when `install_skill` failed and the agent is continuing\n * the integration WITHOUT the skill (best-effort from its own knowledge).\n * Format: \"[SKILL-INSTALL-FAILED] <skill id — reason>\". Non-fatal by\n * design: a freestyled integration beats an outright failure, but the run\n * must be measurable — the runner captures it as an analytics event.\n */\n SKILL_INSTALL_FAILED: '[SKILL-INSTALL-FAILED]',\n /**\n * Signal emitted when the agent cannot complete the program and is\n * aborting intentionally (distinct from errors). Format: \"[ABORT] <reason>\".\n * Programs can declare an onAbort handler to render a custom screen.\n */\n ABORT: '[ABORT]',\n /** Signal emitted when the agent provides a remark about its run */\n WIZARD_REMARK: '[WIZARD-REMARK]',\n /** Signal prefix for benchmark logging */\n BENCHMARK: '[BENCHMARK]',\n /**\n * Signal emitted when the agent has created a PostHog dashboard for the\n * user. Format: `[DASHBOARD_URL] <full https url>`. The URL is captured\n * onto `session.dashboardUrl` and surfaced by programs in their outro.\n */\n DASHBOARD_URL: '[DASHBOARD_URL]',\n /**\n * Signal emitted when the agent has uploaded a report to a PostHog\n * notebook. Format: `[NOTEBOOK_URL] <full https url>`. The URL is captured\n * onto `session.notebookUrl` and surfaced by programs in their outro.\n */\n NOTEBOOK_URL: '[NOTEBOOK_URL]',\n} as const;\n\nexport type AgentSignal = (typeof AgentSignals)[keyof typeof AgentSignals];\n\n/**\n * End-of-run reflection ask, shared by both harnesses so remarks are\n * comparable. The format clause comes FIRST and nothing trails the marker —\n * literal models (gpt-5-mini) echo whatever text follows it. The parser also\n * drops remarks that quote this instruction (see AgentOutputSignals.remark).\n */\nexport const REMARK_INSTRUCTION = `Reply with a single line that starts with ${AgentSignals.WIZARD_REMARK} and no other lines. In that line, state briefly what information or guidance would have been useful to have in the integration prompt or documentation for this run — specifically anything that would have prevented tool failures, erroneous edits, or other wasted turns.`;\n\n/**\n * First prompt of a session resumed after a mid-run re-mint. The transcript\n * carries the work so far; the model only needs to pick it up.\n */\nexport const RESUME_INSTRUCTION =\n 'Your previous request failed with a transient gateway authentication error that has since been fixed. Continue the task from where you left off.';\n\n/**\n * Error types that can be returned from agent execution.\n * These correspond to the error signals that the agent emits.\n */\nexport enum AgentErrorType {\n /** The configured run deadline elapsed and the SDK query was aborted */\n AGENTIC_DETECTION_TIMEOUT = 'WIZARD_AGENTIC_DETECTION_TIMEOUT',\n /** Agent could not access the PostHog MCP server */\n MCP_MISSING = 'WIZARD_MCP_MISSING',\n /** Agent could not access the setup resource */\n RESOURCE_MISSING = 'WIZARD_RESOURCE_MISSING',\n /** API rate limit exceeded */\n RATE_LIMIT = 'WIZARD_RATE_LIMIT',\n /** Generic API error */\n API_ERROR = 'WIZARD_API_ERROR',\n /** YARA scanner detected a security violation */\n YARA_VIOLATION = 'WIZARD_YARA_VIOLATION',\n /** Agent intentionally aborted the program (emitted [ABORT] <reason>) */\n ABORT = 'WIZARD_ABORT',\n /** Agent ended without making a single tool call — a no-op run that did no work */\n NO_PROGRESS = 'WIZARD_NO_PROGRESS',\n /** A schema-bound run ended without output matching its schema */\n INVALID_STRUCTURED_OUTPUT = 'WIZARD_INVALID_STRUCTURED_OUTPUT',\n /** Agent acted but stopped short — planned tasks left open and/or no skill installed */\n INCOMPLETE_TASKS = 'WIZARD_INCOMPLETE_TASKS',\n}\n","/**\n * PostHog AI gateway provider spec for pi sessions, shared by the linear run\n * and the orchestrator's per-task runs so both speak to the gateway\n * identically: bearer auth, the wizard properties header, transport shape\n * inferred from the model id. The caller registers the spec on its own\n * (lazily imported, properly typed) pi ModelRegistry.\n */\n\nimport {\n buildWizardPropertiesBlob,\n isPastRefresh,\n type GatewayAuth,\n} from '../../../gateway-session';\nimport {\n modelCapabilities,\n type ThinkingLevel,\n} from '../../switchboard/models';\nimport { AgentErrorType } from '../../../signals';\n\n/** Provider registered on the in-memory registry for this run. */\nexport const GATEWAY_PROVIDER = 'posthog-gateway';\n\n/** The pi transports the gateway serves. */\nexport type GatewayApi =\n | 'anthropic-messages'\n | 'openai-completions'\n | 'openai-responses';\n\n/**\n * The gateway speaks two shapes on two endpoints: Anthropic models over\n * `anthropic-messages` (the SDK appends `/v1/messages`, so the base URL has no\n * `/v1`), and OpenAI-class models (`openai/gpt-5`, …) over an OpenAI shape at\n * `/v1/responses` or `/v1/chat/completions` (base URL keeps `/v1`). Infer the\n * shape from the model id so a pair's model selects the right transport.\n *\n * OpenAI models take the Responses API because OpenAI rejects function tools\n * combined with `reasoning_effort` on chat completions and every task sends both.\n */\nexport function gatewayApiFor(modelId: string): GatewayApi {\n return modelId.startsWith('openai/')\n ? 'openai-responses'\n : 'anthropic-messages';\n}\n\n/**\n * Gateway HTTP headers, mirroring `buildAgentEnv` on the anthropic path: one\n * `X-PostHog-Properties` JSON blob (Bedrock fallback is native, so no opt-in)\n * plus the 1M context beta, since pi otherwise runs at 200k and overflows on\n * larger projects (the post-run compaction failures).\n */\nexport function buildGatewayHeaders(\n wizardMetadata: Record<string, string>,\n wizardFlags: Record<string, string>,\n teamId?: number,\n): Record<string, string> {\n return {\n 'anthropic-beta': 'context-1m-2025-08-07',\n 'X-PostHog-Properties': buildWizardPropertiesBlob(\n wizardMetadata,\n wizardFlags,\n teamId,\n ),\n };\n}\n\nexport interface GatewayProviderInputs {\n gatewayUrl: string;\n accessToken: string;\n /** Customer team for the properties blob (from the mint response). */\n teamId?: number;\n wizardMetadata: Record<string, string>;\n wizardFlags: Record<string, string>;\n modelId: string;\n // Resolved effort override — the switchboard's flag/payload pick on linear\n // runs, the prompt-frontmatter effort on per-task agents. Overrides the\n // table default for a reasoning model when set.\n effort?: ThinkingLevel;\n}\n\n/**\n * One gateway model spec — the single description of how to reach a model on\n * the gateway. The provider spec below wraps it for pi's registry; one-shot\n * callers (scan triage) hand it straight to `completeSimple`.\n */\nexport function buildGatewayModel(inputs: GatewayProviderInputs) {\n const { gatewayUrl, wizardMetadata, wizardFlags, modelId, teamId } = inputs;\n const api = gatewayApiFor(modelId);\n return {\n id: modelId,\n name: `${modelId} (PostHog Gateway)`,\n api,\n provider: GATEWAY_PROVIDER,\n // Anthropic drops /v1 (the SDK appends /v1/messages); the OpenAI shape keeps it.\n baseUrl: api === 'anthropic-messages' ? gatewayUrl : `${gatewayUrl}/v1`,\n // A model trait resolved by the switchboard, not a harness guess:\n // non-reasoning openai models reject `reasoning_effort` (gpt-4o → gateway\n // UnsupportedParamsError → the run no-ops).\n reasoning: modelCapabilities(modelId).reasoning,\n input: ['text' as const],\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n contextWindow: 1_000_000,\n maxTokens: 64_000,\n headers: buildGatewayHeaders(wizardMetadata, wizardFlags, teamId),\n };\n}\n\n/**\n * The provider object for `registry.registerProvider(GATEWAY_PROVIDER, …)`,\n * plus the derived traits the session setup needs (`caps.thinkingLevel`).\n */\nexport function buildGatewayProvider(inputs: GatewayProviderInputs): {\n provider: Record<string, unknown>;\n api: GatewayApi;\n caps: ReturnType<typeof modelCapabilities>;\n gatewayUrl: string;\n baseUrl: string;\n} {\n const { gatewayUrl, accessToken, modelId, effort } = inputs;\n const api = gatewayApiFor(modelId);\n // One resolution point for the model's traits and the run's effort override.\n // pi clamps whatever comes out of here against the levels this spec declares,\n // so a level the spec doesn't carry is silently reduced by the session.\n const tableCaps = modelCapabilities(modelId);\n const caps =\n effort && effort !== 'off' && tableCaps.reasoning\n ? modelCapabilities(modelId, effort)\n : effort === 'off' && tableCaps.reasoning\n ? { ...tableCaps, thinkingLevel: 'off' as const }\n : tableCaps;\n\n const model = buildGatewayModel(inputs);\n const provider = {\n name: 'PostHog Gateway',\n baseUrl: model.baseUrl,\n apiKey: accessToken,\n authHeader: true,\n api,\n headers: model.headers,\n models: [model],\n };\n return { provider, api, caps, gatewayUrl, baseUrl: model.baseUrl };\n}\n\n/** The part of a pi assistant turn that says why it failed. */\nexport interface GatewayTurnError {\n errorMessage?: string;\n diagnostics?: { error?: { name?: string; code?: string | number } }[];\n}\n\nexport type GatewayTerminalFailure = {\n classification:\n | AgentErrorType.API_ERROR\n | AgentErrorType.RATE_LIMIT\n | AgentErrorType.ABORT;\n message: string;\n status?: number;\n};\n\nexport function gatewayTerminalFailure(\n turn: ({ stopReason?: string } & GatewayTurnError) | undefined,\n): GatewayTerminalFailure | undefined {\n if (!turn || (turn.stopReason !== 'error' && turn.stopReason !== 'aborted'))\n return undefined;\n const message =\n turn.errorMessage ||\n (turn.stopReason === 'aborted'\n ? 'Agent turn aborted'\n : 'Gateway request failed');\n if (turn.stopReason === 'aborted') {\n return { classification: AgentErrorType.ABORT, message };\n }\n const codes =\n turn.diagnostics\n ?.map((d) => d.error?.code)\n .filter((code) => code !== undefined) ?? [];\n const structuredStatus = codes\n .map(Number)\n .find((code) => Number.isInteger(code) && code >= 400 && code < 600);\n const rateLimited =\n structuredStatus !== undefined\n ? structuredStatus === 429\n : /\\b429\\b|rate limit/i.test(message);\n return {\n classification: rateLimited\n ? AgentErrorType.RATE_LIMIT\n : AgentErrorType.API_ERROR,\n message,\n status:\n structuredStatus ?? (isGatewayAuthRejection(turn) ? 401 : undefined),\n };\n}\n\n/**\n * Whether a turn's error is the gateway rejecting the bearer. pi attaches the\n * SDK's own error to `diagnostics`, so its code decides when one is present.\n * The message match is the fallback for a turn that failed before pi built a\n * diagnostic, where the status survives only as prose.\n */\nexport function isGatewayAuthRejection(\n turn: GatewayTurnError | string | undefined,\n): boolean {\n const { errorMessage, diagnostics } =\n typeof turn === 'string'\n ? { errorMessage: turn, diagnostics: undefined }\n : turn ?? {};\n const structuredStatus = (diagnostics ?? [])\n .map((diagnostic) => Number(diagnostic.error?.code))\n .find((code) => Number.isInteger(code) && code >= 400 && code < 600);\n if (structuredStatus !== undefined) return structuredStatus === 401;\n for (const diagnostic of diagnostics ?? []) {\n const code = diagnostic.error?.code;\n if (code === 401 || code === '401') return true;\n if (/^authentication_?error$/i.test(diagnostic.error?.name ?? ''))\n return true;\n }\n return /\\b401\\b|authentication_error|unauthorized/i.test(errorMessage ?? '');\n}\n\nexport interface GatewayRemintOptions {\n signal?: AbortSignal;\n session: { prompt(text: string): Promise<void> };\n registry: { registerProvider(providerName: string, config: never): void };\n auth: GatewayAuth;\n /** The cache: the same token while fresh, a new mint past the refresh point. */\n refreshAuth: () => Promise<GatewayAuth>;\n providerInputs: (auth: GatewayAuth) => GatewayProviderInputs;\n /** The prompt that resumes the work after a re-mint. */\n continueText: string | (() => string);\n onRemint?: () => void;\n}\n\n/**\n * Wraps a pi session's prompt(): when a turn ends on a 401 from a bearer past\n * its refresh instant, mint once, re-register the provider with the new\n * bearer (pi resolves the apiKey per request), and continue. A 401 on a fresh\n * bearer, or a second one, is left to the harness's normal failure path.\n */\nexport function withGatewayRemint(opts: GatewayRemintOptions): {\n prompt(text: string): Promise<void>;\n /** Feed every assistant `message_end`; the last turn decides. */\n noteAssistantTurn(message: unknown): void;\n terminalFailure(): GatewayTerminalFailure | undefined;\n} {\n let auth = opts.auth;\n let rejected = false;\n let reminted = false;\n let lastTurn: ({ stopReason?: string } & GatewayTurnError) | undefined;\n return {\n noteAssistantTurn(message) {\n lastTurn = message as\n | ({ stopReason?: string } & GatewayTurnError)\n | undefined;\n rejected =\n lastTurn?.stopReason === 'error' && isGatewayAuthRejection(lastTurn);\n },\n terminalFailure: () => gatewayTerminalFailure(lastTurn),\n async prompt(text) {\n if (opts.signal?.aborted) return;\n rejected = false;\n lastTurn = undefined;\n await opts.session.prompt(text);\n if (opts.signal?.aborted || !rejected || reminted || !isPastRefresh(auth))\n return;\n reminted = true;\n auth = await opts.refreshAuth();\n if (opts.signal?.aborted) return;\n opts.registry.registerProvider(\n GATEWAY_PROVIDER,\n buildGatewayProvider(opts.providerInputs(auth)).provider as never,\n );\n opts.onRemint?.();\n rejected = false;\n lastTurn = undefined;\n const next = opts.continueText;\n if (opts.signal?.aborted) return;\n await opts.session.prompt(typeof next === 'function' ? next() : next);\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/headless/index.ts
|
|
2
|
+
/** Run `config` headlessly; resolves with the exit code. */
|
|
3
|
+
async function runHeadless(config, launch) {
|
|
4
|
+
const { runHeadless: run } = await import("./run-DDCvLILJ.js");
|
|
5
|
+
return run(config, launch);
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { runHeadless as t };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=headless-BJjhP0SI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-BJjhP0SI.js","names":[],"sources":["../src/headless/index.ts"],"sourcesContent":["/** Headless's one entry for other layers; `runHeadless` loads the host on first call. */\nimport type { ProgramConfig } from '@programs/types';\nimport type { HeadlessLaunch } from './run';\n\nexport type { HeadlessLaunch, NonInteractiveMode } from './run';\nexport { modeLabel } from './mode-label';\n\n/** Run `config` headlessly; resolves with the exit code. */\nexport async function runHeadless(\n config: ProgramConfig,\n launch: HeadlessLaunch,\n): Promise<number> {\n const { runHeadless: run } = await import('./run');\n return run(config, launch);\n}\n"],"mappings":";;AAQA,eAAsB,YACpB,QACA,QACiB;CACjB,MAAM,EAAE,aAAa,QAAQ,MAAM,OAAO;AAC1C,QAAO,IAAI,QAAQ,OAAO"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import "./debug-BfQPD2Hg.js";
|
|
2
|
+
import { at as MCP_LOCAL_URL } from "./analytics-D21z3E5l.js";
|
|
3
|
+
import { n as getCloudUrl, o as getUiHostFromHost, r as getHost, s as resolveBaseUrl, t as detectRegion } from "./urls-BDELGZHq.js";
|
|
4
|
+
//#region src/shared/host-resolution.ts
|
|
5
|
+
/**
|
|
6
|
+
* HostResolution — the single, immutable snapshot of where the wizard talks to
|
|
7
|
+
* PostHog for one run.
|
|
8
|
+
*
|
|
9
|
+
* One cloud region (or a pinned `--base-url`) implies a whole family of hosts:
|
|
10
|
+
* the event-ingestion/API host, the user-facing web app host, the CDN asset
|
|
11
|
+
* host, the LLM gateway, and the MCP server. Rather than re-deriving each of
|
|
12
|
+
* these at every call site and threading `region` + `baseUrl` around as loose
|
|
13
|
+
* params, resolve once at auth time and pass this frozen object around — read
|
|
14
|
+
* the property you need.
|
|
15
|
+
*
|
|
16
|
+
* The actual region→URL math (and the `--base-url` override) lives in
|
|
17
|
+
* `@utils/urls`; this class is a thin, immutable façade over those resolvers so
|
|
18
|
+
* the override flows through every field without callers having to know about
|
|
19
|
+
* it. The OAuth-server URL stays in `@utils/urls` (`getOAuthUrl`) because it is
|
|
20
|
+
* needed *before* a region is known, so it can't come from this post-auth object.
|
|
21
|
+
*/
|
|
22
|
+
const MCP_PROD_URL = "https://mcp.posthog.com/mcp";
|
|
23
|
+
function assetHostFor(region, baseUrl) {
|
|
24
|
+
const override = resolveBaseUrl(baseUrl);
|
|
25
|
+
if (override) return override;
|
|
26
|
+
return region === "eu" ? "https://eu-assets.i.posthog.com" : "https://us-assets.i.posthog.com";
|
|
27
|
+
}
|
|
28
|
+
function assetHostFromApiHost(apiHost) {
|
|
29
|
+
if (apiHost.includes("us.i.posthog.com")) return "https://us-assets.i.posthog.com";
|
|
30
|
+
if (apiHost.includes("eu.i.posthog.com")) return "https://eu-assets.i.posthog.com";
|
|
31
|
+
return apiHost;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Dev/CI only: the env override (see env.ts) wins even under --local-mcp;
|
|
35
|
+
* published builds strip the read. Don't name that env var in comments here —
|
|
36
|
+
* smoke-test.sh greps dist/*.js for it, and JSDoc survives bundling.
|
|
37
|
+
*/
|
|
38
|
+
function mcpUrlFor(localMcp) {
|
|
39
|
+
return localMcp ? MCP_LOCAL_URL : MCP_PROD_URL;
|
|
40
|
+
}
|
|
41
|
+
var HostResolution = class HostResolution {
|
|
42
|
+
/** The resolved cloud region. `'us'` when a base URL is pinned. */
|
|
43
|
+
region;
|
|
44
|
+
/**
|
|
45
|
+
* Event-ingestion / REST API host (e.g. `https://us.i.posthog.com`, or the
|
|
46
|
+
* pinned `--base-url`). The SDK `host` written into the user's `.env`, the
|
|
47
|
+
* base for the wizard-session REST calls, and the host shown to the agent.
|
|
48
|
+
*/
|
|
49
|
+
apiHost;
|
|
50
|
+
/**
|
|
51
|
+
* User-facing web app host (e.g. `https://us.posthog.com`). Use for any link
|
|
52
|
+
* we hand to the user or open in their browser (dashboards, settings, inbox,
|
|
53
|
+
* deep-link base).
|
|
54
|
+
*/
|
|
55
|
+
appHost;
|
|
56
|
+
/** CDN asset host (e.g. `https://us-assets.i.posthog.com`). */
|
|
57
|
+
assetHost;
|
|
58
|
+
/**
|
|
59
|
+
* PostHog MCP server URL the agent connects to. Region-independent — the
|
|
60
|
+
* server resolves the user's region from the bearer token — so this is driven
|
|
61
|
+
* only by `--local-mcp` / `--local-dev` and the dev env override, not by
|
|
62
|
+
* region/base-url.
|
|
63
|
+
*/
|
|
64
|
+
mcpUrl;
|
|
65
|
+
constructor(fields) {
|
|
66
|
+
this.region = fields.region;
|
|
67
|
+
this.apiHost = fields.apiHost;
|
|
68
|
+
this.appHost = fields.appHost;
|
|
69
|
+
this.assetHost = fields.assetHost;
|
|
70
|
+
this.mcpUrl = fields.mcpUrl;
|
|
71
|
+
Object.freeze(this);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Canonical path: build the host family from a resolved region. A pinned
|
|
75
|
+
* `--base-url` (via `opts.baseUrl`) wins for every origin; otherwise the
|
|
76
|
+
* region's standard hosts are used. Honors IS_DEV through `resolveBaseUrl`.
|
|
77
|
+
*/
|
|
78
|
+
static fromRegion(region, opts = {}) {
|
|
79
|
+
return new HostResolution({
|
|
80
|
+
region,
|
|
81
|
+
apiHost: getHost(region, opts.baseUrl),
|
|
82
|
+
appHost: getCloudUrl(region, opts.baseUrl),
|
|
83
|
+
assetHost: assetHostFor(region, opts.baseUrl),
|
|
84
|
+
mcpUrl: mcpUrlFor(opts.localMcp ?? false)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build from an ingestion host string (the provisioning API returns one). The
|
|
89
|
+
* given host is preserved verbatim as `apiHost`; the region and the derived
|
|
90
|
+
* app/asset/gateway hosts are inferred from it.
|
|
91
|
+
*/
|
|
92
|
+
static fromApiHost(apiHost, opts = {}) {
|
|
93
|
+
return new HostResolution({
|
|
94
|
+
region: apiHost.includes("eu.") ? "eu" : "us",
|
|
95
|
+
apiHost,
|
|
96
|
+
appHost: getUiHostFromHost(apiHost),
|
|
97
|
+
assetHost: assetHostFromApiHost(apiHost),
|
|
98
|
+
mcpUrl: mcpUrlFor(opts.localMcp ?? false)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve the region from an access token (the us/eu probe, skipped when a
|
|
103
|
+
* base URL is pinned), then build the host family. Used after OAuth and after
|
|
104
|
+
* CI-mode API-key auth.
|
|
105
|
+
*/
|
|
106
|
+
static async fromAccessToken(accessToken, opts = {}) {
|
|
107
|
+
const region = opts.region ?? await detectRegion(accessToken, opts.baseUrl);
|
|
108
|
+
return HostResolution.fromRegion(region, opts);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
//#endregion
|
|
112
|
+
export { mcpUrlFor as n, HostResolution as t };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=host-resolution-D8GhEVoX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-resolution-D8GhEVoX.js","names":[],"sources":["../src/shared/host-resolution.ts"],"sourcesContent":["/**\n * HostResolution — the single, immutable snapshot of where the wizard talks to\n * PostHog for one run.\n *\n * One cloud region (or a pinned `--base-url`) implies a whole family of hosts:\n * the event-ingestion/API host, the user-facing web app host, the CDN asset\n * host, the LLM gateway, and the MCP server. Rather than re-deriving each of\n * these at every call site and threading `region` + `baseUrl` around as loose\n * params, resolve once at auth time and pass this frozen object around — read\n * the property you need.\n *\n * The actual region→URL math (and the `--base-url` override) lives in\n * `@utils/urls`; this class is a thin, immutable façade over those resolvers so\n * the override flows through every field without callers having to know about\n * it. The OAuth-server URL stays in `@utils/urls` (`getOAuthUrl`) because it is\n * needed *before* a region is known, so it can't come from this post-auth object.\n */\n\nimport {\n getHost,\n getCloudUrl,\n getUiHostFromHost,\n detectRegion,\n resolveBaseUrl,\n} from '@utils/urls';\nimport { IS_PRODUCTION_BUILD, runtimeEnv } from '@env';\nimport { MCP_LOCAL_URL } from '@shared/local-dev';\nimport type { CloudRegion } from '@utils/types';\n\n// The wizard's client gets CLI mode (a single `exec` tool) by server default,\n// so no mode is pinned; the dev env override (see env.ts) is taken verbatim.\nconst MCP_PROD_URL = 'https://mcp.posthog.com/mcp';\n\n/** Construction-time inputs that aren't implied by the region. */\nexport interface HostResolutionOptions {\n /** `--local-mcp`: the MCP url only; skills follow `--local-context-mill`. */\n localMcp?: boolean;\n /** `--base-url`: pin every PostHog origin to one URL, bypassing region resolution. */\n baseUrl?: string;\n /** `--region`: trust the explicitly-provided region. */\n region?: CloudRegion;\n}\n\nfunction assetHostFor(region: CloudRegion, baseUrl?: string): string {\n const override = resolveBaseUrl(baseUrl);\n if (override) return override;\n return region === 'eu'\n ? 'https://eu-assets.i.posthog.com'\n : 'https://us-assets.i.posthog.com';\n}\n\nfunction assetHostFromApiHost(apiHost: string): string {\n if (apiHost.includes('us.i.posthog.com')) {\n return 'https://us-assets.i.posthog.com';\n }\n if (apiHost.includes('eu.i.posthog.com')) {\n return 'https://eu-assets.i.posthog.com';\n }\n return apiHost;\n}\n\n/**\n * Dev/CI only: the env override (see env.ts) wins even under --local-mcp;\n * published builds strip the read. Don't name that env var in comments here —\n * smoke-test.sh greps dist/*.js for it, and JSDoc survives bundling.\n */\nexport function mcpUrlFor(localMcp: boolean): string {\n const override = IS_PRODUCTION_BUILD ? undefined : runtimeEnv('MCP_URL');\n if (override) return override;\n return localMcp ? MCP_LOCAL_URL : MCP_PROD_URL;\n}\n\nexport class HostResolution {\n /** The resolved cloud region. `'us'` when a base URL is pinned. */\n readonly region: CloudRegion;\n /**\n * Event-ingestion / REST API host (e.g. `https://us.i.posthog.com`, or the\n * pinned `--base-url`). The SDK `host` written into the user's `.env`, the\n * base for the wizard-session REST calls, and the host shown to the agent.\n */\n readonly apiHost: string;\n /**\n * User-facing web app host (e.g. `https://us.posthog.com`). Use for any link\n * we hand to the user or open in their browser (dashboards, settings, inbox,\n * deep-link base).\n */\n readonly appHost: string;\n /** CDN asset host (e.g. `https://us-assets.i.posthog.com`). */\n readonly assetHost: string;\n /**\n * PostHog MCP server URL the agent connects to. Region-independent — the\n * server resolves the user's region from the bearer token — so this is driven\n * only by `--local-mcp` / `--local-dev` and the dev env override, not by\n * region/base-url.\n */\n readonly mcpUrl: string;\n\n private constructor(fields: {\n region: CloudRegion;\n apiHost: string;\n appHost: string;\n assetHost: string;\n mcpUrl: string;\n }) {\n this.region = fields.region;\n this.apiHost = fields.apiHost;\n this.appHost = fields.appHost;\n this.assetHost = fields.assetHost;\n this.mcpUrl = fields.mcpUrl;\n Object.freeze(this);\n }\n\n /**\n * Canonical path: build the host family from a resolved region. A pinned\n * `--base-url` (via `opts.baseUrl`) wins for every origin; otherwise the\n * region's standard hosts are used. Honors IS_DEV through `resolveBaseUrl`.\n */\n static fromRegion(\n region: CloudRegion,\n opts: HostResolutionOptions = {},\n ): HostResolution {\n const apiHost = getHost(region, opts.baseUrl);\n return new HostResolution({\n region,\n apiHost,\n appHost: getCloudUrl(region, opts.baseUrl),\n assetHost: assetHostFor(region, opts.baseUrl),\n mcpUrl: mcpUrlFor(opts.localMcp ?? false),\n });\n }\n\n /**\n * Build from an ingestion host string (the provisioning API returns one). The\n * given host is preserved verbatim as `apiHost`; the region and the derived\n * app/asset/gateway hosts are inferred from it.\n */\n static fromApiHost(\n apiHost: string,\n opts: Pick<HostResolutionOptions, 'localMcp'> = {},\n ): HostResolution {\n const region: CloudRegion = apiHost.includes('eu.') ? 'eu' : 'us';\n return new HostResolution({\n region,\n apiHost,\n appHost: getUiHostFromHost(apiHost),\n assetHost: assetHostFromApiHost(apiHost),\n mcpUrl: mcpUrlFor(opts.localMcp ?? false),\n });\n }\n\n /**\n * Resolve the region from an access token (the us/eu probe, skipped when a\n * base URL is pinned), then build the host family. Used after OAuth and after\n * CI-mode API-key auth.\n */\n static async fromAccessToken(\n accessToken: string,\n opts: HostResolutionOptions = {},\n ): Promise<HostResolution> {\n const region =\n opts.region ?? (await detectRegion(accessToken, opts.baseUrl));\n return HostResolution.fromRegion(region, opts);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA+BA,MAAM,eAAe;AAYrB,SAAS,aAAa,QAAqB,SAA0B;CACnE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SAAU,QAAO;AACrB,QAAO,WAAW,OACd,oCACA;;AAGN,SAAS,qBAAqB,SAAyB;AACrD,KAAI,QAAQ,SAAS,mBAAmB,CACtC,QAAO;AAET,KAAI,QAAQ,SAAS,mBAAmB,CACtC,QAAO;AAET,QAAO;;;;;;;AAQT,SAAgB,UAAU,UAA2B;AAGnD,QAAO,WAAW,gBAAgB;;AAGpC,IAAa,iBAAb,MAAa,eAAe;;CAE1B;;;;;;CAMA;;;;;;CAMA;;CAEA;;;;;;;CAOA;CAEA,YAAoB,QAMjB;AACD,OAAK,SAAS,OAAO;AACrB,OAAK,UAAU,OAAO;AACtB,OAAK,UAAU,OAAO;AACtB,OAAK,YAAY,OAAO;AACxB,OAAK,SAAS,OAAO;AACrB,SAAO,OAAO,KAAK;;;;;;;CAQrB,OAAO,WACL,QACA,OAA8B,EAAE,EAChB;AAEhB,SAAO,IAAI,eAAe;GACxB;GACA,SAHc,QAAQ,QAAQ,KAAK,QAAQ;GAI3C,SAAS,YAAY,QAAQ,KAAK,QAAQ;GAC1C,WAAW,aAAa,QAAQ,KAAK,QAAQ;GAC7C,QAAQ,UAAU,KAAK,YAAY,MAAM;GAC1C,CAAC;;;;;;;CAQJ,OAAO,YACL,SACA,OAAgD,EAAE,EAClC;AAEhB,SAAO,IAAI,eAAe;GACxB,QAF0B,QAAQ,SAAS,MAAM,GAAG,OAAO;GAG3D;GACA,SAAS,kBAAkB,QAAQ;GACnC,WAAW,qBAAqB,QAAQ;GACxC,QAAQ,UAAU,KAAK,YAAY,MAAM;GAC1C,CAAC;;;;;;;CAQJ,aAAa,gBACX,aACA,OAA8B,EAAE,EACP;EACzB,MAAM,SACJ,KAAK,UAAW,MAAM,aAAa,aAAa,KAAK,QAAQ;AAC/D,SAAO,eAAe,WAAW,QAAQ,KAAK"}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as analytics } from "./analytics-
|
|
3
|
-
import {
|
|
4
|
-
import { t as
|
|
5
|
-
import { a as getNativeHTTPServerConfig,
|
|
1
|
+
import { o as logToFile, v as runtimeEnv } from "./debug-BfQPD2Hg.js";
|
|
2
|
+
import { n as analytics } from "./analytics-D21z3E5l.js";
|
|
3
|
+
import { t as openTrackedLink } from "./links-Cyj6v8kg.js";
|
|
4
|
+
import { a as scrubHomePaths, i as redactSecrets, s as toClientResult, t as expectedFailureHint } from "./results-DtKICAdz.js";
|
|
5
|
+
import { a as getNativeHTTPServerConfig, i as getDefaultServerConfig, r as buildMCPUrl } from "./defaults-DDVl3tKN.js";
|
|
6
6
|
import * as fs$2 from "fs";
|
|
7
7
|
import * as path$3 from "path";
|
|
8
8
|
import * as os from "node:os";
|
|
9
9
|
import * as path$2 from "node:path";
|
|
10
10
|
import { execFile, execSync } from "node:child_process";
|
|
11
11
|
import * as fs$1 from "node:fs";
|
|
12
|
-
import z$1 from "zod";
|
|
13
12
|
import * as os$1 from "os";
|
|
14
|
-
import
|
|
13
|
+
import z$1 from "zod";
|
|
15
14
|
import { execFile as execFile$1, execSync as execSync$1 } from "child_process";
|
|
16
|
-
|
|
15
|
+
import * as jsonc from "jsonc-parser";
|
|
16
|
+
//#region src/shared/mcp-clients/MCPClient.ts
|
|
17
17
|
var MCPClient = class {
|
|
18
18
|
name;
|
|
19
19
|
};
|
|
@@ -111,7 +111,7 @@ var DefaultMCPClient = class extends MCPClient {
|
|
|
111
111
|
}
|
|
112
112
|
};
|
|
113
113
|
//#endregion
|
|
114
|
-
//#region src/
|
|
114
|
+
//#region src/shared/mcp-clients/clients/cursor.ts
|
|
115
115
|
var CursorMCPClient = class extends DefaultMCPClient {
|
|
116
116
|
name = "Cursor";
|
|
117
117
|
constructor() {
|
|
@@ -128,7 +128,7 @@ var CursorMCPClient = class extends DefaultMCPClient {
|
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
//#endregion
|
|
131
|
-
//#region src/
|
|
131
|
+
//#region src/shared/mcp-clients/clients/claude-code.ts
|
|
132
132
|
const PLUGIN_NAME = "posthog";
|
|
133
133
|
const PLUGIN_MARKETPLACE$1 = "posthog";
|
|
134
134
|
const PLUGIN_MARKETPLACE_SOURCE$1 = "PostHog/ai-plugin";
|
|
@@ -168,13 +168,13 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
168
168
|
"/opt/homebrew/bin/claude"
|
|
169
169
|
];
|
|
170
170
|
for (const claudePath of possiblePaths) if (fs$2.existsSync(claudePath)) {
|
|
171
|
-
|
|
171
|
+
logToFile(` Found claude binary at: ${claudePath}`);
|
|
172
172
|
this.claudeBinaryPath = claudePath;
|
|
173
173
|
return claudePath;
|
|
174
174
|
}
|
|
175
175
|
try {
|
|
176
176
|
execSync$1("command -v claude", { stdio: "pipe" });
|
|
177
|
-
|
|
177
|
+
logToFile(" Found claude in PATH");
|
|
178
178
|
this.claudeBinaryPath = "claude";
|
|
179
179
|
return "claude";
|
|
180
180
|
} catch {}
|
|
@@ -182,20 +182,20 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
182
182
|
}
|
|
183
183
|
isClientSupported() {
|
|
184
184
|
try {
|
|
185
|
-
|
|
185
|
+
logToFile(" Checking for Claude Code...");
|
|
186
186
|
const claudeBinary = this.findClaudeBinary();
|
|
187
187
|
if (!claudeBinary) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
188
|
+
logToFile(" Claude Code not found. Installation paths checked:");
|
|
189
|
+
logToFile(` - ${path$3.join(os$1.homedir(), ".claude", "local", "claude")}`);
|
|
190
|
+
logToFile(` - /usr/local/bin/claude`);
|
|
191
|
+
logToFile(` - /opt/homebrew/bin/claude`);
|
|
192
|
+
logToFile(` - PATH`);
|
|
193
193
|
return Promise.resolve(false);
|
|
194
194
|
}
|
|
195
|
-
|
|
195
|
+
logToFile(` Claude Code detected: ${execSync$1(`${claudeBinary} --version`, { stdio: "pipe" }).toString().trim()}`);
|
|
196
196
|
return Promise.resolve(true);
|
|
197
197
|
} catch (error) {
|
|
198
|
-
|
|
198
|
+
logToFile(` Claude Code check failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
199
199
|
return Promise.resolve(false);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
@@ -440,7 +440,7 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
440
440
|
"marketplace",
|
|
441
441
|
"list"
|
|
442
442
|
]))?.some(isOurMarketplace)) {
|
|
443
|
-
|
|
443
|
+
logToFile(` Marketplace ${PLUGIN_MARKETPLACE$1} already registered`);
|
|
444
444
|
return;
|
|
445
445
|
}
|
|
446
446
|
const added = await this.runClaude(binary, [
|
|
@@ -450,13 +450,13 @@ var ClaudeCodeMCPClient = class extends DefaultMCPClient {
|
|
|
450
450
|
PLUGIN_MARKETPLACE_SOURCE$1
|
|
451
451
|
]);
|
|
452
452
|
if (!added.ok) {
|
|
453
|
-
|
|
453
|
+
logToFile(` Marketplace add failed: ${added.output}`);
|
|
454
454
|
return added.output;
|
|
455
455
|
}
|
|
456
456
|
}
|
|
457
457
|
};
|
|
458
458
|
//#endregion
|
|
459
|
-
//#region src/
|
|
459
|
+
//#region src/shared/mcp-clients/clients/claude-web.ts
|
|
460
460
|
/**
|
|
461
461
|
* Claude Desktop / Claude.ai (web). PostHog ships here as a hosted connector,
|
|
462
462
|
* not a local config — so instead of writing files we open the connector
|
|
@@ -565,7 +565,7 @@ var ZedClient = class extends DefaultMCPClient {
|
|
|
565
565
|
}
|
|
566
566
|
};
|
|
567
567
|
//#endregion
|
|
568
|
-
//#region src/
|
|
568
|
+
//#region src/shared/mcp-clients/clients/codex.ts
|
|
569
569
|
const PLUGIN_MARKETPLACE = "posthog";
|
|
570
570
|
const PLUGIN_MARKETPLACE_SOURCE = "PostHog/ai-plugin";
|
|
571
571
|
const PLUGIN_REF = `posthog@${PLUGIN_MARKETPLACE}`;
|
|
@@ -1046,12 +1046,12 @@ var OpenCodeMCPClient = class extends DefaultMCPClient {
|
|
|
1046
1046
|
}
|
|
1047
1047
|
};
|
|
1048
1048
|
//#endregion
|
|
1049
|
-
//#region src/
|
|
1049
|
+
//#region src/shared/mcp-clients/plugin-client.ts
|
|
1050
1050
|
function isPluginCapable(client) {
|
|
1051
1051
|
return typeof client === "object" && client !== null && "supportsPlugin" in client && "installPlugin" in client;
|
|
1052
1052
|
}
|
|
1053
1053
|
//#endregion
|
|
1054
|
-
//#region src/
|
|
1054
|
+
//#region src/shared/mcp-clients/install.ts
|
|
1055
1055
|
const getSupportedClients = async () => {
|
|
1056
1056
|
const allClients = [
|
|
1057
1057
|
new ClaudeCodeMCPClient(),
|
|
@@ -1063,81 +1063,15 @@ const getSupportedClients = async () => {
|
|
|
1063
1063
|
new OpenCodeMCPClient()
|
|
1064
1064
|
];
|
|
1065
1065
|
const supportedClients = [];
|
|
1066
|
-
|
|
1066
|
+
logToFile("Checking for supported MCP clients...");
|
|
1067
1067
|
for (const client of allClients) {
|
|
1068
1068
|
const isSupported = await client.isClientSupported();
|
|
1069
|
-
|
|
1069
|
+
logToFile(`${client.name}: ${isSupported ? "✓ supported" : "✗ not supported"}`);
|
|
1070
1070
|
if (isSupported) supportedClients.push(client);
|
|
1071
1071
|
}
|
|
1072
|
-
|
|
1072
|
+
logToFile(`Found ${supportedClients.length} supported client(s): ${supportedClients.map((c) => c.name).join(", ")}`);
|
|
1073
1073
|
return supportedClients;
|
|
1074
1074
|
};
|
|
1075
|
-
/**
|
|
1076
|
-
* Add MCP server to clients. No prompts — pure orchestration.
|
|
1077
|
-
* Prompts are handled by McpScreen (TUI) or auto-accepted (CI).
|
|
1078
|
-
*/
|
|
1079
|
-
const addMCPServerToClientsStep = async ({ integration, local = false, ci = false, cloudRegion: _cloudRegion, features, apiKey }) => {
|
|
1080
|
-
const ui = getUI();
|
|
1081
|
-
if (ci) {
|
|
1082
|
-
ui.log.info("Skipping MCP installation (CI mode)");
|
|
1083
|
-
return {
|
|
1084
|
-
installed: [],
|
|
1085
|
-
failed: []
|
|
1086
|
-
};
|
|
1087
|
-
}
|
|
1088
|
-
const supportedClients = await getSupportedClients();
|
|
1089
|
-
if (supportedClients.length === 0) {
|
|
1090
|
-
ui.log.info("No supported MCP clients detected. Skipping MCP installation.");
|
|
1091
|
-
return {
|
|
1092
|
-
installed: [],
|
|
1093
|
-
failed: []
|
|
1094
|
-
};
|
|
1095
|
-
}
|
|
1096
|
-
const results = await withProgress("adding mcp servers", () => addMCPServer(supportedClients, apiKey, features ?? [...ALL_FEATURE_VALUES], local));
|
|
1097
|
-
const installed = namesWithStatus(results, "changed");
|
|
1098
|
-
const already = namesWithStatus(results, "unchanged");
|
|
1099
|
-
const failed = results.filter((r) => r.status === "failed");
|
|
1100
|
-
if (installed.length > 0) ui.log.success(`Added the MCP server to:\n${bulletList(installed)}`);
|
|
1101
|
-
if (already.length > 0) ui.log.info(`The PostHog MCP server was already installed, so nothing changed for:\n${bulletList(already)}`);
|
|
1102
|
-
if (failed.length > 0) ui.log.warn(`Couldn't add the MCP server to:\n${bulletList(failed.map((r) => r.detail ? `${r.name} — ${r.detail}` : r.name))}`);
|
|
1103
|
-
const withServer = [...installed, ...already];
|
|
1104
|
-
analytics.wizardCapture("mcp servers added", {
|
|
1105
|
-
clients: withServer,
|
|
1106
|
-
already_installed_clients: already,
|
|
1107
|
-
failed_clients: failed.map((r) => r.name),
|
|
1108
|
-
attempted_clients: supportedClients.map((c) => c.name),
|
|
1109
|
-
integration
|
|
1110
|
-
});
|
|
1111
|
-
return {
|
|
1112
|
-
installed: withServer,
|
|
1113
|
-
failed: failed.map((r) => r.name)
|
|
1114
|
-
};
|
|
1115
|
-
};
|
|
1116
|
-
const bulletList = (items) => items.map((item) => ` - ${item}`).join("\n");
|
|
1117
|
-
const removeMCPServerFromClientsStep = async ({ integration, local = false }) => {
|
|
1118
|
-
const ui = getUI();
|
|
1119
|
-
const installedClients = await getInstalledClients(local);
|
|
1120
|
-
if (installedClients.length === 0) {
|
|
1121
|
-
ui.log.info("The PostHog MCP server is not installed for any supported client. Nothing to remove.");
|
|
1122
|
-
analytics.wizardCapture("mcp no servers to remove", { integration });
|
|
1123
|
-
return [];
|
|
1124
|
-
}
|
|
1125
|
-
const results = await withProgress("removing mcp servers", () => removeMCPServer(installedClients, local));
|
|
1126
|
-
const removed = namesWithStatus(results, "changed");
|
|
1127
|
-
const nothingToDo = namesWithStatus(results, "unchanged");
|
|
1128
|
-
const failed = results.filter((r) => r.status === "failed");
|
|
1129
|
-
if (removed.length > 0) ui.log.success(`Removed the MCP server from:\n${bulletList(removed)}`);
|
|
1130
|
-
if (nothingToDo.length > 0) ui.log.info(`No PostHog MCP entry left to remove for:\n${bulletList(nothingToDo)}`);
|
|
1131
|
-
if (failed.length > 0) ui.log.warn(`Couldn't remove the MCP server from:\n${bulletList(failed.map((r) => r.detail ? `${r.name} — ${r.detail}` : r.name))}`);
|
|
1132
|
-
analytics.wizardCapture("mcp servers removed", {
|
|
1133
|
-
clients: removed,
|
|
1134
|
-
nothing_to_remove_clients: nothingToDo,
|
|
1135
|
-
failed_clients: failed.map((r) => r.name),
|
|
1136
|
-
attempted_clients: installedClients.map((c) => c.name),
|
|
1137
|
-
integration
|
|
1138
|
-
});
|
|
1139
|
-
return removed;
|
|
1140
|
-
};
|
|
1141
1075
|
const getInstalledClients = async (local) => {
|
|
1142
1076
|
const clients = await getSupportedClients();
|
|
1143
1077
|
const installedClients = [];
|
|
@@ -1153,7 +1087,7 @@ const addMCPServer = async (clients, personalApiKey, selectedFeatures, local) =>
|
|
|
1153
1087
|
const result = await client.addServer(personalApiKey, selectedFeatures, local);
|
|
1154
1088
|
results.push(toClientResult(client.name, result));
|
|
1155
1089
|
} catch (err) {
|
|
1156
|
-
|
|
1090
|
+
logToFile(`[addMCPServer] addServer threw for ${client.name}: ${err}`);
|
|
1157
1091
|
results.push(toClientResult(client.name, {
|
|
1158
1092
|
success: false,
|
|
1159
1093
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -1169,7 +1103,7 @@ const installPlugins = async (clients) => {
|
|
|
1169
1103
|
for (const client of clients) try {
|
|
1170
1104
|
results.push(toClientResult(client.name, await client.installPlugin()));
|
|
1171
1105
|
} catch (err) {
|
|
1172
|
-
|
|
1106
|
+
logToFile(`[installPlugins] installPlugin threw for ${client.name}: ${err}`);
|
|
1173
1107
|
results.push(toClientResult(client.name, {
|
|
1174
1108
|
success: false,
|
|
1175
1109
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -1193,7 +1127,7 @@ const removeMCPServer = async (clients, local) => {
|
|
|
1193
1127
|
}
|
|
1194
1128
|
results.push(toClientResult(client.name, result));
|
|
1195
1129
|
} catch (err) {
|
|
1196
|
-
|
|
1130
|
+
logToFile(`[removeMCPServer] removeServer threw for ${client.name}: ${err}`);
|
|
1197
1131
|
results.push(toClientResult(client.name, {
|
|
1198
1132
|
success: false,
|
|
1199
1133
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -1202,6 +1136,6 @@ const removeMCPServer = async (clients, local) => {
|
|
|
1202
1136
|
return results;
|
|
1203
1137
|
};
|
|
1204
1138
|
//#endregion
|
|
1205
|
-
export {
|
|
1139
|
+
export { installPlugins as a, getSupportedPluginClients as i, getInstalledClients as n, removeMCPServer as o, getSupportedClients as r, isPluginCapable as s, addMCPServer as t };
|
|
1206
1140
|
|
|
1207
|
-
//# sourceMappingURL=
|
|
1141
|
+
//# sourceMappingURL=install-paPCzPHI.js.map
|