@posthog/wizard 2.64.1 → 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 (118) hide show
  1. package/README.md +7 -2
  2. package/dist/{add-mcp-server-to-clients-BUqb93_I.js → add-mcp-server-to-clients-DWDEuDUR.js} +210 -46
  3. package/dist/add-mcp-server-to-clients-DWDEuDUR.js.map +1 -0
  4. package/dist/{agent-interface-NurnwA01.js → agent-interface-D3MNaDp3.js} +405 -47
  5. package/dist/agent-interface-D3MNaDp3.js.map +1 -0
  6. package/dist/{agent-prompt-loader-CbowPuWI.js → agent-prompt-loader-D8Bajo-L.js} +10 -5
  7. package/dist/agent-prompt-loader-D8Bajo-L.js.map +1 -0
  8. package/dist/{agent-runner-DisJWxJa.js → agent-runner-DEeMqJxy.js} +111 -53
  9. package/dist/agent-runner-DEeMqJxy.js.map +1 -0
  10. package/dist/{analytics-D3vKvr3l.js → analytics-D8JNuPAT.js} +2 -2
  11. package/dist/{analytics-D3vKvr3l.js.map → analytics-D8JNuPAT.js.map} +1 -1
  12. package/dist/analytics-DN3Kzf7H.js +2 -0
  13. package/dist/{api-Bhe8jpUR.js → api-CemGgyBv.js} +3 -3
  14. package/dist/{api-Bhe8jpUR.js.map → api-CemGgyBv.js.map} +1 -1
  15. package/dist/bin.js +245 -93
  16. package/dist/bin.js.map +1 -1
  17. package/dist/{bounded-fs-BeWc675I.js → bounded-fs-C6OjqZst.js} +3 -3
  18. package/dist/{bounded-fs-BeWc675I.js.map → bounded-fs-C6OjqZst.js.map} +1 -1
  19. package/dist/{ci-install-BpNzfghY.js → ci-install-DIB2n4Ju.js} +4 -4
  20. package/dist/{ci-install-BpNzfghY.js.map → ci-install-DIB2n4Ju.js.map} +1 -1
  21. package/dist/{debug-hy6aWAyk.js → debug-BKqv-yfT.js} +14 -9
  22. package/dist/debug-BKqv-yfT.js.map +1 -0
  23. package/dist/{debug-DGfRPr2A.js → debug-H-GTKvvU.js} +1 -1
  24. package/dist/{defaults-mrAre0xM.js → defaults-BHhXrX9F.js} +1 -1
  25. package/dist/{defaults-mrAre0xM.js.map → defaults-BHhXrX9F.js.map} +1 -1
  26. package/dist/{env-api-key-CMPe-WJp.js → env-api-key-CzHDwfV2.js} +2 -2
  27. package/dist/{env-api-key-CMPe-WJp.js.map → env-api-key-CzHDwfV2.js.map} +1 -1
  28. package/dist/{environment-Ktu0Ktjl.js → environment-Cl-fIQku.js} +4 -4
  29. package/dist/{environment-Ktu0Ktjl.js.map → environment-Cl-fIQku.js.map} +1 -1
  30. package/dist/{file-watcher-CqJ1dgjq.js → file-watcher-Cr-4tA-e.js} +2 -2
  31. package/dist/{file-watcher-CqJ1dgjq.js.map → file-watcher-Cr-4tA-e.js.map} +1 -1
  32. package/dist/{headless-ui-zZLgs4QL.js → headless-ui-DT3Db1bk.js} +2 -2
  33. package/dist/{headless-ui-zZLgs4QL.js.map → headless-ui-DT3Db1bk.js.map} +1 -1
  34. package/dist/{interactive-BUw1SEOz.js → interactive-D3LdFxZG.js} +2 -2
  35. package/dist/{interactive-BUw1SEOz.js.map → interactive-D3LdFxZG.js.map} +1 -1
  36. package/dist/local-dev-BN6NKQ0B.js +135 -0
  37. package/dist/local-dev-BN6NKQ0B.js.map +1 -0
  38. package/dist/{mcp-C7NMhhWa.js → mcp-BjckYQmP.js} +2 -2
  39. package/dist/{mcp-C7NMhhWa.js.map → mcp-BjckYQmP.js.map} +1 -1
  40. package/dist/mcp-install-smoke-test.ts +477 -0
  41. package/dist/{mcp-prompt-streaming-CKyqqB10.js → mcp-prompt-streaming--sRErHKv.js} +20 -4
  42. package/dist/mcp-prompt-streaming--sRErHKv.js.map +1 -0
  43. package/dist/{non-interactive-73xGtug6.js → non-interactive-CNoYoEZp.js} +2 -2
  44. package/dist/{non-interactive-73xGtug6.js.map → non-interactive-CNoYoEZp.js.map} +1 -1
  45. package/dist/{orchestrator-tools-DcMJzfDH.js → orchestrator-tools-8bGyDDhn.js} +3 -3
  46. package/dist/{orchestrator-tools-DcMJzfDH.js.map → orchestrator-tools-8bGyDDhn.js.map} +1 -1
  47. package/dist/{package-json-CDs1ZVKu.js → package-json-D0DCWpe5.js} +1 -1
  48. package/dist/{package-json-CDs1ZVKu.js.map → package-json-D0DCWpe5.js.map} +1 -1
  49. package/dist/{package-manager-KweKX3u_.js → package-manager-BQDHm7ER.js} +58 -3
  50. package/dist/package-manager-BQDHm7ER.js.map +1 -0
  51. package/dist/{pi-B4p4gpr0.js → pi-W-4RUPFY.js} +11 -11
  52. package/dist/{pi-B4p4gpr0.js.map → pi-W-4RUPFY.js.map} +1 -1
  53. package/dist/{playground-AEkWcB1E.js → playground-uHHgZChe.js} +7 -7
  54. package/dist/{playground-AEkWcB1E.js.map → playground-uHHgZChe.js.map} +1 -1
  55. package/dist/{posthog-4PljLcIz.js → posthog-ChzdlmCs.js} +2 -2
  56. package/dist/{posthog-4PljLcIz.js.map → posthog-ChzdlmCs.js.map} +1 -1
  57. package/dist/{posthog-integration-DKlEg8-Q.js → posthog-integration-LxEBGkoe.js} +680 -49
  58. package/dist/posthog-integration-LxEBGkoe.js.map +1 -0
  59. package/dist/{provisioning-QsG7HDCm.js → provisioning-BHTl91OZ.js} +3 -3
  60. package/dist/{provisioning-QsG7HDCm.js.map → provisioning-BHTl91OZ.js.map} +1 -1
  61. package/dist/{queue-tools-Jlz9dV_B.js → queue-tools-DABh1Ssc.js} +33 -7
  62. package/dist/queue-tools-DABh1Ssc.js.map +1 -0
  63. package/dist/{registry-PG_nV5Bf.js → registry-CxNpCNAj.js} +309 -6
  64. package/dist/registry-CxNpCNAj.js.map +1 -0
  65. package/dist/{security-BKUJk-Gg.js → security-B4jU_-7q.js} +5 -5
  66. package/dist/{security-BKUJk-Gg.js.map → security-B4jU_-7q.js.map} +1 -1
  67. package/dist/{setup-utils-DNpldqge.js → setup-utils-aWZEdfwh.js} +18 -13
  68. package/dist/setup-utils-aWZEdfwh.js.map +1 -0
  69. package/dist/smoke-test-ci.sh +12 -1
  70. package/dist/{start-tui-D4B0-2nr.js → start-tui-BQH4mQIZ.js} +138 -27
  71. package/dist/start-tui-BQH4mQIZ.js.map +1 -0
  72. package/dist/{steps-Dy0AXdGo.js → steps-5HAqjUvn.js} +7 -7
  73. package/dist/{steps-Dy0AXdGo.js.map → steps-5HAqjUvn.js.map} +1 -1
  74. package/dist/{store-DouLLelV.js → store-P_7zUfbj.js} +22 -7
  75. package/dist/store-P_7zUfbj.js.map +1 -0
  76. package/dist/{subagent-B4yVs5A2.js → subagent-uGPDXPfS.js} +2 -2
  77. package/dist/{subagent-B4yVs5A2.js.map → subagent-uGPDXPfS.js.map} +1 -1
  78. package/dist/{task-DRKYEbKM.js → task-oh8OAnvR.js} +29 -18
  79. package/dist/task-oh8OAnvR.js.map +1 -0
  80. package/dist/{task-stream-BGUP7yA-.js → task-stream-jUARpyB5.js} +5 -5
  81. package/dist/{task-stream-BGUP7yA-.js.map → task-stream-jUARpyB5.js.map} +1 -1
  82. package/dist/{tasks-B2GzXsZ0.js → tasks-2mu3lAvm.js} +2 -2
  83. package/dist/{tasks-B2GzXsZ0.js.map → tasks-2mu3lAvm.js.map} +1 -1
  84. package/dist/{telemetry-6zaFfCcy.js → telemetry-BllPiBKw.js} +3 -3
  85. package/dist/{telemetry-6zaFfCcy.js.map → telemetry-BllPiBKw.js.map} +1 -1
  86. package/dist/{terminal-Bu3eHFn0.js → terminal-aWQrDy8s.js} +99 -98
  87. package/dist/terminal-aWQrDy8s.js.map +1 -0
  88. package/dist/{tools-DQO5tKJg.js → tools-u8TaJFqa.js} +54 -47
  89. package/dist/tools-u8TaJFqa.js.map +1 -0
  90. package/dist/{wizard-abort-D6jJh8u5.js → wizard-abort-D9jiMkZA.js} +4 -4
  91. package/dist/{wizard-abort-D6jJh8u5.js.map → wizard-abort-D9jiMkZA.js.map} +1 -1
  92. package/dist/{wizard-abort-PgTdRS1l.js → wizard-abort-pFFH7dcx.js} +1 -1
  93. package/dist/{wizard-session-DZUDtS5d.js → wizard-session-Cw7-_OcZ.js} +1 -1
  94. package/dist/{wizard-session-BUhlJ1b8.js → wizard-session-DTyLMPsX.js} +17 -3
  95. package/dist/wizard-session-DTyLMPsX.js.map +1 -0
  96. package/dist/{yara-hooks-DjReXmTQ.js → yara-hooks-BXDBIOBq.js} +4 -4
  97. package/dist/{yara-hooks-DjReXmTQ.js.map → yara-hooks-BXDBIOBq.js.map} +1 -1
  98. package/dist/yara-hooks-i2jOabhI.js +2 -0
  99. package/package.json +2 -1
  100. package/dist/add-mcp-server-to-clients-BUqb93_I.js.map +0 -1
  101. package/dist/agent-interface-NurnwA01.js.map +0 -1
  102. package/dist/agent-prompt-loader-CbowPuWI.js.map +0 -1
  103. package/dist/agent-runner-DisJWxJa.js.map +0 -1
  104. package/dist/analytics-hNca7GLq.js +0 -2
  105. package/dist/debug-hy6aWAyk.js.map +0 -1
  106. package/dist/mcp-prompt-streaming-CKyqqB10.js.map +0 -1
  107. package/dist/package-manager-KweKX3u_.js.map +0 -1
  108. package/dist/posthog-integration-DKlEg8-Q.js.map +0 -1
  109. package/dist/queue-tools-Jlz9dV_B.js.map +0 -1
  110. package/dist/registry-PG_nV5Bf.js.map +0 -1
  111. package/dist/setup-utils-DNpldqge.js.map +0 -1
  112. package/dist/start-tui-D4B0-2nr.js.map +0 -1
  113. package/dist/store-DouLLelV.js.map +0 -1
  114. package/dist/task-DRKYEbKM.js.map +0 -1
  115. package/dist/terminal-Bu3eHFn0.js.map +0 -1
  116. package/dist/tools-DQO5tKJg.js.map +0 -1
  117. package/dist/wizard-session-BUhlJ1b8.js.map +0 -1
  118. package/dist/yara-hooks-CN_uFGCu.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"file-watcher-CqJ1dgjq.js","names":["fs"],"sources":["../src/lib/file-watcher.ts"],"sourcesContent":["/**\n * JSON file watcher shared by runner and UI machinery.\n *\n * `fs.watch` alone is unreliable for atomic-rename writes, so the watcher\n * pairs it with a continuous mtime-polled re-read. The poll catches missed\n * events; the watch keeps latency low when it does fire.\n */\n\nimport * as fs from 'fs';\nimport { basename, dirname } from 'node:path';\nimport { logToFile } from '@utils/debug';\n\nconst DEFAULT_POLL_INTERVAL_MS = 5000;\nconst DEFAULT_ATTACH_RETRY_INTERVAL_MS = 1000;\nconst DEFAULT_WATCH_DEBOUNCE_MS = 25;\n\nexport interface FileWatcherHandle {\n refresh(): void;\n stop(): void;\n}\n\nexport interface FileWatcherOptions {\n /** ms between mtime checks once the file exists. */\n pollIntervalMs?: number;\n /** ms between attach attempts while waiting for the file to appear. */\n attachRetryIntervalMs?: number;\n /** ms to coalesce duplicate filesystem events. */\n watchDebounceMs?: number;\n /** Ignore the file that exists when the watcher starts until it changes. */\n ignoreInitialFile?: boolean;\n /** Refuse to read files larger than this many bytes. */\n maxFileSizeBytes?: number;\n}\n\n/** Watch `path` for JSON updates and call `onUpdate(parsed)` whenever the\n * file's mtime changes and the contents are valid JSON. Caller must invoke\n * `handle.stop()` to release the watcher. */\nexport function startFileWatcher(\n path: string,\n onUpdate: (parsed: unknown) => void,\n options: FileWatcherOptions = {},\n): FileWatcherHandle {\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const attachRetryIntervalMs =\n options.attachRetryIntervalMs ?? DEFAULT_ATTACH_RETRY_INTERVAL_MS;\n const watchDebounceMs = options.watchDebounceMs ?? DEFAULT_WATCH_DEBOUNCE_MS;\n\n const watchers: fs.FSWatcher[] = [];\n const intervals: Array<ReturnType<typeof setInterval>> = [];\n const targetDir = dirname(path);\n const targetName = basename(path);\n let lastMtimeMs = 0;\n let ignoredInitialSignature: string | null = null;\n let watchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n let lastReadErrorSignature: string | null = null;\n let stopped = false;\n\n const signature = (stat: fs.Stats): string =>\n `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;\n\n if (options.ignoreInitialFile) {\n try {\n const stat = fs.lstatSync(path);\n if (stat.isFile() && !stat.isSymbolicLink()) {\n ignoredInitialSignature = signature(stat);\n }\n } catch {\n // No initial file to ignore.\n }\n }\n\n const logReadError = (errorSignature: string, message: string) => {\n if (lastReadErrorSignature === errorSignature) return;\n lastReadErrorSignature = errorSignature;\n logToFile(`[file-watcher] ${message}: ${path}`);\n };\n\n const read = (force = false) => {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(path);\n } catch {\n return;\n }\n\n if (!stat.isFile() || stat.isSymbolicLink()) return;\n const fileSignature = signature(stat);\n\n try {\n if (ignoredInitialSignature) {\n if (fileSignature === ignoredInitialSignature) return;\n ignoredInitialSignature = null;\n }\n if (\n options.maxFileSizeBytes !== undefined &&\n stat.size > options.maxFileSizeBytes\n ) {\n logReadError(\n `oversized:${fileSignature}`,\n `refusing oversized JSON file (${stat.size} bytes, limit ${options.maxFileSizeBytes} bytes)`,\n );\n return;\n }\n if (!force && stat.mtimeMs === lastMtimeMs) return;\n lastMtimeMs = stat.mtimeMs;\n const parsed: unknown = JSON.parse(fs.readFileSync(path, 'utf-8'));\n lastReadErrorSignature = null;\n onUpdate(parsed);\n } catch (error) {\n logReadError(\n `invalid:${fileSignature}:${String(error)}`,\n `could not read valid JSON (${String(error)})`,\n );\n }\n };\n\n const scheduleRead = () => {\n if (stopped) return;\n if (watchDebounceTimer) clearTimeout(watchDebounceTimer);\n watchDebounceTimer = setTimeout(() => {\n watchDebounceTimer = null;\n read(true);\n }, watchDebounceMs);\n };\n\n const attachWatch = () => {\n watchers.push(\n fs.watch(targetDir, (_eventType, filename) => {\n if (filename == null || filename.toString() === targetName) {\n scheduleRead();\n }\n }),\n );\n };\n\n intervals.push(setInterval(() => read(), pollIntervalMs));\n\n try {\n attachWatch();\n // Defer the initial callback until the caller has received the handle, so\n // callbacks that stop their watcher cannot race handle assignment.\n queueMicrotask(() => {\n if (!stopped) read(true);\n });\n } catch {\n // Parent directory does not exist yet. Polling still covers a later file;\n // retry attaching the low-latency directory watcher until it appears.\n const attachInterval = setInterval(() => {\n try {\n fs.accessSync(targetDir);\n clearInterval(attachInterval);\n const idx = intervals.indexOf(attachInterval);\n if (idx >= 0) intervals.splice(idx, 1);\n attachWatch();\n read(true);\n } catch {\n // Still waiting.\n }\n }, attachRetryIntervalMs);\n intervals.push(attachInterval);\n }\n\n return {\n refresh() {\n if (stopped) return;\n if (watchDebounceTimer) {\n clearTimeout(watchDebounceTimer);\n watchDebounceTimer = null;\n }\n read(true);\n },\n stop() {\n stopped = true;\n if (watchDebounceTimer) {\n clearTimeout(watchDebounceTimer);\n watchDebounceTimer = null;\n }\n for (const watcher of watchers) watcher.close();\n for (const interval of intervals) clearInterval(interval);\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"file-watcher-Cr-4tA-e.js","names":["fs"],"sources":["../src/lib/file-watcher.ts"],"sourcesContent":["/**\n * JSON file watcher shared by runner and UI machinery.\n *\n * `fs.watch` alone is unreliable for atomic-rename writes, so the watcher\n * pairs it with a continuous mtime-polled re-read. The poll catches missed\n * events; the watch keeps latency low when it does fire.\n */\n\nimport * as fs from 'fs';\nimport { basename, dirname } from 'node:path';\nimport { logToFile } from '@utils/debug';\n\nconst DEFAULT_POLL_INTERVAL_MS = 5000;\nconst DEFAULT_ATTACH_RETRY_INTERVAL_MS = 1000;\nconst DEFAULT_WATCH_DEBOUNCE_MS = 25;\n\nexport interface FileWatcherHandle {\n refresh(): void;\n stop(): void;\n}\n\nexport interface FileWatcherOptions {\n /** ms between mtime checks once the file exists. */\n pollIntervalMs?: number;\n /** ms between attach attempts while waiting for the file to appear. */\n attachRetryIntervalMs?: number;\n /** ms to coalesce duplicate filesystem events. */\n watchDebounceMs?: number;\n /** Ignore the file that exists when the watcher starts until it changes. */\n ignoreInitialFile?: boolean;\n /** Refuse to read files larger than this many bytes. */\n maxFileSizeBytes?: number;\n}\n\n/** Watch `path` for JSON updates and call `onUpdate(parsed)` whenever the\n * file's mtime changes and the contents are valid JSON. Caller must invoke\n * `handle.stop()` to release the watcher. */\nexport function startFileWatcher(\n path: string,\n onUpdate: (parsed: unknown) => void,\n options: FileWatcherOptions = {},\n): FileWatcherHandle {\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const attachRetryIntervalMs =\n options.attachRetryIntervalMs ?? DEFAULT_ATTACH_RETRY_INTERVAL_MS;\n const watchDebounceMs = options.watchDebounceMs ?? DEFAULT_WATCH_DEBOUNCE_MS;\n\n const watchers: fs.FSWatcher[] = [];\n const intervals: Array<ReturnType<typeof setInterval>> = [];\n const targetDir = dirname(path);\n const targetName = basename(path);\n let lastMtimeMs = 0;\n let ignoredInitialSignature: string | null = null;\n let watchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n let lastReadErrorSignature: string | null = null;\n let stopped = false;\n\n const signature = (stat: fs.Stats): string =>\n `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;\n\n if (options.ignoreInitialFile) {\n try {\n const stat = fs.lstatSync(path);\n if (stat.isFile() && !stat.isSymbolicLink()) {\n ignoredInitialSignature = signature(stat);\n }\n } catch {\n // No initial file to ignore.\n }\n }\n\n const logReadError = (errorSignature: string, message: string) => {\n if (lastReadErrorSignature === errorSignature) return;\n lastReadErrorSignature = errorSignature;\n logToFile(`[file-watcher] ${message}: ${path}`);\n };\n\n const read = (force = false) => {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(path);\n } catch {\n return;\n }\n\n if (!stat.isFile() || stat.isSymbolicLink()) return;\n const fileSignature = signature(stat);\n\n try {\n if (ignoredInitialSignature) {\n if (fileSignature === ignoredInitialSignature) return;\n ignoredInitialSignature = null;\n }\n if (\n options.maxFileSizeBytes !== undefined &&\n stat.size > options.maxFileSizeBytes\n ) {\n logReadError(\n `oversized:${fileSignature}`,\n `refusing oversized JSON file (${stat.size} bytes, limit ${options.maxFileSizeBytes} bytes)`,\n );\n return;\n }\n if (!force && stat.mtimeMs === lastMtimeMs) return;\n lastMtimeMs = stat.mtimeMs;\n const parsed: unknown = JSON.parse(fs.readFileSync(path, 'utf-8'));\n lastReadErrorSignature = null;\n onUpdate(parsed);\n } catch (error) {\n logReadError(\n `invalid:${fileSignature}:${String(error)}`,\n `could not read valid JSON (${String(error)})`,\n );\n }\n };\n\n const scheduleRead = () => {\n if (stopped) return;\n if (watchDebounceTimer) clearTimeout(watchDebounceTimer);\n watchDebounceTimer = setTimeout(() => {\n watchDebounceTimer = null;\n read(true);\n }, watchDebounceMs);\n };\n\n const attachWatch = () => {\n watchers.push(\n fs.watch(targetDir, (_eventType, filename) => {\n if (filename == null || filename.toString() === targetName) {\n scheduleRead();\n }\n }),\n );\n };\n\n intervals.push(setInterval(() => read(), pollIntervalMs));\n\n try {\n attachWatch();\n // Defer the initial callback until the caller has received the handle, so\n // callbacks that stop their watcher cannot race handle assignment.\n queueMicrotask(() => {\n if (!stopped) read(true);\n });\n } catch {\n // Parent directory does not exist yet. Polling still covers a later file;\n // retry attaching the low-latency directory watcher until it appears.\n const attachInterval = setInterval(() => {\n try {\n fs.accessSync(targetDir);\n clearInterval(attachInterval);\n const idx = intervals.indexOf(attachInterval);\n if (idx >= 0) intervals.splice(idx, 1);\n attachWatch();\n read(true);\n } catch {\n // Still waiting.\n }\n }, attachRetryIntervalMs);\n intervals.push(attachInterval);\n }\n\n return {\n refresh() {\n if (stopped) return;\n if (watchDebounceTimer) {\n clearTimeout(watchDebounceTimer);\n watchDebounceTimer = null;\n }\n read(true);\n },\n stop() {\n stopped = true;\n if (watchDebounceTimer) {\n clearTimeout(watchDebounceTimer);\n watchDebounceTimer = null;\n }\n for (const watcher of watchers) watcher.close();\n for (const interval of intervals) clearInterval(interval);\n },\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { m as LoggingUI } from "./debug-hy6aWAyk.js";
1
+ import { m as LoggingUI } from "./debug-BKqv-yfT.js";
2
2
  //#region src/ui/headless-ui.ts
3
3
  /**
4
4
  * `LoggingUI` plus it feeds run state into a `WizardStore` so the background
@@ -25,4 +25,4 @@ var HeadlessUI = class extends LoggingUI {
25
25
  //#endregion
26
26
  export { HeadlessUI };
27
27
 
28
- //# sourceMappingURL=headless-ui-zZLgs4QL.js.map
28
+ //# sourceMappingURL=headless-ui-DT3Db1bk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"headless-ui-zZLgs4QL.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-DKlEg8-Q.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-BUw1SEOz.js.map
11
+ //# sourceMappingURL=interactive-D3LdFxZG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-BUw1SEOz.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"}
@@ -0,0 +1,135 @@
1
+ //#region src/lib/local-dev.ts
2
+ /**
3
+ * Local development targets: context-mill (skills), MCP, and PostHog. Each is
4
+ * independently switchable — CI runs local skills against the *production* MCP
5
+ * — with `--local-dev` as a shorthand for all three.
6
+ *
7
+ * `wizard mcp add --local` is unrelated: it writes a `posthog-local` entry into
8
+ * the user's editor config rather than retargeting this run. Hence no
9
+ * `--local` here.
10
+ */
11
+ const CONTEXT_MILL_LOCAL_URL = "http://localhost:8765";
12
+ const MCP_LOCAL_URL = "http://localhost:8787/mcp";
13
+ /** Pins the API, app, OAuth, and the LLM gateway derived from them. */
14
+ const POSTHOG_LOCAL_URL = "http://localhost:8010";
15
+ /**
16
+ * A specific flag beats `--local-dev` in both directions. `??` is load-bearing:
17
+ * it falls through only on `undefined`, so giving the specific flags a yargs
18
+ * `default: false` would silently break both the umbrella and `--no-local-mcp`.
19
+ */
20
+ function resolveLocalDev(flags) {
21
+ const umbrella = flags.localDev ?? false;
22
+ return {
23
+ localMcp: flags.localMcp ?? umbrella,
24
+ localContextMill: flags.localContextMill ?? umbrella,
25
+ localPosthog: flags.localPosthog ?? umbrella
26
+ };
27
+ }
28
+ /** yargs populates both spellings, so read either. */
29
+ function localDevFromArgv(argv) {
30
+ const read = (kebab, camel) => {
31
+ const value = argv[camel] ?? argv[kebab];
32
+ return typeof value === "boolean" ? value : void 0;
33
+ };
34
+ return resolveLocalDev({
35
+ localDev: read("local-dev", "localDev"),
36
+ localMcp: read("local-mcp", "localMcp"),
37
+ localContextMill: read("local-context-mill", "localContextMill"),
38
+ localPosthog: read("local-posthog", "localPosthog")
39
+ });
40
+ }
41
+ const PRODUCTION_TARGETS = {
42
+ localMcp: false,
43
+ localContextMill: false,
44
+ localPosthog: false
45
+ };
46
+ let resolved = null;
47
+ /**
48
+ * Resolve this process's targets. Called once from the yargs middleware, which
49
+ * covers every command and the env-var spellings alike.
50
+ */
51
+ function initLocalDev(argv) {
52
+ resolved = localDevFromArgv(argv);
53
+ return resolved;
54
+ }
55
+ /**
56
+ * Where this run points. Resolved once because the flags are parsed at startup
57
+ * and never change; threading them through state let call sites read whichever
58
+ * field they happened to have, which is how the intro screens ended up asking
59
+ * the MCP flag where to fetch skills.
60
+ *
61
+ * Uninitialized means no CLI parse ran (a direct-call test) — production.
62
+ */
63
+ function getLocalDev() {
64
+ return resolved ?? PRODUCTION_TARGETS;
65
+ }
66
+ const LOCAL_SERVICES = [
67
+ {
68
+ key: "localContextMill",
69
+ label: "context-mill",
70
+ flag: "--local-context-mill",
71
+ url: `${CONTEXT_MILL_LOCAL_URL}/skill-menu.json`,
72
+ startHint: "npm run dev (in the context-mill repo)"
73
+ },
74
+ {
75
+ key: "localMcp",
76
+ label: "MCP server",
77
+ flag: "--local-mcp",
78
+ url: MCP_LOCAL_URL,
79
+ startHint: "hogli start (or pnpm dev:local-resources in posthog/services/mcp)"
80
+ },
81
+ {
82
+ key: "localPosthog",
83
+ label: "PostHog",
84
+ flag: "--local-posthog",
85
+ url: POSTHOG_LOCAL_URL,
86
+ startHint: "./bin/start (in the posthog repo)"
87
+ }
88
+ ];
89
+ const PROBE_TIMEOUT_MS = 2e3;
90
+ const PROBE_ATTEMPTS = 3;
91
+ const PROBE_BACKOFF_MS = 250;
92
+ async function isReachable(url) {
93
+ for (let attempt = 1; attempt <= PROBE_ATTEMPTS; attempt++) try {
94
+ await fetch(url, { signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });
95
+ return true;
96
+ } catch {
97
+ if (attempt < PROBE_ATTEMPTS) await new Promise((r) => setTimeout(r, PROBE_BACKOFF_MS * 2 ** (attempt - 1)));
98
+ }
99
+ return false;
100
+ }
101
+ /**
102
+ * Probe every service the flags asked to be local. Returns one message naming
103
+ * each unreachable one, or undefined if all are up (or none were requested).
104
+ *
105
+ * Without this a dead local server surfaces late and badly: a missing
106
+ * context-mill looks like a registry outage, a missing MCP fails mid-run after
107
+ * the agent has already edited files.
108
+ */
109
+ async function checkLocalServices(resolved) {
110
+ const requested = LOCAL_SERVICES.filter((s) => resolved[s.key]);
111
+ if (requested.length === 0) return void 0;
112
+ const reachable = await Promise.all(requested.map((s) => isReachable(s.url)));
113
+ const dead = requested.filter((_, i) => !reachable[i]);
114
+ if (dead.length === 0) return void 0;
115
+ return [
116
+ `Local ${dead.length === 1 ? "service is" : "services are"} not running:`,
117
+ "",
118
+ ...dead.map((s) => ` ${s.label} — nothing listening at ${new URL(s.url).origin}\n requested by ${s.flag}\n start it with: ${s.startHint}`),
119
+ "",
120
+ "Start the missing services, or drop the flag to use production."
121
+ ].join("\n");
122
+ }
123
+ /**
124
+ * `--local-mcp` used to select local skills too; anyone still relying on that
125
+ * would silently get production skills. Temporary — drop after a release or two.
126
+ */
127
+ function localMcpSkillsNotice(flags) {
128
+ if (flags.localMcp !== true) return void 0;
129
+ if (flags.localContextMill !== void 0 || flags.localDev === true) return;
130
+ return "--local-mcp now points only at the local MCP server. For local skills, add --local-context-mill (or use --local-dev for both).";
131
+ }
132
+ //#endregion
133
+ export { getLocalDev as a, resolveLocalDev as c, checkLocalServices as i, MCP_LOCAL_URL as n, initLocalDev as o, POSTHOG_LOCAL_URL as r, localMcpSkillsNotice as s, CONTEXT_MILL_LOCAL_URL as t };
134
+
135
+ //# sourceMappingURL=local-dev-BN6NKQ0B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-dev-BN6NKQ0B.js","names":[],"sources":["../src/lib/local-dev.ts"],"sourcesContent":["/**\n * Local development targets: context-mill (skills), MCP, and PostHog. Each is\n * independently switchable — CI runs local skills against the *production* MCP\n * — with `--local-dev` as a shorthand for all three.\n *\n * `wizard mcp add --local` is unrelated: it writes a `posthog-local` entry into\n * the user's editor config rather than retargeting this run. Hence no\n * `--local` here.\n */\n\nexport const CONTEXT_MILL_LOCAL_URL = 'http://localhost:8765';\nexport const MCP_LOCAL_URL = 'http://localhost:8787/mcp';\n/** Pins the API, app, OAuth, and the LLM gateway derived from them. */\nexport const POSTHOG_LOCAL_URL = 'http://localhost:8010';\n\n/**\n * Raw yargs values. The three specific flags are declared without a `default`\n * so they stay `undefined` when absent — see `resolveLocalDev`.\n */\nexport type LocalDevFlags = {\n localDev?: boolean;\n localMcp?: boolean;\n localContextMill?: boolean;\n localPosthog?: boolean;\n};\n\nexport type ResolvedLocalDev = {\n localMcp: boolean;\n localContextMill: boolean;\n localPosthog: boolean;\n};\n\n/**\n * A specific flag beats `--local-dev` in both directions. `??` is load-bearing:\n * it falls through only on `undefined`, so giving the specific flags a yargs\n * `default: false` would silently break both the umbrella and `--no-local-mcp`.\n */\nexport function resolveLocalDev(flags: LocalDevFlags): ResolvedLocalDev {\n const umbrella = flags.localDev ?? false;\n return {\n localMcp: flags.localMcp ?? umbrella,\n localContextMill: flags.localContextMill ?? umbrella,\n localPosthog: flags.localPosthog ?? umbrella,\n };\n}\n\n/** yargs populates both spellings, so read either. */\nexport function localDevFromArgv(\n argv: Record<string, unknown>,\n): ResolvedLocalDev {\n const read = (kebab: string, camel: string): boolean | undefined => {\n const value = argv[camel] ?? argv[kebab];\n return typeof value === 'boolean' ? value : undefined;\n };\n return resolveLocalDev({\n localDev: read('local-dev', 'localDev'),\n localMcp: read('local-mcp', 'localMcp'),\n localContextMill: read('local-context-mill', 'localContextMill'),\n localPosthog: read('local-posthog', 'localPosthog'),\n });\n}\n\nconst PRODUCTION_TARGETS: ResolvedLocalDev = {\n localMcp: false,\n localContextMill: false,\n localPosthog: false,\n};\n\nlet resolved: ResolvedLocalDev | null = null;\n\n/**\n * Resolve this process's targets. Called once from the yargs middleware, which\n * covers every command and the env-var spellings alike.\n */\nexport function initLocalDev(argv: Record<string, unknown>): ResolvedLocalDev {\n resolved = localDevFromArgv(argv);\n return resolved;\n}\n\n/**\n * Where this run points. Resolved once because the flags are parsed at startup\n * and never change; threading them through state let call sites read whichever\n * field they happened to have, which is how the intro screens ended up asking\n * the MCP flag where to fetch skills.\n *\n * Uninitialized means no CLI parse ran (a direct-call test) — production.\n */\nexport function getLocalDev(): ResolvedLocalDev {\n return resolved ?? PRODUCTION_TARGETS;\n}\n\n/** Tests only. */\nexport function resetLocalDev(): void {\n resolved = null;\n}\n\ntype LocalService = {\n key: keyof ResolvedLocalDev;\n label: string;\n flag: string;\n /** Probed for reachability — any HTTP reply proves the port is bound. */\n url: string;\n startHint: string;\n};\n\nconst LOCAL_SERVICES: readonly LocalService[] = [\n {\n key: 'localContextMill',\n label: 'context-mill',\n flag: '--local-context-mill',\n url: `${CONTEXT_MILL_LOCAL_URL}/skill-menu.json`,\n startHint: 'npm run dev (in the context-mill repo)',\n },\n {\n key: 'localMcp',\n label: 'MCP server',\n flag: '--local-mcp',\n url: MCP_LOCAL_URL,\n startHint:\n 'hogli start (or pnpm dev:local-resources in posthog/services/mcp)',\n },\n {\n key: 'localPosthog',\n label: 'PostHog',\n flag: '--local-posthog',\n url: POSTHOG_LOCAL_URL,\n startHint: './bin/start (in the posthog repo)',\n },\n] as const;\n\n// Retries because this gate gates `fetchWithRetry` (see fetch-retry.ts) — a\n// blip it would ride out must not abort the run instead. A missing server\n// refuses instantly, so the retries only cost time when one is slow to answer,\n// which is exactly when they're worth paying for.\nconst PROBE_TIMEOUT_MS = 2_000;\nconst PROBE_ATTEMPTS = 3;\nconst PROBE_BACKOFF_MS = 250;\n\nasync function isReachable(url: string): Promise<boolean> {\n for (let attempt = 1; attempt <= PROBE_ATTEMPTS; attempt++) {\n try {\n // Any reply — including 404 or 405 — proves something is listening, which\n // is the only question here. Deliberately not `fetchWithRetry`: that\n // treats a non-ok status as failure, and here it is a pass.\n await fetch(url, { signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });\n return true;\n } catch {\n if (attempt < PROBE_ATTEMPTS) {\n await new Promise((r) =>\n setTimeout(r, PROBE_BACKOFF_MS * 2 ** (attempt - 1)),\n );\n }\n }\n }\n return false;\n}\n\n/**\n * Probe every service the flags asked to be local. Returns one message naming\n * each unreachable one, or undefined if all are up (or none were requested).\n *\n * Without this a dead local server surfaces late and badly: a missing\n * context-mill looks like a registry outage, a missing MCP fails mid-run after\n * the agent has already edited files.\n */\nexport async function checkLocalServices(\n resolved: ResolvedLocalDev,\n): Promise<string | undefined> {\n const requested = LOCAL_SERVICES.filter((s) => resolved[s.key]);\n if (requested.length === 0) return undefined;\n\n const reachable = await Promise.all(requested.map((s) => isReachable(s.url)));\n const dead = requested.filter((_, i) => !reachable[i]);\n if (dead.length === 0) return undefined;\n\n return [\n `Local ${dead.length === 1 ? 'service is' : 'services are'} not running:`,\n '',\n ...dead.map(\n (s) =>\n ` ${s.label} — nothing listening at ${new URL(s.url).origin}\\n` +\n ` requested by ${s.flag}\\n` +\n ` start it with: ${s.startHint}`,\n ),\n '',\n 'Start the missing services, or drop the flag to use production.',\n ].join('\\n');\n}\n\n/**\n * `--local-mcp` used to select local skills too; anyone still relying on that\n * would silently get production skills. Temporary — drop after a release or two.\n */\nexport function localMcpSkillsNotice(flags: LocalDevFlags): string | undefined {\n if (flags.localMcp !== true) return undefined;\n if (flags.localContextMill !== undefined || flags.localDev === true) {\n return undefined;\n }\n return (\n '--local-mcp now points only at the local MCP server. ' +\n 'For local skills, add --local-context-mill (or use --local-dev for both).'\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAa,yBAAyB;AACtC,MAAa,gBAAgB;;AAE7B,MAAa,oBAAoB;;;;;;AAwBjC,SAAgB,gBAAgB,OAAwC;CACtE,MAAM,WAAW,MAAM,YAAY;AACnC,QAAO;EACL,UAAU,MAAM,YAAY;EAC5B,kBAAkB,MAAM,oBAAoB;EAC5C,cAAc,MAAM,gBAAgB;EACrC;;;AAIH,SAAgB,iBACd,MACkB;CAClB,MAAM,QAAQ,OAAe,UAAuC;EAClE,MAAM,QAAQ,KAAK,UAAU,KAAK;AAClC,SAAO,OAAO,UAAU,YAAY,QAAQ,KAAA;;AAE9C,QAAO,gBAAgB;EACrB,UAAU,KAAK,aAAa,WAAW;EACvC,UAAU,KAAK,aAAa,WAAW;EACvC,kBAAkB,KAAK,sBAAsB,mBAAmB;EAChE,cAAc,KAAK,iBAAiB,eAAe;EACpD,CAAC;;AAGJ,MAAM,qBAAuC;CAC3C,UAAU;CACV,kBAAkB;CAClB,cAAc;CACf;AAED,IAAI,WAAoC;;;;;AAMxC,SAAgB,aAAa,MAAiD;AAC5E,YAAW,iBAAiB,KAAK;AACjC,QAAO;;;;;;;;;;AAWT,SAAgB,cAAgC;AAC9C,QAAO,YAAY;;AAiBrB,MAAM,iBAA0C;CAC9C;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,KAAK,GAAG,uBAAuB;EAC/B,WAAW;EACZ;CACD;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,KAAK;EACL,WACE;EACH;CACD;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,KAAK;EACL,WAAW;EACZ;CACF;AAMD,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AAEzB,eAAe,YAAY,KAA+B;AACxD,MAAK,IAAI,UAAU,GAAG,WAAW,gBAAgB,UAC/C,KAAI;AAIF,QAAM,MAAM,KAAK,EAAE,QAAQ,YAAY,QAAQ,iBAAiB,EAAE,CAAC;AACnE,SAAO;SACD;AACN,MAAI,UAAU,eACZ,OAAM,IAAI,SAAS,MACjB,WAAW,GAAG,mBAAmB,MAAM,UAAU,GAAG,CACrD;;AAIP,QAAO;;;;;;;;;;AAWT,eAAsB,mBACpB,UAC6B;CAC7B,MAAM,YAAY,eAAe,QAAQ,MAAM,SAAS,EAAE,KAAK;AAC/D,KAAI,UAAU,WAAW,EAAG,QAAO,KAAA;CAEnC,MAAM,YAAY,MAAM,QAAQ,IAAI,UAAU,KAAK,MAAM,YAAY,EAAE,IAAI,CAAC,CAAC;CAC7E,MAAM,OAAO,UAAU,QAAQ,GAAG,MAAM,CAAC,UAAU,GAAG;AACtD,KAAI,KAAK,WAAW,EAAG,QAAO,KAAA;AAE9B,QAAO;EACL,SAAS,KAAK,WAAW,IAAI,eAAe,eAAe;EAC3D;EACA,GAAG,KAAK,KACL,MACC,KAAK,EAAE,MAAM,0BAA0B,IAAI,IAAI,EAAE,IAAI,CAAC,OAAO,qBACzC,EAAE,KAAK,uBACL,EAAE,YAC3B;EACD;EACA;EACD,CAAC,KAAK,KAAK;;;;;;AAOd,SAAgB,qBAAqB,OAA0C;AAC7E,KAAI,MAAM,aAAa,KAAM,QAAO,KAAA;AACpC,KAAI,MAAM,qBAAqB,KAAA,KAAa,MAAM,aAAa,KAC7D;AAEF,QACE"}
@@ -1,4 +1,4 @@
1
- import { gt as VERSION, s as logToFile } from "./debug-hy6aWAyk.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-C7NMhhWa.js.map
64
+ //# sourceMappingURL=mcp-BjckYQmP.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-C7NMhhWa.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"}