@posthog/wizard 2.65.0 → 2.66.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 (101) hide show
  1. package/dist/{add-mcp-server-to-clients-ArtlMX9-.js → add-mcp-server-to-clients-DWDEuDUR.js} +209 -45
  2. package/dist/add-mcp-server-to-clients-DWDEuDUR.js.map +1 -0
  3. package/dist/{agent-interface-ORzGEFNM.js → agent-interface-D3MNaDp3.js} +337 -44
  4. package/dist/agent-interface-D3MNaDp3.js.map +1 -0
  5. package/dist/{agent-prompt-loader-D3w6sc34.js → agent-prompt-loader-D8Bajo-L.js} +5 -5
  6. package/dist/{agent-prompt-loader-D3w6sc34.js.map → agent-prompt-loader-D8Bajo-L.js.map} +1 -1
  7. package/dist/{agent-runner-Ca-e2TOQ.js → agent-runner-DEeMqJxy.js} +100 -49
  8. package/dist/agent-runner-DEeMqJxy.js.map +1 -0
  9. package/dist/{analytics-zBrIVjMV.js → analytics-D8JNuPAT.js} +2 -2
  10. package/dist/{analytics-zBrIVjMV.js.map → analytics-D8JNuPAT.js.map} +1 -1
  11. package/dist/analytics-DN3Kzf7H.js +2 -0
  12. package/dist/{api-Wgb7AhrP.js → api-CemGgyBv.js} +3 -3
  13. package/dist/{api-Wgb7AhrP.js.map → api-CemGgyBv.js.map} +1 -1
  14. package/dist/bin.js +95 -67
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{bounded-fs-DqsVmh4r.js → bounded-fs-C6OjqZst.js} +3 -3
  17. package/dist/{bounded-fs-DqsVmh4r.js.map → bounded-fs-C6OjqZst.js.map} +1 -1
  18. package/dist/{ci-install-D1QqmJIc.js → ci-install-DIB2n4Ju.js} +4 -4
  19. package/dist/{ci-install-D1QqmJIc.js.map → ci-install-DIB2n4Ju.js.map} +1 -1
  20. package/dist/{debug-Cm1hvkVy.js → debug-BKqv-yfT.js} +3 -3
  21. package/dist/{debug-Cm1hvkVy.js.map → debug-BKqv-yfT.js.map} +1 -1
  22. package/dist/{debug-CtQ13sCW.js → debug-H-GTKvvU.js} +1 -1
  23. package/dist/{env-api-key-CdI2XZIz.js → env-api-key-CzHDwfV2.js} +2 -2
  24. package/dist/{env-api-key-CdI2XZIz.js.map → env-api-key-CzHDwfV2.js.map} +1 -1
  25. package/dist/{environment-BhFvfkQg.js → environment-Cl-fIQku.js} +4 -4
  26. package/dist/{environment-BhFvfkQg.js.map → environment-Cl-fIQku.js.map} +1 -1
  27. package/dist/{file-watcher-Dciz09Rr.js → file-watcher-Cr-4tA-e.js} +2 -2
  28. package/dist/{file-watcher-Dciz09Rr.js.map → file-watcher-Cr-4tA-e.js.map} +1 -1
  29. package/dist/{headless-ui-B4FnKm11.js → headless-ui-DT3Db1bk.js} +2 -2
  30. package/dist/{headless-ui-B4FnKm11.js.map → headless-ui-DT3Db1bk.js.map} +1 -1
  31. package/dist/{interactive-DxHFVYr2.js → interactive-D3LdFxZG.js} +2 -2
  32. package/dist/{interactive-DxHFVYr2.js.map → interactive-D3LdFxZG.js.map} +1 -1
  33. package/dist/{mcp-t0UxAPur.js → mcp-BjckYQmP.js} +2 -2
  34. package/dist/{mcp-t0UxAPur.js.map → mcp-BjckYQmP.js.map} +1 -1
  35. package/dist/mcp-install-smoke-test.ts +477 -0
  36. package/dist/{mcp-prompt-streaming-ro98iUDc.js → mcp-prompt-streaming--sRErHKv.js} +4 -4
  37. package/dist/{mcp-prompt-streaming-ro98iUDc.js.map → mcp-prompt-streaming--sRErHKv.js.map} +1 -1
  38. package/dist/{non-interactive-BA2L_jDT.js → non-interactive-CNoYoEZp.js} +2 -2
  39. package/dist/{non-interactive-BA2L_jDT.js.map → non-interactive-CNoYoEZp.js.map} +1 -1
  40. package/dist/{orchestrator-tools-vZmNsHy9.js → orchestrator-tools-8bGyDDhn.js} +3 -3
  41. package/dist/{orchestrator-tools-vZmNsHy9.js.map → orchestrator-tools-8bGyDDhn.js.map} +1 -1
  42. package/dist/{package-manager-DgqJdAQk.js → package-manager-BQDHm7ER.js} +2 -2
  43. package/dist/{package-manager-DgqJdAQk.js.map → package-manager-BQDHm7ER.js.map} +1 -1
  44. package/dist/{pi-nwrCARRp.js → pi-W-4RUPFY.js} +11 -11
  45. package/dist/{pi-nwrCARRp.js.map → pi-W-4RUPFY.js.map} +1 -1
  46. package/dist/{playground-xkEke_h0.js → playground-uHHgZChe.js} +7 -7
  47. package/dist/{playground-xkEke_h0.js.map → playground-uHHgZChe.js.map} +1 -1
  48. package/dist/{posthog-9To56cSd.js → posthog-ChzdlmCs.js} +2 -2
  49. package/dist/{posthog-9To56cSd.js.map → posthog-ChzdlmCs.js.map} +1 -1
  50. package/dist/{posthog-integration-CoPvN6YZ.js → posthog-integration-LxEBGkoe.js} +661 -35
  51. package/dist/posthog-integration-LxEBGkoe.js.map +1 -0
  52. package/dist/{provisioning-BYFSHSHY.js → provisioning-BHTl91OZ.js} +3 -3
  53. package/dist/{provisioning-BYFSHSHY.js.map → provisioning-BHTl91OZ.js.map} +1 -1
  54. package/dist/{queue-tools-BREbgGSC.js → queue-tools-DABh1Ssc.js} +33 -7
  55. package/dist/queue-tools-DABh1Ssc.js.map +1 -0
  56. package/dist/{registry-DGJQ_8QI.js → registry-CxNpCNAj.js} +5 -5
  57. package/dist/{registry-DGJQ_8QI.js.map → registry-CxNpCNAj.js.map} +1 -1
  58. package/dist/{security-wc-naGq5.js → security-B4jU_-7q.js} +5 -5
  59. package/dist/{security-wc-naGq5.js.map → security-B4jU_-7q.js.map} +1 -1
  60. package/dist/{setup-utils-Cz0wPLsQ.js → setup-utils-aWZEdfwh.js} +9 -9
  61. package/dist/{setup-utils-Cz0wPLsQ.js.map → setup-utils-aWZEdfwh.js.map} +1 -1
  62. package/dist/{start-tui-DDW9uVnD.js → start-tui-BQH4mQIZ.js} +43 -21
  63. package/dist/start-tui-BQH4mQIZ.js.map +1 -0
  64. package/dist/{steps-CZI0B24_.js → steps-5HAqjUvn.js} +7 -7
  65. package/dist/{steps-CZI0B24_.js.map → steps-5HAqjUvn.js.map} +1 -1
  66. package/dist/{store-xMkU8xAa.js → store-P_7zUfbj.js} +7 -6
  67. package/dist/{store-xMkU8xAa.js.map → store-P_7zUfbj.js.map} +1 -1
  68. package/dist/{subagent-BztacyoV.js → subagent-uGPDXPfS.js} +2 -2
  69. package/dist/{subagent-BztacyoV.js.map → subagent-uGPDXPfS.js.map} +1 -1
  70. package/dist/{task-CJ7x3McC.js → task-oh8OAnvR.js} +12 -12
  71. package/dist/{task-CJ7x3McC.js.map → task-oh8OAnvR.js.map} +1 -1
  72. package/dist/{task-stream-BK7JQ27G.js → task-stream-jUARpyB5.js} +5 -5
  73. package/dist/{task-stream-BK7JQ27G.js.map → task-stream-jUARpyB5.js.map} +1 -1
  74. package/dist/{tasks-FGzp_zBd.js → tasks-2mu3lAvm.js} +2 -2
  75. package/dist/{tasks-FGzp_zBd.js.map → tasks-2mu3lAvm.js.map} +1 -1
  76. package/dist/{telemetry-By56gAtF.js → telemetry-BllPiBKw.js} +3 -3
  77. package/dist/{telemetry-By56gAtF.js.map → telemetry-BllPiBKw.js.map} +1 -1
  78. package/dist/{terminal-C_rmkaku.js → terminal-aWQrDy8s.js} +72 -79
  79. package/dist/terminal-aWQrDy8s.js.map +1 -0
  80. package/dist/{tools-BpCJgMez.js → tools-u8TaJFqa.js} +54 -47
  81. package/dist/tools-u8TaJFqa.js.map +1 -0
  82. package/dist/{wizard-abort-CzwID162.js → wizard-abort-D9jiMkZA.js} +4 -4
  83. package/dist/{wizard-abort-CzwID162.js.map → wizard-abort-D9jiMkZA.js.map} +1 -1
  84. package/dist/{wizard-abort-BlDla_Jd.js → wizard-abort-pFFH7dcx.js} +1 -1
  85. package/dist/{wizard-session-UxA_A0cA.js → wizard-session-Cw7-_OcZ.js} +1 -1
  86. package/dist/{wizard-session-Bn6dO1gE.js → wizard-session-DTyLMPsX.js} +2 -1
  87. package/dist/{wizard-session-Bn6dO1gE.js.map → wizard-session-DTyLMPsX.js.map} +1 -1
  88. package/dist/{yara-hooks-BrisBebM.js → yara-hooks-BXDBIOBq.js} +4 -4
  89. package/dist/{yara-hooks-BrisBebM.js.map → yara-hooks-BXDBIOBq.js.map} +1 -1
  90. package/dist/yara-hooks-i2jOabhI.js +2 -0
  91. package/package.json +2 -1
  92. package/dist/add-mcp-server-to-clients-ArtlMX9-.js.map +0 -1
  93. package/dist/agent-interface-ORzGEFNM.js.map +0 -1
  94. package/dist/agent-runner-Ca-e2TOQ.js.map +0 -1
  95. package/dist/analytics-C4j6grao.js +0 -2
  96. package/dist/posthog-integration-CoPvN6YZ.js.map +0 -1
  97. package/dist/queue-tools-BREbgGSC.js.map +0 -1
  98. package/dist/start-tui-DDW9uVnD.js.map +0 -1
  99. package/dist/terminal-C_rmkaku.js.map +0 -1
  100. package/dist/tools-BpCJgMez.js.map +0 -1
  101. package/dist/yara-hooks-D2B7Fd9G.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"headless-ui-B4FnKm11.js","names":[],"sources":["../src/ui/headless-ui.ts"],"sourcesContent":["import { LoggingUI } from './logging-ui';\nimport type { WizardStore } from './tui/store';\n\n/**\n * `LoggingUI` plus it feeds run state into a `WizardStore` so the background\n * wizard-session sync (`TaskStreamPush`) can observe a headless run. We extend\n * `LoggingUI` (not `InkUI`) because its blocking/gate methods would wait on a\n * TUI that never renders; the runner drives phase transitions on the store\n * directly, so only UI-originated per-run updates tee through here. Runner\n * machinery loads agent-authored artifacts such as the event plan directly\n * into the store.\n */\nexport class HeadlessUI extends LoggingUI {\n constructor(private readonly store: WizardStore) {\n super();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n super.syncTodos(todos);\n this.store.syncTodos(todos);\n }\n\n setHandoffText(text: string): void {\n this.store.setHandoffText(text);\n }\n}\n"],"mappings":";;;;;;;;;;;AAYA,IAAa,aAAb,cAAgC,UAAU;CACxC,YAAY,OAAqC;AAC/C,SAAO;AADoB,OAAA,QAAA;;CAI7B,UACE,OACM;AACN,QAAM,UAAU,MAAM;AACtB,OAAK,MAAM,UAAU,MAAM;;CAG7B,eAAe,MAAoB;AACjC,OAAK,MAAM,eAAe,KAAK"}
1
+ {"version":3,"file":"headless-ui-DT3Db1bk.js","names":[],"sources":["../src/ui/headless-ui.ts"],"sourcesContent":["import { LoggingUI } from './logging-ui';\nimport type { WizardStore } from './tui/store';\n\n/**\n * `LoggingUI` plus it feeds run state into a `WizardStore` so the background\n * wizard-session sync (`TaskStreamPush`) can observe a headless run. We extend\n * `LoggingUI` (not `InkUI`) because its blocking/gate methods would wait on a\n * TUI that never renders; the runner drives phase transitions on the store\n * directly, so only UI-originated per-run updates tee through here. Runner\n * machinery loads agent-authored artifacts such as the event plan directly\n * into the store.\n */\nexport class HeadlessUI extends LoggingUI {\n constructor(private readonly store: WizardStore) {\n super();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n super.syncTodos(todos);\n this.store.syncTodos(todos);\n }\n\n setHandoffText(text: string): void {\n this.store.setHandoffText(text);\n }\n}\n"],"mappings":";;;;;;;;;;;AAYA,IAAa,aAAb,cAAgC,UAAU;CACxC,YAAY,OAAqC;AAC/C,SAAO;AADoB,OAAA,QAAA;;CAI7B,UACE,OACM;AACN,QAAM,UAAU,MAAM;AACtB,OAAK,MAAM,UAAU,MAAM;;CAG7B,eAAe,MAAoB;AACjC,OAAK,MAAM,eAAe,KAAK"}
@@ -1,4 +1,4 @@
1
- import { r as posthogIntegrationConfig } from "./posthog-integration-CoPvN6YZ.js";
1
+ import { r as posthogIntegrationConfig } from "./posthog-integration-LxEBGkoe.js";
2
2
  import { u as runWizard } from "./bin.js";
3
3
  //#region src/commands/basic-integration/interactive.ts
4
4
  /** Default flow: run the posthog-integration program through the TUI. */
@@ -8,4 +8,4 @@ function runInteractive(argv) {
8
8
  //#endregion
9
9
  export { runInteractive };
10
10
 
11
- //# sourceMappingURL=interactive-DxHFVYr2.js.map
11
+ //# sourceMappingURL=interactive-D3LdFxZG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-DxHFVYr2.js","names":[],"sources":["../src/commands/basic-integration/interactive.ts"],"sourcesContent":["import type { Arguments } from 'yargs';\nimport { runWizard } from '@lib/runners';\nimport { posthogIntegrationConfig } from '@lib/programs/posthog-integration/index';\n\n/** Default flow: run the posthog-integration program through the TUI. */\nexport function runInteractive(argv: Arguments): void {\n runWizard(posthogIntegrationConfig, argv);\n}\n"],"mappings":";;;;AAKA,SAAgB,eAAe,MAAuB;AACpD,WAAU,0BAA0B,KAAK"}
1
+ {"version":3,"file":"interactive-D3LdFxZG.js","names":[],"sources":["../src/commands/basic-integration/interactive.ts"],"sourcesContent":["import type { Arguments } from 'yargs';\nimport { runWizard } from '@lib/runners';\nimport { posthogIntegrationConfig } from '@lib/programs/posthog-integration/index';\n\n/** Default flow: run the posthog-integration program through the TUI. */\nexport function runInteractive(argv: Arguments): void {\n runWizard(posthogIntegrationConfig, argv);\n}\n"],"mappings":";;;;AAKA,SAAgB,eAAe,MAAuB;AACpD,WAAU,0BAA0B,KAAK"}
@@ -1,4 +1,4 @@
1
- import { gt as VERSION, s as logToFile } from "./debug-Cm1hvkVy.js";
1
+ import { gt as VERSION, s as logToFile } from "./debug-BKqv-yfT.js";
2
2
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
3
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
4
  import { createJiti } from "jiti";
@@ -61,4 +61,4 @@ async function setupPostHogMcp(opts) {
61
61
  //#endregion
62
62
  export { fetchInstructions, setupPostHogMcp };
63
63
 
64
- //# sourceMappingURL=mcp-t0UxAPur.js.map
64
+ //# sourceMappingURL=mcp-BjckYQmP.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-t0UxAPur.js","names":[],"sources":["../src/lib/agent/runner/harness/pi/mcp.ts"],"sourcesContent":["/**\n * pi has no built-in MCP; `pi-mcp-adapter` — pi's own MCP extension, built here\n * with its supported `createMcpAdapter` embedding API — bridges the same hosted\n * MCP the anthropic path uses into the agent.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { createJiti } from 'jiti';\nimport { VERSION } from '@lib/version';\nimport { logToFile } from '@utils/debug';\n\nconst MCP_TOKEN_ENV = 'POSTHOG_MCP_TOKEN';\n\nexport interface PostHogMcpSetup {\n /** pi ExtensionFactory to add to the resource loader's `extensionFactories`. */\n extensionFactory: (pi: unknown) => void;\n /** Drop the token env var. Call after the run. */\n cleanup: () => void;\n}\n\n/** Server `instructions` for the system prompt — the adapter exposes no accessor, so one standard-SDK handshake; best-effort. */\nexport async function fetchInstructions(\n mcpUrl: string,\n accessToken: string,\n userAgent: string,\n): Promise<string | undefined> {\n const client = new Client({ name: 'posthog-wizard', version: VERSION });\n try {\n const transport = new StreamableHTTPClientTransport(new URL(mcpUrl), {\n requestInit: {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': userAgent,\n },\n },\n });\n await client.connect(transport);\n const instructions = client.getInstructions() || undefined;\n logToFile(`[pi-mcp] instructions ${instructions?.length ?? 0} chars`);\n return instructions;\n } catch (err) {\n logToFile(`[pi-mcp] instructions fetch skipped: ${String(err)}`);\n return undefined;\n } finally {\n await client.close().catch(() => undefined);\n }\n}\n\nexport async function setupPostHogMcp(opts: {\n mcpUrl: string;\n accessToken: string;\n userAgent: string;\n}): Promise<PostHogMcpSetup> {\n const { mcpUrl, accessToken, userAgent } = opts;\n\n // By env NAME: the token stays in this process, off disk, and never reaches pi's env-scrubbed tool subprocesses.\n process.env[MCP_TOKEN_ENV] = accessToken;\n\n // The adapter ships raw TypeScript; loading through jiti is its documented requirement.\n const jiti = createJiti(import.meta.url);\n const mod = await jiti.import('pi-mcp-adapter');\n const extensionFactory = mod.createMcpAdapter({\n config: {\n mcpServers: {\n posthog: {\n url: mcpUrl,\n auth: 'bearer',\n bearerTokenEnv: MCP_TOKEN_ENV,\n headers: { 'User-Agent': userAgent },\n // Connect at extension load — direct tools register without a session_start.\n lifecycle: 'eager',\n // Register only `exec`: `directTools: true` also mints a `posthog_get_<name>` tool per MCP resource, whose sentence-length names overflow Anthropic's 128-char tool-name limit and 400 the whole request.\n directTools: ['exec'],\n exposeResources: false,\n },\n },\n // Disable the proxy `mcp` tool (its search indirection pollutes context); the adapter re-enables it only if no direct tools resolve.\n settings: { disableProxyTool: true, toolPrefix: 'posthog' },\n },\n });\n logToFile(`[pi-mcp] adapter loaded; posthog MCP at ${mcpUrl}`);\n\n const cleanup = (): void => {\n delete process.env[MCP_TOKEN_ENV];\n };\n\n return { extensionFactory, cleanup };\n}\n"],"mappings":";;;;;;;;;;AAYA,MAAM,gBAAgB;;AAUtB,eAAsB,kBACpB,QACA,aACA,WAC6B;CAC7B,MAAM,SAAS,IAAI,OAAO;EAAE,MAAM;EAAkB,SAAS;EAAS,CAAC;AACvE,KAAI;EACF,MAAM,YAAY,IAAI,8BAA8B,IAAI,IAAI,OAAO,EAAE,EACnE,aAAa,EACX,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf,EACF,EACF,CAAC;AACF,QAAM,OAAO,QAAQ,UAAU;EAC/B,MAAM,eAAe,OAAO,iBAAiB,IAAI,KAAA;AACjD,YAAU,yBAAyB,cAAc,UAAU,EAAE,QAAQ;AACrE,SAAO;UACA,KAAK;AACZ,YAAU,wCAAwC,OAAO,IAAI,GAAG;AAChE;WACQ;AACR,QAAM,OAAO,OAAO,CAAC,YAAY,KAAA,EAAU;;;AAI/C,eAAsB,gBAAgB,MAIT;CAC3B,MAAM,EAAE,QAAQ,aAAa,cAAc;AAG3C,SAAQ,IAAI,iBAAiB;CAK7B,MAAM,oBADM,MADC,WAAW,OAAO,KAAK,IAAI,CACjB,OAAO,iBAAiB,EAClB,iBAAiB,EAC5C,QAAQ;EACN,YAAY,EACV,SAAS;GACP,KAAK;GACL,MAAM;GACN,gBAAgB;GAChB,SAAS,EAAE,cAAc,WAAW;GAEpC,WAAW;GAEX,aAAa,CAAC,OAAO;GACrB,iBAAiB;GAClB,EACF;EAED,UAAU;GAAE,kBAAkB;GAAM,YAAY;GAAW;EAC5D,EACF,CAAC;AACF,WAAU,2CAA2C,SAAS;CAE9D,MAAM,gBAAsB;AAC1B,SAAO,QAAQ,IAAI;;AAGrB,QAAO;EAAE;EAAkB;EAAS"}
1
+ {"version":3,"file":"mcp-BjckYQmP.js","names":[],"sources":["../src/lib/agent/runner/harness/pi/mcp.ts"],"sourcesContent":["/**\n * pi has no built-in MCP; `pi-mcp-adapter` — pi's own MCP extension, built here\n * with its supported `createMcpAdapter` embedding API — bridges the same hosted\n * MCP the anthropic path uses into the agent.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { createJiti } from 'jiti';\nimport { VERSION } from '@lib/version';\nimport { logToFile } from '@utils/debug';\n\nconst MCP_TOKEN_ENV = 'POSTHOG_MCP_TOKEN';\n\nexport interface PostHogMcpSetup {\n /** pi ExtensionFactory to add to the resource loader's `extensionFactories`. */\n extensionFactory: (pi: unknown) => void;\n /** Drop the token env var. Call after the run. */\n cleanup: () => void;\n}\n\n/** Server `instructions` for the system prompt — the adapter exposes no accessor, so one standard-SDK handshake; best-effort. */\nexport async function fetchInstructions(\n mcpUrl: string,\n accessToken: string,\n userAgent: string,\n): Promise<string | undefined> {\n const client = new Client({ name: 'posthog-wizard', version: VERSION });\n try {\n const transport = new StreamableHTTPClientTransport(new URL(mcpUrl), {\n requestInit: {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': userAgent,\n },\n },\n });\n await client.connect(transport);\n const instructions = client.getInstructions() || undefined;\n logToFile(`[pi-mcp] instructions ${instructions?.length ?? 0} chars`);\n return instructions;\n } catch (err) {\n logToFile(`[pi-mcp] instructions fetch skipped: ${String(err)}`);\n return undefined;\n } finally {\n await client.close().catch(() => undefined);\n }\n}\n\nexport async function setupPostHogMcp(opts: {\n mcpUrl: string;\n accessToken: string;\n userAgent: string;\n}): Promise<PostHogMcpSetup> {\n const { mcpUrl, accessToken, userAgent } = opts;\n\n // By env NAME: the token stays in this process, off disk, and never reaches pi's env-scrubbed tool subprocesses.\n process.env[MCP_TOKEN_ENV] = accessToken;\n\n // The adapter ships raw TypeScript; loading through jiti is its documented requirement.\n const jiti = createJiti(import.meta.url);\n const mod = await jiti.import('pi-mcp-adapter');\n const extensionFactory = mod.createMcpAdapter({\n config: {\n mcpServers: {\n posthog: {\n url: mcpUrl,\n auth: 'bearer',\n bearerTokenEnv: MCP_TOKEN_ENV,\n headers: { 'User-Agent': userAgent },\n // Connect at extension load — direct tools register without a session_start.\n lifecycle: 'eager',\n // Register only `exec`: `directTools: true` also mints a `posthog_get_<name>` tool per MCP resource, whose sentence-length names overflow Anthropic's 128-char tool-name limit and 400 the whole request.\n directTools: ['exec'],\n exposeResources: false,\n },\n },\n // Disable the proxy `mcp` tool (its search indirection pollutes context); the adapter re-enables it only if no direct tools resolve.\n settings: { disableProxyTool: true, toolPrefix: 'posthog' },\n },\n });\n logToFile(`[pi-mcp] adapter loaded; posthog MCP at ${mcpUrl}`);\n\n const cleanup = (): void => {\n delete process.env[MCP_TOKEN_ENV];\n };\n\n return { extensionFactory, cleanup };\n}\n"],"mappings":";;;;;;;;;;AAYA,MAAM,gBAAgB;;AAUtB,eAAsB,kBACpB,QACA,aACA,WAC6B;CAC7B,MAAM,SAAS,IAAI,OAAO;EAAE,MAAM;EAAkB,SAAS;EAAS,CAAC;AACvE,KAAI;EACF,MAAM,YAAY,IAAI,8BAA8B,IAAI,IAAI,OAAO,EAAE,EACnE,aAAa,EACX,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf,EACF,EACF,CAAC;AACF,QAAM,OAAO,QAAQ,UAAU;EAC/B,MAAM,eAAe,OAAO,iBAAiB,IAAI,KAAA;AACjD,YAAU,yBAAyB,cAAc,UAAU,EAAE,QAAQ;AACrE,SAAO;UACA,KAAK;AACZ,YAAU,wCAAwC,OAAO,IAAI,GAAG;AAChE;WACQ;AACR,QAAM,OAAO,OAAO,CAAC,YAAY,KAAA,EAAU;;;AAI/C,eAAsB,gBAAgB,MAIT;CAC3B,MAAM,EAAE,QAAQ,aAAa,cAAc;AAG3C,SAAQ,IAAI,iBAAiB;CAK7B,MAAM,oBADM,MADC,WAAW,OAAO,KAAK,IAAI,CACjB,OAAO,iBAAiB,EAClB,iBAAiB,EAC5C,QAAQ;EACN,YAAY,EACV,SAAS;GACP,KAAK;GACL,MAAM;GACN,gBAAgB;GAChB,SAAS,EAAE,cAAc,WAAW;GAEpC,WAAW;GAEX,aAAa,CAAC,OAAO;GACrB,iBAAiB;GAClB,EACF;EAED,UAAU;GAAE,kBAAkB;GAAM,YAAY;GAAW;EAC5D,EACF,CAAC;AACF,WAAU,2CAA2C,SAAS;CAE9D,MAAM,gBAAsB;AAC1B,SAAO,QAAQ,IAAI;;AAGrB,QAAO;EAAE;EAAkB;EAAS"}
@@ -0,0 +1,477 @@
1
+ /**
2
+ * Runs a headless `wizard mcp add` against a real editor CLI in a throwaway HOME
3
+ * and asserts the config that comes out. Drives the built binary rather than
4
+ * importing client classes, so arg parsing and command wiring are covered too.
5
+ *
6
+ * Needs no credentials: the OAuth path writes a tokenless entry and defers auth
7
+ * to the editor's own login command.
8
+ *
9
+ * Usage: tsx scripts/mcp-install-smoke-test.ts --provider=claude-code|codex
10
+ */
11
+
12
+ import { execFileSync, spawnSync } from 'node:child_process';
13
+ import * as fs from 'node:fs';
14
+ import * as os from 'node:os';
15
+ import * as path from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+
18
+ import { HEADLESS_FLAG } from '../src/lib/headless-mode';
19
+
20
+ const PROVIDERS = ['claude-code', 'codex'] as const;
21
+ type Provider = (typeof PROVIDERS)[number];
22
+
23
+ const MCP_URL = 'https://mcp.posthog.com/mcp';
24
+ const WIZARD = path.resolve(
25
+ fileURLToPath(import.meta.url),
26
+ '..',
27
+ '..',
28
+ 'dist',
29
+ 'bin.js',
30
+ );
31
+
32
+ interface ProviderSpec {
33
+ /** Editor CLI binary, looked up on PATH. */
34
+ binary: string;
35
+ /** The login subcommand the wizard tells the user to run, minus the server name. */
36
+ loginProbe: string[];
37
+ /** Config file relative to HOME, set only when the file is the contract. */
38
+ configPath?: string;
39
+ /** Exit code of a "is posthog installed" probe against the editor itself. */
40
+ isInstalled: () => boolean;
41
+ }
42
+
43
+ const SPECS: Record<Provider, ProviderSpec> = {
44
+ 'claude-code': {
45
+ binary: 'claude',
46
+ loginProbe: ['mcp', 'login', '--help'],
47
+ isInstalled: () => run('claude', ['mcp', 'get', 'posthog']).status === 0,
48
+ },
49
+ codex: {
50
+ binary: 'codex',
51
+ loginProbe: ['mcp', 'login', '--help'],
52
+ configPath: '.codex/config.toml',
53
+ isInstalled: () =>
54
+ (
55
+ readIfPresent(path.join(process.env.HOME!, '.codex', 'config.toml')) ??
56
+ ''
57
+ ).includes('[mcp_servers.posthog]'),
58
+ },
59
+ };
60
+
61
+ // ── harness ───────────────────────────────────────────────────────────────
62
+
63
+ const failures: string[] = [];
64
+ let currentScenario = '';
65
+
66
+ function fail(message: string): void {
67
+ failures.push(`${currentScenario}: ${message}`);
68
+ console.log(` ✗ ${message}`);
69
+ }
70
+
71
+ function pass(message: string): void {
72
+ console.log(` ✔ ${message}`);
73
+ }
74
+
75
+ function check(condition: boolean, message: string): boolean {
76
+ if (condition) pass(message);
77
+ else fail(message);
78
+ return condition;
79
+ }
80
+
81
+ interface Run {
82
+ status: number;
83
+ stdout: string;
84
+ stderr: string;
85
+ }
86
+
87
+ function run(binary: string, args: string[]): Run {
88
+ const r = spawnSync(binary, args, { encoding: 'utf-8' });
89
+ return {
90
+ status: r.error ? -1 : r.status ?? -1,
91
+ stdout: r.stdout ?? '',
92
+ stderr: r.stderr ?? '',
93
+ };
94
+ }
95
+
96
+ /** `wizard <args>` against the built binary, inheriting the sandbox HOME. */
97
+ function wizard(...args: string[]): Run {
98
+ return run(process.execPath, [WIZARD, ...args]);
99
+ }
100
+
101
+ /**
102
+ * The non-interactive install. Reuses the run pipeline's headless flag, so the
103
+ * name is imported rather than spelled out — see @lib/headless-mode.
104
+ */
105
+ function mcpAdd(...extra: string[]): Run {
106
+ return wizard('mcp', 'add', `--${HEADLESS_FLAG}`, ...extra);
107
+ }
108
+
109
+ function mcpRemove(): Run {
110
+ return wizard('mcp', 'remove', `--${HEADLESS_FLAG}`);
111
+ }
112
+
113
+ /**
114
+ * `os.homedir()` reads $HOME on POSIX and both editor CLIs store config under
115
+ * it, so one env var isolates the wizard and the CLI it shells out to. A
116
+ * pristine dir per scenario is what a first-time user actually has.
117
+ */
118
+ async function withSandboxHome(
119
+ spec: ProviderSpec,
120
+ fn: (home: string) => Promise<void>,
121
+ ): Promise<void> {
122
+ const realHome = process.env.HOME;
123
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'wizard-mcp-'));
124
+ const before = failures.length;
125
+ process.env.HOME = home;
126
+ try {
127
+ await fn(home);
128
+ } finally {
129
+ // The sandbox is about to go and CI has nothing else to look at.
130
+ if (failures.length > before && spec.configPath) {
131
+ const contents = readIfPresent(path.join(home, spec.configPath));
132
+ console.log(
133
+ contents === null
134
+ ? ` ── ${spec.configPath} was never written ──`
135
+ : ` ── ${spec.configPath} ──\n${contents.replace(/^/gm, ' │ ')}`,
136
+ );
137
+ }
138
+ process.env.HOME = realHome;
139
+ fs.rmSync(home, { recursive: true, force: true });
140
+ }
141
+ }
142
+
143
+ function seed(home: string, relative: string, contents: string): void {
144
+ const target = path.join(home, relative);
145
+ fs.mkdirSync(path.dirname(target), { recursive: true });
146
+ fs.writeFileSync(target, contents);
147
+ }
148
+
149
+ function readIfPresent(file: string): string | null {
150
+ try {
151
+ return fs.readFileSync(file, 'utf-8');
152
+ } catch {
153
+ return null;
154
+ }
155
+ }
156
+
157
+ /** Asserts a clean exit, quoting the reason only when it failed. */
158
+ function checkRun(r: Run, label: string): boolean {
159
+ if (r.status === 0) return check(true, label);
160
+ const lines = (r.stderr + r.stdout)
161
+ .split('\n')
162
+ .map((l) => l.trim())
163
+ .filter(Boolean);
164
+ // The step prints failures as `- <client> — <detail>` under a success header,
165
+ // so the first line is usually the wrong one to quote.
166
+ const reason =
167
+ lines.find((l) => l.includes('—')) ?? lines[0] ?? `exit ${r.status}`;
168
+ return check(false, `${label} — ${reason}`);
169
+ }
170
+
171
+ // ── scenarios ─────────────────────────────────────────────────────────────
172
+
173
+ /** A fresh box has no editor config directory at all — the write must create it. */
174
+ async function scenarioFreshInstall(spec: ProviderSpec): Promise<void> {
175
+ await withSandboxHome(spec, async (home) => {
176
+ check(!spec.isInstalled(), 'reports not-installed on a fresh HOME');
177
+
178
+ const r = mcpAdd();
179
+ if (!checkRun(r, 'mcp add exits 0')) return;
180
+ check(spec.isInstalled(), 'the editor reports the server installed');
181
+
182
+ if (spec.configPath) {
183
+ const contents = readIfPresent(path.join(home, spec.configPath));
184
+ if (!check(contents !== null, `wrote ${spec.configPath}`)) return;
185
+ // Match the whole configured value, not a URL substring — `includes`
186
+ // on a bare URL also accepts hosts that merely embed it.
187
+ check(
188
+ contents!.includes(`"${MCP_URL}"`),
189
+ 'the written config carries exactly the MCP url',
190
+ );
191
+ check(
192
+ /startup_timeout_sec\s*=/.test(contents!),
193
+ 'the written config carries a startup timeout',
194
+ );
195
+ }
196
+ });
197
+ }
198
+
199
+ /**
200
+ * A config the wizard is happy with and the editor rejects is the worst case:
201
+ * we report "installed" and the user loses every server in the file.
202
+ */
203
+ async function scenarioEditorAcceptsConfig(spec: ProviderSpec): Promise<void> {
204
+ await withSandboxHome(spec, async () => {
205
+ const r = mcpAdd();
206
+ if (!checkRun(r, 'mcp add exits 0')) return;
207
+
208
+ check(
209
+ run(spec.binary, ['mcp', 'list']).status === 0,
210
+ `${spec.binary} mcp list parses the config (exit 0)`,
211
+ );
212
+ });
213
+ }
214
+
215
+ /** Re-running the wizard is the common case, not the edge case. */
216
+ async function scenarioIdempotent(spec: ProviderSpec): Promise<void> {
217
+ await withSandboxHome(spec, async (home) => {
218
+ const first = mcpAdd();
219
+ if (!checkRun(first, 'first add exits 0')) return;
220
+
221
+ const second = mcpAdd();
222
+ checkRun(second, 'second add exits 0');
223
+ check(
224
+ /already installed|nothing changed/i.test(second.stdout + second.stderr),
225
+ 'second add reports it changed nothing',
226
+ );
227
+
228
+ if (spec.configPath) {
229
+ const contents = readIfPresent(path.join(home, spec.configPath)) ?? '';
230
+ const sections = contents.match(/^\s*\[mcp_servers\.posthog\]/gm) ?? [];
231
+ // Two definitions of one TOML table is a parse error on the whole file.
232
+ check(
233
+ sections.length === 1,
234
+ `exactly one [mcp_servers.posthog] section (found ${sections.length})`,
235
+ );
236
+ check(
237
+ run(spec.binary, ['mcp', 'list']).status === 0,
238
+ 'the editor still parses the config after a re-run',
239
+ );
240
+ }
241
+ });
242
+ }
243
+
244
+ /**
245
+ * `--features` is a documented flag. Honouring it or rejecting it are both
246
+ * defensible; accepting it and installing full scope anyway is not.
247
+ */
248
+ async function scenarioFeaturesFlag(spec: ProviderSpec): Promise<void> {
249
+ await withSandboxHome(spec, async (home) => {
250
+ const r = mcpAdd('--features', 'flags,insights');
251
+ if (!checkRun(r, 'mcp add --features exits 0')) return;
252
+
253
+ // Claude Code owns its own store, so read the URL back through its CLI.
254
+ const url = spec.configPath
255
+ ? readIfPresent(path.join(home, spec.configPath)) ?? ''
256
+ : run(spec.binary, ['mcp', 'get', 'posthog']).stdout;
257
+
258
+ check(
259
+ url.includes('features=flags,insights'),
260
+ 'the installed URL carries the requested features',
261
+ );
262
+ });
263
+ }
264
+
265
+ /** The update path is separate code from the create path, and can no-op silently. */
266
+ async function scenarioUpdatesExistingEntry(spec: ProviderSpec): Promise<void> {
267
+ if (!spec.configPath) return;
268
+
269
+ await withSandboxHome(spec, async (home) => {
270
+ seed(
271
+ home,
272
+ spec.configPath!,
273
+ [
274
+ '[mcp_servers.unrelated]',
275
+ 'command = "some-other-server"',
276
+ '',
277
+ '[mcp_servers.posthog]',
278
+ 'url = "https://mcp.posthog.com/mcp?features=flags"',
279
+ 'startup_timeout_sec = 30',
280
+ '',
281
+ ].join('\n'),
282
+ );
283
+
284
+ const r = mcpAdd();
285
+ if (!checkRun(r, 'mcp add exits 0')) return;
286
+
287
+ const contents = readIfPresent(path.join(home, spec.configPath!)) ?? '';
288
+ check(
289
+ contents.includes(`url = "${MCP_URL}"`),
290
+ 'the stale features URL was replaced',
291
+ );
292
+ check(
293
+ contents.includes('[mcp_servers.unrelated]'),
294
+ "an unrelated user's server survived the write",
295
+ );
296
+ check(
297
+ run(spec.binary, ['mcp', 'list']).status === 0,
298
+ 'the editor still parses the config after an update',
299
+ );
300
+ });
301
+ }
302
+
303
+ /**
304
+ * TOML does not care about key order, so anything assuming `url` sits on the
305
+ * line after the header reads this as "no match".
306
+ */
307
+ async function scenarioUpdatesReorderedEntry(
308
+ spec: ProviderSpec,
309
+ ): Promise<void> {
310
+ if (!spec.configPath) return;
311
+
312
+ await withSandboxHome(spec, async (home) => {
313
+ seed(
314
+ home,
315
+ spec.configPath!,
316
+ [
317
+ '[mcp_servers.posthog]',
318
+ 'startup_timeout_sec = 30',
319
+ 'url = "https://mcp.posthog.com/mcp?features=flags"',
320
+ '',
321
+ ].join('\n'),
322
+ );
323
+
324
+ const r = mcpAdd();
325
+ const contents = readIfPresent(path.join(home, spec.configPath!)) ?? '';
326
+
327
+ // Rewrite it or refuse and say so; claiming success without writing is the
328
+ // only outcome that isn't defensible.
329
+ if (r.status !== 0) {
330
+ pass("declined to edit a key order it can't handle");
331
+ } else {
332
+ check(
333
+ contents.includes(`url = "${MCP_URL}"`),
334
+ 'a reported success actually replaced the stale URL',
335
+ );
336
+ }
337
+ });
338
+ }
339
+
340
+ /**
341
+ * TOML permits a quoted table key. A substring scan for the bare form misses it
342
+ * and appends a second definition of the same table.
343
+ */
344
+ async function scenarioQuotedTableKey(spec: ProviderSpec): Promise<void> {
345
+ if (!spec.configPath) return;
346
+
347
+ await withSandboxHome(spec, async (home) => {
348
+ seed(
349
+ home,
350
+ spec.configPath!,
351
+ ['[mcp_servers."posthog"]', `url = "${MCP_URL}"`, ''].join('\n'),
352
+ );
353
+
354
+ mcpAdd();
355
+
356
+ check(
357
+ run(spec.binary, ['mcp', 'list']).status === 0,
358
+ 'the editor still parses a config that used a quoted table key',
359
+ );
360
+ });
361
+ }
362
+
363
+ /** `mcp remove` reporting success while leaving the server in place is the bug. */
364
+ async function scenarioRemove(spec: ProviderSpec): Promise<void> {
365
+ await withSandboxHome(spec, async () => {
366
+ const added = mcpAdd();
367
+ if (!checkRun(added, 'mcp add exits 0')) return;
368
+
369
+ const removed = mcpRemove();
370
+ if (!checkRun(removed, 'mcp remove exits 0')) return;
371
+
372
+ check(!spec.isInstalled(), 'the editor reports the server gone');
373
+ });
374
+ }
375
+
376
+ /**
377
+ * The wizard prints a login command for the user to run by hand. If the editor
378
+ * renames that subcommand, nothing else in the build notices.
379
+ */
380
+ async function scenarioLoginCommandExists(spec: ProviderSpec): Promise<void> {
381
+ const probe = run(spec.binary, spec.loginProbe);
382
+ check(
383
+ probe.status === 0,
384
+ `${spec.binary} ${spec.loginProbe.join(' ')} exists (exit 0)`,
385
+ );
386
+ }
387
+
388
+ // ── runner ────────────────────────────────────────────────────────────────
389
+
390
+ const SCENARIOS: Array<{
391
+ name: string;
392
+ run: (spec: ProviderSpec) => Promise<void>;
393
+ }> = [
394
+ { name: 'fresh install on an empty HOME', run: scenarioFreshInstall },
395
+ {
396
+ name: 'the editor can parse what we wrote',
397
+ run: scenarioEditorAcceptsConfig,
398
+ },
399
+ { name: 're-running the install is a no-op', run: scenarioIdempotent },
400
+ { name: '--features reaches the installed URL', run: scenarioFeaturesFlag },
401
+ { name: 'updates an existing entry', run: scenarioUpdatesExistingEntry },
402
+ {
403
+ name: 'updates an entry with reordered keys',
404
+ run: scenarioUpdatesReorderedEntry,
405
+ },
406
+ { name: 'survives a quoted TOML table key', run: scenarioQuotedTableKey },
407
+ { name: 'remove actually removes', run: scenarioRemove },
408
+ {
409
+ name: 'the login command it prints exists',
410
+ run: scenarioLoginCommandExists,
411
+ },
412
+ ];
413
+
414
+ function parseProvider(): Provider {
415
+ const arg = process.argv
416
+ .find((a) => a.startsWith('--provider='))
417
+ ?.split('=')[1];
418
+ if (!arg || !(PROVIDERS as readonly string[]).includes(arg)) {
419
+ console.error(`Pass --provider=<${PROVIDERS.join('|')}>.`);
420
+ process.exit(2);
421
+ }
422
+ return arg as Provider;
423
+ }
424
+
425
+ async function main(): Promise<void> {
426
+ const provider = parseProvider();
427
+ const spec = SPECS[provider];
428
+
429
+ if (!fs.existsSync(WIZARD)) {
430
+ console.error(`✗ ${WIZARD} not found — run \`pnpm build\` first.`);
431
+ process.exit(1);
432
+ }
433
+
434
+ // Hard failure, not a skip — a skipped matrix leg looks green on the PR page.
435
+ let version: string;
436
+ try {
437
+ version = execFileSync(spec.binary, ['--version'], { encoding: 'utf-8' })
438
+ .trim()
439
+ .split('\n')[0]!;
440
+ } catch (err) {
441
+ console.error(
442
+ `✗ ${spec.binary} is not runnable on this machine — ${
443
+ (err as Error).message
444
+ }`,
445
+ );
446
+ process.exit(1);
447
+ }
448
+
449
+ console.log(`\nMCP install smoke test — ${provider} (${version})\n`);
450
+
451
+ for (const scenario of SCENARIOS) {
452
+ currentScenario = scenario.name;
453
+ console.log(`▸ ${scenario.name}`);
454
+ try {
455
+ await scenario.run(spec);
456
+ } catch (err) {
457
+ fail(`threw — ${(err as Error).message}`);
458
+ }
459
+ }
460
+
461
+ if (failures.length > 0) {
462
+ console.error(
463
+ `\n✗ MCP install smoke test FAILED for ${provider} (${failures.length}):`,
464
+ );
465
+ for (const f of failures) console.error(` - ${f}`);
466
+ process.exit(1);
467
+ }
468
+
469
+ console.log(
470
+ `\n✔ MCP install smoke test passed for ${provider} (${SCENARIOS.length} scenarios)`,
471
+ );
472
+ }
473
+
474
+ main().catch((err) => {
475
+ console.error('MCP install smoke test crashed:', err);
476
+ process.exit(1);
477
+ });
@@ -1,6 +1,6 @@
1
- import { D as DEFAULT_AGENT_MODEL, pt as WIZARD_USER_AGENT, s as logToFile } from "./debug-Cm1hvkVy.js";
2
- import { n as analytics } from "./analytics-zBrIVjMV.js";
3
- import { d as sanitizeAgentSubprocessEnv, n as buildRunTags, t as buildAgentEnv } from "./agent-interface-ORzGEFNM.js";
1
+ import { D as DEFAULT_AGENT_MODEL, pt as WIZARD_USER_AGENT, s as logToFile } from "./debug-BKqv-yfT.js";
2
+ import { n as analytics } from "./analytics-D8JNuPAT.js";
3
+ import { d as sanitizeAgentSubprocessEnv, n as buildRunTags, t as buildAgentEnv } from "./agent-interface-D3MNaDp3.js";
4
4
  //#region src/lib/agent/mcp-prompt-streaming.ts
5
5
  let _sdkModule = null;
6
6
  async function loadSdk() {
@@ -246,4 +246,4 @@ async function* runMcpPromptViaSdk(args) {
246
246
  //#endregion
247
247
  export { runMcpPromptViaSdk };
248
248
 
249
- //# sourceMappingURL=mcp-prompt-streaming-ro98iUDc.js.map
249
+ //# sourceMappingURL=mcp-prompt-streaming--sRErHKv.js.map