@posthog/wizard 2.67.0 → 2.69.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 (104) hide show
  1. package/dist/{add-mcp-server-to-clients-DHTRbyJX.js → add-mcp-server-to-clients-Cl2HBuxp.js} +4 -4
  2. package/dist/{add-mcp-server-to-clients-DHTRbyJX.js.map → add-mcp-server-to-clients-Cl2HBuxp.js.map} +1 -1
  3. package/dist/{agent-interface-tM_b0l__.js → agent-interface-CI89BrWE.js} +301 -51
  4. package/dist/agent-interface-CI89BrWE.js.map +1 -0
  5. package/dist/{agent-prompt-loader-BSMh5bfD.js → agent-prompt-loader-Dc1g5Oub.js} +5 -5
  6. package/dist/{agent-prompt-loader-BSMh5bfD.js.map → agent-prompt-loader-Dc1g5Oub.js.map} +1 -1
  7. package/dist/{agent-runner-DD65OMkB.js → agent-runner-D5dhuE4z.js} +38 -18
  8. package/dist/agent-runner-D5dhuE4z.js.map +1 -0
  9. package/dist/{analytics-CtIYzkK4.js → analytics-D90QbLf5.js} +2 -2
  10. package/dist/{analytics-CtIYzkK4.js.map → analytics-D90QbLf5.js.map} +1 -1
  11. package/dist/analytics-Dmf_Jm3K.js +2 -0
  12. package/dist/{api-BJft9v6K.js → api-BHhrT6wb.js} +3 -3
  13. package/dist/{api-BJft9v6K.js.map → api-BHhrT6wb.js.map} +1 -1
  14. package/dist/bin.js +51 -51
  15. package/dist/{bounded-fs-BWqoFQvQ.js → bounded-fs-BhlVkP1r.js} +3 -3
  16. package/dist/{bounded-fs-BWqoFQvQ.js.map → bounded-fs-BhlVkP1r.js.map} +1 -1
  17. package/dist/{ci-install-BXGnVI7T.js → ci-install-94wC3a4K.js} +5 -5
  18. package/dist/{ci-install-BXGnVI7T.js.map → ci-install-94wC3a4K.js.map} +1 -1
  19. package/dist/{debug-BsHD83Vy.js → debug-CifTS9lQ.js} +3 -3
  20. package/dist/{debug-BsHD83Vy.js.map → debug-CifTS9lQ.js.map} +1 -1
  21. package/dist/{debug-mO3yg4Z7.js → debug-DtixqVEY.js} +1 -1
  22. package/dist/{env-api-key-DS0ghlcO.js → env-api-key-CwhtZrik.js} +2 -2
  23. package/dist/{env-api-key-DS0ghlcO.js.map → env-api-key-CwhtZrik.js.map} +1 -1
  24. package/dist/environment-DhacWZf7.js +44 -0
  25. package/dist/environment-DhacWZf7.js.map +1 -0
  26. package/dist/{errors-BHervYGs.js → errors-BSdz2lsl.js} +3 -2
  27. package/dist/errors-BSdz2lsl.js.map +1 -0
  28. package/dist/{file-watcher-D1bdo9mq.js → file-watcher-L28OpUV2.js} +2 -2
  29. package/dist/{file-watcher-D1bdo9mq.js.map → file-watcher-L28OpUV2.js.map} +1 -1
  30. package/dist/{headless-ui-6QuByWZ_.js → headless-ui-DNcOVJxU.js} +2 -2
  31. package/dist/{headless-ui-6QuByWZ_.js.map → headless-ui-DNcOVJxU.js.map} +1 -1
  32. package/dist/{interactive-DUpW84WU.js → interactive-DlNrV77o.js} +2 -2
  33. package/dist/{interactive-DUpW84WU.js.map → interactive-DlNrV77o.js.map} +1 -1
  34. package/dist/{mcp-CHo9h-WV.js → mcp-CJEem9qs.js} +2 -2
  35. package/dist/{mcp-CHo9h-WV.js.map → mcp-CJEem9qs.js.map} +1 -1
  36. package/dist/{mcp-prompt-streaming-CHRPxxd0.js → mcp-prompt-streaming-DER7MG3q.js} +13 -12
  37. package/dist/mcp-prompt-streaming-DER7MG3q.js.map +1 -0
  38. package/dist/{non-interactive-Cr-chffe.js → non-interactive-CbvniKHm.js} +3 -3
  39. package/dist/{non-interactive-Cr-chffe.js.map → non-interactive-CbvniKHm.js.map} +1 -1
  40. package/dist/{orchestrator-tools-Tx18_TMb.js → orchestrator-tools-Czf3Wo_y.js} +3 -3
  41. package/dist/{orchestrator-tools-Tx18_TMb.js.map → orchestrator-tools-Czf3Wo_y.js.map} +1 -1
  42. package/dist/{package-manager-CLfc31yf.js → package-manager-CNNlFA2q.js} +2 -2
  43. package/dist/{package-manager-CLfc31yf.js.map → package-manager-CNNlFA2q.js.map} +1 -1
  44. package/dist/{pi-RlnYUHdb.js → pi-kpN-bO9z.js} +17 -14
  45. package/dist/pi-kpN-bO9z.js.map +1 -0
  46. package/dist/{playground-DQ633rje.js → playground-ZYaQmfBa.js} +7 -7
  47. package/dist/{playground-DQ633rje.js.map → playground-ZYaQmfBa.js.map} +1 -1
  48. package/dist/{posthog-DSn9bIZc.js → posthog-D1zHPgYJ.js} +2 -2
  49. package/dist/{posthog-DSn9bIZc.js.map → posthog-D1zHPgYJ.js.map} +1 -1
  50. package/dist/{posthog-integration-DFfBRGOC.js → posthog-integration-DdeIUkYw.js} +17 -16
  51. package/dist/posthog-integration-DdeIUkYw.js.map +1 -0
  52. package/dist/{provisioning-Cvy_vQHV.js → provisioning-e3roaLgp.js} +3 -3
  53. package/dist/{provisioning-Cvy_vQHV.js.map → provisioning-e3roaLgp.js.map} +1 -1
  54. package/dist/{queue-tools-BC9HxOV6.js → queue-tools-zrqCiy6q.js} +3 -3
  55. package/dist/{queue-tools-BC9HxOV6.js.map → queue-tools-zrqCiy6q.js.map} +1 -1
  56. package/dist/{registry-DCAElOyj.js → registry-C1t8v5tE.js} +5 -5
  57. package/dist/{registry-DCAElOyj.js.map → registry-C1t8v5tE.js.map} +1 -1
  58. package/dist/{security-CuSX3XVo.js → security-CIfhIscL.js} +5 -5
  59. package/dist/{security-CuSX3XVo.js.map → security-CIfhIscL.js.map} +1 -1
  60. package/dist/{setup-utils-D1tv0v_R.js → setup-utils-B_06xag2.js} +9 -9
  61. package/dist/{setup-utils-D1tv0v_R.js.map → setup-utils-B_06xag2.js.map} +1 -1
  62. package/dist/{start-tui-B5YfmqNr.js → start-tui-BafJXVNT.js} +20 -20
  63. package/dist/{start-tui-B5YfmqNr.js.map → start-tui-BafJXVNT.js.map} +1 -1
  64. package/dist/{steps-CLaSMwfR.js → steps-DR-Yo_IT.js} +7 -7
  65. package/dist/{steps-CLaSMwfR.js.map → steps-DR-Yo_IT.js.map} +1 -1
  66. package/dist/{store-DzEgsAPN.js → store-DSUCWMRO.js} +5 -5
  67. package/dist/{store-DzEgsAPN.js.map → store-DSUCWMRO.js.map} +1 -1
  68. package/dist/{subagent-BUV6aD7p.js → subagent-DjZM3G7y.js} +2 -2
  69. package/dist/{subagent-BUV6aD7p.js.map → subagent-DjZM3G7y.js.map} +1 -1
  70. package/dist/{task-GnWId75q.js → task-Czzz3tzt.js} +18 -15
  71. package/dist/task-Czzz3tzt.js.map +1 -0
  72. package/dist/{task-stream-DSzvwJrD.js → task-stream-uxG6wJfj.js} +6 -6
  73. package/dist/{task-stream-DSzvwJrD.js.map → task-stream-uxG6wJfj.js.map} +1 -1
  74. package/dist/{tasks-BO0W8ocx.js → tasks-CVmG8qFw.js} +2 -2
  75. package/dist/{tasks-BO0W8ocx.js.map → tasks-CVmG8qFw.js.map} +1 -1
  76. package/dist/{telemetry-Vi9dWddJ.js → telemetry-B1VEXHpL.js} +3 -3
  77. package/dist/{telemetry-Vi9dWddJ.js.map → telemetry-B1VEXHpL.js.map} +1 -1
  78. package/dist/{terminal-B5wZK7aS.js → terminal-Czuo0x8i.js} +12 -12
  79. package/dist/{terminal-B5wZK7aS.js.map → terminal-Czuo0x8i.js.map} +1 -1
  80. package/dist/{tools-C9cNluqc.js → tools-DOZg9n3A.js} +10 -7
  81. package/dist/tools-DOZg9n3A.js.map +1 -0
  82. package/dist/{wizard-abort-BsNbguJt.js → wizard-abort-BZOeapsf.js} +1 -1
  83. package/dist/{wizard-abort-CGv3lVxw.js → wizard-abort-CFMdj6sZ.js} +5 -5
  84. package/dist/{wizard-abort-CGv3lVxw.js.map → wizard-abort-CFMdj6sZ.js.map} +1 -1
  85. package/dist/{wizard-session-Cex1BiXs.js → wizard-session-C_7r3-rO.js} +2 -1
  86. package/dist/wizard-session-C_7r3-rO.js.map +1 -0
  87. package/dist/{wizard-session-DHbUcjI7.js → wizard-session-D1KQqUml.js} +1 -1
  88. package/dist/yara-hooks-BhNAWw7W.js +2 -0
  89. package/dist/{yara-hooks-DZIVzhA6.js → yara-hooks-CmQT-oBy.js} +4 -4
  90. package/dist/{yara-hooks-DZIVzhA6.js.map → yara-hooks-CmQT-oBy.js.map} +1 -1
  91. package/package.json +1 -1
  92. package/dist/agent-interface-tM_b0l__.js.map +0 -1
  93. package/dist/agent-runner-DD65OMkB.js.map +0 -1
  94. package/dist/analytics-B4Igh5nv.js +0 -2
  95. package/dist/environment-C7CKGIOE.js +0 -22
  96. package/dist/environment-C7CKGIOE.js.map +0 -1
  97. package/dist/errors-BHervYGs.js.map +0 -1
  98. package/dist/mcp-prompt-streaming-CHRPxxd0.js.map +0 -1
  99. package/dist/pi-RlnYUHdb.js.map +0 -1
  100. package/dist/posthog-integration-DFfBRGOC.js.map +0 -1
  101. package/dist/task-GnWId75q.js.map +0 -1
  102. package/dist/tools-C9cNluqc.js.map +0 -1
  103. package/dist/wizard-session-Cex1BiXs.js.map +0 -1
  104. package/dist/yara-hooks-C3Vm2Gow.js +0 -2
@@ -1 +0,0 @@
1
- {"version":3,"file":"task-GnWId75q.js","names":[],"sources":["../src/lib/agent/runner/harness/pi/task.ts"],"sourcesContent":["/**\n * Orchestrator-mode execution on pi: one fresh pi session per unit of work —\n * the seed plan, or one drained task. The linear pipeline's concerns (skill\n * menu, todo panel, event-plan cleanup) stay in `index.ts`; this module builds\n * the leaner per-task session: gateway model, security fence, the task's\n * allowed coding tools, the wizard env tools, and the in-process orchestrator\n * queue tools.\n *\n * The task's `allowedTools` / `disallowedTools` arrive in the wizard's tool\n * vocabulary (`Read`, `Edit`, `Glob`, …, plus MCP-qualified orchestrator names\n * from `agentRunTools`). pi is where they become real: allowed names decide\n * which pi tool definitions get registered at all, and the disallow list is\n * ALSO handed to the security fence, so a name that never got registered stays\n * blocked even if the model hallucinates it.\n *\n * Loaded lazily from `index.ts` (typebox/ESM constraint, same as tools.ts).\n */\n\nimport { getUI } from '@ui';\nimport { logToFile } from '@utils/debug';\nimport { analytics } from '@utils/analytics';\nimport {\n Harness,\n Sequence,\n WIZARD_REMARK_EVENT_NAME,\n WIZARD_USER_AGENT,\n} from '@lib/constants';\nimport {\n allowsPostHogMcp,\n queueTools,\n renderToolInventory,\n} from '@lib/agent/agent-prompt-loader';\nimport { AgentErrorType } from '@lib/agent/agent-interface';\nimport { REMARK_INSTRUCTION } from '@lib/agent/signals';\nimport { AgentOutputSignals } from '@lib/agent/output-signals';\nimport { TaskStatus } from '../../sequence/orchestrator/queue';\nimport type { OrchestratorToolsContext } from '../../sequence/orchestrator/queue-tools';\nimport type { AgentResult, TaskRunInputs } from '../types';\nimport { buildGatewayProvider, GATEWAY_PROVIDER } from './gateway';\nimport { assembleCommandments } from '../../switchboard/commandments';\nimport {\n applyOutroMarkers,\n buildScrubbedEnv,\n extractText,\n lastStatusLine,\n withMode,\n} from './index';\nimport { createAioCapture } from '@lib/agent/aio-capture';\n\n/** wizard tool vocabulary → the pi tool definitions it unlocks. */\nconst CODING_TOOL_MAP: Record<string, readonly string[]> = {\n Read: ['read'],\n Edit: ['edit'],\n Write: ['write'],\n Bash: ['bash'],\n Glob: ['find', 'ls'],\n Grep: ['grep'],\n};\n\n/** `mcp__wizard-tools__wizard_ask` → `wizard_ask`; native names pass through. */\nfunction shortToolName(name: string): string {\n return name.replace(/^mcp__.+?__/, '');\n}\n\n/**\n * The pi coding tools a task may use. An empty allow list means \"no\n * restriction\" (mirrors the SDK), so every coding tool registers.\n */\nexport function allowedPiCodingTools(\n allowedTools: readonly string[] | undefined,\n): Set<string> {\n const allowed = (allowedTools ?? []).map(shortToolName);\n const names = allowed.length\n ? allowed.flatMap((name) => CODING_TOOL_MAP[name] ?? [])\n : Object.values(CODING_TOOL_MAP).flat();\n return new Set(names);\n}\n\n/**\n * The orchestrator queue tools this agent gets. Everything not disallowed:\n * the seed's frontmatter disallows `complete_task` (it is not a task), a\n * task's disallows `enqueue_task` (the seed owns the graph).\n */\nexport function allowedOrchestratorTools(\n disallowedTools: readonly string[] | undefined,\n): Set<string> {\n return new Set(queueTools(disallowedTools ?? []));\n}\n\n/**\n * The wizard tools a task gets. Four are always on — their handlers are fenced\n * and the coding tasks depend on them. The rest are opt-in per task through\n * its frontmatter: `wizard_ask` stops the run until a person answers, and the\n * skill-menu pair (`load_skill_menu`, `install_skill`) lets a task pull its\n * own skill variant.\n */\nconst ALWAYS_ON_WIZARD_TOOLS = [\n 'check_env_keys',\n 'set_env_values',\n 'detect_package_manager',\n 'publish_handoff',\n];\n\nconst OPT_IN_WIZARD_TOOLS = ['wizard_ask', 'load_skill_menu', 'install_skill'];\n\nexport function allowedPiWizardTools(\n allowedTools: readonly string[] | undefined,\n): Set<string> {\n const allowed = (allowedTools ?? []).map(shortToolName);\n return new Set([\n ...ALWAYS_ON_WIZARD_TOOLS,\n ...OPT_IN_WIZARD_TOOLS.filter((tool) => allowed.includes(tool)),\n ]);\n}\n\n/**\n * The disallow list for the security fence: the wizard-vocabulary names as\n * given (the fence translates pi built-ins to the same vocabulary) plus the\n * short names, so a disallowed orchestrator tool is blocked under the name pi\n * would call it by.\n */\nexport function fenceDisallowList(\n disallowedTools: readonly string[] | undefined,\n): string[] {\n const names = disallowedTools ?? [];\n return [...new Set([...names, ...names.map(shortToolName)])];\n}\n\n/** Nudges when the session returns without the work reaching a terminal state. */\nconst MAX_TASK_NUDGES = 3;\n\nconst TASK_NUDGE =\n 'You have not called complete_task yet. Finish your task now: if the work is done, call complete_task with your handoff; if it cannot be done, call it with status \"failed\" or \"not needed\" and say why.';\n\nconst SEED_NUDGE =\n 'The queue is still empty. Seed it now with enqueue_task calls for the task graph you planned.';\n\n/** Whether this unit of work has reached its terminal state. */\nfunction isSettled(ctx: OrchestratorToolsContext): boolean {\n if (!ctx.currentTaskId) {\n // The seed's job is a seeded queue, not a complete_task call.\n return ctx.store.list().length > 0;\n }\n const task = ctx.store.get(ctx.currentTaskId);\n return (\n !!task &&\n (task.status === TaskStatus.Done ||\n task.status === TaskStatus.Failed ||\n task.status === TaskStatus.Skipped)\n );\n}\n\nexport async function runPiTask(inputs: TaskRunInputs): Promise<AgentResult> {\n const {\n session,\n programConfig,\n boot,\n prompt,\n spinner,\n model: modelId,\n effort,\n allowedTools,\n disallowedTools,\n askBridge,\n orchestrator,\n spinnerMessage,\n successMessage,\n errorMessage,\n requestRemark,\n analyticsProperties,\n } = inputs;\n\n if (spinnerMessage) spinner.start(spinnerMessage);\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 const startTime = Date.now();\n const signals = new AgentOutputSignals();\n let assistantTurns = 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 ...analyticsProperties,\n });\n\n try {\n const sdk = await import('@earendil-works/pi-coding-agent');\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 } = sdk;\n\n const { provider, caps } = buildGatewayProvider({\n gatewayUrl: boot.credentials.host.gatewayUrl,\n accessToken: boot.credentials.accessToken,\n wizardMetadata: boot.wizardMetadata,\n wizardFlags: boot.wizardFlags,\n modelId,\n // Per-task agents own their effort via the prompt frontmatter, falling\n // back to the model table.\n effort,\n });\n const registry = ModelRegistry.inMemory(AuthStorage.create());\n registry.registerProvider(GATEWAY_PROVIDER, provider as never);\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 // Shared flag: true while a wizard_ask overlay is open. The ask tool sets\n // it (onAskPendingChange, below); the security fence reads it to pause\n // Write/Edit until the answer comes back. Wired the same way as the linear\n // pi run — without it the warehouse task could mutate files while its\n // credential prompt sits open (up to TASK_ASK_TIMEOUT_MS).\n const askState = { pending: false };\n\n // The same fail-closed fence as the linear run, with the task's disallow\n // list layered in (both the wizard-vocabulary and pi-short names).\n const { createSecurityExtension } = await import('./security');\n const security = createSecurityExtension({\n disallowedTools: fenceDisallowList(disallowedTools),\n triageProvider: boot.triageProvider,\n getWizardAskPending: () => askState.pending,\n });\n const { prewarmYaraScanner } = await import('@lib/yara-hooks');\n void prewarmYaraScanner();\n\n // PostHog MCP, for the tasks whose prompt requests it. Tasks that never\n // asked skip the handshake and never see a posthog tool.\n const extensionFactories = [security.factory] as Array<\n (pi: unknown) => void\n >;\n let mcpCleanup: (() => void) | undefined;\n let posthogMcp = false;\n if (allowsPostHogMcp(allowedTools)) {\n try {\n const { setupPostHogMcp } = await import('./mcp');\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 posthogMcp = true;\n } catch (err) {\n // Silent here reads as a task failure minutes later: a task that asked\n // for this tool can only skip or fail without it.\n logToFile(`[pi-task] PostHog MCP setup skipped: ${String(err)}`);\n analytics.wizardCapture('mcp setup failed', {\n harness: 'pi',\n scope: 'task',\n error: String(err).slice(0, 300),\n });\n }\n }\n\n const codingTools = allowedPiCodingTools(allowedTools);\n const orchestratorTools = allowedOrchestratorTools(disallowedTools);\n\n const resourceLoader = new DefaultResourceLoader({\n cwd: session.installDir,\n agentDir: getAgentDir(),\n systemPrompt: assembleCommandments({\n program: programConfig.id,\n sequence: Sequence.orchestrator,\n harness: Harness.pi,\n caps: { bash: codingTools.has('bash'), posthogMcp },\n }),\n noExtensions: true,\n noSkills: true,\n noContextFiles: true,\n noPromptTemplates: true,\n noThemes: true,\n extensionFactories,\n });\n await resourceLoader.reload();\n\n // The task's coding tools, gated by its allow list. Reads and searches run\n // in parallel; mutating tools stay sequential. Bash subprocesses get the\n // scrubbed env, same as the linear run.\n const dir = session.installDir;\n const codingToolFactories = {\n read: () => withMode(createReadToolDefinition(dir), 'parallel'),\n edit: () => withMode(createEditToolDefinition(dir), 'sequential'),\n write: () => withMode(createWriteToolDefinition(dir), 'sequential'),\n bash: () =>\n withMode(\n createBashToolDefinition(dir, {\n spawnHook: (ctx) => ({ ...ctx, env: buildScrubbedEnv() }),\n }),\n 'sequential',\n ),\n ls: () => withMode(createLsToolDefinition(dir), 'parallel'),\n find: () => withMode(createFindToolDefinition(dir), 'parallel'),\n grep: () => withMode(createGrepToolDefinition(dir), 'parallel'),\n } as const;\n const codingToolDefs = Object.entries(codingToolFactories)\n .filter(([name]) => codingTools.has(name))\n .map(([, make]) => make());\n\n // Wizard env + package-manager tools are always on — their handlers are\n // fenced, and init/build tasks depend on them. publish_handoff rides\n // along (store-only handler) so the report task can publish the handoff.\n const { createWizardPiTools } = await import('./tools');\n const wizardToolNames = allowedPiWizardTools(allowedTools);\n const wizardTools = createWizardPiTools({\n workingDirectory: dir,\n skillsBaseUrl: boot.skillsBaseUrl,\n triageProvider: boot.triageProvider,\n // Present only for a task allowed to ask; without it wizard_ask errors\n // instead of hanging on a prompt nobody will ever see.\n askBridge,\n // Pause Write/Edit while the ask overlay is open (see askState above).\n onAskPendingChange: (pending) => {\n askState.pending = pending;\n },\n }).filter((t) => wizardToolNames.has(t.name));\n\n const { createPiOrchestratorTools } = await import('./orchestrator-tools');\n const queueTools = createPiOrchestratorTools(orchestrator).filter((t) =>\n orchestratorTools.has(t.name),\n );\n\n const customTools = [...codingToolDefs, ...wizardTools, ...queueTools];\n const { session: agentSession } = await createAgentSession({\n model,\n modelRegistry: registry,\n thinkingLevel: caps.thinkingLevel,\n cwd: dir,\n sessionManager: SessionManager.inMemory(dir),\n resourceLoader,\n noTools: 'builtin',\n customTools,\n });\n await agentSession.bindExtensions({});\n\n // The one complete list: exactly the tools registered on this session, in\n // the names the agent will call them by. posthog_exec binds as an extension.\n const toolNames = [\n ...customTools.map((t) => t.name),\n ...(posthogMcp ? ['posthog_exec'] : []),\n ];\n logToFile(`[pi-task] tools passed to model: ${toolNames.join(', ')}`);\n const taskPrompt = `${prompt}\\n\\n${renderToolInventory(toolNames)}`;\n\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 is authoritative.\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 const assistant = extractText(event.message).trim();\n if (assistant) {\n logToFile(`[pi-task] assistant: ${assistant.slice(0, 1000)}`);\n applyOutroMarkers(assistant);\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 const args = JSON.stringify(event.args ?? {}).slice(0, 200);\n logToFile(`[pi-task] → ${event.toolName} ${args}`);\n break;\n }\n case 'tool_execution_end': {\n if (event.isError) {\n const detail =\n typeof event.result === 'string'\n ? event.result\n : JSON.stringify(event.result ?? '');\n logToFile(`[pi-task] ✗ ${event.toolName}: ${detail.slice(0, 300)}`);\n }\n break;\n }\n default:\n break;\n }\n });\n\n // Seed AIO capture with this task's prompt — includes any handoff data\n // from prior tasks (the orchestrator bakes it into the prompt string\n // before it reaches this call site).\n capture.setInitialPrompt(taskPrompt);\n\n try {\n await agentSession.prompt(taskPrompt);\n\n // pi's prompt() resolves the moment a turn carries no tool call — which\n // an agent mid-plan does emit. While the work has not reached its\n // terminal state (task not reported, seed queue still empty), nudge.\n let nudges = 0;\n while (\n nudges < MAX_TASK_NUDGES &&\n !security.state.criticalViolation &&\n !isSettled(orchestrator)\n ) {\n nudges += 1;\n logToFile(\n `[pi-task] completion guard: not settled, nudge ${nudges}/${MAX_TASK_NUDGES}`,\n );\n await agentSession.prompt(\n orchestrator.currentTaskId ? TASK_NUDGE : SEED_NUDGE,\n );\n }\n\n if (requestRemark && !security.state.criticalViolation) {\n try {\n await agentSession.prompt(REMARK_INSTRUCTION);\n } catch (err) {\n logToFile(`[pi-task] remark request failed: ${String(err)}`);\n }\n }\n } finally {\n unsubscribe();\n mcpCleanup?.();\n }\n\n if (security.state.criticalViolation) {\n spinner.stop('Security violation detected');\n logToFile(\n `[pi-task] terminated: YARA violation (blocked ${security.state.blockedCount} call(s))`,\n );\n captureAborted();\n return { error: AgentErrorType.YARA_VIOLATION };\n }\n\n const remark = signals.remark();\n if (remark) {\n analytics.capture(WIZARD_REMARK_EVENT_NAME, { remark });\n }\n\n const stats = agentSession.getSessionStats();\n const durations = runDurations();\n analytics.wizardCapture('agent completed', {\n ...durations,\n model: modelId,\n num_turns: assistantTurns,\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 ...analyticsProperties,\n });\n // Per-task usage on one parseable line so a run's per-task time and cost are\n // observable from the log, not only from analytics.\n const taskType =\n typeof (analyticsProperties as { task_type?: unknown })?.task_type ===\n 'string'\n ? (analyticsProperties as { task_type: string }).task_type\n : modelId;\n logToFile(\n `[pi-task] usage task=${taskType} model=${modelId} effort=${caps.thinkingLevel} dur=${durations.duration_seconds}s turns=${assistantTurns} in=${stats.tokens.input} out=${stats.tokens.output} cacheR=${stats.tokens.cacheRead} cacheW=${stats.tokens.cacheWrite}`,\n );\n if (successMessage) spinner.stop(successMessage);\n return {};\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[pi-task] run error: ${message}`);\n if (errorMessage || spinnerMessage) {\n spinner.stop(errorMessage ?? 'Task failed');\n }\n captureAborted();\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"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tools-C9cNluqc.js","names":["checkEnvKeys","checkEnvKeysCore"],"sources":["../src/lib/agent/runner/harness/pi/tools.ts"],"sourcesContent":["/**\n * Wizard capabilities as pi custom tools (#5). pi does not mount MCP servers,\n * so the tools the wizard prompt depends on — skill discovery/install and\n * fenced `.env` edits — are exposed to pi as native `defineTool` tools backed\n * by the same helpers the claude-agent-sdk path uses (`fetchSkillMenu`,\n * `installSkillById`, `checkEnvKeys`, `mergeEnvValues`). Same tool names as the\n * MCP server so the shared prompt is unchanged. `wizard_ask` is wired here too\n * (same schema, caps, and askBridge as the MCP tool) so interactive programs\n * can interview the user on pi; without a bridge (CI) it errors on call.\n * Sensitive answers are vaulted to `{secretRef}` and resolved host-side by\n * set_env_values — the raw value never enters the model conversation.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { Type } from 'typebox';\nimport { defineTool } from '@earendil-works/pi-coding-agent';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport {\n CHECK_ENV_KEYS_DESCRIPTION,\n CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION,\n DEFAULT_ASK_MAX_QUESTIONS,\n ENV_FILE_PATH_DESCRIPTION,\n WIZARD_TOOL_NAMES,\n checkEnvKeys as checkEnvKeysCore,\n createAskAccounting,\n fetchSkillMenu,\n installSkillById,\n mergeEnvValues,\n resolveEnvPath,\n resolveEnvSecretRefs,\n templateEnvWriteRefusal,\n vaultSensitiveAnswers,\n WIZARD_ASK_SENSITIVE_DESCRIPTION,\n WIZARD_ASK_SUBJECT_DESCRIPTION,\n WIZARD_ASK_TOOL_DESCRIPTION,\n} from '@lib/wizard-tools/tools';\nimport type { LLMProvider } from '@posthog/warlock';\nimport { isFullyCancelled, type WizardAskBridge } from '@lib/wizard-ask-bridge';\nimport {\n PUBLISH_HANDOFF_CONTENT_DESCRIPTION,\n PUBLISH_HANDOFF_DESCRIPTION,\n PUBLISH_HANDOFF_TOOL_NAME,\n publishHandoff,\n} from '@lib/wizard-tools/handoff';\nimport { createSecretVault } from '@lib/secret-vault';\nimport { withMode } from './index';\nimport {\n detectNodePackageManagers,\n type PackageManagerDetector,\n} from '@lib/detection/package-manager';\n\nfunction text(s: string): {\n content: [{ type: 'text'; text: string }];\n details: unknown;\n} {\n return { content: [{ type: 'text', text: s }], details: {} };\n}\n\nexport interface PiToolsContext {\n workingDirectory: string;\n skillsBaseUrl: string;\n /** Framework's package-manager detector. Defaults to Node detection. */\n detectPackageManager?: PackageManagerDetector;\n /** Drives the `wizard_ask` overlay. Omitted in CI → the tool errors on call. */\n askBridge?: WizardAskBridge;\n /** Per-run cap on wizard_ask calls. Defaults to {@link DEFAULT_ASK_MAX_QUESTIONS}. */\n maxQuestions?: number;\n /** Overlay open/closed signal — the security gate blocks Write/Edit while open. */\n onAskPendingChange?: (pending: boolean) => void;\n /** Program disallow list; gates wizard_ask here since pi tools carry bare names the MCP-prefixed security gate misses. */\n disallowedTools?: readonly string[];\n /** Scan-triage classifier, resolved once in bootstrap. Absent → scans fail closed. */\n triageProvider?: LLMProvider;\n}\n\nexport function createWizardPiTools(ctx: PiToolsContext): ToolDefinition[] {\n const {\n workingDirectory,\n skillsBaseUrl,\n askBridge,\n onAskPendingChange,\n triageProvider,\n } = ctx;\n const detectPackageManager =\n ctx.detectPackageManager ?? detectNodePackageManagers;\n const askMaxQuestions = ctx.maxQuestions ?? DEFAULT_ASK_MAX_QUESTIONS;\n // Per-run wizard_ask accounting (total cap + one-time per-subject adjacency\n // nudge). Same shared implementation the MCP server drives, so the two\n // facades cannot diverge on the cap, the nudge or the refund.\n const askAccounting = createAskAccounting(askMaxQuestions);\n // Session-scoped secret vault, same contract as the MCP server: wizard_ask\n // mints `{secretRef}` for sensitive answers, set_env_values resolves them.\n const secretVault = createSecretVault();\n\n // Fetch the skill menu at most once per run — the agent calls load_skill_menu\n // 2-3× otherwise, each a fresh HTTP round-trip (profiled slowness).\n let menuPromise: ReturnType<typeof fetchSkillMenu> | undefined;\n const getSkillMenu = () => (menuPromise ??= fetchSkillMenu(skillsBaseUrl));\n\n const loadSkillMenu = defineTool({\n name: 'load_skill_menu',\n label: 'Load skill menu',\n description:\n 'Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then install_skill with the chosen ID.',\n promptSnippet:\n 'load_skill_menu(category) — list installable PostHog skills',\n parameters: Type.Object({\n category: Type.String({\n description: 'Skill category, e.g. \"integration\"',\n }),\n }),\n async execute(_id, args) {\n const menu = await getSkillMenu();\n if (!menu) return text('Error: could not load the skill menu.');\n const skills = menu.categories[args.category] ?? [];\n if (skills.length === 0) {\n return text(`No skills found for category \"${args.category}\".`);\n }\n logToFile(`[pi] load_skill_menu: ${skills.length} skills`);\n return text(skills.map((s) => `- ${s.id}: ${s.name}`).join('\\n'));\n },\n });\n\n const installSkill = defineTool({\n name: 'install_skill',\n label: 'Install skill',\n description:\n 'Download and install a PostHog skill by ID into .claude/skills/<skillId>/. Call load_skill_menu first. Then read the installed SKILL.md and follow it.',\n promptSnippet:\n 'install_skill(skillId) — install a skill, then read its SKILL.md',\n parameters: Type.Object({\n skillId: Type.String({ description: 'Skill ID from load_skill_menu' }),\n }),\n async execute(_id, args) {\n const result = await installSkillById(\n args.skillId,\n workingDirectory,\n skillsBaseUrl,\n { triage: triageProvider },\n );\n if (result.kind !== 'ok') {\n logToFile(`[pi] install_skill ${args.skillId}: ${result.kind}`);\n return text(\n `Error installing skill \"${args.skillId}\": ${result.kind}. Use load_skill_menu to see valid IDs.`,\n );\n }\n logToFile(`[pi] install_skill ${args.skillId} -> ${result.path}`);\n return text(\n `Installed \"${args.skillId}\" at ${result.path}. Read ${result.path}/SKILL.md and follow it.`,\n );\n },\n });\n\n const checkEnvKeys = defineTool({\n name: 'check_env_keys',\n label: 'Check env keys',\n description: CHECK_ENV_KEYS_DESCRIPTION,\n promptSnippet:\n 'check_env_keys(keys) — see which .env keys exist, and in which file',\n parameters: Type.Object({\n filePath: Type.Optional(\n Type.String({\n description: CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION,\n }),\n ),\n keys: Type.Array(Type.String(), {\n description: 'Environment variable key names to check',\n }),\n }),\n // `async` with nothing to await, on purpose: it is what turns a thrown\n // error into a rejection. `checkEnvKeys` throws on a filePath that escapes\n // the working directory, and pi wraps `execute` in a plain (non-async)\n // arrow, so without this the throw leaves the tool synchronously instead\n // of arriving as a failed tool call. The scan replaced an awaited read,\n // which is the only reason there is nothing left to await.\n // eslint-disable-next-line @typescript-eslint/require-await\n async execute(_id, args) {\n const results = checkEnvKeysCore(\n workingDirectory,\n args.keys,\n args.filePath,\n );\n return text(JSON.stringify(results, null, 2));\n },\n });\n\n const setEnvValues = defineTool({\n name: 'set_env_values',\n label: 'Set env values',\n description:\n 'Create or update environment variable keys in a .env file (creates the file if missing). Each value is either a literal string or a secret reference `{ \"secretRef\": \"secret:...\" }` returned by wizard_ask — refs are resolved locally, so the actual value is written to the file but never returned to the agent.',\n promptSnippet:\n 'set_env_values(filePath, values) — write .env keys (never hardcode secrets in source)',\n parameters: Type.Object({\n filePath: Type.String({\n description: ENV_FILE_PATH_DESCRIPTION,\n }),\n values: Type.Record(\n Type.String(),\n Type.Union([Type.String(), Type.Object({ secretRef: Type.String() })]),\n {\n description:\n 'Key → (literal string OR { secretRef } pointing to a vaulted secret)',\n },\n ),\n }),\n async execute(_id, args) {\n const forbidden = Object.keys(args.values).find(\n (k) => k.toUpperCase() === 'POSTHOG_KEY',\n );\n if (forbidden) {\n return text(\n `Error: \"${forbidden}\" is not a valid PostHog env var name. Use the framework-specific key (e.g. NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN).`,\n );\n }\n // Resolve secret refs host-side; the value never reaches the agent.\n const resolution = resolveEnvSecretRefs(args.values, secretVault);\n if (!resolution.ok) {\n return text(\n `Error: secret reference \"${resolution.secretRef}\" for key \"${resolution.key}\" is not known to the vault. The ref may have expired, been minted in a different run, or been mistyped.`,\n );\n }\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const templateRefusal = templateEnvWriteRefusal(resolved);\n if (templateRefusal) {\n logToFile(`[pi] set_env_values: refused template target ${resolved}`);\n analytics.wizardCapture('set_env_values template target refused', {\n file_name: path.basename(resolved),\n });\n return text(templateRefusal);\n }\n const existing = fs.existsSync(resolved)\n ? await fs.promises.readFile(resolved, 'utf8')\n : '';\n const merged = mergeEnvValues(existing, resolution.values);\n const dir = path.dirname(resolved);\n if (!fs.existsSync(dir))\n await fs.promises.mkdir(dir, { recursive: true });\n await fs.promises.writeFile(resolved, merged, 'utf8');\n logToFile(\n `[pi] set_env_values: ${resolved} keys=${Object.keys(args.values).join(\n ',',\n )}`,\n );\n return text(\n `Wrote ${Object.keys(args.values).length} key(s) to ${args.filePath}.`,\n );\n },\n });\n\n const detectPm = defineTool({\n name: 'detect_package_manager',\n label: 'Detect package manager',\n description:\n \"Detect the project's package manager(s). Returns the name and the install command for each. Call this before installing a dependency, then RUN the returned install command (with the posthog package) via bash — the SDK package must end up in the project manifest, or the app will not build.\",\n promptSnippet:\n 'detect_package_manager() — find the PM + install command, then run it via bash to add the SDK',\n parameters: Type.Object({}),\n async execute() {\n const result = await detectPackageManager(workingDirectory);\n logToFile(\n `[pi] detect_package_manager: ${result.detected.length} detected`,\n );\n return text(JSON.stringify(result, null, 2));\n },\n });\n\n // Native mirror of the MCP `wizard_ask` tool: same name, schema, and\n // askBridge, so the shared prompt is unchanged.\n const wizardAsk = defineTool({\n name: 'wizard_ask',\n label: 'Ask the user',\n description: WIZARD_ASK_TOOL_DESCRIPTION,\n promptSnippet:\n 'wizard_ask(questions, subject) — ask the user structured questions and wait for answers; tag each call with the subject it collects for',\n parameters: Type.Object({\n questions: Type.Array(\n Type.Object({\n id: Type.String({\n description: 'Stable key for the answer in the response map',\n }),\n prompt: Type.String({\n description: 'Question text shown to the user',\n }),\n kind: Type.Union(\n [\n Type.Literal('single'),\n Type.Literal('multi'),\n Type.Literal('text'),\n ],\n {\n description:\n \"'single' = pick one option, 'multi' = pick any, 'text' = free-form single-line answer\",\n },\n ),\n options: Type.Optional(\n Type.Array(\n Type.Object({\n label: Type.String(),\n value: Type.String(),\n description: Type.Optional(Type.String()),\n }),\n {\n description:\n 'Required for kind=single|multi; ignored for kind=text',\n },\n ),\n ),\n required: Type.Optional(\n Type.Boolean({ description: 'Defaults to true' }),\n ),\n sensitive: Type.Optional(\n Type.Boolean({\n description: WIZARD_ASK_SENSITIVE_DESCRIPTION,\n }),\n ),\n }),\n { minItems: 1, maxItems: 8 },\n ),\n subject: Type.Optional(\n Type.String({ description: WIZARD_ASK_SUBJECT_DESCRIPTION }),\n ),\n }),\n async execute(_id, args) {\n if (!askBridge) {\n return text(\n 'Error: wizard_ask is not available in this environment (CI / non-interactive). Proceed with sensible defaults or emit [ABORT] requirements-incomplete.',\n );\n }\n\n const cap = askAccounting.evaluate(args.subject);\n if (cap.kind === 'capped') {\n const { callCount } = askAccounting.snapshot();\n logToFile(\n `[pi] wizard_ask capped: reason=${cap.reason} count=${callCount} subject=${cap.subject} run=${cap.subjectRunLength}`,\n );\n analytics.wizardCapture('wizard_ask capped', {\n reason: cap.reason,\n call_count: callCount,\n max_questions: askMaxQuestions,\n subject: cap.subject,\n subject_run_length: cap.subjectRunLength,\n });\n return text(cap.message);\n }\n\n // The schema can't enforce per-kind requirements or unique ids.\n const ids = new Set<string>();\n for (const q of args.questions) {\n if ((q.kind === 'single' || q.kind === 'multi') && !q.options?.length) {\n return text(\n `Error: question \"${q.id}\" has kind=\"${q.kind}\" but no options. Provide at least one { label, value }, or use kind=\"text\".`,\n );\n }\n if (q.sensitive && q.kind !== 'text') {\n return text(\n `Error: question \"${q.id}\" sets sensitive=true but kind=\"${q.kind}\". Only kind=\"text\" answers can be sensitive.`,\n );\n }\n if (ids.has(q.id)) {\n return text(\n `Error: duplicate question id \"${q.id}\". Each question needs a unique id.`,\n );\n }\n ids.add(q.id);\n }\n\n // Optimistically take the slot; refund it on a cancellation or a bridge\n // error so a declined/failed ask doesn't burn the budget for later ones.\n askAccounting.record(args.subject);\n // Block Write/Edit for as long as the overlay is open, so the agent can't\n // mutate files while it's waiting on the user's answer.\n onAskPendingChange?.(true);\n try {\n const answers = await askBridge.request({ questions: args.questions });\n if (isFullyCancelled(answers)) askAccounting.refund(args.subject);\n // Sensitive answers go to the vault; the agent sees an opaque ref\n // (same contract as the MCP wizard_ask).\n const sanitised = vaultSensitiveAnswers(\n args.questions,\n answers,\n secretVault,\n );\n logToFile(\n `[pi] wizard_ask: resolved ${\n Object.keys(answers).length\n } answer(s) for ${args.questions.length} question(s)`,\n );\n return text(JSON.stringify({ answers: sanitised }, null, 2));\n } catch (err) {\n askAccounting.refund(args.subject);\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[pi] wizard_ask: error: ${message}`);\n return text(`Error: wizard_ask failed: ${message}`);\n } finally {\n onAskPendingChange?.(false);\n }\n },\n });\n\n // Native mirror of the MCP `publish_handoff` tool (shared description, so no drift).\n const publishHandoffTool = defineTool({\n name: PUBLISH_HANDOFF_TOOL_NAME,\n label: 'Publish handoff',\n description: PUBLISH_HANDOFF_DESCRIPTION,\n promptSnippet:\n 'publish_handoff(content) — publish the full report markdown to the wizard session',\n parameters: Type.Object({\n content: Type.String({\n description: PUBLISH_HANDOFF_CONTENT_DESCRIPTION,\n }),\n }),\n execute(_id, args) {\n const result = publishHandoff(args.content);\n logToFile(`[pi] publish_handoff: ${result.message}`);\n return Promise.resolve(text(result.message));\n },\n });\n\n const tools = [\n loadSkillMenu,\n installSkill,\n checkEnvKeys,\n setEnvValues,\n detectPm,\n // Sequential: it mutates the store's handoff state.\n withMode(publishHandoffTool, 'sequential'),\n ];\n // Register wizard_ask only when the program allows it. posthog-integration\n // disallows it (runs without structured user input); self-driving keeps it.\n // Sequential: the ask bridge holds a single in-flight question slot, so a\n // batched turn must never dispatch two asks (or an ask + a write) at once.\n const askDisallowed =\n ctx.disallowedTools?.includes(WIZARD_TOOL_NAMES.wizardAsk) ?? false;\n if (!askDisallowed) tools.push(withMode(wizardAsk, 'sequential'));\n return tools;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"wizard-session-Cex1BiXs.js","names":[],"sources":["../src/lib/wizard-session.ts"],"sourcesContent":["/**\n * WizardSession — single source of truth for every decision the wizard needs.\n *\n * Populated in layers:\n * CLI args / env vars → populate fields directly\n * Auto-detection → framework, typescript, package manager\n * TUI screens → region, framework disambiguation, etc.\n * OAuth → credentials\n *\n * Business logic reads from the session. Never calls a prompt.\n */\n\nimport { POSTHOG_LOCAL_URL, resolveLocalDev } from './local-dev';\nimport type { Harness, Integration, Sequence } from './constants';\nimport type { FrameworkConfig } from './framework-config';\nimport type { WizardReadinessResult } from './health-checks/readiness';\nimport type { SettingsConflict } from './agent/claude-settings';\nimport type { ApiUser, ApiProject } from './api';\nimport type { HostResolution } from './host-resolution';\n\nexport interface Credentials {\n accessToken: string;\n projectApiKey: string;\n /** Resolved at auth time and immutable thereafter — see {@link HostResolution}. */\n host: HostResolution;\n projectId: number;\n /**\n * Requested OAuth scopes the grant came back without — deselected on the\n * consent screen or clamped by the app's ceiling. Read when a run fails so\n * the error can name the missing permission and the fix (re-run and grant\n * it during the OAuth flow) instead of the generic report-a-bug line.\n * Empty/absent on CI api-key runs, where there is no scope request to diff\n * against.\n */\n missingScopes?: readonly string[];\n}\n\nfunction parseProjectIdArg(value: string | undefined): number | undefined {\n if (value === undefined || value === '') return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n > 0 ? n : undefined;\n}\n\nexport type CloudRegion = 'us' | 'eu';\n\n/** Lifecycle phase of the main work (agent run, MCP install, etc.) */\nexport enum RunPhase {\n /** Still gathering input (intro, setup screens) */\n Idle = 'idle',\n /** Main work is in progress */\n Running = 'running',\n /** Main work finished successfully */\n Completed = 'completed',\n /** Main work finished with an error */\n Error = 'error',\n}\n\n/** Features discovered by the feature-discovery subagent */\nexport enum DiscoveredFeature {\n Stripe = 'stripe',\n LLM = 'llm',\n}\n\n/** Additional features the agent can integrate after the main setup */\nexport enum AdditionalFeature {\n LLM = 'llm',\n}\n\n/** Human-readable labels for additional features (used in TUI progress) */\nexport const ADDITIONAL_FEATURE_LABELS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: 'AI observability',\n};\n\n/** Agent prompts for each additional feature, injected via the stop hook */\nexport const ADDITIONAL_FEATURE_PROMPTS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: `Now integrate AI observability with PostHog. Use the PostHog MCP server to find the appropriate AI observability skill, install it, and follow its workflow. PostHog basics are already installed. Update the setup report markdown file when complete with additions from this task. `,\n};\n\n/** Outcome of the MCP server installation step */\nexport enum McpOutcome {\n NoClients = 'no_clients',\n Skipped = 'skipped',\n Installed = 'installed',\n Failed = 'failed',\n}\n\n/** Outcome kind for the outro screen */\nexport enum OutroKind {\n Success = 'success',\n Error = 'error',\n Cancel = 'cancel',\n}\n\nexport interface OutroData {\n kind: OutroKind;\n /** Main headline (green check for Success, red X for Error, etc.) */\n message?: string;\n /** Free-form body text shown under the headline. Use \\n for paragraph breaks. */\n body?: string;\n /** Success-only: bulleted list of \"what the agent did\" */\n changes?: string[];\n /**\n * Success-only: a prominent, labeled link to where the user should go\n * next (e.g. an inbox the program just configured). Rendered right under\n * the headline and shown verbatim — no UTM tagging — so the URL stays\n * clean and copy-pasteable. Set per-program in buildOutroData.\n */\n primaryLink?: { label: string; url: string };\n /**\n * Success-only: a short \"what to do next\" checklist with its own heading,\n * rendered as a bulleted list. Distinct from `changes`, which recaps what\n * the agent already did.\n */\n nextSteps?: { heading: string; items: string[] };\n docsUrl?: string;\n continueUrl?: string;\n /** Report file the agent wrote (e.g. \"posthog-setup-report.md\") */\n reportFile?: string;\n /** Stable machine-readable error code from the error catalog (@lib/errors). */\n errorCode?: import('@lib/errors').ErrorCode;\n /** Structured context for the error code; safe for telemetry payloads. */\n errorDetail?: Record<string, unknown>;\n /** PostHog dashboard URL the program created on the user's behalf. */\n dashboardUrl?: string;\n /** PostHog notebook URL the program uploaded the report to. */\n notebookUrl?: string;\n /**\n * Copy-paste prompt the operator hands to their coding agent to finish the\n * job (work the report's checklist). Printed to the terminal's main buffer on\n * exit (see getExitLine in start-tui.ts) — the TUI's alternate screen is wiped\n * on exit, so the scrollback line is where it survives and can be\n * triple-click-selected. Set per-program in buildOutroData.\n */\n handoffPrompt?: string;\n}\n\n/** A single question rendered by the WizardAsk overlay. */\nexport interface AskQuestion {\n /** Key for the response map */\n id: string;\n prompt: string;\n /** text = single-line free input; single/multi = picker */\n kind: 'single' | 'multi' | 'text';\n /** Required for `single` and `multi`. Ignored for `text`. */\n options?: { label: string; value: string; description?: string }[];\n /** Defaults to true */\n required?: boolean;\n /**\n * Only meaningful for kind='text'. When true, the wizard-tools `wizard_ask`\n * tool stores the user's answer in the session secret vault and returns\n * `{ secretRef }` to the agent instead of the plain string — so the value\n * never enters the LLM conversation. The TUI may also mask input\n * accordingly. See `secret-vault.ts`.\n */\n sensitive?: boolean;\n}\n\n/**\n * Copy for a modal shown before an optional step runs, so the user can decline\n * it. The program that owns the step supplies the words; the runner and the\n * screen only carry them.\n */\nexport interface TaskNotice {\n title: string;\n /** Paragraphs, in order. */\n body: string[];\n /** Optional highlighted list, e.g. what was detected. */\n items?: string[];\n docsLabel?: string;\n docsUrl?: string;\n confirmLabel: string;\n cancelLabel: string;\n prompt: string;\n}\n\n/** Map of question id → answer (string for single/text, string[] for multi). */\nexport type AskAnswers = Record<string, string | string[]>;\n\n/** A pending wizard_ask request held by the store. */\nexport interface PendingQuestion {\n id: string;\n questions: AskQuestion[];\n /**\n * UTC ISO 8601 timestamp of when the ask was created. Published on the\n * task stream as `pending_input.asked_at` so the web app can age the\n * prompt; stable across pushes for the lifetime of one ask.\n */\n askedAt?: string;\n /** Skill id of the caller. Set by the wizard from session.skillId. */\n source: string;\n /**\n * When true, the ask overlay renders standalone URLs in prompt text as\n * OSC 8 hyperlinks and copies a lone URL to the clipboard. Opt-in per\n * program (set from `ProgramRun.richLinks` via the ask bridge); defaults\n * to false so existing flows render prompts exactly as before. See\n * `LinkText` / `link-helpers`.\n */\n richLinks?: boolean;\n}\n\n/**\n * PostHog dashboard URL emitted by the agent during a program run.\n * Populated via the `[DASHBOARD_URL]` text marker in agent assistant messages\n * — see `handleSDKMessage` in `agent/agent-interface.ts`. Read by programs\n * (e.g. events-audit) inside `buildOutroData` to surface a dashboard link\n * the agent actually created.\n */\n\nexport interface WizardSession {\n // From CLI args\n debug: boolean;\n installDir: string;\n ci: boolean;\n signup: boolean;\n /**\n * `--local-posthog` folds into `baseUrl`, and `--local-context-mill` is read\n * from `getLocalDev()` — neither belongs here. This one stays because\n * `mcp add|remove|tutorial --local` populate it from their own flag.\n */\n localMcp: boolean;\n mcpFeatures?: string[];\n apiKey?: string;\n email?: string;\n region?: CloudRegion;\n /**\n * Explicit PostHog base URL (`--base-url`). When set, it pins every PostHog\n * origin — API host, cloud/app URL, OAuth server — and `region` is ignored.\n * The runtime equivalent of the dev-build localhost routing; lets the shipped\n * wizard target a local/self-hosted stack. Threaded into the URL helpers in\n * `@utils/urls`. Empty/unset → region-based resolution.\n */\n baseUrl?: string;\n benchmark: boolean;\n yaraReport: boolean;\n projectId?: number;\n noTelemetry: boolean;\n\n /**\n * `--capture-aio`: mirror every wizard LLM call as an `$ai_generation` event\n * into the authenticated project's AI Observability tab. Dev/test builds\n * only — the flag is undeclared in published builds so this stays `false`\n * there. See `src/lib/agent/aio-capture.ts`.\n */\n captureAio: boolean;\n\n /** `--harness` override, read by `resolveHarness`. Wins over the runner flag. */\n harness?: Harness;\n /** `--sequence` override, read in `runProgram`. Wins over the orchestrator flag. */\n sequence?: Sequence;\n /** `--model` override (gateway id), read by `resolveHarness`. Wins over the binding's model. */\n model?: string;\n\n // From detection + screens\n setupConfirmed: boolean;\n integration: Integration | null;\n frameworkContext: Record<string, unknown>;\n typescript: boolean;\n\n /** Human-readable label for the detected framework variant (e.g., \"Django with Wagtail CMS\") */\n detectedFrameworkLabel: string | null;\n\n /** True once framework detection has run (whether it found something or not) */\n detectionComplete: boolean;\n\n /** Set when the detected framework version is too old for the wizard */\n unsupportedVersion: {\n current: string;\n minimum: string;\n docsUrl: string;\n } | null;\n\n // From OAuth\n credentials: Credentials | null;\n\n /**\n * `role_at_organization` from `/api/users/@me/`. Null when the upstream\n * value is missing (older accounts, fresh signups before onboarding).\n * Drives role-tailored MCP prompt suggestions on the McpSuggestedPromptsScreen.\n *\n * Mirrors `apiUser?.role_at_organization` — kept as a top-level convenience\n * because it has dedicated UI semantics (role-tailored kits) and pre-dates\n * the broader `apiUser` plumbing.\n */\n roleAtOrganization: string | null;\n\n /**\n * Full user payload from `/api/users/@me/` — identifiers, profile,\n * current team + organization, preferences, etc. Null until OAuth /\n * CI-key auth populates it. Schema lives in `src/lib/api.ts` and\n * passes through unknown upstream fields so downstream features can\n * read account context (plan, org name, email, etc.) without\n * re-fetching.\n */\n apiUser: ApiUser | null;\n\n /**\n * Project payload resolved at authentication, kept so a second agent run in\n * the same invocation (e.g. self-driving's integration phase) reuses the\n * first login wholesale instead of re-authenticating. The resolved region\n * lives on `credentials.host.region`.\n */\n apiProject: ApiProject | null;\n\n // Lifecycle\n runPhase: RunPhase;\n loginUrl: string | null;\n // Direct PostHog authorize URL, shown in the manual-paste modal for\n // headless/remote shells (the localhost loginUrl is unreachable there).\n authorizeUrl: string | null;\n\n // Feature discovery\n discoveredFeatures: DiscoveredFeature[];\n llmOptIn: boolean;\n\n // ScreenId completion\n mcpComplete: boolean;\n mcpOutcome: McpOutcome | null;\n mcpInstalledClients: string[];\n /** Editor-owned login commands still to run (e.g. `claude mcp login posthog`), echoed at exit. */\n mcpLoginCommands: string[];\n mcpSuggestedPromptsDismissed: boolean;\n /** True once the user has acted on (opened or skipped) the Connect-Slack step. */\n slackStepDismissed: boolean;\n /**\n * Whether the project already has a Slack integration connected.\n * `null` until detected. Prefetched by the tutorial screen as soon as\n * credentials exist so the Connect-Slack step renders the right\n * variant immediately instead of flashing the nudge first.\n */\n slackConnected: boolean | null;\n skillsComplete: boolean;\n outroDismissed: boolean;\n\n /**\n * Self-driving only: whether to integrate PostHog as part of this run.\n * `null` until decided. When detection finds no PostHog SDK, the\n * integration-check screen sets this to `true` (Self-driving needs an SDK,\n * so we always integrate in that case) — and, on the same screen, asks\n * whether the user already has a PostHog account: \"yes\" leaves `signup`\n * false (OAuth login); \"no\" flips `signup` and collects `email`/`region`\n * so auth provisions a new account. The `--integrate` flag pre-sets this to\n * `true`, skipping the screen entirely and defaulting to the OAuth login.\n * When `true`, the self-driving prompt has the agent set up the SDK before\n * the Self-driving steps. Unused by other programs.\n */\n integrate: boolean | null;\n\n /**\n * Ids of composed run steps that have completed — e.g. self-driving's\n * `integrate-run`. Lets a run step's `isComplete` hold after it ran,\n * independent of the shared `runPhase`.\n */\n completedRuns: string[];\n\n /**\n * Self-driving only: whether the user confirmed the handoff screen shown\n * after the integration run (\"PostHog is installed — now set up Self-driving\").\n * Gates the Self-driving run so it doesn't start until acknowledged. Only\n * reached in the integrate path; the already-has-PostHog path skips it.\n */\n selfDrivingHandoffConfirmed: boolean;\n\n // Runtime\n readinessResult: WizardReadinessResult | null;\n outageDismissed: boolean;\n settingsOverrideKeys: string[] | null;\n settingsConflicts: SettingsConflict[] | null;\n authErrorDetail: {\n hasSettingsConflict: boolean;\n conflicts?: SettingsConflict[];\n logFilePath: string;\n } | null;\n portConflictProcess: {\n command: string;\n pid: string;\n port: number;\n user: string;\n } | null;\n /** Copy for the task-notice modal, set while it is open. */\n taskNotice: TaskNotice | null;\n outroData: OutroData | null;\n dashboardUrl: string | null;\n notebookUrl: string | null;\n\n // Additional features queue (drained via stop hook after main integration)\n additionalFeatureQueue: AdditionalFeature[];\n\n // Program metadata (set by runWizard in bin.ts)\n programLabel: string | null;\n skillId: string | null;\n\n // Resolved framework config (set after integration is known)\n frameworkConfig: FrameworkConfig | null;\n\n /** Active wizard_ask request, set by the bridge when the agent calls the tool. */\n pendingQuestion: PendingQuestion | null;\n}\n\n/**\n * Build a WizardSession from CLI args, pre-populating whatever is known.\n */\nexport function buildSession(args: {\n debug?: boolean;\n installDir?: string;\n ci?: boolean;\n signup?: boolean;\n localDev?: boolean;\n localMcp?: boolean;\n localPosthog?: boolean;\n mcpFeatures?: string[];\n apiKey?: string;\n email?: string;\n region?: CloudRegion;\n baseUrl?: string;\n integration?: Integration;\n benchmark?: boolean;\n yaraReport?: boolean;\n projectId?: string;\n noTelemetry?: boolean;\n harness?: Harness;\n sequence?: Sequence;\n model?: string;\n integrate?: boolean;\n captureAio?: boolean;\n}): WizardSession {\n const local = resolveLocalDev(args);\n return {\n debug: args.debug ?? false,\n installDir: args.installDir ?? process.cwd(),\n ci: args.ci ?? false,\n signup: args.signup ?? false,\n localMcp: local.localMcp,\n mcpFeatures: args.mcpFeatures,\n apiKey: args.apiKey,\n email: args.email,\n region: args.region,\n // `--local-posthog` is sugar over `--base-url`, which every downstream URL\n // helper already honours. An explicit `--base-url` is more specific, so it wins.\n baseUrl:\n args.baseUrl ?? (local.localPosthog ? POSTHOG_LOCAL_URL : undefined),\n benchmark: args.benchmark ?? false,\n yaraReport: args.yaraReport ?? false,\n projectId: parseProjectIdArg(args.projectId),\n noTelemetry: args.noTelemetry ?? false,\n captureAio: args.captureAio ?? false,\n harness: args.harness,\n sequence: args.sequence,\n model: args.model,\n\n setupConfirmed: false,\n integration: args.integration ?? null,\n frameworkContext: {},\n typescript: false,\n detectedFrameworkLabel: null,\n detectionComplete: false,\n unsupportedVersion: null,\n\n runPhase: RunPhase.Idle,\n discoveredFeatures: [],\n llmOptIn: false,\n mcpComplete: false,\n mcpOutcome: null,\n mcpInstalledClients: [],\n mcpLoginCommands: [],\n mcpSuggestedPromptsDismissed: false,\n slackStepDismissed: false,\n slackConnected: null,\n skillsComplete: false,\n outroDismissed: false,\n // `--integrate` forces integration (skip the question); otherwise the\n // integration-check screen resolves it from null.\n integrate: args.integrate === true ? true : null,\n completedRuns: [],\n selfDrivingHandoffConfirmed: false,\n loginUrl: null,\n authorizeUrl: null,\n credentials: null,\n roleAtOrganization: null,\n apiUser: null,\n apiProject: null,\n readinessResult: null,\n outageDismissed: false,\n settingsOverrideKeys: null,\n settingsConflicts: null,\n authErrorDetail: null,\n portConflictProcess: null,\n taskNotice: null,\n outroData: null,\n dashboardUrl: null,\n notebookUrl: null,\n additionalFeatureQueue: [],\n programLabel: null,\n skillId: null,\n frameworkConfig: null,\n pendingQuestion: null,\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAqCA,SAAS,kBAAkB,OAA+C;AACxE,KAAI,UAAU,KAAA,KAAa,UAAU,GAAI,QAAO,KAAA;CAChD,MAAM,IAAI,OAAO,MAAM;AACvB,QAAO,OAAO,UAAU,EAAE,IAAI,IAAI,IAAI,IAAI,KAAA;;;AAM5C,IAAY,WAAL,yBAAA,UAAA;;AAEL,UAAA,UAAA;;AAEA,UAAA,aAAA;;AAEA,UAAA,eAAA;;AAEA,UAAA,WAAA;;KACD;;AAcD,MAAa,4BAA+D,GAAA,QACjD,oBAC1B;;AAGD,MAAa,6BAAgE,GAAA,QAClD,0RAC1B;;AAWD,IAAY,YAAL,yBAAA,WAAA;AACL,WAAA,aAAA;AACA,WAAA,WAAA;AACA,WAAA,YAAA;;KACD;;;;AAsTD,SAAgB,aAAa,MAuBX;CAChB,MAAM,QAAQ,gBAAgB,KAAK;AACnC,QAAO;EACL,OAAO,KAAK,SAAS;EACrB,YAAY,KAAK,cAAc,QAAQ,KAAK;EAC5C,IAAI,KAAK,MAAM;EACf,QAAQ,KAAK,UAAU;EACvB,UAAU,MAAM;EAChB,aAAa,KAAK;EAClB,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,QAAQ,KAAK;EAGb,SACE,KAAK,YAAY,MAAM,eAAA,0BAAmC,KAAA;EAC5D,WAAW,KAAK,aAAa;EAC7B,YAAY,KAAK,cAAc;EAC/B,WAAW,kBAAkB,KAAK,UAAU;EAC5C,aAAa,KAAK,eAAe;EACjC,YAAY,KAAK,cAAc;EAC/B,SAAS,KAAK;EACd,UAAU,KAAK;EACf,OAAO,KAAK;EAEZ,gBAAgB;EAChB,aAAa,KAAK,eAAe;EACjC,kBAAkB,EAAE;EACpB,YAAY;EACZ,wBAAwB;EACxB,mBAAmB;EACnB,oBAAoB;EAEpB,UAAA;EACA,oBAAoB,EAAE;EACtB,UAAU;EACV,aAAa;EACb,YAAY;EACZ,qBAAqB,EAAE;EACvB,kBAAkB,EAAE;EACpB,8BAA8B;EAC9B,oBAAoB;EACpB,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAGhB,WAAW,KAAK,cAAc,OAAO,OAAO;EAC5C,eAAe,EAAE;EACjB,6BAA6B;EAC7B,UAAU;EACV,cAAc;EACd,aAAa;EACb,oBAAoB;EACpB,SAAS;EACT,YAAY;EACZ,iBAAiB;EACjB,iBAAiB;EACjB,sBAAsB;EACtB,mBAAmB;EACnB,iBAAiB;EACjB,qBAAqB;EACrB,YAAY;EACZ,WAAW;EACX,cAAc;EACd,aAAa;EACb,wBAAwB,EAAE;EAC1B,cAAc;EACd,SAAS;EACT,iBAAiB;EACjB,iBAAiB;EAClB"}
@@ -1,2 +0,0 @@
1
- import { l as prewarmYaraScanner } from "./yara-hooks-DZIVzhA6.js";
2
- export { prewarmYaraScanner };