@posthog/wizard 2.73.1 → 2.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +32 -28
  2. package/dist/README.md +11 -4
  3. package/dist/{add-mcp-server-to-clients-D47ONFCD.js → add-mcp-server-to-clients-BtWwRG7O.js} +4 -4
  4. package/dist/{add-mcp-server-to-clients-D47ONFCD.js.map → add-mcp-server-to-clients-BtWwRG7O.js.map} +1 -1
  5. package/dist/{agent-interface-CQ_iz7g7.js → agent-interface-CK6pmvkF.js} +485 -340
  6. package/dist/agent-interface-CK6pmvkF.js.map +1 -0
  7. package/dist/{agent-prompt-loader-Dh2CZEw4.js → agent-prompt-loader-CPCNMvGh.js} +6 -7
  8. package/dist/agent-prompt-loader-CPCNMvGh.js.map +1 -0
  9. package/dist/{agent-runner-kj8juD_r.js → agent-runner-jz4yiJfh.js} +49 -67
  10. package/dist/agent-runner-jz4yiJfh.js.map +1 -0
  11. package/dist/analytics-CfadnLFG.js +2 -0
  12. package/dist/{analytics-DHkqXgxG.js → analytics-DZNb3aRN.js} +2 -2
  13. package/dist/{analytics-DHkqXgxG.js.map → analytics-DZNb3aRN.js.map} +1 -1
  14. package/dist/{api-BM5Gaf2x.js → api-DXGaiK94.js} +3 -3
  15. package/dist/{api-BM5Gaf2x.js.map → api-DXGaiK94.js.map} +1 -1
  16. package/dist/bin.js +59 -54
  17. package/dist/bin.js.map +1 -1
  18. package/dist/{bounded-fs-Byv2xRSy.js → bounded-fs-CErPpkN2.js} +3 -3
  19. package/dist/{bounded-fs-Byv2xRSy.js.map → bounded-fs-CErPpkN2.js.map} +1 -1
  20. package/dist/{ci-install-BUUD2hSG.js → ci-install-CzWzi_qu.js} +21 -24
  21. package/dist/ci-install-CzWzi_qu.js.map +1 -0
  22. package/dist/{debug-C14qe0b-.js → debug-D4y9vVWt.js} +1 -1
  23. package/dist/{debug-D0k3Quos.js → debug-ECdmmlDM.js} +21 -33
  24. package/dist/debug-ECdmmlDM.js.map +1 -0
  25. package/dist/{env-api-key-CBjWUJTZ.js → env-api-key-g5w775Ve.js} +2 -2
  26. package/dist/{env-api-key-CBjWUJTZ.js.map → env-api-key-g5w775Ve.js.map} +1 -1
  27. package/dist/{environment-DqdmG3WX.js → environment-DDkdsWUr.js} +4 -4
  28. package/dist/{environment-DqdmG3WX.js.map → environment-DDkdsWUr.js.map} +1 -1
  29. package/dist/{errors-u8z27V-x.js → errors--OqLxmWR.js} +34 -3
  30. package/dist/errors--OqLxmWR.js.map +1 -0
  31. package/dist/{file-watcher-CxStDuTR.js → file-watcher-BNdFPlI8.js} +2 -2
  32. package/dist/{file-watcher-CxStDuTR.js.map → file-watcher-BNdFPlI8.js.map} +1 -1
  33. package/dist/{headless-ui-DC1Qus7M.js → headless-ui-DBZCl4CG.js} +2 -2
  34. package/dist/{headless-ui-DC1Qus7M.js.map → headless-ui-DBZCl4CG.js.map} +1 -1
  35. package/dist/{interactive-DeNrHRZE.js → interactive-BKxXUB0T.js} +3 -3
  36. package/dist/{interactive-DeNrHRZE.js.map → interactive-BKxXUB0T.js.map} +1 -1
  37. package/dist/{mcp-Bnjc-Qsz.js → mcp-CwM45_Kp.js} +2 -2
  38. package/dist/{mcp-Bnjc-Qsz.js.map → mcp-CwM45_Kp.js.map} +1 -1
  39. package/dist/{mcp-prompt-streaming-Va6vRL7E.js → mcp-prompt-streaming-R8H7uhuO.js} +5 -5
  40. package/dist/mcp-prompt-streaming-R8H7uhuO.js.map +1 -0
  41. package/dist/{non-interactive-ZACUU6DC.js → non-interactive-DxzBwNxJ.js} +3 -3
  42. package/dist/{non-interactive-ZACUU6DC.js.map → non-interactive-DxzBwNxJ.js.map} +1 -1
  43. package/dist/{orchestrator-tools-BI3suN6p.js → orchestrator-tools-CTpKnk5-.js} +3 -3
  44. package/dist/{orchestrator-tools-BI3suN6p.js.map → orchestrator-tools-CTpKnk5-.js.map} +1 -1
  45. package/dist/{package-manager-DgRcS6CY.js → package-manager-Bi6gaPa4.js} +2 -2
  46. package/dist/{package-manager-DgRcS6CY.js.map → package-manager-Bi6gaPa4.js.map} +1 -1
  47. package/dist/{pi-DbEYScTs.js → pi-DpWFwz5u.js} +35 -20
  48. package/dist/pi-DpWFwz5u.js.map +1 -0
  49. package/dist/{playground-xa1G6pym.js → playground-BtTCVaSD.js} +7 -12
  50. package/dist/playground-BtTCVaSD.js.map +1 -0
  51. package/dist/{posthog-Dk8S5c6h.js → posthog-B99H8Zyk.js} +2 -2
  52. package/dist/{posthog-Dk8S5c6h.js.map → posthog-B99H8Zyk.js.map} +1 -1
  53. package/dist/{posthog-integration-BG5Y9Fb4.js → posthog-integration-CxvkKY1j.js} +13 -13
  54. package/dist/{posthog-integration-BG5Y9Fb4.js.map → posthog-integration-CxvkKY1j.js.map} +1 -1
  55. package/dist/{provisioning-e7J3SvpF.js → provisioning-BewSEuFX.js} +4 -10
  56. package/dist/provisioning-BewSEuFX.js.map +1 -0
  57. package/dist/{queue-tools-C3D_nwy_.js → queue-tools-CbRM-OET.js} +4 -31
  58. package/dist/queue-tools-CbRM-OET.js.map +1 -0
  59. package/dist/{registry-Bw-e1Fes.js → registry-Bt2Mc4vC.js} +5 -5
  60. package/dist/{registry-Bw-e1Fes.js.map → registry-Bt2Mc4vC.js.map} +1 -1
  61. package/dist/{security-BUg5_2uC.js → security-Cmxb64bz.js} +5 -5
  62. package/dist/{security-BUg5_2uC.js.map → security-Cmxb64bz.js.map} +1 -1
  63. package/dist/{setup-utils-CzMg2Vpy.js → setup-utils-CCphwDIz.js} +9 -15
  64. package/dist/setup-utils-CCphwDIz.js.map +1 -0
  65. package/dist/smoke-test-ci.sh +5 -2
  66. package/dist/{start-tui-Kt61g7LE.js → start-tui-BRwZzlWb.js} +22 -22
  67. package/dist/{start-tui-Kt61g7LE.js.map → start-tui-BRwZzlWb.js.map} +1 -1
  68. package/dist/{steps-De2a1a0X.js → steps-CJrx1t72.js} +7 -7
  69. package/dist/{steps-De2a1a0X.js.map → steps-CJrx1t72.js.map} +1 -1
  70. package/dist/{store-DDrR7nF6.js → store-BhcCTIn4.js} +6 -10
  71. package/dist/store-BhcCTIn4.js.map +1 -0
  72. package/dist/{subagent-cD2JOzo1.js → subagent-BeMPBF5r.js} +2 -2
  73. package/dist/{subagent-cD2JOzo1.js.map → subagent-BeMPBF5r.js.map} +1 -1
  74. package/dist/{task-FBY3mllc.js → task-DX3eZgBL.js} +36 -21
  75. package/dist/task-DX3eZgBL.js.map +1 -0
  76. package/dist/{task-stream-BjTFIY4l.js → task-stream-BW7BG70C.js} +5 -5
  77. package/dist/{task-stream-BjTFIY4l.js.map → task-stream-BW7BG70C.js.map} +1 -1
  78. package/dist/{tasks-BjevyqMO.js → tasks-Did1AR7v.js} +2 -2
  79. package/dist/{tasks-BjevyqMO.js.map → tasks-Did1AR7v.js.map} +1 -1
  80. package/dist/{telemetry-Asp60nwm.js → telemetry-CPWHrsXK.js} +3 -3
  81. package/dist/{telemetry-Asp60nwm.js.map → telemetry-CPWHrsXK.js.map} +1 -1
  82. package/dist/{terminal-CVgx_zHz.js → terminal-CpVFsbGu.js} +12 -12
  83. package/dist/{terminal-CVgx_zHz.js.map → terminal-CpVFsbGu.js.map} +1 -1
  84. package/dist/{tools-CPwnElLN.js → tools-DjiwCd53.js} +6 -6
  85. package/dist/{tools-CPwnElLN.js.map → tools-DjiwCd53.js.map} +1 -1
  86. package/dist/{wizard-abort-owSE9WC8.js → wizard-abort-DjJ-6y6S.js} +1 -1
  87. package/dist/{wizard-abort-DKpVH-t6.js → wizard-abort-RUnY1Dax.js} +4 -4
  88. package/dist/{wizard-abort-DKpVH-t6.js.map → wizard-abort-RUnY1Dax.js.map} +1 -1
  89. package/dist/yara-hooks-CBMSmD9F.js +2 -0
  90. package/dist/{yara-hooks-D-QD1ZCB.js → yara-hooks-jBqAkgxw.js} +4 -4
  91. package/dist/{yara-hooks-D-QD1ZCB.js.map → yara-hooks-jBqAkgxw.js.map} +1 -1
  92. package/package.json +1 -1
  93. package/dist/agent-interface-CQ_iz7g7.js.map +0 -1
  94. package/dist/agent-prompt-loader-Dh2CZEw4.js.map +0 -1
  95. package/dist/agent-runner-kj8juD_r.js.map +0 -1
  96. package/dist/analytics-BYknS_x4.js +0 -2
  97. package/dist/ci-install-BUUD2hSG.js.map +0 -1
  98. package/dist/debug-D0k3Quos.js.map +0 -1
  99. package/dist/errors-u8z27V-x.js.map +0 -1
  100. package/dist/mcp-prompt-streaming-Va6vRL7E.js.map +0 -1
  101. package/dist/pi-DbEYScTs.js.map +0 -1
  102. package/dist/playground-xa1G6pym.js.map +0 -1
  103. package/dist/provisioning-e7J3SvpF.js.map +0 -1
  104. package/dist/queue-tools-C3D_nwy_.js.map +0 -1
  105. package/dist/setup-utils-CzMg2Vpy.js.map +0 -1
  106. package/dist/store-DDrR7nF6.js.map +0 -1
  107. package/dist/task-FBY3mllc.js.map +0 -1
  108. package/dist/yara-hooks-DPo3t8nU.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager-DgRcS6CY.js","names":["detectPythonPM","path"],"sources":["../src/frameworks/python/utils.ts","../src/lib/detection/package-manager.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport enum PythonPackageManager {\n UV = 'uv',\n POETRY = 'poetry',\n PDM = 'pdm',\n HATCH = 'hatch',\n RYE = 'rye',\n PIPENV = 'pipenv',\n CONDA = 'conda',\n PIP = 'pip',\n UNKNOWN = 'unknown',\n}\n\n/**\n * Get the installed Python version\n */\nexport function getPythonVersion(\n options: WizardRunOptions,\n): string | undefined {\n try {\n const version = execSync('python --version || python3 --version', {\n cwd: options.installDir,\n encoding: 'utf-8',\n })\n .trim()\n .replace('Python ', '');\n return version;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Bucket Python version for analytics (e.g., \"3.11.x\" -> \"3.11\")\n */\nexport function getPythonVersionBucket(version: string): string {\n const match = version.match(/^(\\d+\\.\\d+)/);\n return match ? match[1] : version;\n}\n\n/**\n * Detect which package manager the project uses\n */\nexport async function detectPackageManager(\n options: WizardRunOptions,\n): Promise<PythonPackageManager> {\n const { installDir } = options;\n const fs = await import('node:fs');\n const path = await import('node:path');\n\n // Check for uv (uv.lock)\n if (fs.existsSync(path.join(installDir, 'uv.lock'))) {\n return PythonPackageManager.UV;\n }\n\n // Check pyproject.toml for various tools\n if (fs.existsSync(path.join(installDir, 'pyproject.toml'))) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, 'pyproject.toml'),\n 'utf-8',\n );\n\n // Check for Poetry\n if (content.includes('[tool.poetry]')) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM\n if (content.includes('[tool.pdm]')) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Hatch\n if (content.includes('[tool.hatch]')) {\n return PythonPackageManager.HATCH;\n }\n\n // Check for Rye\n if (content.includes('[tool.rye]')) {\n return PythonPackageManager.RYE;\n }\n } catch {\n // Continue checking\n }\n }\n\n // Check for Poetry lock file\n if (fs.existsSync(path.join(installDir, 'poetry.lock'))) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM lock file\n if (fs.existsSync(path.join(installDir, 'pdm.lock'))) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Pipenv (Pipfile or Pipfile.lock)\n if (\n fs.existsSync(path.join(installDir, 'Pipfile')) ||\n fs.existsSync(path.join(installDir, 'Pipfile.lock'))\n ) {\n return PythonPackageManager.PIPENV;\n }\n\n // Check for Conda (environment.yml or environment.yaml)\n if (\n fs.existsSync(path.join(installDir, 'environment.yml')) ||\n fs.existsSync(path.join(installDir, 'environment.yaml'))\n ) {\n return PythonPackageManager.CONDA;\n }\n\n // Check for pip (requirements.txt, setup.py, setup.cfg, or pyproject.toml)\n if (\n fs.existsSync(path.join(installDir, 'requirements.txt')) ||\n fs.existsSync(path.join(installDir, 'setup.py')) ||\n fs.existsSync(path.join(installDir, 'setup.cfg')) ||\n fs.existsSync(path.join(installDir, 'pyproject.toml'))\n ) {\n return PythonPackageManager.PIP;\n }\n\n // Check for requirements directory\n try {\n const requirementsDir = path.join(installDir, 'requirements');\n if (\n fs.existsSync(requirementsDir) &&\n fs.statSync(requirementsDir).isDirectory()\n ) {\n const files = fs.readdirSync(requirementsDir);\n if (files.some((f) => f.endsWith('.txt'))) {\n return PythonPackageManager.PIP;\n }\n }\n } catch {\n // Continue\n }\n\n return PythonPackageManager.UNKNOWN;\n}\n\n/**\n * Get package manager display name\n */\nexport function getPackageManagerName(\n packageManager: PythonPackageManager,\n): string {\n switch (packageManager) {\n case PythonPackageManager.UV:\n return 'uv';\n case PythonPackageManager.POETRY:\n return 'Poetry';\n case PythonPackageManager.PDM:\n return 'PDM';\n case PythonPackageManager.HATCH:\n return 'Hatch';\n case PythonPackageManager.RYE:\n return 'Rye';\n case PythonPackageManager.PIPENV:\n return 'Pipenv';\n case PythonPackageManager.CONDA:\n return 'Conda';\n case PythonPackageManager.PIP:\n return 'pip';\n case PythonPackageManager.UNKNOWN:\n return 'unknown';\n }\n}\n","/**\n * Cross-ecosystem package manager detection.\n *\n * Provides a common interface (PackageManagerDetector) that each FrameworkConfig\n * implements, plus shared helpers for Node.js, Python, PHP, and Swift ecosystems.\n * The MCP tool in wizard-tools.ts delegates to whatever detector the\n * current framework supplies.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n detectAllPackageManagers,\n type PackageManager,\n} from '@utils/package-manager';\nimport {\n detectPackageManager as detectPythonPM,\n PythonPackageManager,\n} from '@frameworks/python/utils';\n\n// ---------------------------------------------------------------------------\n// Common types\n// ---------------------------------------------------------------------------\n\n/** Structured package manager info the agent can act on */\nexport interface DetectedPackageManager {\n name: string;\n label: string;\n installCommand: string;\n runCommand?: string;\n}\n\n/** Result returned by every detector */\nexport interface PackageManagerInfo {\n detected: DetectedPackageManager[];\n primary: DetectedPackageManager | null;\n recommendation: string;\n}\n\n/** Signature each framework implements */\nexport type PackageManagerDetector = (\n installDir: string,\n) => Promise<PackageManagerInfo>;\n\n// ---------------------------------------------------------------------------\n// Node.js helper\n// ---------------------------------------------------------------------------\n\nfunction serializeNodePM(pm: PackageManager): DetectedPackageManager {\n return {\n name: pm.name,\n label: pm.label,\n installCommand: pm.installCommand,\n runCommand: pm.runScriptCommand,\n };\n}\n\n/**\n * Detect Node.js package managers via lockfiles.\n * Wraps the existing detectAllPackageManagers() from utils/package-manager.ts.\n */\nexport function detectNodePackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const detected = detectAllPackageManagers({ installDir }).map(\n serializeNodePM,\n );\n\n if (detected.length === 0) {\n return Promise.resolve({\n detected: [],\n primary: null,\n recommendation: 'No lockfile found. Default to npm (npm add, npm run).',\n });\n }\n\n const primary = detected[0];\n return Promise.resolve({\n detected,\n primary,\n recommendation:\n detected.length === 1\n ? `Use ${primary.label} (${primary.installCommand}).`\n : `Multiple package managers detected. Prefer ${primary.label} (${primary.installCommand}).`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Python helper\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PM_INFO: Record<PythonPackageManager, DetectedPackageManager> = {\n [PythonPackageManager.UV]: {\n name: 'uv',\n label: 'uv',\n installCommand: 'uv add',\n runCommand: 'uv run',\n },\n [PythonPackageManager.POETRY]: {\n name: 'poetry',\n label: 'Poetry',\n installCommand: 'poetry add',\n runCommand: 'poetry run',\n },\n [PythonPackageManager.PDM]: {\n name: 'pdm',\n label: 'PDM',\n installCommand: 'pdm add',\n runCommand: 'pdm run',\n },\n [PythonPackageManager.HATCH]: {\n name: 'hatch',\n label: 'Hatch',\n installCommand: 'hatch add',\n runCommand: 'hatch run',\n },\n [PythonPackageManager.RYE]: {\n name: 'rye',\n label: 'Rye',\n installCommand: 'rye add',\n runCommand: 'rye run',\n },\n [PythonPackageManager.PIPENV]: {\n name: 'pipenv',\n label: 'Pipenv',\n installCommand: 'pipenv install',\n runCommand: 'pipenv run',\n },\n [PythonPackageManager.CONDA]: {\n name: 'conda',\n label: 'Conda',\n installCommand: 'conda install',\n runCommand: 'conda run',\n },\n [PythonPackageManager.PIP]: {\n name: 'pip',\n label: 'pip',\n installCommand: 'pip install',\n },\n [PythonPackageManager.UNKNOWN]: {\n name: 'pip',\n label: 'pip (default)',\n installCommand: 'pip install',\n },\n};\n\n/**\n * Detect Python package managers via lockfiles and config files.\n * Wraps the existing detectPackageManager() from python/utils.ts.\n */\nexport async function detectPythonPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const pm = await detectPythonPM({ installDir } as any);\n const info = PYTHON_PM_INFO[pm];\n\n return {\n detected: [info],\n primary: info,\n recommendation: `Use ${info.label} (${info.installCommand}).`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PHP (Composer) helper\n// ---------------------------------------------------------------------------\n\nconst COMPOSER: DetectedPackageManager = {\n name: 'composer',\n label: 'Composer',\n installCommand: 'composer require',\n};\n\nexport function composerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [COMPOSER],\n primary: COMPOSER,\n recommendation: 'Use Composer (composer require).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Swift (SPM) helper\n// ---------------------------------------------------------------------------\n\nconst SPM: DetectedPackageManager = {\n name: 'spm',\n label: 'Swift Package Manager',\n installCommand: 'swift package add-dependency',\n};\n\nexport function swiftPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [SPM],\n primary: SPM,\n recommendation:\n 'Use Swift Package Manager. Add the dependency to Package.swift or via Xcode.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ruby (Bundler) helper\n// ---------------------------------------------------------------------------\n\nconst BUNDLER: DetectedPackageManager = {\n name: 'bundler',\n label: 'Bundler',\n installCommand: 'bundle add',\n runCommand: 'bundle exec',\n};\n\nexport function bundlerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [BUNDLER],\n primary: BUNDLER,\n recommendation: 'Use Bundler (bundle add). Run commands with bundle exec.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Rust (Cargo) helper\n// ---------------------------------------------------------------------------\n\nconst CARGO: DetectedPackageManager = {\n name: 'cargo',\n label: 'Cargo',\n installCommand: 'cargo add',\n};\n\nexport function cargoPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [CARGO],\n primary: CARGO,\n recommendation: 'Use Cargo (cargo add).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Elixir (Mix) helper\n// ---------------------------------------------------------------------------\n\nconst MIX: DetectedPackageManager = {\n name: 'mix',\n label: 'Mix',\n installCommand: 'mix deps.get',\n};\n\nexport function mixPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [MIX],\n primary: MIX,\n recommendation:\n 'Use Mix. Add the dependency to the deps list in mix.exs, then run mix deps.get.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Go (modules) helper\n// ---------------------------------------------------------------------------\n\nconst GO_MODULES: DetectedPackageManager = {\n name: 'go',\n label: 'Go modules',\n installCommand: 'go get',\n};\n\nexport function goModulesPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GO_MODULES],\n primary: GO_MODULES,\n recommendation:\n 'Use Go modules (go get). Run go mod tidy after imports change.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Flutter (pub) helper\n// ---------------------------------------------------------------------------\n\nconst PUB: DetectedPackageManager = {\n name: 'pub',\n label: 'pub',\n installCommand: 'flutter pub add',\n runCommand: 'flutter',\n};\n\nexport function pubPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [PUB],\n primary: PUB,\n recommendation:\n 'Use flutter pub add to add dependencies; it updates pubspec.yaml automatically.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Android (Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst GRADLE: DetectedPackageManager = {\n name: 'gradle',\n label: 'Gradle',\n installCommand: 'implementation',\n};\n\nexport function gradlePackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GRADLE],\n primary: GRADLE,\n recommendation:\n 'Add dependencies to build.gradle(.kts) using implementation().',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Java (Maven or Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst MAVEN: DetectedPackageManager = {\n name: 'maven',\n label: 'Maven',\n installCommand: 'mvn install',\n};\n\n/**\n * Java backends split between Maven and Gradle; pom.xml decides.\n * Defaults to Gradle when neither manifest is present.\n */\nexport function detectJavaPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n if (fs.existsSync(path.join(installDir, 'pom.xml'))) {\n return Promise.resolve({\n detected: [MAVEN],\n primary: MAVEN,\n recommendation:\n 'Use Maven. Add the dependency to pom.xml, then run mvn install to resolve it.',\n });\n }\n return gradlePackageManager();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"package-manager-Bi6gaPa4.js","names":["detectPythonPM","path"],"sources":["../src/frameworks/python/utils.ts","../src/lib/detection/package-manager.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport enum PythonPackageManager {\n UV = 'uv',\n POETRY = 'poetry',\n PDM = 'pdm',\n HATCH = 'hatch',\n RYE = 'rye',\n PIPENV = 'pipenv',\n CONDA = 'conda',\n PIP = 'pip',\n UNKNOWN = 'unknown',\n}\n\n/**\n * Get the installed Python version\n */\nexport function getPythonVersion(\n options: WizardRunOptions,\n): string | undefined {\n try {\n const version = execSync('python --version || python3 --version', {\n cwd: options.installDir,\n encoding: 'utf-8',\n })\n .trim()\n .replace('Python ', '');\n return version;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Bucket Python version for analytics (e.g., \"3.11.x\" -> \"3.11\")\n */\nexport function getPythonVersionBucket(version: string): string {\n const match = version.match(/^(\\d+\\.\\d+)/);\n return match ? match[1] : version;\n}\n\n/**\n * Detect which package manager the project uses\n */\nexport async function detectPackageManager(\n options: WizardRunOptions,\n): Promise<PythonPackageManager> {\n const { installDir } = options;\n const fs = await import('node:fs');\n const path = await import('node:path');\n\n // Check for uv (uv.lock)\n if (fs.existsSync(path.join(installDir, 'uv.lock'))) {\n return PythonPackageManager.UV;\n }\n\n // Check pyproject.toml for various tools\n if (fs.existsSync(path.join(installDir, 'pyproject.toml'))) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, 'pyproject.toml'),\n 'utf-8',\n );\n\n // Check for Poetry\n if (content.includes('[tool.poetry]')) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM\n if (content.includes('[tool.pdm]')) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Hatch\n if (content.includes('[tool.hatch]')) {\n return PythonPackageManager.HATCH;\n }\n\n // Check for Rye\n if (content.includes('[tool.rye]')) {\n return PythonPackageManager.RYE;\n }\n } catch {\n // Continue checking\n }\n }\n\n // Check for Poetry lock file\n if (fs.existsSync(path.join(installDir, 'poetry.lock'))) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM lock file\n if (fs.existsSync(path.join(installDir, 'pdm.lock'))) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Pipenv (Pipfile or Pipfile.lock)\n if (\n fs.existsSync(path.join(installDir, 'Pipfile')) ||\n fs.existsSync(path.join(installDir, 'Pipfile.lock'))\n ) {\n return PythonPackageManager.PIPENV;\n }\n\n // Check for Conda (environment.yml or environment.yaml)\n if (\n fs.existsSync(path.join(installDir, 'environment.yml')) ||\n fs.existsSync(path.join(installDir, 'environment.yaml'))\n ) {\n return PythonPackageManager.CONDA;\n }\n\n // Check for pip (requirements.txt, setup.py, setup.cfg, or pyproject.toml)\n if (\n fs.existsSync(path.join(installDir, 'requirements.txt')) ||\n fs.existsSync(path.join(installDir, 'setup.py')) ||\n fs.existsSync(path.join(installDir, 'setup.cfg')) ||\n fs.existsSync(path.join(installDir, 'pyproject.toml'))\n ) {\n return PythonPackageManager.PIP;\n }\n\n // Check for requirements directory\n try {\n const requirementsDir = path.join(installDir, 'requirements');\n if (\n fs.existsSync(requirementsDir) &&\n fs.statSync(requirementsDir).isDirectory()\n ) {\n const files = fs.readdirSync(requirementsDir);\n if (files.some((f) => f.endsWith('.txt'))) {\n return PythonPackageManager.PIP;\n }\n }\n } catch {\n // Continue\n }\n\n return PythonPackageManager.UNKNOWN;\n}\n\n/**\n * Get package manager display name\n */\nexport function getPackageManagerName(\n packageManager: PythonPackageManager,\n): string {\n switch (packageManager) {\n case PythonPackageManager.UV:\n return 'uv';\n case PythonPackageManager.POETRY:\n return 'Poetry';\n case PythonPackageManager.PDM:\n return 'PDM';\n case PythonPackageManager.HATCH:\n return 'Hatch';\n case PythonPackageManager.RYE:\n return 'Rye';\n case PythonPackageManager.PIPENV:\n return 'Pipenv';\n case PythonPackageManager.CONDA:\n return 'Conda';\n case PythonPackageManager.PIP:\n return 'pip';\n case PythonPackageManager.UNKNOWN:\n return 'unknown';\n }\n}\n","/**\n * Cross-ecosystem package manager detection.\n *\n * Provides a common interface (PackageManagerDetector) that each FrameworkConfig\n * implements, plus shared helpers for Node.js, Python, PHP, and Swift ecosystems.\n * The MCP tool in wizard-tools.ts delegates to whatever detector the\n * current framework supplies.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n detectAllPackageManagers,\n type PackageManager,\n} from '@utils/package-manager';\nimport {\n detectPackageManager as detectPythonPM,\n PythonPackageManager,\n} from '@frameworks/python/utils';\n\n// ---------------------------------------------------------------------------\n// Common types\n// ---------------------------------------------------------------------------\n\n/** Structured package manager info the agent can act on */\nexport interface DetectedPackageManager {\n name: string;\n label: string;\n installCommand: string;\n runCommand?: string;\n}\n\n/** Result returned by every detector */\nexport interface PackageManagerInfo {\n detected: DetectedPackageManager[];\n primary: DetectedPackageManager | null;\n recommendation: string;\n}\n\n/** Signature each framework implements */\nexport type PackageManagerDetector = (\n installDir: string,\n) => Promise<PackageManagerInfo>;\n\n// ---------------------------------------------------------------------------\n// Node.js helper\n// ---------------------------------------------------------------------------\n\nfunction serializeNodePM(pm: PackageManager): DetectedPackageManager {\n return {\n name: pm.name,\n label: pm.label,\n installCommand: pm.installCommand,\n runCommand: pm.runScriptCommand,\n };\n}\n\n/**\n * Detect Node.js package managers via lockfiles.\n * Wraps the existing detectAllPackageManagers() from utils/package-manager.ts.\n */\nexport function detectNodePackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const detected = detectAllPackageManagers({ installDir }).map(\n serializeNodePM,\n );\n\n if (detected.length === 0) {\n return Promise.resolve({\n detected: [],\n primary: null,\n recommendation: 'No lockfile found. Default to npm (npm add, npm run).',\n });\n }\n\n const primary = detected[0];\n return Promise.resolve({\n detected,\n primary,\n recommendation:\n detected.length === 1\n ? `Use ${primary.label} (${primary.installCommand}).`\n : `Multiple package managers detected. Prefer ${primary.label} (${primary.installCommand}).`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Python helper\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PM_INFO: Record<PythonPackageManager, DetectedPackageManager> = {\n [PythonPackageManager.UV]: {\n name: 'uv',\n label: 'uv',\n installCommand: 'uv add',\n runCommand: 'uv run',\n },\n [PythonPackageManager.POETRY]: {\n name: 'poetry',\n label: 'Poetry',\n installCommand: 'poetry add',\n runCommand: 'poetry run',\n },\n [PythonPackageManager.PDM]: {\n name: 'pdm',\n label: 'PDM',\n installCommand: 'pdm add',\n runCommand: 'pdm run',\n },\n [PythonPackageManager.HATCH]: {\n name: 'hatch',\n label: 'Hatch',\n installCommand: 'hatch add',\n runCommand: 'hatch run',\n },\n [PythonPackageManager.RYE]: {\n name: 'rye',\n label: 'Rye',\n installCommand: 'rye add',\n runCommand: 'rye run',\n },\n [PythonPackageManager.PIPENV]: {\n name: 'pipenv',\n label: 'Pipenv',\n installCommand: 'pipenv install',\n runCommand: 'pipenv run',\n },\n [PythonPackageManager.CONDA]: {\n name: 'conda',\n label: 'Conda',\n installCommand: 'conda install',\n runCommand: 'conda run',\n },\n [PythonPackageManager.PIP]: {\n name: 'pip',\n label: 'pip',\n installCommand: 'pip install',\n },\n [PythonPackageManager.UNKNOWN]: {\n name: 'pip',\n label: 'pip (default)',\n installCommand: 'pip install',\n },\n};\n\n/**\n * Detect Python package managers via lockfiles and config files.\n * Wraps the existing detectPackageManager() from python/utils.ts.\n */\nexport async function detectPythonPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const pm = await detectPythonPM({ installDir } as any);\n const info = PYTHON_PM_INFO[pm];\n\n return {\n detected: [info],\n primary: info,\n recommendation: `Use ${info.label} (${info.installCommand}).`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PHP (Composer) helper\n// ---------------------------------------------------------------------------\n\nconst COMPOSER: DetectedPackageManager = {\n name: 'composer',\n label: 'Composer',\n installCommand: 'composer require',\n};\n\nexport function composerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [COMPOSER],\n primary: COMPOSER,\n recommendation: 'Use Composer (composer require).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Swift (SPM) helper\n// ---------------------------------------------------------------------------\n\nconst SPM: DetectedPackageManager = {\n name: 'spm',\n label: 'Swift Package Manager',\n installCommand: 'swift package add-dependency',\n};\n\nexport function swiftPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [SPM],\n primary: SPM,\n recommendation:\n 'Use Swift Package Manager. Add the dependency to Package.swift or via Xcode.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ruby (Bundler) helper\n// ---------------------------------------------------------------------------\n\nconst BUNDLER: DetectedPackageManager = {\n name: 'bundler',\n label: 'Bundler',\n installCommand: 'bundle add',\n runCommand: 'bundle exec',\n};\n\nexport function bundlerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [BUNDLER],\n primary: BUNDLER,\n recommendation: 'Use Bundler (bundle add). Run commands with bundle exec.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Rust (Cargo) helper\n// ---------------------------------------------------------------------------\n\nconst CARGO: DetectedPackageManager = {\n name: 'cargo',\n label: 'Cargo',\n installCommand: 'cargo add',\n};\n\nexport function cargoPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [CARGO],\n primary: CARGO,\n recommendation: 'Use Cargo (cargo add).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Elixir (Mix) helper\n// ---------------------------------------------------------------------------\n\nconst MIX: DetectedPackageManager = {\n name: 'mix',\n label: 'Mix',\n installCommand: 'mix deps.get',\n};\n\nexport function mixPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [MIX],\n primary: MIX,\n recommendation:\n 'Use Mix. Add the dependency to the deps list in mix.exs, then run mix deps.get.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Go (modules) helper\n// ---------------------------------------------------------------------------\n\nconst GO_MODULES: DetectedPackageManager = {\n name: 'go',\n label: 'Go modules',\n installCommand: 'go get',\n};\n\nexport function goModulesPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GO_MODULES],\n primary: GO_MODULES,\n recommendation:\n 'Use Go modules (go get). Run go mod tidy after imports change.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Flutter (pub) helper\n// ---------------------------------------------------------------------------\n\nconst PUB: DetectedPackageManager = {\n name: 'pub',\n label: 'pub',\n installCommand: 'flutter pub add',\n runCommand: 'flutter',\n};\n\nexport function pubPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [PUB],\n primary: PUB,\n recommendation:\n 'Use flutter pub add to add dependencies; it updates pubspec.yaml automatically.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Android (Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst GRADLE: DetectedPackageManager = {\n name: 'gradle',\n label: 'Gradle',\n installCommand: 'implementation',\n};\n\nexport function gradlePackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GRADLE],\n primary: GRADLE,\n recommendation:\n 'Add dependencies to build.gradle(.kts) using implementation().',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Java (Maven or Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst MAVEN: DetectedPackageManager = {\n name: 'maven',\n label: 'Maven',\n installCommand: 'mvn install',\n};\n\n/**\n * Java backends split between Maven and Gradle; pom.xml decides.\n * Defaults to Gradle when neither manifest is present.\n */\nexport function detectJavaPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n if (fs.existsSync(path.join(installDir, 'pom.xml'))) {\n return Promise.resolve({\n detected: [MAVEN],\n primary: MAVEN,\n recommendation:\n 'Use Maven. Add the dependency to pom.xml, then run mvn install to resolve it.',\n });\n }\n return gradlePackageManager();\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { a as AgentSignals, o as REMARK_INSTRUCTION } from "./errors-u8z27V-x.js";
2
- import { _t as VERSION, a as getLogFilePath, f as getUI, ft as WIZARD_REMARK_EVENT_NAME, mt as WIZARD_USER_AGENT, s as logToFile } from "./debug-D0k3Quos.js";
3
- import { n as analytics } from "./analytics-DHkqXgxG.js";
4
- import { W as gatewayAuth, _ as buildGatewayProvider, g as GATEWAY_PROVIDER, m as assembleCommandments, p as AgentOutputSignals } from "./agent-interface-CQ_iz7g7.js";
1
+ import { o as AgentSignals, s as REMARK_INSTRUCTION } from "./errors--OqLxmWR.js";
2
+ import { a as getLogFilePath, dt as WIZARD_USER_AGENT, f as getUI, lt as WIZARD_REMARK_EVENT_NAME, mt as VERSION, s as logToFile } from "./debug-ECdmmlDM.js";
3
+ import { n as analytics } from "./analytics-DZNb3aRN.js";
4
+ import { G as gatewayAuth, _ as buildGatewayProvider, g as GATEWAY_PROVIDER, m as assembleCommandments, p as AgentOutputSignals, v as withGatewayRemint } from "./agent-interface-CK6pmvkF.js";
5
5
  import fs from "fs";
6
6
  import path from "path";
7
7
  //#region src/lib/agent/aio-capture.ts
@@ -365,17 +365,19 @@ const piBackend = {
365
365
  });
366
366
  try {
367
367
  const { createAgentSession, DefaultResourceLoader, SessionManager, AuthStorage, ModelRegistry, getAgentDir, createLsToolDefinition, createFindToolDefinition, createGrepToolDefinition, createBashToolDefinition, createReadToolDefinition, createEditToolDefinition, createWriteToolDefinition } = await import("@earendil-works/pi-coding-agent");
368
- const auth = await gatewayAuth(boot.credentials.host, boot.credentials.accessToken, boot.programId);
369
- const { provider, caps } = buildGatewayProvider({
370
- gatewayUrl: auth.gatewayUrl,
371
- accessToken: auth.token,
372
- edition: auth.edition,
373
- teamId: auth.teamId,
368
+ const refreshAuth = () => gatewayAuth(boot.credentials.host, boot.credentials.accessToken, boot.programId);
369
+ const auth = await refreshAuth();
370
+ const providerInputs = (current) => ({
371
+ gatewayUrl: current.gatewayUrl,
372
+ accessToken: current.token,
373
+ teamId: current.teamId,
374
+ legacy: current.legacy,
374
375
  wizardMetadata: boot.wizardMetadata,
375
376
  wizardFlags: boot.wizardFlags,
376
377
  modelId,
377
378
  effort: inputs.thinkingLevel
378
379
  });
380
+ const { provider, caps } = buildGatewayProvider(providerInputs(auth));
379
381
  const registry = ModelRegistry.inMemory(AuthStorage.create());
380
382
  registry.registerProvider(GATEWAY_PROVIDER, provider);
381
383
  const model = registry.find(GATEWAY_PROVIDER, modelId);
@@ -384,21 +386,21 @@ const piBackend = {
384
386
  message: "pi: gateway model could not be resolved"
385
387
  };
386
388
  const askState = { pending: false };
387
- const { createSecurityExtension } = await import("./security-BUg5_2uC.js");
389
+ const { createSecurityExtension } = await import("./security-Cmxb64bz.js");
388
390
  const security = createSecurityExtension({
389
391
  disallowedTools: programConfig.disallowedTools,
390
392
  getWizardAskPending: () => askState.pending,
391
393
  triageProvider: boot.triageProvider,
392
394
  workingDirectory: session.installDir
393
395
  });
394
- const { prewarmYaraScanner } = await import("./yara-hooks-DPo3t8nU.js");
396
+ const { prewarmYaraScanner } = await import("./yara-hooks-CBMSmD9F.js");
395
397
  prewarmYaraScanner();
396
398
  const extensionFactories = [security.factory];
397
399
  let mcpCleanup;
398
400
  let mcpInstructions;
399
401
  let posthogMcp = false;
400
402
  try {
401
- const { setupPostHogMcp, fetchInstructions } = await import("./mcp-Bnjc-Qsz.js");
403
+ const { setupPostHogMcp, fetchInstructions } = await import("./mcp-CwM45_Kp.js");
402
404
  const instructionsPromise = fetchInstructions(boot.credentials.host.mcpUrl, boot.credentials.accessToken, WIZARD_USER_AGENT);
403
405
  const mcp = await setupPostHogMcp({
404
406
  mcpUrl: boot.credentials.host.mcpUrl,
@@ -437,9 +439,9 @@ const piBackend = {
437
439
  extensionFactories
438
440
  });
439
441
  await resourceLoader.reload();
440
- const { createWizardPiTools } = await import("./tools-CPwnElLN.js");
441
- const { createWizardPiTaskTools } = await import("./tasks-BjevyqMO.js");
442
- const { createDispatchAgentTool } = await import("./subagent-cD2JOzo1.js");
442
+ const { createWizardPiTools } = await import("./tools-DjiwCd53.js");
443
+ const { createWizardPiTaskTools } = await import("./tasks-Did1AR7v.js");
444
+ const { createDispatchAgentTool } = await import("./subagent-BeMPBF5r.js");
443
445
  const wizardTaskTools = createWizardPiTaskTools();
444
446
  const scrubbedBash = withMode(createBashToolDefinition(session.installDir, { spawnHook: (ctx) => ({
445
447
  ...ctx,
@@ -491,12 +493,25 @@ const piBackend = {
491
493
  customTools
492
494
  });
493
495
  await agentSession.bindExtensions({});
496
+ const turns = withGatewayRemint({
497
+ session: agentSession,
498
+ registry,
499
+ auth,
500
+ refreshAuth,
501
+ providerInputs,
502
+ continueText: CONTINUE_INSTRUCTION,
503
+ onRemint: () => {
504
+ logToFile("[pi] gateway token renewed after a 401; continuing");
505
+ analytics.wizardCapture("gateway token reminted", { harness: "pi" });
506
+ }
507
+ });
494
508
  const unsubscribe = agentSession.subscribe((event) => {
495
509
  capture.captureFromPiMessageEndEvent(event);
496
510
  switch (event.type) {
497
511
  case "message_end": {
498
512
  if (event.message?.role !== "assistant") break;
499
513
  assistantTurns += 1;
514
+ turns.noteAssistantTurn(event.message);
500
515
  const assistant = extractText(event.message).trim();
501
516
  if (assistant) {
502
517
  logToFile(`[pi] assistant: ${assistant.slice(0, 1e3)}`);
@@ -527,12 +542,12 @@ const piBackend = {
527
542
  });
528
543
  capture.setInitialPrompt(prompt);
529
544
  try {
530
- await agentSession.prompt(prompt);
545
+ await turns.prompt(prompt);
531
546
  let continueNudges = 0;
532
547
  while (continueNudges < MAX_CONTINUE_NUDGES && !security.state.criticalViolation && hasOpenTasks(wizardTaskTools.store)) {
533
548
  continueNudges += 1;
534
549
  logToFile(`[pi] completion guard: tasks still open, nudge ${continueNudges}/${MAX_CONTINUE_NUDGES}`);
535
- await agentSession.prompt(CONTINUE_INSTRUCTION);
550
+ await turns.prompt(CONTINUE_INSTRUCTION);
536
551
  }
537
552
  if (!security.state.criticalViolation) try {
538
553
  await agentSession.prompt(REMARK_INSTRUCTION);
@@ -608,11 +623,11 @@ const piBackend = {
608
623
  }
609
624
  },
610
625
  async runTask(inputs) {
611
- const { runPiTask } = await import("./task-FBY3mllc.js");
626
+ const { runPiTask } = await import("./task-DX3eZgBL.js");
612
627
  return runPiTask(inputs);
613
628
  }
614
629
  };
615
630
  //#endregion
616
631
  export { piBackend as a, lastStatusLine as i, buildScrubbedEnv as n, withMode as o, extractText as r, createAioCapture as s, applyOutroMarkers as t };
617
632
 
618
- //# sourceMappingURL=pi-DbEYScTs.js.map
633
+ //# sourceMappingURL=pi-DpWFwz5u.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-DpWFwz5u.js","names":[],"sources":["../src/lib/agent/aio-capture.ts","../src/lib/agent/runner/harness/pi/completion.ts","../src/lib/agent/runner/harness/pi/index.ts"],"sourcesContent":["/**\n * aio-capture — mirror wizard LLM calls into the authenticated project's\n * AI Observability tab as `$ai_generation` events. Gated on `--capture-aio`\n * (dev/test builds only); returns a no-op instance when disabled so the\n * wire-in points stay a no-op with zero overhead.\n *\n * The wizard's LLM calls happen inside subprocesses we don't own (the\n * claude-agent-sdk CLI on the anthropic path, pi's own runtime on pi), so we\n * can't wrap the client with `posthog-node`'s `wrapAnthropic`. Instead, each\n * harness surfaces assistant turns on the way back — the SDK message stream\n * on anthropic, `agentSession.subscribe(message_end)` on pi — and this module\n * composes an `$ai_generation` event from either shape.\n *\n * For the Conversation tab in AIO to render anything, each generation needs\n * `$ai_input` (the messages the model saw when it produced this turn). The\n * initial prompt is passed to the SDK subprocess and never echoed back on\n * the stream, so callers must hand it to `setInitialPrompt` before the run\n * starts. From there we track user/assistant turns as they flow through the\n * stream, snapshotting the running conversation into each generation's\n * `$ai_input` and firing `$ai_input_state` / `$ai_output_state` on the\n * terminal `$ai_trace` event.\n *\n * POSTs are fire-and-forget: failures are debug-logged and never surfaced to\n * the main agent flow. Losing an AIO event must never break a run.\n */\n\nimport { logToFile } from '@utils/debug';\nimport { VERSION } from '@lib/version';\n\n/** Conversation turn shape both harnesses normalize to. Matches Anthropic\n * message role/content conventions, which is also what AIO's Conversation\n * tab knows how to render. */\ntype Turn = { role: 'user' | 'assistant'; content: unknown };\n\n/** Common shape both harness transforms emit; fed to the shared POST. */\ntype LLMTurn = {\n provider: 'anthropic' | 'openai';\n model: string;\n /** Conversation up to (but not including) this assistant turn — the\n * messages the model saw. Sent as `$ai_input`. */\n input: Turn[];\n /** Content blocks (text + tool_use), passed through as $ai_output_choices. */\n outputChoices: unknown[];\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n /** Wall-clock ms since the previous assistant turn on this stream. */\n latencyMs: number;\n generationId?: string;\n isError: boolean;\n};\n\nexport type AioCapture = {\n /** Set the initial prompt the harness is about to send to the LLM. The\n * wizard passes this into the SDK subprocess out-of-band, so it never\n * appears on the return message stream — the caller must hand it to us\n * explicitly if we want `$ai_input` to include it. Safe to call multiple\n * times: latest wins, prior conversation state resets. */\n setInitialPrompt(prompt: string): void;\n /** Called for every SDK message on the anthropic harness stream. */\n captureFromAnthropicSDKMessage(msg: unknown): void;\n /** Called for every subscribe event on the pi harness. */\n captureFromPiMessageEndEvent(event: unknown): void;\n};\n\nconst noop = (_: unknown): void => undefined;\nconst NOOP: AioCapture = {\n setInitialPrompt: noop,\n captureFromAnthropicSDKMessage: noop,\n captureFromPiMessageEndEvent: noop,\n};\n\nexport function createAioCapture(args: {\n enabled: boolean;\n projectApiKey: string;\n apiHost: string;\n /** Trace tags from `buildRunTags` (program_id, integration, run_id, build, skill_id). */\n runTags: Record<string, string>;\n}): AioCapture {\n if (!args.enabled || !args.projectApiKey || !args.apiHost) return NOOP;\n\n const { projectApiKey, apiHost, runTags } = args;\n const distinctId = `wizard-cli-${VERSION}`;\n const captureUrl = `${apiHost.replace(/\\/$/, '')}/capture/`;\n const runStartAt = Date.now();\n // Latency is measured against the previous assistant turn on this stream —\n // a rough proxy for time-to-first-token that doesn't require SDK-internal\n // timings. Reset per createAioCapture (once per agent run).\n let prevTurnAt = runStartAt;\n // Fire the top-level `$ai_trace` event at most once per instance. Both\n // harnesses can emit terminal signals, and pi in particular may emit\n // multiple `agent_end` events across nudges — first-wins keeps trace\n // metadata stable in AIO.\n let traceEnded = false;\n\n // Running conversation state — grows as user and assistant turns flow\n // through the stream. Snapshotted into `$ai_input` on each generation.\n let initialPrompt: string | undefined;\n let conversation: Turn[] = [];\n let lastAssistantContent: unknown[] | undefined;\n\n const postEvent = (\n event: string,\n properties: Record<string, unknown>,\n ): void => {\n const body = {\n api_key: projectApiKey,\n event,\n distinct_id: distinctId,\n properties: {\n $ai_trace_id: runTags.run_id ?? '',\n ...runTags,\n ...properties,\n },\n timestamp: new Date().toISOString(),\n };\n\n // Fire-and-forget. `.then` + `.catch` (not `await`) so the caller returns\n // immediately; both branches only log. Errors must never propagate into\n // the agent stream loop.\n fetch(captureUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n .then((res) => {\n if (!res.ok) {\n logToFile(`[aio-capture] POST failed status=${res.status}`);\n }\n })\n .catch((err) => {\n logToFile(\n `[aio-capture] POST error: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n });\n };\n\n const postGeneration = (turn: LLMTurn): void => {\n postEvent('$ai_generation', {\n $ai_provider: turn.provider,\n $ai_model: turn.model,\n $ai_input: turn.input,\n $ai_output_choices: turn.outputChoices,\n $ai_input_tokens: turn.inputTokens ?? 0,\n $ai_output_tokens: turn.outputTokens ?? 0,\n $ai_cache_read_input_tokens: turn.cacheReadTokens ?? 0,\n $ai_cache_creation_input_tokens: turn.cacheCreationTokens ?? 0,\n $ai_latency: turn.latencyMs / 1000,\n $ai_generation_id: turn.generationId ?? '',\n $ai_is_error: turn.isError,\n });\n };\n\n // Emit the top-level `$ai_trace` event. Without this, PostHog builds a\n // pseudo-trace from the generations — the timeline and aggregates still\n // work, but the trace has no readable name and the Conversation tab shows\n // \"No top-level trace event\". Sending this once per run fills that in,\n // and `$ai_input_state` / `$ai_output_state` populate the trace-level\n // Conversation view.\n const sendTraceEnd = (opts: { isError: boolean }): void => {\n if (traceEnded) return;\n traceEnded = true;\n postEvent('$ai_trace', {\n $ai_span_name: runTags.program_id ?? 'wizard-run',\n $ai_latency: (Date.now() - runStartAt) / 1000,\n $ai_is_error: opts.isError,\n $ai_input_state: initialPrompt\n ? [{ role: 'user', content: [{ type: 'text', text: initialPrompt }] }]\n : [],\n $ai_output_state: lastAssistantContent ?? [],\n });\n };\n\n const anthropicAssistantTurn = (msg: unknown): LLMTurn | null => {\n const m = msg as {\n type?: string;\n message?: {\n id?: string;\n model?: string;\n content?: unknown;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n };\n if (m?.type !== 'assistant' || !m.message) return null;\n const now = Date.now();\n const latencyMs = now - prevTurnAt;\n prevTurnAt = now;\n return {\n provider: 'anthropic',\n model: m.message.model ?? 'unknown',\n input: [...conversation],\n outputChoices: Array.isArray(m.message.content) ? m.message.content : [],\n inputTokens: m.message.usage?.input_tokens,\n outputTokens: m.message.usage?.output_tokens,\n cacheReadTokens: m.message.usage?.cache_read_input_tokens,\n cacheCreationTokens: m.message.usage?.cache_creation_input_tokens,\n latencyMs,\n generationId: m.message.id,\n isError: false,\n };\n };\n\n const piAssistantTurn = (event: unknown): LLMTurn | null => {\n const e = event as {\n type?: string;\n message?: {\n id?: string;\n role?: string;\n model?: string;\n content?: unknown;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n };\n // Pi emits message_end for user prompts too — filter to assistant only,\n // mirroring the existing role guard at harness/pi/index.ts:434.\n if (e?.type !== 'message_end' || e.message?.role !== 'assistant') {\n return null;\n }\n const now = Date.now();\n const latencyMs = now - prevTurnAt;\n prevTurnAt = now;\n return {\n provider: 'anthropic',\n model: e.message.model ?? 'unknown',\n input: [...conversation],\n outputChoices: Array.isArray(e.message.content) ? e.message.content : [],\n inputTokens: e.message.usage?.input_tokens,\n outputTokens: e.message.usage?.output_tokens,\n cacheReadTokens: e.message.usage?.cache_read_input_tokens,\n cacheCreationTokens: e.message.usage?.cache_creation_input_tokens,\n latencyMs,\n generationId: e.message.id,\n isError: false,\n };\n };\n\n return {\n setInitialPrompt(prompt) {\n initialPrompt = prompt;\n // Reset conversation to the initial user turn — this is the only way\n // the initial prompt gets into `$ai_input` for the first generation,\n // since the SDK subprocess consumes it internally and doesn't echo it\n // on the return stream.\n conversation = [\n { role: 'user', content: [{ type: 'text', text: prompt }] },\n ];\n lastAssistantContent = undefined;\n },\n captureFromAnthropicSDKMessage(msg) {\n try {\n // User turns (tool_result blocks between assistant turns) accumulate\n // in the conversation so the next assistant generation carries the\n // full context the model actually saw.\n const m = msg as {\n type?: string;\n message?: { role?: string; content?: unknown };\n is_error?: boolean;\n };\n if (m?.type === 'user' && m.message) {\n conversation.push({\n role: 'user',\n content: m.message.content ?? [],\n });\n }\n const turn = anthropicAssistantTurn(msg);\n if (turn) {\n postGeneration(turn);\n // Push the assistant turn AFTER posting so the current generation's\n // $ai_input is the conversation as the model saw it (not including\n // its own response), and later turns include this one.\n conversation.push({\n role: 'assistant',\n content: turn.outputChoices,\n });\n lastAssistantContent = turn.outputChoices;\n }\n // Terminal: SDK emits a `result` message at end of run.\n if (m?.type === 'result') {\n sendTraceEnd({ isError: !!m.is_error });\n }\n } catch (err) {\n logToFile(\n `[aio-capture] anthropic compose failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n },\n captureFromPiMessageEndEvent(event) {\n try {\n // Pi's subscribe callback surfaces both user and assistant\n // message_end events. Accumulate user turns the same way as the\n // anthropic path so `$ai_input` matches the model's view.\n const e = event as {\n type?: string;\n message?: { role?: string; content?: unknown };\n willRetry?: boolean;\n };\n if (\n e?.type === 'message_end' &&\n e.message?.role === 'user' &&\n e.message\n ) {\n conversation.push({\n role: 'user',\n content: e.message.content ?? [],\n });\n }\n const turn = piAssistantTurn(event);\n if (turn) {\n postGeneration(turn);\n conversation.push({\n role: 'assistant',\n content: turn.outputChoices,\n });\n lastAssistantContent = turn.outputChoices;\n }\n // Terminal: pi emits `agent_end` when the session's prompt() resolves.\n if (e?.type === 'agent_end' && !e.willRetry) {\n sendTraceEnd({ isError: false });\n }\n } catch (err) {\n logToFile(\n `[aio-capture] pi compose failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n },\n };\n}\n","import { AgentErrorType } from '@lib/agent/signals';\n\n/** Which completion guard should fail a pi run, or undefined for a clean finish. */\nexport function completionFailure(args: {\n toolCalls: number;\n openTasks: boolean;\n}): AgentErrorType | undefined {\n // No tool call at all — the project was never touched.\n if (args.toolCalls === 0) return AgentErrorType.NO_PROGRESS;\n // Acted but left tasks in its own plan unfinished (skill install not required).\n if (args.openTasks) return AgentErrorType.INCOMPLETE_TASKS;\n return undefined;\n}\n","/**\n * The `pi` backend — the challenger. Drives pi.dev's coding agent\n * (`@earendil-works/pi-coding-agent`) against the PostHog LLM gateway, behind\n * `wizard-orchestrator`. It owns the agent loop and model transport; prompt\n * assembly, error routing, and the outro stay in `linear.ts`, shared with the\n * `anthropic` control.\n *\n * Transport: the gateway is registered as an `anthropic-messages` provider\n * (same protocol the claude-agent-sdk path uses), bearer auth, Bedrock-fallback\n * + wizard metadata/flag headers, model id matched to `anthropic` for a clean\n * A/B. Security parity (canUseTool + YARA) and skills/MCP discovery are\n * follow-ups (#525, #524 skills) — v1 uses pi's built-in coding tools.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { getUI } from '@ui';\nimport { getLogFilePath, logToFile } from '@utils/debug';\nimport {\n Harness,\n Sequence,\n WIZARD_REMARK_EVENT_NAME,\n WIZARD_USER_AGENT,\n} from '@lib/constants';\nimport { analytics } from '@utils/analytics';\nimport { AgentErrorType } from '@lib/agent/agent-interface';\nimport { AgentSignals, REMARK_INSTRUCTION } from '@lib/agent/signals';\nimport { AgentOutputSignals } from '@lib/agent/output-signals';\nimport { assembleCommandments } from '../../switchboard/commandments';\nimport { gatewayAuth, type GatewayAuth } from '@lib/gateway-session';\nimport {\n buildGatewayProvider,\n GATEWAY_PROVIDER,\n withGatewayRemint,\n} from './gateway';\nimport { createAioCapture } from '@lib/agent/aio-capture';\nimport type {\n AgentResult,\n AgentHarness,\n BackendRunInputs,\n TaskRunInputs,\n} from '../types';\nimport type { BootstrapResult } from '@lib/agent/runner/shared/types';\nimport type { TaskStore } from './tasks';\nimport { completionFailure } from './completion';\n\n/** Injects the MCP server `instructions` pi-mcp-adapter drops (project env, skill steer, tool domains) into the system prompt, falling back to a bootstrap-derived project block when the warm-connect captured none. */\nfunction piMcpContext(\n boot: BootstrapResult,\n instructions?: string,\n posthogMcp = true,\n): string {\n // No tool, no block. The fallback below names `posthog_exec`, so emitting it\n // after a failed handshake points the agent at a tool that is not registered.\n if (!posthogMcp) return '';\n if (instructions) {\n // Heading + verbatim server instructions (see PR #862 for a full sample).\n return ['', '## PostHog MCP server', instructions].join('\\n');\n }\n const project = boot.project?.name\n ? `${boot.project.name} (id ${boot.credentials.projectId})`\n : `id ${boot.credentials.projectId}`;\n // Fallback: a `## PostHog project` block with name/id, host, region.\n return [\n '',\n '## PostHog project',\n 'Your `posthog_exec` calls run against this project:',\n `- Project: ${project}`,\n `- Host: ${boot.credentials.host.apiHost}`,\n `- Region: ${boot.credentials.host.region}`,\n ].join('\\n');\n}\n\n/**\n * The ONLY environment variables pi's tool subprocesses (bash → npm/pip/…) are\n * allowed to see. Everything else — every secret (POSTHOG_PERSONAL_API_KEY,\n * ANTHROPIC_*, AWS_*), every ambient credential, the parent process's whole env\n * — is dropped before a child is spawned. pi's own gateway auth is programmatic\n * (the access token never lives in env), so a minimal env costs the agent\n * nothing while closing the leak that exposed the key before. Kept to what a\n * package manager genuinely needs to run.\n */\nconst ALLOWED_SUBPROCESS_ENV_KEYS = [\n 'PATH',\n 'HOME',\n 'SHELL',\n 'USER',\n 'LOGNAME',\n 'TMPDIR',\n 'TMP',\n 'TEMP',\n 'TERM',\n 'LANG',\n 'LC_ALL',\n 'LC_CTYPE',\n 'NODE_EXTRA_CA_CERTS',\n 'SSL_CERT_FILE',\n 'SSL_CERT_DIR',\n 'HTTP_PROXY',\n 'HTTPS_PROXY',\n 'NO_PROXY',\n 'http_proxy',\n 'https_proxy',\n 'no_proxy',\n];\n\n/** A fresh subprocess env holding only the allowlisted keys present in process.env. */\nexport function buildScrubbedEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {};\n for (const key of ALLOWED_SUBPROCESS_ENV_KEYS) {\n const value = process.env[key];\n if (value !== undefined) env[key] = value;\n }\n return env;\n}\n\n/**\n * Tag a tool with an execution mode (mutates + returns it). Read-only tools are\n * `parallel` so a single turn that batches independent reads/searches runs them\n * at once; mutating/install tools are `sequential` so a batch never races writes\n * or concurrent installs. pi-agent-core runs a batch in parallel only when no\n * tool in it is `sequential`.\n */\nexport function withMode<T>(tool: T, mode: 'sequential' | 'parallel'): T {\n (tool as { executionMode?: 'sequential' | 'parallel' }).executionMode = mode;\n return tool;\n}\n\n/** Pull plain text out of a pi AgentMessage (content is text/image blocks). */\nexport function extractText(message: unknown): string {\n const content = (message as { content?: unknown })?.content;\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .filter((c): c is { type: string; text: string } => {\n const block = c as { type?: string; text?: unknown };\n return block?.type === 'text' && typeof block.text === 'string';\n })\n .map((c) => c.text)\n .join('');\n }\n return '';\n}\n\n/**\n * Surface `[DASHBOARD_URL]` / `[NOTEBOOK_URL]` markers the agent prints (after\n * the MCP creates them) into the outro link, mirroring the anthropic path's\n * signal parsing (#9). The marker carries the URL the MCP returned.\n */\nexport function applyOutroMarkers(textBlock: string): void {\n const markers: Array<[string, (url: string) => void]> = [\n [AgentSignals.DASHBOARD_URL, (url) => getUI().setDashboardUrl(url)],\n [AgentSignals.NOTEBOOK_URL, (url) => getUI().setNotebookUrl(url)],\n ];\n for (const [marker, apply] of markers) {\n const idx = textBlock.indexOf(marker);\n if (idx === -1) continue;\n const url = textBlock\n .slice(idx + marker.length)\n .trim()\n .split(/\\s/)[0];\n if (url) apply(url);\n }\n}\n\n/**\n * The text of the last `[STATUS] …` line in a block, if any. Last wins so the\n * spinner shows the most recent action when a turn prints several.\n */\nexport function lastStatusLine(textBlock: string): string | undefined {\n let status: string | undefined;\n for (const line of textBlock.split('\\n')) {\n const idx = line.indexOf(AgentSignals.STATUS);\n if (idx !== -1) {\n status = line.slice(idx + AgentSignals.STATUS.length).trim();\n }\n }\n return status || undefined;\n}\n\n/** Cap on completion-guard re-prompts while tasks remain open (see the run loop). */\nconst MAX_CONTINUE_NUDGES = 20;\n\n/** Nudge re-sent when the agent stops early with tasks still open. */\nconst CONTINUE_INSTRUCTION =\n 'You still have open tasks in your list (not all are marked `completed`). Do not stop — pick up the next `in_progress` or `pending` task and keep working until every task is `completed`. Continue now.';\n\n/** True while any task in the store is not yet `completed`. */\nfunction hasOpenTasks(store: TaskStore): boolean {\n for (const t of store.values()) if (t.status !== 'completed') return true;\n return false;\n}\n\nexport const piBackend: AgentHarness = {\n name: Harness.pi,\n\n async run(inputs: BackendRunInputs): Promise<AgentResult> {\n const { session, boot, prompt, spinner, config, programConfig } = inputs;\n const modelId = inputs.model;\n\n const capture = createAioCapture({\n enabled: session.captureAio,\n projectApiKey: boot.credentials.projectApiKey,\n apiHost: boot.credentials.host.apiHost,\n runTags: boot.wizardMetadata,\n });\n\n // Init banner (parity #5).\n getUI().log.step('Initializing Wizard agent...');\n getUI().log.step(`Verbose logs: ${getLogFilePath()}`);\n getUI().log.success(\"Agent initialized. Let's get cooking!\");\n\n spinner.start(config.spinnerMessage ?? 'Customizing your PostHog setup...');\n\n // Same `agent completed`/`agent aborted` shape as anthropic.\n const startTime = Date.now();\n const signals = new AgentOutputSignals();\n let assistantTurns = 0;\n // Tool calls across the whole run. Zero means the agent only ever produced\n // text and never acted — a no-op that leaves the project untouched.\n let toolCalls = 0;\n const runDurations = () => {\n const durationMs = Date.now() - startTime;\n return {\n duration_ms: durationMs,\n duration_seconds: Math.round(durationMs / 1000),\n };\n };\n const captureAborted = () =>\n analytics.wizardCapture('agent aborted', {\n ...runDurations(),\n model: modelId,\n });\n\n try {\n const {\n createAgentSession,\n DefaultResourceLoader,\n SessionManager,\n AuthStorage,\n ModelRegistry,\n getAgentDir,\n createLsToolDefinition,\n createFindToolDefinition,\n createGrepToolDefinition,\n createBashToolDefinition,\n createReadToolDefinition,\n createEditToolDefinition,\n createWriteToolDefinition,\n } = await import('@earendil-works/pi-coding-agent');\n\n // the claude-agent-sdk path. The provider spec is shared with the\n // orchestrator's per-task sessions (gateway.ts). gatewayAuth mints the\n // run's scoped token.\n const refreshAuth = () =>\n gatewayAuth(\n boot.credentials.host,\n boot.credentials.accessToken,\n boot.programId,\n );\n const auth = await refreshAuth();\n const providerInputs = (current: GatewayAuth) => ({\n gatewayUrl: current.gatewayUrl,\n accessToken: current.token,\n teamId: current.teamId,\n legacy: current.legacy,\n wizardMetadata: boot.wizardMetadata,\n wizardFlags: boot.wizardFlags,\n modelId,\n effort: inputs.thinkingLevel,\n });\n const { provider, caps } = buildGatewayProvider(providerInputs(auth));\n const registry = ModelRegistry.inMemory(AuthStorage.create());\n registry.registerProvider(GATEWAY_PROVIDER, provider as never);\n\n const model = registry.find(GATEWAY_PROVIDER, modelId);\n if (!model) {\n return {\n error: AgentErrorType.API_ERROR,\n message: 'pi: gateway model could not be resolved',\n };\n }\n\n // System prompt = wizard commandments. Skip project context files /\n // user extensions / skills so the run is hermetic; skills discovery is a\n // follow-up (#524).\n //\n // Fail-closed security (#525): an extension intercepts EVERY tool call —\n // built-in and custom — and reuses the anthropic policy (canUseTool\n // allowlist + .env fencing + YARA). `noExtensions: true` only suppresses\n // disk-discovered extensions; explicit `extensionFactories` still load,\n // so the fence is on while the target project can't inject its own.\n // Shared flag: true while a wizard_ask overlay is open. The ask tool\n // flips it; the security gate reads it to block Write/Edit meanwhile.\n const askState = { pending: false };\n\n const { createSecurityExtension } = await import('./security');\n const security = createSecurityExtension({\n disallowedTools: programConfig.disallowedTools,\n getWizardAskPending: () => askState.pending,\n triageProvider: boot.triageProvider,\n // Where pi's bash runs; the rm allowance is confined to this tree.\n workingDirectory: session.installDir,\n });\n\n // Pay warlock's WASM-init + rule-compile cost now, off the tool-call\n // path, so the first scanned call doesn't eat cold-start latency.\n const { prewarmYaraScanner } = await import('@lib/yara-hooks');\n void prewarmYaraScanner();\n\n // Wire the real PostHog MCP into pi (#10): load pi's MCP adapter and point\n // it at the hosted MCP the anthropic path uses, so dashboards/insights are\n // created through the sanctioned MCP. Best-effort — if it can't load or\n // connect, the run continues (minus the dashboard step) rather than failing\n // the whole integration. The security factory is always first.\n const extensionFactories = [security.factory] as Array<\n (pi: unknown) => void\n >;\n let mcpCleanup: (() => void) | undefined;\n let mcpInstructions: string | undefined;\n // Whether the agent really got the tool. The commandments below claim\n // `posthog_exec` exists when this is true, so it must track the setup and\n // not the intent — a hardcoded `true` told the agent to call a tool the\n // failed handshake never registered. `task.ts` has always done this.\n let posthogMcp = false;\n try {\n const { setupPostHogMcp, fetchInstructions } = await import('./mcp');\n // Overlaps the network handshake with the adapter's jiti load.\n const instructionsPromise = fetchInstructions(\n boot.credentials.host.mcpUrl,\n boot.credentials.accessToken,\n WIZARD_USER_AGENT,\n );\n const mcp = await setupPostHogMcp({\n mcpUrl: boot.credentials.host.mcpUrl,\n accessToken: boot.credentials.accessToken,\n userAgent: WIZARD_USER_AGENT,\n });\n extensionFactories.push(mcp.extensionFactory);\n mcpCleanup = mcp.cleanup;\n mcpInstructions = await instructionsPromise;\n posthogMcp = true;\n } catch (err) {\n logToFile(`[pi] PostHog MCP setup skipped: ${String(err)}`);\n analytics.wizardCapture('mcp setup failed', {\n harness: 'pi',\n scope: 'run',\n error: String(err).slice(0, 300),\n });\n }\n\n const resourceLoader = new DefaultResourceLoader({\n cwd: session.installDir,\n agentDir: getAgentDir(),\n systemPrompt:\n assembleCommandments({\n program: programConfig.id,\n sequence: Sequence.linear,\n harness: Harness.pi,\n caps: { bash: true, posthogMcp },\n }) +\n '\\n' +\n piMcpContext(boot, mcpInstructions, posthogMcp),\n noExtensions: true,\n noSkills: true,\n noContextFiles: true,\n noPromptTemplates: true,\n noThemes: true,\n extensionFactories,\n });\n await resourceLoader.reload();\n\n // Wizard capabilities as custom tools (pi has no MCP): skill\n // discovery/install + fenced .env edits, same names as the MCP server so\n // the shared prompt is unchanged. pi's built-in Read/Write/Edit/Bash do\n // the code changes. Loaded lazily — it pulls in typebox (ESM), which must\n // stay out of the static module graph so CommonJS unit tests can load the\n // backend seam without parsing it.\n const { createWizardPiTools } = await import('./tools');\n const { createWizardPiTaskTools } = await import('./tasks');\n const { createDispatchAgentTool } = await import('./subagent');\n // Created once so the run loop can read the store for the completion guard.\n const wizardTaskTools = createWizardPiTaskTools();\n // The one bash the agent (and its subagents) may use: every subprocess it\n // spawns gets a scrubbed env, so no secret or ambient variable reaches an\n // `npm install`. Shared with the subagent so the lockdown is inherited.\n const scrubbedBash = withMode(\n createBashToolDefinition(session.installDir, {\n spawnHook: (ctx) => ({ ...ctx, env: buildScrubbedEnv() }),\n }),\n 'sequential',\n );\n\n const customTools = [\n // Built-ins re-registered explicitly. `noTools: 'builtin'` disables pi's\n // defaults so we can supply the env-scrubbed bash above; read/edit/write\n // are the stock definitions. Reads run in parallel so a batched turn of\n // independent reads executes at once; edit/write/bash stay sequential.\n withMode(createReadToolDefinition(session.installDir), 'parallel'),\n withMode(createEditToolDefinition(session.installDir), 'sequential'),\n withMode(createWriteToolDefinition(session.installDir), 'sequential'),\n scrubbedBash,\n // Native ls/find/grep so the agent explores with proper tools instead\n // of fence-blocked `bash {ls/find}` (the profiled retry-spirals came\n // from this gap). Parallel — exploration batches cleanly.\n withMode(createLsToolDefinition(session.installDir), 'parallel'),\n withMode(createFindToolDefinition(session.installDir), 'parallel'),\n withMode(createGrepToolDefinition(session.installDir), 'parallel'),\n ...createWizardPiTools({\n workingDirectory: session.installDir,\n skillsBaseUrl: boot.skillsBaseUrl,\n triageProvider: boot.triageProvider,\n detectPackageManager: config.detectPackageManager,\n // The host ask bridge — lets interactive programs (self-driving) ask\n // the user through pi. Threaded from the runner, same path as the\n // anthropic harness. Absent in CI → the tool errors on call.\n askBridge: inputs.askBridge,\n maxQuestions: config.maxQuestions,\n onAskPendingChange: (pending) => {\n askState.pending = pending;\n },\n // Skip wizard_ask when the program disallows it (bare pi tool names\n // don't match the MCP-prefixed disallow list at the security gate).\n disallowedTools: programConfig.disallowedTools,\n }),\n // Task/todo tools (#526): render the todo list live in the TUI, parity\n // with the anthropic path.\n ...wizardTaskTools.tools,\n // Controlled subagent dispatch (#526): a nested fenced session with a\n // read-only toolset and no dispatch_agent of its own, so it can't\n // escape the fence or recurse.\n createDispatchAgentTool({\n model,\n modelRegistry: registry,\n cwd: session.installDir,\n agentDir: getAgentDir(),\n securityFactory: security.factory as (pi: unknown) => void,\n bashTool: scrubbedBash,\n sdk: { createAgentSession, DefaultResourceLoader, SessionManager },\n }),\n ];\n\n const { session: agentSession } = await createAgentSession({\n model,\n modelRegistry: registry,\n // Reasoning effort from the switchboard capability matrix (undefined =\n // pi's default). Sent as `reasoning_effort` for openai-completions.\n thinkingLevel: caps.thinkingLevel,\n cwd: session.installDir,\n sessionManager: SessionManager.inMemory(session.installDir),\n resourceLoader,\n // Disable the default built-in tools; `customTools` re-registers\n // read/edit/write + an env-scrubbed bash, so no subprocess inherits the\n // host env. Custom + extension tools stay enabled.\n noTools: 'builtin',\n customTools,\n });\n\n // Fire the extension lifecycle — what interactive mode does via\n // rebindCurrentSession. createAgentSession builds the session but does not\n // emit session_start on its own, and the MCP adapter connects on that\n // event; without this its tools report \"MCP not initialized\".\n await agentSession.bindExtensions({});\n\n // A turn that ends on a 401 from an aged bearer re-mints once and\n // continues; pi resolves the provider's apiKey per request, so\n // re-registering is enough.\n const turns = withGatewayRemint({\n session: agentSession,\n registry,\n auth,\n refreshAuth,\n providerInputs,\n continueText: CONTINUE_INSTRUCTION,\n onRemint: () => {\n logToFile('[pi] gateway token renewed after a 401; continuing');\n analytics.wizardCapture('gateway token reminted', { harness: 'pi' });\n },\n });\n\n // Map pi events onto the run spinner + the log file, mirroring the\n // anthropic path's log shape (assistant turns + tool I/O) and driving the\n // single run spinner with one stable status at a time (no overlap).\n const unsubscribe = agentSession.subscribe((event) => {\n // Mirror the turn into AIO. No-op when --capture-aio is off. Runs\n // before the role guard so the module's own filter (assistant-only)\n // stays the single source of truth for what's captured.\n capture.captureFromPiMessageEndEvent(event);\n\n switch (event.type) {\n case 'message_end': {\n // User prompts also emit message_end; only assistant turns count.\n if ((event.message as { role?: string })?.role !== 'assistant') {\n break;\n }\n assistantTurns += 1;\n turns.noteAssistantTurn(event.message);\n const assistant = extractText(event.message).trim();\n if (assistant) {\n logToFile(`[pi] assistant: ${assistant.slice(0, 1000)}`);\n applyOutroMarkers(assistant);\n // Surface [STATUS] lines into the live spinner + status history,\n // mirroring the anthropic path — pi otherwise drops them.\n const statusText = lastStatusLine(assistant);\n if (statusText) {\n getUI().pushStatus(statusText);\n spinner.message(statusText);\n }\n for (const line of assistant.split('\\n')) signals.push(line);\n }\n break;\n }\n case 'tool_execution_start': {\n toolCalls += 1;\n const args = JSON.stringify(event.args ?? {}).slice(0, 200);\n logToFile(`[pi] → ${event.toolName} ${args}`);\n // Don't surface raw tool names in the spinner — the anthropic path\n // doesn't, and it reads as noise. The Task panel (syncTodos) is the\n // visible progress, matching the anthropic presentation.\n break;\n }\n case 'tool_execution_end': {\n // Log every result in full, matching the anthropic path's\n // SDK-message logging. Call-only logs make failed runs\n // undiagnosable: a tool can fail (or return something the model\n // misreads) with no trace of what came back.\n logToFile(\n `[pi] ${event.isError ? '✗' : '←'} ${event.toolName}: ${\n typeof event.result === 'string'\n ? event.result\n : JSON.stringify(event.result ?? '')\n }`,\n );\n break;\n }\n case 'agent_end': {\n logToFile(`[pi] agent_end (willRetry=${String(event.willRetry)})`);\n break;\n }\n default:\n break;\n }\n });\n\n // Seed AIO capture with the initial prompt so the first assistant\n // turn's `$ai_input` includes it — pi's subscribe stream doesn't emit\n // a message_end for the initial prompt, only for tool_result user\n // turns that follow.\n capture.setInitialPrompt(prompt);\n\n try {\n // Non-streaming: resolves when the agent run completes. Throws if no\n // model/api key, or on a transport error.\n await turns.prompt(prompt);\n\n // Completion guard: pi's prompt() resolves the moment the model returns\n // a turn with no tool call (e.g. a lone [STATUS] line), even mid-plan.\n // While tasks remain open and we're under the cap, nudge it to continue.\n let continueNudges = 0;\n while (\n continueNudges < MAX_CONTINUE_NUDGES &&\n !security.state.criticalViolation &&\n hasOpenTasks(wizardTaskTools.store)\n ) {\n continueNudges += 1;\n logToFile(\n `[pi] completion guard: tasks still open, nudge ${continueNudges}/${MAX_CONTINUE_NUDGES}`,\n );\n await turns.prompt(CONTINUE_INSTRUCTION);\n }\n\n // Best-effort remark ask — a failed turn never fails a successful run.\n if (!security.state.criticalViolation) {\n try {\n await agentSession.prompt(REMARK_INSTRUCTION);\n } catch (err) {\n logToFile(`[pi] remark request failed: ${String(err)}`);\n }\n }\n } finally {\n unsubscribe();\n mcpCleanup?.();\n }\n\n // A latched post-scan violation terminates the run as a YARA violation,\n // matching the anthropic path's AgentErrorType.YARA_VIOLATION.\n if (security.state.criticalViolation) {\n spinner.stop('Security violation detected');\n logToFile(\n `[pi] terminated: YARA violation (blocked ${security.state.blockedCount} call(s))`,\n );\n captureAborted();\n return { error: AgentErrorType.YARA_VIOLATION };\n }\n\n // pi ends a run on any tool-call-less turn, so guard against a hollow\n // success reaching the outro (nothing done, or stopped mid-plan).\n const openTasks = hasOpenTasks(wizardTaskTools.store);\n const failure = completionFailure({ toolCalls, openTasks });\n if (failure === AgentErrorType.NO_PROGRESS) {\n spinner.stop('Agent made no changes');\n logToFile(\n `[pi] no progress: ${assistantTurns} assistant turn(s), 0 tool calls`,\n );\n analytics.wizardCapture('agent no progress', {\n assistant_turns: assistantTurns,\n });\n captureAborted();\n return { error: failure };\n }\n if (failure === AgentErrorType.INCOMPLETE_TASKS) {\n spinner.stop('Agent stopped before finishing');\n logToFile('[pi] incomplete: tasks left open');\n analytics.wizardCapture('agent incomplete tasks', { open_tasks: true });\n captureAborted();\n return { error: failure };\n }\n\n const remark = signals.remark();\n if (remark) {\n analytics.capture(WIZARD_REMARK_EVENT_NAME, { remark });\n }\n\n // A failed install_skill is non-fatal — the agent continues best-effort\n // without the skill — but every such run must be measurable.\n const skillFailure = signals.skillInstallFailure();\n if (skillFailure !== undefined) {\n analytics.wizardCapture('agent continued without skill', {\n detail: skillFailure,\n });\n }\n\n // The skill plans events into .posthog-events.json then asks to remove it\n // on completion; pi's `rm` is fence-blocked, so the agent can't — clean it\n // up host-side rather than leave a stale (often empty) artifact (#15).\n try {\n const planFile = path.join(session.installDir, '.posthog-events.json');\n if (fs.existsSync(planFile)) await fs.promises.rm(planFile);\n } catch (err) {\n logToFile(`[pi] .posthog-events.json cleanup skipped: ${String(err)}`);\n }\n\n const stats = agentSession.getSessionStats();\n analytics.wizardCapture('agent completed', {\n ...runDurations(),\n model: modelId,\n num_turns: assistantTurns,\n // API-reported tokens only; no total_cost_usd — the API returns no\n // cost, and $ai_generation already prices the run authoritatively.\n input_tokens: stats.tokens.input,\n output_tokens: stats.tokens.output,\n cache_creation_input_tokens: stats.tokens.cacheWrite,\n cache_read_input_tokens: stats.tokens.cacheRead,\n });\n spinner.stop(config.successMessage ?? 'PostHog integration complete');\n return {};\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[pi] run error: ${message}`);\n spinner.stop(config.errorMessage ?? `${config.integrationLabel} failed`);\n getUI().log.error(`pi backend error: ${message}`);\n captureAborted();\n\n const lower = message.toLowerCase();\n if (lower.includes('rate limit') || lower.includes('429')) {\n return { error: AgentErrorType.RATE_LIMIT, message };\n }\n return { error: AgentErrorType.API_ERROR, message };\n }\n },\n\n // Orchestrator mode: one fresh pi session per seed plan / drained task, with\n // the in-process queue tools registered as pi custom tools. Lazily imported —\n // task.ts pulls in typebox (ESM), which must stay out of the static module\n // graph so CommonJS unit tests can load the backend seam without parsing it.\n async runTask(inputs: TaskRunInputs): Promise<AgentResult> {\n const { runPiTask } = await import('./task');\n return runPiTask(inputs);\n },\n};\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import { _t as VERSION, l as WIZARD_LOG_FILE, v as getBlockingServiceKeys } from "./debug-D0k3Quos.js";
1
+ import { l as WIZARD_LOG_FILE, mt as VERSION, v as getBlockingServiceKeys } from "./debug-ECdmmlDM.js";
2
2
  import "./wizard-session-GdDN_aMS.js";
3
- import { l as HostResolution } from "./setup-utils-CzMg2Vpy.js";
4
- import { h as Icons, m as Colors } from "./posthog-integration-BG5Y9Fb4.js";
5
- import { A as getContentBlocks, d as PROGRAM_REGISTRY, o as ConfirmButton, p as getProgramConfig, t as PickerMenu } from "./bin.js";
6
- import { t as WizardStore } from "./store-DDrR7nF6.js";
7
- import { A as ViewportTooSmall, B as SplitView, C as VisualizerTab, D as HNViewer, E as ContentSequencer, F as ModalOverlay, I as ConfirmationInput, L as GroupedPickerMenu, M as LogViewer, O as TabContainer, R as ProgressList, S as ServiceHealthList, T as LearnCard, V as CardLayout, _ as TAILORED_ROLES, c as SlackConnectScreen, d as AuditChecksViewer, h as assembleProfile, j as EventPlanViewer, k as ScreenContainer, l as AUDIT_AREA_SLIDES, m as McpSuggestedPromptsScreen, n as releaseTerminal, o as OutroScreen, p as seededProfile, r as AiOptInRequiredScreen, t as enterDarkTerminal, v as McpScreen, w as TipsCard, y as IssueTable, z as LoadingBox } from "./terminal-CVgx_zHz.js";
3
+ import { l as HostResolution } from "./setup-utils-CCphwDIz.js";
4
+ import { h as Icons, m as Colors } from "./posthog-integration-CxvkKY1j.js";
5
+ import { f as PROGRAM_REGISTRY, j as getContentBlocks, m as getProgramConfig, o as ConfirmButton, t as PickerMenu } from "./bin.js";
6
+ import { t as WizardStore } from "./store-BhcCTIn4.js";
7
+ import { A as ViewportTooSmall, B as SplitView, C as VisualizerTab, D as HNViewer, E as ContentSequencer, F as ModalOverlay, I as ConfirmationInput, L as GroupedPickerMenu, M as LogViewer, O as TabContainer, R as ProgressList, S as ServiceHealthList, T as LearnCard, V as CardLayout, _ as TAILORED_ROLES, c as SlackConnectScreen, d as AuditChecksViewer, h as assembleProfile, j as EventPlanViewer, k as ScreenContainer, l as AUDIT_AREA_SLIDES, m as McpSuggestedPromptsScreen, n as releaseTerminal, o as OutroScreen, p as seededProfile, r as AiOptInRequiredScreen, t as enterDarkTerminal, v as McpScreen, w as TipsCard, y as IssueTable, z as LoadingBox } from "./terminal-CpVFsbGu.js";
8
8
  import * as fs$1 from "fs";
9
9
  import * as path$1 from "path";
10
10
  import * as os from "os";
@@ -780,7 +780,6 @@ const MOCK_CONFIRMED_OUTAGE = {
780
780
  },
781
781
  cloudflareOverall: HEALTHY,
782
782
  cloudflareComponents: { status: "healthy" },
783
- llmGateway: HEALTHY,
784
783
  mcp: HEALTHY,
785
784
  skillsOrigin: HEALTHY
786
785
  };
@@ -793,10 +792,6 @@ const MOCK_NO_CONNECTION = {
793
792
  npmComponents: { status: "healthy" },
794
793
  cloudflareOverall: HEALTHY,
795
794
  cloudflareComponents: { status: "healthy" },
796
- llmGateway: {
797
- status: "no-connection",
798
- error: "getaddrinfo ENOTFOUND gateway.us.posthog.com"
799
- },
800
795
  mcp: {
801
796
  status: "no-connection",
802
797
  error: "fetch failed"
@@ -2555,4 +2550,4 @@ function runPlayground() {
2555
2550
  //#endregion
2556
2551
  export { runPlayground };
2557
2552
 
2558
- //# sourceMappingURL=playground-xa1G6pym.js.map
2553
+ //# sourceMappingURL=playground-BtTCVaSD.js.map