@probelabs/visor 0.1.186 → 0.1.187

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 (395) hide show
  1. package/defaults/assistant.yaml +31 -0
  2. package/defaults/code-talk.yaml +32 -0
  3. package/defaults/skills/code-explorer.yaml +6 -0
  4. package/dist/action-cli-bridge.d.ts.map +1 -1
  5. package/dist/agent-protocol/a2a-frontend.d.ts.map +1 -1
  6. package/dist/agent-protocol/index.d.ts.map +1 -1
  7. package/dist/agent-protocol/push-notification-manager.d.ts.map +1 -1
  8. package/dist/agent-protocol/state-transitions.d.ts.map +1 -1
  9. package/dist/agent-protocol/task-evaluator.d.ts.map +1 -1
  10. package/dist/agent-protocol/task-live-update-slack.d.ts +10 -0
  11. package/dist/agent-protocol/task-live-update-slack.d.ts.map +1 -1
  12. package/dist/agent-protocol/task-live-update-teams.d.ts.map +1 -1
  13. package/dist/agent-protocol/task-live-update-telegram.d.ts.map +1 -1
  14. package/dist/agent-protocol/task-live-updates.d.ts +10 -0
  15. package/dist/agent-protocol/task-live-updates.d.ts.map +1 -1
  16. package/dist/agent-protocol/task-progress-tool.d.ts.map +1 -1
  17. package/dist/agent-protocol/task-queue.d.ts.map +1 -1
  18. package/dist/agent-protocol/task-store.d.ts.map +1 -1
  19. package/dist/agent-protocol/task-stream-manager.d.ts.map +1 -1
  20. package/dist/agent-protocol/task-trace-resolution.d.ts.map +1 -1
  21. package/dist/agent-protocol/tasks-cli-handler.d.ts.map +1 -1
  22. package/dist/agent-protocol/tasks-tui.d.ts.map +1 -1
  23. package/dist/agent-protocol/trace-serializer.d.ts +43 -1
  24. package/dist/agent-protocol/trace-serializer.d.ts.map +1 -1
  25. package/dist/agent-protocol/track-execution.d.ts.map +1 -1
  26. package/dist/agent-protocol/types.d.ts.map +1 -1
  27. package/dist/ai-review-service.d.ts +22 -1
  28. package/dist/ai-review-service.d.ts.map +1 -1
  29. package/dist/check-execution-engine.d.ts.map +1 -1
  30. package/dist/cli-main.d.ts +1 -0
  31. package/dist/cli-main.d.ts.map +1 -1
  32. package/dist/cli.d.ts.map +1 -1
  33. package/dist/commands.d.ts.map +1 -1
  34. package/dist/config/cli-handler.d.ts.map +1 -1
  35. package/dist/config/config-reloader.d.ts.map +1 -1
  36. package/dist/config/config-snapshot-store.d.ts.map +1 -1
  37. package/dist/config/config-watcher.d.ts.map +1 -1
  38. package/dist/config/types.d.ts.map +1 -1
  39. package/dist/config.d.ts.map +1 -1
  40. package/dist/cron-scheduler.d.ts.map +1 -1
  41. package/dist/debug-visualizer/debug-span-exporter.d.ts.map +1 -1
  42. package/dist/debug-visualizer/trace-reader.d.ts.map +1 -1
  43. package/dist/debug-visualizer/ws-server.d.ts.map +1 -1
  44. package/dist/defaults/assistant.yaml +31 -0
  45. package/dist/defaults/code-talk.yaml +32 -0
  46. package/dist/defaults/skills/code-explorer.yaml +6 -0
  47. package/dist/dependency-resolver.d.ts.map +1 -1
  48. package/dist/docs/telemetry-setup.md +18 -2
  49. package/dist/email/adapter.d.ts.map +1 -1
  50. package/dist/email/client.d.ts.map +1 -1
  51. package/dist/email/markdown.d.ts.map +1 -1
  52. package/dist/email/polling-runner.d.ts +1 -0
  53. package/dist/email/polling-runner.d.ts.map +1 -1
  54. package/dist/engine/on-finish/orchestrator.d.ts.map +1 -1
  55. package/dist/engine/on-finish/utils.d.ts.map +1 -1
  56. package/dist/event-bus/event-bus.d.ts.map +1 -1
  57. package/dist/event-bus/types.d.ts.map +1 -1
  58. package/dist/event-mapper.d.ts.map +1 -1
  59. package/dist/failure-condition-evaluator.d.ts.map +1 -1
  60. package/dist/footer.d.ts.map +1 -1
  61. package/dist/frontends/email-frontend.d.ts.map +1 -1
  62. package/dist/frontends/github-frontend.d.ts.map +1 -1
  63. package/dist/frontends/host.d.ts.map +1 -1
  64. package/dist/frontends/ndjson-sink.d.ts.map +1 -1
  65. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  66. package/dist/frontends/teams-frontend.d.ts.map +1 -1
  67. package/dist/frontends/telegram-frontend.d.ts.map +1 -1
  68. package/dist/frontends/whatsapp-frontend.d.ts.map +1 -1
  69. package/dist/generated/config-schema.d.ts +16 -8
  70. package/dist/generated/config-schema.d.ts.map +1 -1
  71. package/dist/git-repository-analyzer.d.ts.map +1 -1
  72. package/dist/github-auth.d.ts.map +1 -1
  73. package/dist/github-check-service.d.ts.map +1 -1
  74. package/dist/github-comments.d.ts.map +1 -1
  75. package/dist/github-reactions.d.ts.map +1 -1
  76. package/dist/index.d.ts +1 -0
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +7656 -1458
  79. package/dist/issue-filter.d.ts.map +1 -1
  80. package/dist/liquid-extensions.d.ts.map +1 -1
  81. package/dist/logger.d.ts.map +1 -1
  82. package/dist/mcp-job-manager.d.ts.map +1 -1
  83. package/dist/mcp-server.d.ts.map +1 -1
  84. package/dist/memory-store.d.ts.map +1 -1
  85. package/dist/output/traces/{run-2026-05-05T12-31-47-571Z.ndjson → run-2026-08-20T13-50-06-218Z.ndjson} +2699 -2699
  86. package/dist/output-formatters.d.ts.map +1 -1
  87. package/dist/policy/default-engine.d.ts.map +1 -1
  88. package/dist/policy/index.d.ts.map +1 -1
  89. package/dist/policy/policy-check-command.d.ts.map +1 -1
  90. package/dist/policy/types.d.ts.map +1 -1
  91. package/dist/pr-analyzer.d.ts.map +1 -1
  92. package/dist/pr-detector.d.ts.map +1 -1
  93. package/dist/providers/a2a-check-provider.d.ts.map +1 -1
  94. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  95. package/dist/providers/api-tool-executor.d.ts.map +1 -1
  96. package/dist/providers/check-provider-registry.d.ts.map +1 -1
  97. package/dist/providers/check-provider.interface.d.ts.map +1 -1
  98. package/dist/providers/claude-code-check-provider.d.ts.map +1 -1
  99. package/dist/providers/claude-code-types.d.ts.map +1 -1
  100. package/dist/providers/command-check-provider.d.ts.map +1 -1
  101. package/dist/providers/custom-tool-executor.d.ts.map +1 -1
  102. package/dist/providers/git-checkout-provider.d.ts.map +1 -1
  103. package/dist/providers/github-ops-provider.d.ts.map +1 -1
  104. package/dist/providers/http-check-provider.d.ts.map +1 -1
  105. package/dist/providers/http-client-provider.d.ts.map +1 -1
  106. package/dist/providers/http-input-provider.d.ts.map +1 -1
  107. package/dist/providers/human-input-check-provider.d.ts.map +1 -1
  108. package/dist/providers/index.d.ts.map +1 -1
  109. package/dist/providers/log-check-provider.d.ts.map +1 -1
  110. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  111. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
  112. package/dist/providers/mcp-tools.d.ts.map +1 -1
  113. package/dist/providers/memory-check-provider.d.ts.map +1 -1
  114. package/dist/providers/noop-check-provider.d.ts.map +1 -1
  115. package/dist/providers/script-check-provider.d.ts.map +1 -1
  116. package/dist/providers/utcp-check-provider.d.ts.map +1 -1
  117. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  118. package/dist/providers/workflow-tool-executor.d.ts.map +1 -1
  119. package/dist/reviewer.d.ts.map +1 -1
  120. package/dist/runners/config-reload-runtime.d.ts.map +1 -1
  121. package/dist/runners/graceful-restart.d.ts.map +1 -1
  122. package/dist/runners/mcp-server-runner.d.ts.map +1 -1
  123. package/dist/runners/process-cli-handler.d.ts.map +1 -1
  124. package/dist/runners/process-discovery.d.ts.map +1 -1
  125. package/dist/runners/runner-factory.d.ts.map +1 -1
  126. package/dist/runners/runner-host.d.ts.map +1 -1
  127. package/dist/runners/runner.d.ts.map +1 -1
  128. package/dist/runners/telemetry-init.d.ts.map +1 -1
  129. package/dist/sandbox/bubblewrap-sandbox.d.ts.map +1 -1
  130. package/dist/sandbox/cache-volume-manager.d.ts.map +1 -1
  131. package/dist/sandbox/check-runner.d.ts.map +1 -1
  132. package/dist/sandbox/compose-generator.d.ts.map +1 -1
  133. package/dist/sandbox/docker-compose-sandbox.d.ts.map +1 -1
  134. package/dist/sandbox/docker-image-sandbox.d.ts.map +1 -1
  135. package/dist/sandbox/env-filter.d.ts.map +1 -1
  136. package/dist/sandbox/index.d.ts.map +1 -1
  137. package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
  138. package/dist/sandbox/sandbox-telemetry.d.ts.map +1 -1
  139. package/dist/sandbox/seatbelt-sandbox.d.ts.map +1 -1
  140. package/dist/sandbox/trace-ingester.d.ts.map +1 -1
  141. package/dist/sandbox/types.d.ts.map +1 -1
  142. package/dist/scheduler/cli-handler.d.ts.map +1 -1
  143. package/dist/scheduler/index.d.ts.map +1 -1
  144. package/dist/scheduler/message-trigger.d.ts.map +1 -1
  145. package/dist/scheduler/schedule-parser.d.ts.map +1 -1
  146. package/dist/scheduler/schedule-store.d.ts.map +1 -1
  147. package/dist/scheduler/schedule-tool.d.ts.map +1 -1
  148. package/dist/scheduler/scheduler.d.ts.map +1 -1
  149. package/dist/scheduler/store/index.d.ts.map +1 -1
  150. package/dist/scheduler/store/json-migrator.d.ts.map +1 -1
  151. package/dist/scheduler/store/sqlite-store.d.ts.map +1 -1
  152. package/dist/scheduler/store/types.d.ts.map +1 -1
  153. package/dist/sdk/{a2a-frontend-L3TQ7QQ6.mjs → a2a-frontend-XCQ4CQUF.mjs} +3 -3
  154. package/dist/sdk/{check-provider-registry-RQYIEQLJ.mjs → check-provider-registry-2D3MCWP3.mjs} +14 -11
  155. package/dist/sdk/{chunk-WZQMTD7W.mjs → chunk-2LLKENYD.mjs} +3 -3
  156. package/dist/sdk/{chunk-WZQMTD7W.mjs.map → chunk-2LLKENYD.mjs.map} +1 -1
  157. package/dist/sdk/{chunk-XXAEN5KU.mjs → chunk-77AKSSW2.mjs} +43 -65
  158. package/dist/sdk/chunk-77AKSSW2.mjs.map +1 -0
  159. package/dist/sdk/chunk-7QI6F66G.mjs +145 -0
  160. package/dist/sdk/chunk-7QI6F66G.mjs.map +1 -0
  161. package/dist/sdk/{chunk-NEZY2MXM.mjs → chunk-B2LQT6QU.mjs} +4 -4
  162. package/dist/sdk/{chunk-NEZY2MXM.mjs.map → chunk-B2LQT6QU.mjs.map} +1 -1
  163. package/dist/sdk/{chunk-IY5PQ5EN.mjs → chunk-BVEATT5V.mjs} +822 -51
  164. package/dist/sdk/chunk-BVEATT5V.mjs.map +1 -0
  165. package/dist/sdk/{chunk-TSX3YS3F.mjs → chunk-HW4MPCOW.mjs} +5 -139
  166. package/dist/sdk/chunk-HW4MPCOW.mjs.map +1 -0
  167. package/dist/sdk/chunk-PGBV3VZB.mjs +122 -0
  168. package/dist/sdk/chunk-PGBV3VZB.mjs.map +1 -0
  169. package/dist/sdk/{chunk-PDQTEBOJ.mjs → chunk-QT766ZLD.mjs} +5 -1
  170. package/dist/sdk/chunk-QT766ZLD.mjs.map +1 -0
  171. package/dist/sdk/{chunk-5TXIAPRA.mjs → chunk-S3GSZRYC.mjs} +2 -2
  172. package/dist/sdk/{chunk-NPOVLLKH.mjs → chunk-TGQBEM3Y.mjs} +570 -259
  173. package/dist/sdk/chunk-TGQBEM3Y.mjs.map +1 -0
  174. package/dist/sdk/chunk-TL3ZTYFY.mjs +141 -0
  175. package/dist/sdk/chunk-TL3ZTYFY.mjs.map +1 -0
  176. package/dist/sdk/{chunk-4UMDSYC7.mjs → chunk-VS3JE2DL.mjs} +3 -3
  177. package/dist/sdk/{chunk-A4WHMRK2.mjs → chunk-YETG675X.mjs} +2 -2
  178. package/dist/sdk/{chunk-XX6WT332.mjs → chunk-YTG5DN72.mjs} +17 -9
  179. package/dist/sdk/chunk-YTG5DN72.mjs.map +1 -0
  180. package/dist/sdk/{chunk-SRU5TFNY.mjs → chunk-YU3VR5SZ.mjs} +145 -16
  181. package/dist/sdk/chunk-YU3VR5SZ.mjs.map +1 -0
  182. package/dist/sdk/{config-BCYAVJ5S.mjs → config-H5IOLBFA.mjs} +2 -2
  183. package/dist/sdk/{email-frontend-P7QE4UUJ.mjs → email-frontend-AE5TYWNC.mjs} +18 -3
  184. package/dist/sdk/{email-frontend-P7QE4UUJ.mjs.map → email-frontend-AE5TYWNC.mjs.map} +1 -1
  185. package/dist/sdk/{failure-condition-evaluator-ZBOSD574.mjs → failure-condition-evaluator-66PWLV3D.mjs} +4 -4
  186. package/dist/sdk/{github-frontend-4WHT5JEU.mjs → github-frontend-BBFKCY4M.mjs} +4 -4
  187. package/dist/sdk/{host-FKR7H26C.mjs → host-UQRZDLT7.mjs} +8 -8
  188. package/dist/sdk/oauth2-token-cache-OS7WHLDI.mjs +13 -0
  189. package/dist/sdk/{routing-IB2PXYFC.mjs → routing-Q647KUMO.mjs} +5 -5
  190. package/dist/sdk/{schedule-tool-LB33KL2W.mjs → schedule-tool-WMGSM6IT.mjs} +14 -11
  191. package/dist/sdk/{schedule-tool-handler-KYWZHKSS.mjs → schedule-tool-handler-JMDHCGZ2.mjs} +14 -11
  192. package/dist/sdk/sdk.d.mts +14 -2
  193. package/dist/sdk/sdk.d.ts +14 -2
  194. package/dist/sdk/sdk.js +1927 -643
  195. package/dist/sdk/sdk.js.map +1 -1
  196. package/dist/sdk/sdk.mjs +13 -10
  197. package/dist/sdk/sdk.mjs.map +1 -1
  198. package/dist/sdk/session-registry-CENXWIFR.mjs +12 -0
  199. package/dist/sdk/{slack-frontend-K3TPGERM.mjs → slack-frontend-JMX5MUVZ.mjs} +42 -12
  200. package/dist/sdk/slack-frontend-JMX5MUVZ.mjs.map +1 -0
  201. package/dist/sdk/{task-evaluator-H3BXC7SE.mjs → task-evaluator-4QG4CYQA.mjs} +7 -6
  202. package/dist/sdk/task-evaluator-4QG4CYQA.mjs.map +1 -0
  203. package/dist/sdk/{teams-frontend-6RRW533K.mjs → teams-frontend-6MDAN7OR.mjs} +17 -4
  204. package/dist/sdk/teams-frontend-6MDAN7OR.mjs.map +1 -0
  205. package/dist/sdk/{telegram-frontend-5UA77YAT.mjs → telegram-frontend-NLX2ZHS4.mjs} +17 -4
  206. package/dist/sdk/telegram-frontend-NLX2ZHS4.mjs.map +1 -0
  207. package/dist/sdk/{trace-helpers-AMZ2524G.mjs → trace-helpers-AIUGQLK5.mjs} +3 -3
  208. package/dist/sdk/{trace-serializer-EBHTHZYT.mjs → trace-serializer-4TOIAVQL.mjs} +10 -2
  209. package/dist/sdk/{track-execution-VW6P3OYO.mjs → track-execution-CFRZXMEC.mjs} +91 -20
  210. package/dist/sdk/track-execution-CFRZXMEC.mjs.map +1 -0
  211. package/dist/sdk/{utcp-check-provider-Q4PD5EP2.mjs → utcp-check-provider-WDTSQ7DZ.mjs} +3 -2
  212. package/dist/sdk/{whatsapp-frontend-72XEIUIR.mjs → whatsapp-frontend-3EMMNC7R.mjs} +15 -2
  213. package/dist/sdk/whatsapp-frontend-3EMMNC7R.mjs.map +1 -0
  214. package/dist/sdk/{workflow-check-provider-N6KSDPWU.mjs → workflow-check-provider-G7A67EPP.mjs} +14 -11
  215. package/dist/sdk/workflow-check-provider-G7A67EPP.mjs.map +1 -0
  216. package/dist/sdk.d.ts.map +1 -1
  217. package/dist/session-registry.d.ts +2 -7
  218. package/dist/session-registry.d.ts.map +1 -1
  219. package/dist/slack/adapter.d.ts.map +1 -1
  220. package/dist/slack/cache-prewarmer.d.ts.map +1 -1
  221. package/dist/slack/client.d.ts +8 -0
  222. package/dist/slack/client.d.ts.map +1 -1
  223. package/dist/slack/markdown.d.ts.map +1 -1
  224. package/dist/slack/prompt-state.d.ts.map +1 -1
  225. package/dist/slack/rate-limiter.d.ts.map +1 -1
  226. package/dist/slack/schedule-tool-handler.d.ts.map +1 -1
  227. package/dist/slack/signature.d.ts.map +1 -1
  228. package/dist/slack/slack-output-adapter.d.ts.map +1 -1
  229. package/dist/slack/socket-runner.d.ts +1 -0
  230. package/dist/slack/socket-runner.d.ts.map +1 -1
  231. package/dist/slack/thread-cache.d.ts.map +1 -1
  232. package/dist/snapshot-store.d.ts.map +1 -1
  233. package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
  234. package/dist/state-machine/context/workflow-inputs.d.ts.map +1 -1
  235. package/dist/state-machine/dispatch/debounce-manager.d.ts +44 -0
  236. package/dist/state-machine/dispatch/debounce-manager.d.ts.map +1 -0
  237. package/dist/state-machine/dispatch/dependency-gating.d.ts.map +1 -1
  238. package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -1
  239. package/dist/state-machine/dispatch/foreach-processor.d.ts.map +1 -1
  240. package/dist/state-machine/dispatch/history-snapshot.d.ts.map +1 -1
  241. package/dist/state-machine/dispatch/on-init-handlers.d.ts.map +1 -1
  242. package/dist/state-machine/dispatch/policy-gate.d.ts.map +1 -1
  243. package/dist/state-machine/dispatch/renderer-schema.d.ts.map +1 -1
  244. package/dist/state-machine/dispatch/sandbox-routing.d.ts.map +1 -1
  245. package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -1
  246. package/dist/state-machine/dispatch/template-renderer.d.ts.map +1 -1
  247. package/dist/state-machine/execution/summary.d.ts.map +1 -1
  248. package/dist/state-machine/runner.d.ts.map +1 -1
  249. package/dist/state-machine/states/check-running.d.ts.map +1 -1
  250. package/dist/state-machine/states/completed.d.ts.map +1 -1
  251. package/dist/state-machine/states/error.d.ts.map +1 -1
  252. package/dist/state-machine/states/init.d.ts.map +1 -1
  253. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
  254. package/dist/state-machine/states/plan-ready.d.ts.map +1 -1
  255. package/dist/state-machine/states/routing.d.ts.map +1 -1
  256. package/dist/state-machine/states/wave-planning.d.ts.map +1 -1
  257. package/dist/state-machine/workflow-projection.d.ts.map +1 -1
  258. package/dist/state-machine-execution-engine.d.ts +1 -0
  259. package/dist/state-machine-execution-engine.d.ts.map +1 -1
  260. package/dist/teams/adapter.d.ts.map +1 -1
  261. package/dist/teams/client.d.ts.map +1 -1
  262. package/dist/teams/markdown.d.ts.map +1 -1
  263. package/dist/teams/webhook-runner.d.ts +1 -0
  264. package/dist/teams/webhook-runner.d.ts.map +1 -1
  265. package/dist/telegram/adapter.d.ts.map +1 -1
  266. package/dist/telegram/client.d.ts.map +1 -1
  267. package/dist/telegram/markdown.d.ts.map +1 -1
  268. package/dist/telegram/polling-runner.d.ts +1 -0
  269. package/dist/telegram/polling-runner.d.ts.map +1 -1
  270. package/dist/telemetry/fallback-ndjson.d.ts.map +1 -1
  271. package/dist/telemetry/file-span-exporter.d.ts.map +1 -1
  272. package/dist/telemetry/lazy-otel.d.ts.map +1 -1
  273. package/dist/telemetry/metrics.d.ts.map +1 -1
  274. package/dist/telemetry/opentelemetry.d.ts.map +1 -1
  275. package/dist/telemetry/state-capture.d.ts.map +1 -1
  276. package/dist/telemetry/trace-helpers.d.ts.map +1 -1
  277. package/dist/telemetry/trace-report-exporter.d.ts.map +1 -1
  278. package/dist/test-runner/assertions.d.ts.map +1 -1
  279. package/dist/test-runner/conversation-sugar.d.ts.map +1 -1
  280. package/dist/test-runner/core/environment.d.ts.map +1 -1
  281. package/dist/test-runner/core/fixture.d.ts.map +1 -1
  282. package/dist/test-runner/core/flow-stage.d.ts.map +1 -1
  283. package/dist/test-runner/core/mocks.d.ts.map +1 -1
  284. package/dist/test-runner/core/test-execution-wrapper.d.ts.map +1 -1
  285. package/dist/test-runner/evaluators.d.ts.map +1 -1
  286. package/dist/test-runner/fixture-loader.d.ts.map +1 -1
  287. package/dist/test-runner/index.d.ts.map +1 -1
  288. package/dist/test-runner/llm-judge.d.ts.map +1 -1
  289. package/dist/test-runner/recorders/github-recorder.d.ts.map +1 -1
  290. package/dist/test-runner/recorders/global-recorder.d.ts.map +1 -1
  291. package/dist/test-runner/recorders/slack-recorder.d.ts.map +1 -1
  292. package/dist/test-runner/utils/selectors.d.ts.map +1 -1
  293. package/dist/test-runner/validator.d.ts.map +1 -1
  294. package/dist/traces/{run-2026-05-05T12-31-47-571Z.ndjson → run-2026-08-20T13-50-06-218Z.ndjson} +2699 -2699
  295. package/dist/tui/chat-runner.d.ts.map +1 -1
  296. package/dist/tui/chat-state.d.ts.map +1 -1
  297. package/dist/tui/chat-tui.d.ts.map +1 -1
  298. package/dist/tui/components/chat-box.d.ts.map +1 -1
  299. package/dist/tui/components/input-bar.d.ts.map +1 -1
  300. package/dist/tui/components/status-bar.d.ts.map +1 -1
  301. package/dist/tui/components/trace-viewer.d.ts.map +1 -1
  302. package/dist/tui/index.d.ts.map +1 -1
  303. package/dist/tui/tui-frontend.d.ts.map +1 -1
  304. package/dist/types/bot.d.ts.map +1 -1
  305. package/dist/types/cli.d.ts.map +1 -1
  306. package/dist/types/config.d.ts +14 -2
  307. package/dist/types/config.d.ts.map +1 -1
  308. package/dist/types/engine.d.ts.map +1 -1
  309. package/dist/types/execution.d.ts.map +1 -1
  310. package/dist/types/git-checkout.d.ts.map +1 -1
  311. package/dist/types/github.d.ts.map +1 -1
  312. package/dist/types/workflow.d.ts.map +1 -1
  313. package/dist/utils/author-permissions.d.ts.map +1 -1
  314. package/dist/utils/child-process-error-handler.d.ts +19 -0
  315. package/dist/utils/child-process-error-handler.d.ts.map +1 -0
  316. package/dist/utils/command-executor.d.ts.map +1 -1
  317. package/dist/utils/comment-metadata.d.ts.map +1 -1
  318. package/dist/utils/config-loader.d.ts.map +1 -1
  319. package/dist/utils/config-merger.d.ts.map +1 -1
  320. package/dist/utils/diff-processor.d.ts.map +1 -1
  321. package/dist/utils/env-exposure.d.ts.map +1 -1
  322. package/dist/utils/env-resolver.d.ts.map +1 -1
  323. package/dist/utils/fair-concurrency-limiter.d.ts.map +1 -1
  324. package/dist/utils/file-exclusion.d.ts.map +1 -1
  325. package/dist/utils/head-sha.d.ts.map +1 -1
  326. package/dist/utils/human-id.d.ts.map +1 -1
  327. package/dist/utils/instance-id.d.ts.map +1 -1
  328. package/dist/utils/interactive-prompt.d.ts.map +1 -1
  329. package/dist/utils/issue-normalizer.d.ts.map +1 -1
  330. package/dist/utils/json-text-extractor.d.ts.map +1 -1
  331. package/dist/utils/mermaid-telemetry.d.ts.map +1 -1
  332. package/dist/utils/oauth2-token-cache.d.ts.map +1 -1
  333. package/dist/utils/rate-limiter.d.ts.map +1 -1
  334. package/dist/utils/sandbox.d.ts.map +1 -1
  335. package/dist/utils/script-memory-ops.d.ts.map +1 -1
  336. package/dist/utils/script-tool-environment.d.ts.map +1 -1
  337. package/dist/utils/stdin-reader.d.ts.map +1 -1
  338. package/dist/utils/template-context.d.ts.map +1 -1
  339. package/dist/utils/tool-resolver.d.ts.map +1 -1
  340. package/dist/utils/toolkit-expander.d.ts.map +1 -1
  341. package/dist/utils/tracer-init.d.ts.map +1 -1
  342. package/dist/utils/ui-helpers.d.ts.map +1 -1
  343. package/dist/utils/user-facing-error.d.ts +4 -0
  344. package/dist/utils/user-facing-error.d.ts.map +1 -0
  345. package/dist/utils/workspace-manager.d.ts +5 -0
  346. package/dist/utils/workspace-manager.d.ts.map +1 -1
  347. package/dist/utils/worktree-cleanup.d.ts +28 -0
  348. package/dist/utils/worktree-cleanup.d.ts.map +1 -1
  349. package/dist/utils/worktree-manager.d.ts +6 -0
  350. package/dist/utils/worktree-manager.d.ts.map +1 -1
  351. package/dist/webhook-server.d.ts.map +1 -1
  352. package/dist/whatsapp/adapter.d.ts.map +1 -1
  353. package/dist/whatsapp/client.d.ts.map +1 -1
  354. package/dist/whatsapp/markdown.d.ts.map +1 -1
  355. package/dist/whatsapp/webhook-runner.d.ts +1 -0
  356. package/dist/whatsapp/webhook-runner.d.ts.map +1 -1
  357. package/dist/workflow-executor.d.ts +7 -0
  358. package/dist/workflow-executor.d.ts.map +1 -1
  359. package/dist/workflow-registry.d.ts.map +1 -1
  360. package/package.json +3 -3
  361. package/dist/output/traces/run-2026-05-05T12-31-09-587Z.ndjson +0 -252
  362. package/dist/sdk/chunk-IY5PQ5EN.mjs.map +0 -1
  363. package/dist/sdk/chunk-NPOVLLKH.mjs.map +0 -1
  364. package/dist/sdk/chunk-PDQTEBOJ.mjs.map +0 -1
  365. package/dist/sdk/chunk-SRU5TFNY.mjs.map +0 -1
  366. package/dist/sdk/chunk-TSX3YS3F.mjs.map +0 -1
  367. package/dist/sdk/chunk-XX6WT332.mjs.map +0 -1
  368. package/dist/sdk/chunk-XXAEN5KU.mjs.map +0 -1
  369. package/dist/sdk/session-registry-6PV6SGEJ.mjs +0 -10
  370. package/dist/sdk/slack-frontend-K3TPGERM.mjs.map +0 -1
  371. package/dist/sdk/task-evaluator-H3BXC7SE.mjs.map +0 -1
  372. package/dist/sdk/teams-frontend-6RRW533K.mjs.map +0 -1
  373. package/dist/sdk/telegram-frontend-5UA77YAT.mjs.map +0 -1
  374. package/dist/sdk/trace-reader-OVE4DL2D.mjs +0 -270
  375. package/dist/sdk/trace-reader-OVE4DL2D.mjs.map +0 -1
  376. package/dist/sdk/track-execution-VW6P3OYO.mjs.map +0 -1
  377. package/dist/sdk/whatsapp-frontend-72XEIUIR.mjs.map +0 -1
  378. package/dist/traces/run-2026-05-05T12-31-09-587Z.ndjson +0 -252
  379. /package/dist/sdk/{a2a-frontend-L3TQ7QQ6.mjs.map → a2a-frontend-XCQ4CQUF.mjs.map} +0 -0
  380. /package/dist/sdk/{check-provider-registry-RQYIEQLJ.mjs.map → check-provider-registry-2D3MCWP3.mjs.map} +0 -0
  381. /package/dist/sdk/{chunk-5TXIAPRA.mjs.map → chunk-S3GSZRYC.mjs.map} +0 -0
  382. /package/dist/sdk/{chunk-4UMDSYC7.mjs.map → chunk-VS3JE2DL.mjs.map} +0 -0
  383. /package/dist/sdk/{chunk-A4WHMRK2.mjs.map → chunk-YETG675X.mjs.map} +0 -0
  384. /package/dist/sdk/{config-BCYAVJ5S.mjs.map → config-H5IOLBFA.mjs.map} +0 -0
  385. /package/dist/sdk/{failure-condition-evaluator-ZBOSD574.mjs.map → failure-condition-evaluator-66PWLV3D.mjs.map} +0 -0
  386. /package/dist/sdk/{github-frontend-4WHT5JEU.mjs.map → github-frontend-BBFKCY4M.mjs.map} +0 -0
  387. /package/dist/sdk/{host-FKR7H26C.mjs.map → host-UQRZDLT7.mjs.map} +0 -0
  388. /package/dist/sdk/{routing-IB2PXYFC.mjs.map → oauth2-token-cache-OS7WHLDI.mjs.map} +0 -0
  389. /package/dist/sdk/{schedule-tool-LB33KL2W.mjs.map → routing-Q647KUMO.mjs.map} +0 -0
  390. /package/dist/sdk/{schedule-tool-handler-KYWZHKSS.mjs.map → schedule-tool-WMGSM6IT.mjs.map} +0 -0
  391. /package/dist/sdk/{session-registry-6PV6SGEJ.mjs.map → schedule-tool-handler-JMDHCGZ2.mjs.map} +0 -0
  392. /package/dist/sdk/{trace-helpers-AMZ2524G.mjs.map → session-registry-CENXWIFR.mjs.map} +0 -0
  393. /package/dist/sdk/{trace-serializer-EBHTHZYT.mjs.map → trace-helpers-AIUGQLK5.mjs.map} +0 -0
  394. /package/dist/sdk/{utcp-check-provider-Q4PD5EP2.mjs.map → trace-serializer-4TOIAVQL.mjs.map} +0 -0
  395. /package/dist/sdk/{workflow-check-provider-N6KSDPWU.mjs.map → utcp-check-provider-WDTSQ7DZ.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/email/client.ts","../../src/email/markdown.ts","../../src/frontends/email-frontend.ts"],"sourcesContent":["// Multi-backend email client for Visor.\n// Supports IMAP+SMTP (universal) and Resend (managed) for send/receive.\n//\n// Receive backends:\n// - IMAP (imapflow): connect, fetchNewMessages, IDLE for push\n// - Resend polling: GET /emails/receiving to list inbound, then GET /emails/{id} for full content\n// - Resend webhook: webhook metadata → GET /emails/{id} for full content+headers\n//\n// Send backends:\n// - SMTP (nodemailer): createTransport once, multipart/alternative\n// - Resend (resend SDK): resend.emails.send() with threading headers\n\nimport { createHash, randomUUID } from 'crypto';\n\nexport interface EmailMessage {\n id: string; // internal ID (IMAP UID or Resend email_id)\n messageId: string; // Message-ID header\n inReplyTo?: string; // In-Reply-To header\n references?: string[]; // References header chain\n from: string;\n to: string[];\n cc?: string[];\n subject: string;\n text: string;\n html?: string;\n date: Date;\n}\n\nexport interface EmailSendOptions {\n to: string | string[];\n subject: string;\n text: string;\n html?: string;\n inReplyTo?: string;\n references?: string[];\n messageId?: string;\n}\n\nexport interface EmailSendResult {\n ok: boolean;\n messageId?: string;\n error?: string;\n}\n\nexport interface ImapConfig {\n host: string;\n port?: number;\n auth: { user: string; pass: string };\n secure?: boolean;\n pollInterval?: number; // seconds (default: 30)\n folder?: string; // default: 'INBOX'\n markRead?: boolean; // default: true\n}\n\nexport interface SmtpConfig {\n host: string;\n port?: number;\n auth: { user: string; pass: string };\n secure?: boolean;\n from: string;\n}\n\nexport interface ResendConfig {\n apiKey: string;\n from?: string; // for sending\n webhookSecret?: string; // for inbound verification\n}\n\ntype ReceiveBackend = 'imap' | 'resend';\ntype SendBackend = 'smtp' | 'resend';\n\nexport class EmailClient {\n private receiveBackend: ReceiveBackend;\n private sendBackend: SendBackend;\n\n // IMAP\n private imapConfig?: ImapConfig;\n private imapClient?: any; // ImapFlow instance (lazily created)\n\n // SMTP\n private smtpConfig?: SmtpConfig;\n private smtpTransport?: any; // nodemailer transport\n\n // Resend\n private resendConfig?: ResendConfig;\n private resendClient?: any; // Resend instance\n\n private fromAddress: string;\n\n constructor(opts: {\n receive?: { type?: string } & Partial<ImapConfig> & Partial<ResendConfig>;\n send?: { type?: string } & Partial<SmtpConfig> & Partial<ResendConfig>;\n }) {\n this.receiveBackend = (opts.receive?.type as ReceiveBackend) || 'imap';\n this.sendBackend = (opts.send?.type as SendBackend) || 'smtp';\n\n // Configure IMAP (only when receive config is provided)\n if (this.receiveBackend === 'imap' && opts.receive) {\n const r = opts.receive;\n if (!r.host && !process.env.EMAIL_IMAP_HOST) {\n throw new Error('IMAP host is required (set receive.host or EMAIL_IMAP_HOST)');\n }\n this.imapConfig = {\n host: r.host || process.env.EMAIL_IMAP_HOST!,\n port: r.port || parseInt(process.env.EMAIL_IMAP_PORT || '993'),\n auth: {\n user: r.auth?.user || process.env.EMAIL_USER || '',\n pass: r.auth?.pass || process.env.EMAIL_PASSWORD || '',\n },\n secure: r.secure ?? true,\n pollInterval: r.pollInterval || parseInt(process.env.EMAIL_POLL_INTERVAL || '30'),\n folder: r.folder || 'INBOX',\n markRead: r.markRead ?? true,\n };\n }\n\n // Configure Resend for receive\n if (this.receiveBackend === 'resend') {\n const r = opts.receive!;\n const apiKey = (r as any).api_key || r.apiKey || process.env.RESEND_API_KEY;\n if (!apiKey) throw new Error('Resend API key is required for receive');\n this.resendConfig = {\n apiKey,\n webhookSecret:\n (r as any).webhook_secret || r.webhookSecret || process.env.RESEND_WEBHOOK_SECRET,\n };\n }\n\n // Configure SMTP\n if (this.sendBackend === 'smtp') {\n const s = opts.send!;\n if (!s.host && !process.env.EMAIL_SMTP_HOST) {\n throw new Error('SMTP host is required (set send.host or EMAIL_SMTP_HOST)');\n }\n this.smtpConfig = {\n host: s.host || process.env.EMAIL_SMTP_HOST!,\n port: s.port || parseInt(process.env.EMAIL_SMTP_PORT || '587'),\n auth: {\n user: s.auth?.user || process.env.EMAIL_USER || '',\n pass: s.auth?.pass || process.env.EMAIL_PASSWORD || '',\n },\n secure: s.secure ?? true,\n from: s.from || process.env.EMAIL_FROM || '',\n };\n }\n\n // Configure Resend for send\n if (this.sendBackend === 'resend') {\n const s = opts.send!;\n const apiKey = (s as any).api_key || s.apiKey || process.env.RESEND_API_KEY;\n if (!apiKey) throw new Error('Resend API key is required for send');\n if (!this.resendConfig) {\n this.resendConfig = { apiKey };\n }\n this.resendConfig.from = s.from || process.env.EMAIL_FROM;\n }\n\n // Determine from address\n this.fromAddress =\n opts.send?.from ||\n process.env.EMAIL_FROM ||\n this.smtpConfig?.from ||\n this.resendConfig?.from ||\n '';\n }\n\n /** Get the configured from address */\n getFromAddress(): string {\n return this.fromAddress;\n }\n\n /** Get the receive backend type */\n getReceiveBackend(): ReceiveBackend {\n return this.receiveBackend;\n }\n\n // ─── IMAP Receive ───\n\n /** Connect to IMAP server */\n async connectImap(): Promise<void> {\n if (this.receiveBackend !== 'imap' || !this.imapConfig) return;\n const { ImapFlow } = await import('imapflow');\n this.imapClient = new ImapFlow({\n host: this.imapConfig.host,\n port: this.imapConfig.port || 993,\n secure: this.imapConfig.secure ?? true,\n auth: this.imapConfig.auth,\n logger: false,\n });\n await this.imapClient.connect();\n }\n\n /** Fetch unseen messages from IMAP */\n async fetchNewMessages(): Promise<EmailMessage[]> {\n if (!this.imapClient || !this.imapConfig) return [];\n const { simpleParser } = await import('mailparser');\n\n const lock = await this.imapClient.getMailboxLock(this.imapConfig.folder || 'INBOX');\n try {\n const messages: EmailMessage[] = [];\n for await (const msg of this.imapClient.fetch({ seen: false }, { source: true, uid: true })) {\n const parsed = await simpleParser(msg.source);\n const messageId = parsed.messageId || `<${randomUUID()}@visor>`;\n const inReplyTo = typeof parsed.inReplyTo === 'string' ? parsed.inReplyTo : undefined;\n const references = parsed.references\n ? Array.isArray(parsed.references)\n ? parsed.references\n : [parsed.references]\n : undefined;\n\n messages.push({\n id: String(msg.uid),\n messageId,\n inReplyTo,\n references,\n from: typeof parsed.from?.text === 'string' ? parsed.from.text : '',\n to: parsed.to\n ? Array.isArray(parsed.to)\n ? parsed.to.map((a: any) => a.text || '')\n : [parsed.to.text || '']\n : [],\n cc: parsed.cc\n ? Array.isArray(parsed.cc)\n ? parsed.cc.map((a: any) => a.text || '')\n : [parsed.cc.text || '']\n : undefined,\n subject: parsed.subject || '',\n text: parsed.text || '',\n html: parsed.html || undefined,\n date: parsed.date || new Date(),\n });\n\n // Mark as read\n if (this.imapConfig.markRead !== false) {\n try {\n await this.imapClient.messageFlagsAdd({ uid: msg.uid }, ['\\\\Seen'], { uid: true });\n } catch {}\n }\n }\n return messages;\n } finally {\n lock.release();\n }\n }\n\n /** Disconnect IMAP */\n async disconnectImap(): Promise<void> {\n if (this.imapClient) {\n try {\n await this.imapClient.logout();\n } catch {}\n this.imapClient = undefined;\n }\n }\n\n // ─── Resend Receive ───\n\n /** Fetch full email content from Resend by ID */\n async fetchResendEmail(emailId: string): Promise<EmailMessage | null> {\n try {\n const resend = await this.getResendClient();\n const result = await resend.emails.get(emailId);\n const email: any = (result as any).data || result;\n if (!email) return null;\n\n // Extract threading headers\n const headers: Record<string, string> = {};\n if (Array.isArray(email.headers)) {\n for (const h of email.headers) {\n if (h.name && h.value) headers[h.name.toLowerCase()] = h.value;\n }\n } else if (email.headers && typeof email.headers === 'object') {\n for (const [k, v] of Object.entries(email.headers)) {\n headers[k.toLowerCase()] = String(v);\n }\n }\n\n const references = headers['references']\n ? headers['references'].split(/\\s+/).filter(Boolean)\n : undefined;\n\n return {\n id: emailId,\n messageId: headers['message-id'] || `<${emailId}@resend>`,\n inReplyTo: headers['in-reply-to'] || undefined,\n references,\n from: typeof email.from === 'string' ? email.from : email.from?.email || '',\n to: Array.isArray(email.to)\n ? email.to.map((t: any) => (typeof t === 'string' ? t : t?.email || ''))\n : [String(email.to || '')],\n subject: email.subject || '',\n text: email.text || email.body || '',\n html: email.html || undefined,\n date: email.created_at ? new Date(email.created_at) : new Date(),\n };\n } catch (err) {\n console.warn(`[EmailClient] Failed to fetch Resend email ${emailId}: ${err}`);\n return null;\n }\n }\n\n /**\n * List received inbound emails from Resend via polling.\n * Uses GET /emails/receiving with cursor-based pagination.\n * Returns email summaries (call fetchResendEmail for full content).\n */\n async listReceivedEmails(opts?: { limit?: number; after?: string }): Promise<{\n emails: Array<{\n id: string;\n from: string;\n to: string[];\n subject: string;\n created_at: string;\n message_id?: string;\n }>;\n hasMore: boolean;\n lastId?: string;\n }> {\n if (!this.resendConfig?.apiKey) {\n return { emails: [], hasMore: false };\n }\n\n try {\n const params = new URLSearchParams();\n if (opts?.limit) params.set('limit', String(opts.limit));\n if (opts?.after) params.set('after', opts.after);\n const qs = params.toString();\n const url = `https://api.resend.com/emails/receiving${qs ? `?${qs}` : ''}`;\n\n const resp = await fetch(url, {\n headers: {\n Authorization: `Bearer ${this.resendConfig.apiKey}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!resp.ok) {\n console.warn(\n `[EmailClient] Resend list received failed: ${resp.status} ${resp.statusText}`\n );\n return { emails: [], hasMore: false };\n }\n\n const body: any = await resp.json();\n const data = Array.isArray(body.data) ? body.data : [];\n const emails = data.map((e: any) => ({\n id: e.id,\n from: typeof e.from === 'string' ? e.from : e.from?.email || '',\n to: Array.isArray(e.to)\n ? e.to.map((t: any) => (typeof t === 'string' ? t : t?.email || ''))\n : [],\n subject: e.subject || '',\n created_at: e.created_at || '',\n message_id: e.message_id,\n }));\n\n const lastId = emails.length > 0 ? emails[emails.length - 1].id : undefined;\n return {\n emails,\n hasMore: !!body.has_more,\n lastId,\n };\n } catch (err) {\n console.warn(`[EmailClient] Resend list received error: ${err}`);\n return { emails: [], hasMore: false };\n }\n }\n\n /** Verify Resend webhook signature */\n async verifyResendWebhook(payload: string, headers: Record<string, string>): Promise<boolean> {\n if (!this.resendConfig?.webhookSecret) return true; // no secret = skip verification\n try {\n const { Webhook } = await import('svix');\n const wh = new Webhook(this.resendConfig.webhookSecret);\n wh.verify(payload, {\n 'svix-id': headers['svix-id'] || '',\n 'svix-timestamp': headers['svix-timestamp'] || '',\n 'svix-signature': headers['svix-signature'] || '',\n });\n return true;\n } catch {\n return false;\n }\n }\n\n // ─── Send ───\n\n /** Send an email via configured backend (SMTP or Resend) */\n async sendEmail(opts: EmailSendOptions): Promise<EmailSendResult> {\n const messageId = opts.messageId || `<${randomUUID()}@visor>`;\n\n if (this.sendBackend === 'resend') {\n return this.sendViaResend(opts, messageId);\n }\n return this.sendViaSmtp(opts, messageId);\n }\n\n private async sendViaSmtp(opts: EmailSendOptions, messageId: string): Promise<EmailSendResult> {\n try {\n const transport = await this.getSmtpTransport();\n const to = Array.isArray(opts.to) ? opts.to.join(', ') : opts.to;\n\n const mailOpts: Record<string, any> = {\n from: this.fromAddress,\n to,\n subject: opts.subject,\n text: opts.text,\n messageId,\n };\n\n if (opts.html) mailOpts.html = opts.html;\n if (opts.inReplyTo) mailOpts.inReplyTo = opts.inReplyTo;\n if (opts.references && opts.references.length > 0) {\n mailOpts.references = opts.references.join(' ');\n }\n\n const info = await transport.sendMail(mailOpts);\n return {\n ok: true,\n messageId: info.messageId || messageId,\n };\n } catch (err: any) {\n const errMsg = err?.message || String(err);\n console.warn(`[EmailClient] SMTP send failed: ${errMsg}`);\n return { ok: false, error: errMsg };\n }\n }\n\n private async sendViaResend(opts: EmailSendOptions, messageId: string): Promise<EmailSendResult> {\n try {\n const resend = await this.getResendClient();\n const to = Array.isArray(opts.to) ? opts.to : [opts.to];\n\n const headers: Record<string, string> = {};\n headers['Message-ID'] = messageId;\n if (opts.inReplyTo) headers['In-Reply-To'] = opts.inReplyTo;\n if (opts.references && opts.references.length > 0) {\n headers['References'] = opts.references.join(' ');\n }\n\n const sendOpts: Record<string, any> = {\n from: this.fromAddress,\n to,\n subject: opts.subject,\n text: opts.text,\n headers,\n };\n if (opts.html) sendOpts.html = opts.html;\n\n const result = await resend.emails.send(sendOpts);\n const data: any = (result as any).data || result;\n return {\n ok: true,\n messageId: data?.id ? `<${data.id}@resend>` : messageId,\n };\n } catch (err: any) {\n const errMsg = err?.message || String(err);\n console.warn(`[EmailClient] Resend send failed: ${errMsg}`);\n return { ok: false, error: errMsg };\n }\n }\n\n // ─── Lazy initialization helpers ───\n\n private async getSmtpTransport(): Promise<any> {\n if (this.smtpTransport) return this.smtpTransport;\n const nodemailer = await import('nodemailer');\n this.smtpTransport = nodemailer.createTransport({\n host: this.smtpConfig!.host,\n port: this.smtpConfig!.port || 587,\n secure: this.smtpConfig!.secure ?? true,\n auth: this.smtpConfig!.auth,\n });\n return this.smtpTransport;\n }\n\n private async getResendClient(): Promise<any> {\n if (this.resendClient) return this.resendClient;\n const { Resend } = await import('resend');\n this.resendClient = new Resend(this.resendConfig!.apiKey);\n return this.resendClient;\n }\n\n /** Generate a deterministic thread ID from a Message-ID chain */\n static deriveThreadId(rootMessageId: string): string {\n return createHash('sha256').update(rootMessageId).digest('hex').slice(0, 16);\n }\n}\n","// Markdown → email HTML converter.\n// Converts AI Markdown output to email-compatible HTML with inline styles.\n//\n// Supported conversions:\n// - # Header → <h1 style=\"...\">Header</h1>\n// - **bold** → <strong>bold</strong>\n// - *italic* → <em>italic</em>\n// - ~~strike~~ → <del>strike</del>\n// - `code` → <code style=\"...\">code</code>\n// - ```block``` → <pre style=\"...\"><code>block</code></pre>\n// - [label](url) → <a href=\"url\">label</a>\n// - > blockquote → <blockquote style=\"...\">text</blockquote>\n// - - item → <ul><li>item</li></ul>\n// - 1. item → <ol><li>item</li></ol>\n// - --- → <hr>\n// HTML entities escaped: & < >\n\n/** Escape HTML entities in text */\nexport function escapeHtml(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\n/**\n * Convert Markdown text to email-compatible HTML.\n * Processes line-by-line, respecting fenced code blocks.\n */\nexport function markdownToEmailHtml(text: string): string {\n if (!text || typeof text !== 'string') return '';\n\n const lines = text.split(/\\r?\\n/);\n const result: string[] = [];\n let inCodeBlock = false;\n let codeBlockLang = '';\n let codeLines: string[] = [];\n let inBlockquote = false;\n let blockquoteLines: string[] = [];\n const listStack: ('ul' | 'ol')[] = [];\n\n const flushBlockquote = () => {\n if (blockquoteLines.length > 0) {\n result.push(\n `<blockquote style=\"border-left:3px solid #ccc;margin:8px 0;padding:4px 12px;color:#555;\">${blockquoteLines.join('<br>')}</blockquote>`\n );\n blockquoteLines = [];\n inBlockquote = false;\n }\n };\n\n const flushList = () => {\n while (listStack.length > 0) {\n const tag = listStack.pop()!;\n result.push(`</${tag}>`);\n }\n };\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trimStart();\n\n // Track fenced code blocks\n if (/^```/.test(trimmed)) {\n if (!inCodeBlock) {\n flushBlockquote();\n flushList();\n inCodeBlock = true;\n codeBlockLang = trimmed.slice(3).trim();\n codeLines = [];\n } else {\n const escaped = codeLines.map(l => escapeHtml(l)).join('\\n');\n const langAttr = codeBlockLang ? ` class=\"language-${escapeHtml(codeBlockLang)}\"` : '';\n result.push(\n `<pre style=\"background:#f4f4f4;padding:12px;border-radius:4px;overflow-x:auto;font-size:13px;\"><code${langAttr}>${escaped}</code></pre>`\n );\n inCodeBlock = false;\n codeBlockLang = '';\n codeLines = [];\n }\n continue;\n }\n if (inCodeBlock) {\n codeLines.push(lines[i]);\n continue;\n }\n\n // Blockquotes: > text\n const bqMatch = /^>\\s?(.*)$/.exec(trimmed);\n if (bqMatch) {\n flushList();\n inBlockquote = true;\n blockquoteLines.push(convertInline(bqMatch[1]));\n continue;\n } else if (inBlockquote) {\n flushBlockquote();\n }\n\n // Bullet lists: \"- item\" or \"* item\"\n const bulletMatch = /^(\\s*)([-*])\\s+(.+)$/.exec(lines[i]);\n if (bulletMatch) {\n if (listStack.length === 0 || listStack[listStack.length - 1] !== 'ul') {\n flushList();\n listStack.push('ul');\n result.push('<ul style=\"margin:4px 0;padding-left:24px;\">');\n }\n result.push(`<li>${convertInline(bulletMatch[3])}</li>`);\n continue;\n }\n\n // Numbered lists: \"1. item\"\n const numMatch = /^(\\s*)(\\d+)\\.\\s+(.+)$/.exec(lines[i]);\n if (numMatch) {\n if (listStack.length === 0 || listStack[listStack.length - 1] !== 'ol') {\n flushList();\n listStack.push('ol');\n result.push('<ol style=\"margin:4px 0;padding-left:24px;\">');\n }\n result.push(`<li>${convertInline(numMatch[3])}</li>`);\n continue;\n }\n\n // Close any open list if we hit a non-list line\n if (listStack.length > 0) flushList();\n\n const line = lines[i];\n\n // Headers: # Header → <h1>...</h1> etc.\n const headerMatch = /^(#{1,6})\\s+(.+)$/.exec(line.trimStart());\n if (headerMatch) {\n const level = headerMatch[1].length;\n const sizes: Record<number, string> = {\n 1: '24px',\n 2: '20px',\n 3: '18px',\n 4: '16px',\n 5: '14px',\n 6: '13px',\n };\n result.push(\n `<h${level} style=\"font-size:${sizes[level]};margin:16px 0 8px 0;\">${convertInline(headerMatch[2].trim())}</h${level}>`\n );\n continue;\n }\n\n // Horizontal rules\n if (/^[-*_]{3,}\\s*$/.test(trimmed)) {\n result.push('<hr style=\"border:none;border-top:1px solid #ddd;margin:16px 0;\">');\n continue;\n }\n\n // Empty lines → <br>\n if (trimmed === '') {\n result.push('<br>');\n continue;\n }\n\n // Regular line: apply inline conversions\n result.push(`<p style=\"margin:4px 0;\">${convertInline(line)}</p>`);\n }\n\n // Close any unclosed code block\n if (inCodeBlock && codeLines.length > 0) {\n const escaped = codeLines.map(l => escapeHtml(l)).join('\\n');\n result.push(\n `<pre style=\"background:#f4f4f4;padding:12px;border-radius:4px;overflow-x:auto;font-size:13px;\"><code>${escaped}</code></pre>`\n );\n }\n flushBlockquote();\n flushList();\n\n return result.join('\\n');\n}\n\n/**\n * Apply inline Markdown conversions to a single line.\n * Order matters: escape HTML first, then apply formatting.\n */\nfunction convertInline(line: string): string {\n // First, identify and protect inline code spans\n const codeSpans: string[] = [];\n let processed = line.replace(/`([^`]+)`/g, (_m, code: string) => {\n const idx = codeSpans.length;\n codeSpans.push(\n `<code style=\"background:#f0f0f0;padding:1px 4px;border-radius:3px;font-size:13px;\">${escapeHtml(code)}</code>`\n );\n return `\\x00CODE${idx}\\x00`;\n });\n\n // Escape HTML in non-code portions\n processed = escapeHtml(processed);\n\n // Images: ![alt](url)\n processed = processed.replace(\n /!\\[([^\\]]*)\\]\\(([^)\\s]+)(?:\\s+&quot;[^&]*&quot;)?\\)/g,\n (_m, alt: string, url: string) =>\n `<img src=\"${url}\" alt=\"${alt || 'image'}\" style=\"max-width:100%;\">`\n );\n\n // Links: [label](url) → <a href=\"url\">label</a>\n processed = processed.replace(\n /\\[([^\\]]+)\\]\\(([^)\\s]+)(?:\\s+&quot;[^&]*&quot;)?\\)/g,\n (_m, label: string, url: string) => `<a href=\"${url}\" style=\"color:#0066cc;\">${label}</a>`\n );\n\n // Bold: **text** or __text__\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/__([^_]+)__/g, '<strong>$1</strong>');\n\n // Italic: *text* (but not inside bold)\n processed = processed.replace(/(?<!\\*)\\*([^*]+)\\*(?!\\*)/g, '<em>$1</em>');\n\n // Strikethrough: ~~text~~\n processed = processed.replace(/~~([^~]+)~~/g, '<del>$1</del>');\n\n // Restore code spans\n processed = processed.replace(\n /\\x00CODE(\\d+)\\x00/g,\n (_m, idx: string) => codeSpans[parseInt(idx)]\n );\n\n return processed;\n}\n\n/**\n * Wrap body HTML in a complete email HTML template with inline CSS.\n */\nexport function wrapInEmailTemplate(bodyHtml: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n<body style=\"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.5;color:#333;max-width:600px;margin:0 auto;padding:16px;\">\n${bodyHtml}\n</body>\n</html>`;\n}\n\n/**\n * Format text as a plain-text email quote (prepend \"> \" to each line).\n */\nexport function formatEmailQuote(text: string): string {\n if (!text) return '';\n return text\n .split(/\\r?\\n/)\n .map(l => `> ${l}`)\n .join('\\n');\n}\n\n/**\n * Add \"Re: \" prefix to subject if not already present.\n */\nexport function addRePrefix(subject: string): string {\n if (!subject) return 'Re:';\n if (/^Re:/i.test(subject.trim())) return subject.trim();\n return `Re: ${subject.trim()}`;\n}\n\n/**\n * Main entry point: convert Markdown to email HTML body (not wrapped in template).\n */\nexport function formatEmailText(text: string): string {\n return markdownToEmailHtml(text);\n}\n","/**\n * Email Frontend for Visor workflows.\n *\n * Mirrors the TelegramFrontend pattern:\n * - Sends AI replies as threaded emails (In-Reply-To, References headers)\n * - Converts Markdown to email HTML format\n * - No reaction equivalent (CheckScheduled is a no-op)\n */\nimport type { Frontend, FrontendContext } from './host';\nimport { EmailClient, type EmailSendOptions } from '../email/client';\nimport { formatEmailText, wrapInEmailTemplate, addRePrefix } from '../email/markdown';\n\ntype EmailFrontendConfig = {\n send?: {\n type?: string;\n host?: string;\n port?: number;\n auth?: { user?: string; pass?: string };\n secure?: boolean;\n from?: string;\n api_key?: string;\n };\n};\n\nexport class EmailFrontend implements Frontend {\n public readonly name = 'email';\n private subs: Array<{ unsubscribe(): void }> = [];\n private cfg: EmailFrontendConfig;\n private errorNotified: boolean = false;\n\n constructor(config?: EmailFrontendConfig) {\n this.cfg = config || {};\n }\n\n start(ctx: FrontendContext): void {\n const bus = ctx.eventBus;\n\n try {\n ctx.logger.info(`[email-frontend] started`);\n } catch {}\n\n // CheckCompleted: send reply email\n this.subs.push(\n bus.on('CheckCompleted', async (env: any) => {\n const ev = (env && env.payload) || env;\n await this.maybePostDirectReply(ctx, ev.checkId, ev.result).catch(() => {});\n })\n );\n\n // CheckErrored: send error email\n this.subs.push(\n bus.on('CheckErrored', async (env: any) => {\n const ev = (env && env.payload) || env;\n const message = ev?.error?.message || 'Execution error';\n await this.maybePostError(ctx, 'Check failed', message, ev?.checkId).catch(() => {});\n })\n );\n\n // Shutdown: send fatal error email\n this.subs.push(\n bus.on('Shutdown', async (env: any) => {\n const ev = (env && env.payload) || env;\n const message = ev?.error?.message || 'Fatal error';\n await this.maybePostError(ctx, 'Run failed', message).catch(() => {});\n })\n );\n\n // CheckScheduled: no-op for email (no reaction equivalent)\n // StateTransition: no-op for email\n }\n\n stop(): void {\n for (const s of this.subs) s.unsubscribe();\n this.subs = [];\n }\n\n private getEmailClient(ctx: FrontendContext): EmailClient | undefined {\n // Prefer injected client (for tests or shared runner context)\n const injected = (ctx as any).emailClient;\n if (injected) return injected;\n // Lazy-create from config\n try {\n const emailConfig = (ctx as any).webhookContext?.webhookData?.get('/bots/email/message');\n const sendCfg = this.cfg.send || (emailConfig as any)?.sendConfig;\n if (sendCfg || process.env.EMAIL_SMTP_HOST || process.env.RESEND_API_KEY) {\n return new EmailClient({\n send: sendCfg || {\n type: process.env.RESEND_API_KEY ? 'resend' : 'smtp',\n },\n });\n }\n } catch {}\n return undefined;\n }\n\n private getInboundEmailPayload(ctx: FrontendContext): any | null {\n try {\n const endpoint = '/bots/email/message';\n return (ctx as any).webhookContext?.webhookData?.get(endpoint) || null;\n } catch {\n return null;\n }\n }\n\n private async maybePostError(\n ctx: FrontendContext,\n title: string,\n message: string,\n checkId?: string\n ): Promise<void> {\n if (this.errorNotified) return;\n const client = this.getEmailClient(ctx);\n if (!client) return;\n const payload = this.getInboundEmailPayload(ctx);\n const ev: any = payload?.event;\n if (!ev?.from) return;\n\n let text = `${title}`;\n if (checkId) text += `\\nCheck: ${checkId}`;\n if (message) text += `\\n${message}`;\n\n const sendOpts: EmailSendOptions = {\n to: ev.from,\n subject: ev.subject ? addRePrefix(ev.subject) : `Visor: ${title}`,\n text,\n html: wrapInEmailTemplate(`<p><strong>${title}</strong></p><p>${message}</p>`),\n };\n\n // Thread the reply\n if (ev.messageId) {\n sendOpts.inReplyTo = ev.messageId;\n sendOpts.references = ev.references ? [...ev.references, ev.messageId] : [ev.messageId];\n }\n\n await client.sendEmail(sendOpts);\n this.errorNotified = true;\n }\n\n private async maybePostDirectReply(\n ctx: FrontendContext,\n checkId: string,\n result: { output?: any; content?: string }\n ): Promise<void> {\n try {\n const cfg: any = ctx.config || {};\n const checkCfg: any = cfg.checks?.[checkId];\n if (!checkCfg) return;\n\n const providerType = (checkCfg.type as string) || '';\n const isAi = providerType === 'ai';\n const isLogChat = providerType === 'log' && checkCfg.group === 'chat';\n const isWorkflow = providerType === 'workflow';\n if (!isAi && !isLogChat && !isWorkflow) return;\n if (checkCfg.criticality === 'internal') return;\n\n // For AI checks, only post simple schemas\n if (isAi) {\n const schema = checkCfg.schema;\n if (typeof schema === 'string') {\n const simpleSchemas = ['code-review', 'markdown', 'text', 'plain'];\n if (!simpleSchemas.includes(schema)) return;\n }\n }\n\n const client = this.getEmailClient(ctx);\n if (!client) return;\n\n const payload = this.getInboundEmailPayload(ctx);\n const ev: any = payload?.event;\n if (!ev?.from) {\n ctx.logger.warn(`[email-frontend] skip posting reply for ${checkId}: missing from address`);\n return;\n }\n\n // Extract text (same logic as TelegramFrontend/SlackFrontend)\n const out: any = (result as any)?.output;\n let text: string | undefined;\n if (out && typeof out.text === 'string' && out.text.trim().length > 0) {\n text = out.text.trim();\n } else if (isAi && typeof checkCfg.schema === 'string') {\n if (\n typeof (result as any)?.content === 'string' &&\n (result as any).content.trim().length > 0\n ) {\n text = (result as any).content.trim();\n }\n } else if (isLogChat && typeof (result as any)?.logOutput === 'string') {\n const raw = (result as any).logOutput;\n if (raw.trim().length > 0) text = raw.trim();\n }\n\n // Append raw output\n if (out && typeof out._rawOutput === 'string' && out._rawOutput.trim().length > 0) {\n text = (text || '') + '\\n\\n' + out._rawOutput.trim();\n }\n\n if (!text) {\n ctx.logger.info(`[email-frontend] skip posting reply for ${checkId}: no renderable text`);\n return;\n }\n\n // Normalize literal \\n escape sequences\n text = text.replace(/\\\\n/g, '\\n');\n\n const htmlBody = formatEmailText(text);\n const sendOpts: EmailSendOptions = {\n to: ev.from,\n subject: ev.subject ? addRePrefix(ev.subject) : `Re: Visor response`,\n text,\n html: wrapInEmailTemplate(htmlBody),\n };\n\n // Thread the reply\n if (ev.messageId) {\n sendOpts.inReplyTo = ev.messageId;\n sendOpts.references = ev.references ? [...ev.references, ev.messageId] : [ev.messageId];\n }\n\n const sendResult = await client.sendEmail(sendOpts);\n\n if (!sendResult.ok) {\n ctx.logger.warn(\n `[email-frontend] failed to send reply for ${checkId}: ${sendResult.error}`\n );\n return;\n }\n ctx.logger.info(\n `[email-frontend] sent reply for ${checkId} to ${ev.from} (messageId=${sendResult.messageId})`\n );\n } catch (err) {\n try {\n ctx.logger.warn(\n `[email-frontend] maybePostDirectReply failed for ${checkId}: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n } catch {}\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/email/client.ts","../../src/email/markdown.ts","../../src/frontends/email-frontend.ts"],"sourcesContent":["// Multi-backend email client for Visor.\n// Supports IMAP+SMTP (universal) and Resend (managed) for send/receive.\n//\n// Receive backends:\n// - IMAP (imapflow): connect, fetchNewMessages, IDLE for push\n// - Resend polling: GET /emails/receiving to list inbound, then GET /emails/{id} for full content\n// - Resend webhook: webhook metadata → GET /emails/{id} for full content+headers\n//\n// Send backends:\n// - SMTP (nodemailer): createTransport once, multipart/alternative\n// - Resend (resend SDK): resend.emails.send() with threading headers\n\nimport { createHash, randomUUID } from 'crypto';\n\nexport interface EmailMessage {\n id: string; // internal ID (IMAP UID or Resend email_id)\n messageId: string; // Message-ID header\n inReplyTo?: string; // In-Reply-To header\n references?: string[]; // References header chain\n from: string;\n to: string[];\n cc?: string[];\n subject: string;\n text: string;\n html?: string;\n date: Date;\n}\n\nexport interface EmailSendOptions {\n to: string | string[];\n subject: string;\n text: string;\n html?: string;\n inReplyTo?: string;\n references?: string[];\n messageId?: string;\n}\n\nexport interface EmailSendResult {\n ok: boolean;\n messageId?: string;\n error?: string;\n}\n\nexport interface ImapConfig {\n host: string;\n port?: number;\n auth: { user: string; pass: string };\n secure?: boolean;\n pollInterval?: number; // seconds (default: 30)\n folder?: string; // default: 'INBOX'\n markRead?: boolean; // default: true\n}\n\nexport interface SmtpConfig {\n host: string;\n port?: number;\n auth: { user: string; pass: string };\n secure?: boolean;\n from: string;\n}\n\nexport interface ResendConfig {\n apiKey: string;\n from?: string; // for sending\n webhookSecret?: string; // for inbound verification\n}\n\ntype ReceiveBackend = 'imap' | 'resend';\ntype SendBackend = 'smtp' | 'resend';\n\nexport class EmailClient {\n private receiveBackend: ReceiveBackend;\n private sendBackend: SendBackend;\n\n // IMAP\n private imapConfig?: ImapConfig;\n private imapClient?: any; // ImapFlow instance (lazily created)\n\n // SMTP\n private smtpConfig?: SmtpConfig;\n private smtpTransport?: any; // nodemailer transport\n\n // Resend\n private resendConfig?: ResendConfig;\n private resendClient?: any; // Resend instance\n\n private fromAddress: string;\n\n constructor(opts: {\n receive?: { type?: string } & Partial<ImapConfig> & Partial<ResendConfig>;\n send?: { type?: string } & Partial<SmtpConfig> & Partial<ResendConfig>;\n }) {\n this.receiveBackend = (opts.receive?.type as ReceiveBackend) || 'imap';\n this.sendBackend = (opts.send?.type as SendBackend) || 'smtp';\n\n // Configure IMAP (only when receive config is provided)\n if (this.receiveBackend === 'imap' && opts.receive) {\n const r = opts.receive;\n if (!r.host && !process.env.EMAIL_IMAP_HOST) {\n throw new Error('IMAP host is required (set receive.host or EMAIL_IMAP_HOST)');\n }\n this.imapConfig = {\n host: r.host || process.env.EMAIL_IMAP_HOST!,\n port: r.port || parseInt(process.env.EMAIL_IMAP_PORT || '993'),\n auth: {\n user: r.auth?.user || process.env.EMAIL_USER || '',\n pass: r.auth?.pass || process.env.EMAIL_PASSWORD || '',\n },\n secure: r.secure ?? true,\n pollInterval: r.pollInterval || parseInt(process.env.EMAIL_POLL_INTERVAL || '30'),\n folder: r.folder || 'INBOX',\n markRead: r.markRead ?? true,\n };\n }\n\n // Configure Resend for receive\n if (this.receiveBackend === 'resend') {\n const r = opts.receive!;\n const apiKey = (r as any).api_key || r.apiKey || process.env.RESEND_API_KEY;\n if (!apiKey) throw new Error('Resend API key is required for receive');\n this.resendConfig = {\n apiKey,\n webhookSecret:\n (r as any).webhook_secret || r.webhookSecret || process.env.RESEND_WEBHOOK_SECRET,\n };\n }\n\n // Configure SMTP\n if (this.sendBackend === 'smtp') {\n const s = opts.send!;\n if (!s.host && !process.env.EMAIL_SMTP_HOST) {\n throw new Error('SMTP host is required (set send.host or EMAIL_SMTP_HOST)');\n }\n this.smtpConfig = {\n host: s.host || process.env.EMAIL_SMTP_HOST!,\n port: s.port || parseInt(process.env.EMAIL_SMTP_PORT || '587'),\n auth: {\n user: s.auth?.user || process.env.EMAIL_USER || '',\n pass: s.auth?.pass || process.env.EMAIL_PASSWORD || '',\n },\n secure: s.secure ?? true,\n from: s.from || process.env.EMAIL_FROM || '',\n };\n }\n\n // Configure Resend for send\n if (this.sendBackend === 'resend') {\n const s = opts.send!;\n const apiKey = (s as any).api_key || s.apiKey || process.env.RESEND_API_KEY;\n if (!apiKey) throw new Error('Resend API key is required for send');\n if (!this.resendConfig) {\n this.resendConfig = { apiKey };\n }\n this.resendConfig.from = s.from || process.env.EMAIL_FROM;\n }\n\n // Determine from address\n this.fromAddress =\n opts.send?.from ||\n process.env.EMAIL_FROM ||\n this.smtpConfig?.from ||\n this.resendConfig?.from ||\n '';\n }\n\n /** Get the configured from address */\n getFromAddress(): string {\n return this.fromAddress;\n }\n\n /** Get the receive backend type */\n getReceiveBackend(): ReceiveBackend {\n return this.receiveBackend;\n }\n\n // ─── IMAP Receive ───\n\n /** Connect to IMAP server */\n async connectImap(): Promise<void> {\n if (this.receiveBackend !== 'imap' || !this.imapConfig) return;\n const { ImapFlow } = await import('imapflow');\n this.imapClient = new ImapFlow({\n host: this.imapConfig.host,\n port: this.imapConfig.port || 993,\n secure: this.imapConfig.secure ?? true,\n auth: this.imapConfig.auth,\n logger: false,\n });\n await this.imapClient.connect();\n }\n\n /** Fetch unseen messages from IMAP */\n async fetchNewMessages(): Promise<EmailMessage[]> {\n if (!this.imapClient || !this.imapConfig) return [];\n const { simpleParser } = await import('mailparser');\n\n const lock = await this.imapClient.getMailboxLock(this.imapConfig.folder || 'INBOX');\n try {\n const messages: EmailMessage[] = [];\n for await (const msg of this.imapClient.fetch({ seen: false }, { source: true, uid: true })) {\n const parsed = await simpleParser(msg.source);\n const messageId = parsed.messageId || `<${randomUUID()}@visor>`;\n const inReplyTo = typeof parsed.inReplyTo === 'string' ? parsed.inReplyTo : undefined;\n const references = parsed.references\n ? Array.isArray(parsed.references)\n ? parsed.references\n : [parsed.references]\n : undefined;\n\n messages.push({\n id: String(msg.uid),\n messageId,\n inReplyTo,\n references,\n from: typeof parsed.from?.text === 'string' ? parsed.from.text : '',\n to: parsed.to\n ? Array.isArray(parsed.to)\n ? parsed.to.map((a: any) => a.text || '')\n : [parsed.to.text || '']\n : [],\n cc: parsed.cc\n ? Array.isArray(parsed.cc)\n ? parsed.cc.map((a: any) => a.text || '')\n : [parsed.cc.text || '']\n : undefined,\n subject: parsed.subject || '',\n text: parsed.text || '',\n html: parsed.html || undefined,\n date: parsed.date || new Date(),\n });\n\n // Mark as read\n if (this.imapConfig.markRead !== false) {\n try {\n await this.imapClient.messageFlagsAdd({ uid: msg.uid }, ['\\\\Seen'], { uid: true });\n } catch {}\n }\n }\n return messages;\n } finally {\n lock.release();\n }\n }\n\n /** Disconnect IMAP */\n async disconnectImap(): Promise<void> {\n if (this.imapClient) {\n try {\n await this.imapClient.logout();\n } catch {}\n this.imapClient = undefined;\n }\n }\n\n // ─── Resend Receive ───\n\n /** Fetch full email content from Resend by ID */\n async fetchResendEmail(emailId: string): Promise<EmailMessage | null> {\n try {\n const resend = await this.getResendClient();\n const result = await resend.emails.get(emailId);\n const email: any = (result as any).data || result;\n if (!email) return null;\n\n // Extract threading headers\n const headers: Record<string, string> = {};\n if (Array.isArray(email.headers)) {\n for (const h of email.headers) {\n if (h.name && h.value) headers[h.name.toLowerCase()] = h.value;\n }\n } else if (email.headers && typeof email.headers === 'object') {\n for (const [k, v] of Object.entries(email.headers)) {\n headers[k.toLowerCase()] = String(v);\n }\n }\n\n const references = headers['references']\n ? headers['references'].split(/\\s+/).filter(Boolean)\n : undefined;\n\n return {\n id: emailId,\n messageId: headers['message-id'] || `<${emailId}@resend>`,\n inReplyTo: headers['in-reply-to'] || undefined,\n references,\n from: typeof email.from === 'string' ? email.from : email.from?.email || '',\n to: Array.isArray(email.to)\n ? email.to.map((t: any) => (typeof t === 'string' ? t : t?.email || ''))\n : [String(email.to || '')],\n subject: email.subject || '',\n text: email.text || email.body || '',\n html: email.html || undefined,\n date: email.created_at ? new Date(email.created_at) : new Date(),\n };\n } catch (err) {\n console.warn(`[EmailClient] Failed to fetch Resend email ${emailId}: ${err}`);\n return null;\n }\n }\n\n /**\n * List received inbound emails from Resend via polling.\n * Uses GET /emails/receiving with cursor-based pagination.\n * Returns email summaries (call fetchResendEmail for full content).\n */\n async listReceivedEmails(opts?: { limit?: number; after?: string }): Promise<{\n emails: Array<{\n id: string;\n from: string;\n to: string[];\n subject: string;\n created_at: string;\n message_id?: string;\n }>;\n hasMore: boolean;\n lastId?: string;\n }> {\n if (!this.resendConfig?.apiKey) {\n return { emails: [], hasMore: false };\n }\n\n try {\n const params = new URLSearchParams();\n if (opts?.limit) params.set('limit', String(opts.limit));\n if (opts?.after) params.set('after', opts.after);\n const qs = params.toString();\n const url = `https://api.resend.com/emails/receiving${qs ? `?${qs}` : ''}`;\n\n const resp = await fetch(url, {\n headers: {\n Authorization: `Bearer ${this.resendConfig.apiKey}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!resp.ok) {\n console.warn(\n `[EmailClient] Resend list received failed: ${resp.status} ${resp.statusText}`\n );\n return { emails: [], hasMore: false };\n }\n\n const body: any = await resp.json();\n const data = Array.isArray(body.data) ? body.data : [];\n const emails = data.map((e: any) => ({\n id: e.id,\n from: typeof e.from === 'string' ? e.from : e.from?.email || '',\n to: Array.isArray(e.to)\n ? e.to.map((t: any) => (typeof t === 'string' ? t : t?.email || ''))\n : [],\n subject: e.subject || '',\n created_at: e.created_at || '',\n message_id: e.message_id,\n }));\n\n const lastId = emails.length > 0 ? emails[emails.length - 1].id : undefined;\n return {\n emails,\n hasMore: !!body.has_more,\n lastId,\n };\n } catch (err) {\n console.warn(`[EmailClient] Resend list received error: ${err}`);\n return { emails: [], hasMore: false };\n }\n }\n\n /** Verify Resend webhook signature */\n async verifyResendWebhook(payload: string, headers: Record<string, string>): Promise<boolean> {\n if (!this.resendConfig?.webhookSecret) return true; // no secret = skip verification\n try {\n const { Webhook } = await import('svix');\n const wh = new Webhook(this.resendConfig.webhookSecret);\n wh.verify(payload, {\n 'svix-id': headers['svix-id'] || '',\n 'svix-timestamp': headers['svix-timestamp'] || '',\n 'svix-signature': headers['svix-signature'] || '',\n });\n return true;\n } catch {\n return false;\n }\n }\n\n // ─── Send ───\n\n /** Send an email via configured backend (SMTP or Resend) */\n async sendEmail(opts: EmailSendOptions): Promise<EmailSendResult> {\n const messageId = opts.messageId || `<${randomUUID()}@visor>`;\n\n if (this.sendBackend === 'resend') {\n return this.sendViaResend(opts, messageId);\n }\n return this.sendViaSmtp(opts, messageId);\n }\n\n private async sendViaSmtp(opts: EmailSendOptions, messageId: string): Promise<EmailSendResult> {\n try {\n const transport = await this.getSmtpTransport();\n const to = Array.isArray(opts.to) ? opts.to.join(', ') : opts.to;\n\n const mailOpts: Record<string, any> = {\n from: this.fromAddress,\n to,\n subject: opts.subject,\n text: opts.text,\n messageId,\n };\n\n if (opts.html) mailOpts.html = opts.html;\n if (opts.inReplyTo) mailOpts.inReplyTo = opts.inReplyTo;\n if (opts.references && opts.references.length > 0) {\n mailOpts.references = opts.references.join(' ');\n }\n\n const info = await transport.sendMail(mailOpts);\n return {\n ok: true,\n messageId: info.messageId || messageId,\n };\n } catch (err: any) {\n const errMsg = err?.message || String(err);\n console.warn(`[EmailClient] SMTP send failed: ${errMsg}`);\n return { ok: false, error: errMsg };\n }\n }\n\n private async sendViaResend(opts: EmailSendOptions, messageId: string): Promise<EmailSendResult> {\n try {\n const resend = await this.getResendClient();\n const to = Array.isArray(opts.to) ? opts.to : [opts.to];\n\n const headers: Record<string, string> = {};\n headers['Message-ID'] = messageId;\n if (opts.inReplyTo) headers['In-Reply-To'] = opts.inReplyTo;\n if (opts.references && opts.references.length > 0) {\n headers['References'] = opts.references.join(' ');\n }\n\n const sendOpts: Record<string, any> = {\n from: this.fromAddress,\n to,\n subject: opts.subject,\n text: opts.text,\n headers,\n };\n if (opts.html) sendOpts.html = opts.html;\n\n const result = await resend.emails.send(sendOpts);\n const data: any = (result as any).data || result;\n return {\n ok: true,\n messageId: data?.id ? `<${data.id}@resend>` : messageId,\n };\n } catch (err: any) {\n const errMsg = err?.message || String(err);\n console.warn(`[EmailClient] Resend send failed: ${errMsg}`);\n return { ok: false, error: errMsg };\n }\n }\n\n // ─── Lazy initialization helpers ───\n\n private async getSmtpTransport(): Promise<any> {\n if (this.smtpTransport) return this.smtpTransport;\n const nodemailer = await import('nodemailer');\n this.smtpTransport = nodemailer.createTransport({\n host: this.smtpConfig!.host,\n port: this.smtpConfig!.port || 587,\n secure: this.smtpConfig!.secure ?? true,\n auth: this.smtpConfig!.auth,\n });\n return this.smtpTransport;\n }\n\n private async getResendClient(): Promise<any> {\n if (this.resendClient) return this.resendClient;\n const { Resend } = await import('resend');\n this.resendClient = new Resend(this.resendConfig!.apiKey);\n return this.resendClient;\n }\n\n /** Generate a deterministic thread ID from a Message-ID chain */\n static deriveThreadId(rootMessageId: string): string {\n return createHash('sha256').update(rootMessageId).digest('hex').slice(0, 16);\n }\n}\n","// Markdown → email HTML converter.\n// Converts AI Markdown output to email-compatible HTML with inline styles.\n//\n// Supported conversions:\n// - # Header → <h1 style=\"...\">Header</h1>\n// - **bold** → <strong>bold</strong>\n// - *italic* → <em>italic</em>\n// - ~~strike~~ → <del>strike</del>\n// - `code` → <code style=\"...\">code</code>\n// - ```block``` → <pre style=\"...\"><code>block</code></pre>\n// - [label](url) → <a href=\"url\">label</a>\n// - > blockquote → <blockquote style=\"...\">text</blockquote>\n// - - item → <ul><li>item</li></ul>\n// - 1. item → <ol><li>item</li></ol>\n// - --- → <hr>\n// HTML entities escaped: & < >\n\n/** Escape HTML entities in text */\nexport function escapeHtml(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\n/**\n * Convert Markdown text to email-compatible HTML.\n * Processes line-by-line, respecting fenced code blocks.\n */\nexport function markdownToEmailHtml(text: string): string {\n if (!text || typeof text !== 'string') return '';\n\n const lines = text.split(/\\r?\\n/);\n const result: string[] = [];\n let inCodeBlock = false;\n let codeBlockLang = '';\n let codeLines: string[] = [];\n let inBlockquote = false;\n let blockquoteLines: string[] = [];\n const listStack: ('ul' | 'ol')[] = [];\n\n const flushBlockquote = () => {\n if (blockquoteLines.length > 0) {\n result.push(\n `<blockquote style=\"border-left:3px solid #ccc;margin:8px 0;padding:4px 12px;color:#555;\">${blockquoteLines.join('<br>')}</blockquote>`\n );\n blockquoteLines = [];\n inBlockquote = false;\n }\n };\n\n const flushList = () => {\n while (listStack.length > 0) {\n const tag = listStack.pop()!;\n result.push(`</${tag}>`);\n }\n };\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trimStart();\n\n // Track fenced code blocks\n if (/^```/.test(trimmed)) {\n if (!inCodeBlock) {\n flushBlockquote();\n flushList();\n inCodeBlock = true;\n codeBlockLang = trimmed.slice(3).trim();\n codeLines = [];\n } else {\n const escaped = codeLines.map(l => escapeHtml(l)).join('\\n');\n const langAttr = codeBlockLang ? ` class=\"language-${escapeHtml(codeBlockLang)}\"` : '';\n result.push(\n `<pre style=\"background:#f4f4f4;padding:12px;border-radius:4px;overflow-x:auto;font-size:13px;\"><code${langAttr}>${escaped}</code></pre>`\n );\n inCodeBlock = false;\n codeBlockLang = '';\n codeLines = [];\n }\n continue;\n }\n if (inCodeBlock) {\n codeLines.push(lines[i]);\n continue;\n }\n\n // Blockquotes: > text\n const bqMatch = /^>\\s?(.*)$/.exec(trimmed);\n if (bqMatch) {\n flushList();\n inBlockquote = true;\n blockquoteLines.push(convertInline(bqMatch[1]));\n continue;\n } else if (inBlockquote) {\n flushBlockquote();\n }\n\n // Bullet lists: \"- item\" or \"* item\"\n const bulletMatch = /^(\\s*)([-*])\\s+(.+)$/.exec(lines[i]);\n if (bulletMatch) {\n if (listStack.length === 0 || listStack[listStack.length - 1] !== 'ul') {\n flushList();\n listStack.push('ul');\n result.push('<ul style=\"margin:4px 0;padding-left:24px;\">');\n }\n result.push(`<li>${convertInline(bulletMatch[3])}</li>`);\n continue;\n }\n\n // Numbered lists: \"1. item\"\n const numMatch = /^(\\s*)(\\d+)\\.\\s+(.+)$/.exec(lines[i]);\n if (numMatch) {\n if (listStack.length === 0 || listStack[listStack.length - 1] !== 'ol') {\n flushList();\n listStack.push('ol');\n result.push('<ol style=\"margin:4px 0;padding-left:24px;\">');\n }\n result.push(`<li>${convertInline(numMatch[3])}</li>`);\n continue;\n }\n\n // Close any open list if we hit a non-list line\n if (listStack.length > 0) flushList();\n\n const line = lines[i];\n\n // Headers: # Header → <h1>...</h1> etc.\n const headerMatch = /^(#{1,6})\\s+(.+)$/.exec(line.trimStart());\n if (headerMatch) {\n const level = headerMatch[1].length;\n const sizes: Record<number, string> = {\n 1: '24px',\n 2: '20px',\n 3: '18px',\n 4: '16px',\n 5: '14px',\n 6: '13px',\n };\n result.push(\n `<h${level} style=\"font-size:${sizes[level]};margin:16px 0 8px 0;\">${convertInline(headerMatch[2].trim())}</h${level}>`\n );\n continue;\n }\n\n // Horizontal rules\n if (/^[-*_]{3,}\\s*$/.test(trimmed)) {\n result.push('<hr style=\"border:none;border-top:1px solid #ddd;margin:16px 0;\">');\n continue;\n }\n\n // Empty lines → <br>\n if (trimmed === '') {\n result.push('<br>');\n continue;\n }\n\n // Regular line: apply inline conversions\n result.push(`<p style=\"margin:4px 0;\">${convertInline(line)}</p>`);\n }\n\n // Close any unclosed code block\n if (inCodeBlock && codeLines.length > 0) {\n const escaped = codeLines.map(l => escapeHtml(l)).join('\\n');\n result.push(\n `<pre style=\"background:#f4f4f4;padding:12px;border-radius:4px;overflow-x:auto;font-size:13px;\"><code>${escaped}</code></pre>`\n );\n }\n flushBlockquote();\n flushList();\n\n return result.join('\\n');\n}\n\n/**\n * Apply inline Markdown conversions to a single line.\n * Order matters: escape HTML first, then apply formatting.\n */\nfunction convertInline(line: string): string {\n // First, identify and protect inline code spans\n const codeSpans: string[] = [];\n let processed = line.replace(/`([^`]+)`/g, (_m, code: string) => {\n const idx = codeSpans.length;\n codeSpans.push(\n `<code style=\"background:#f0f0f0;padding:1px 4px;border-radius:3px;font-size:13px;\">${escapeHtml(code)}</code>`\n );\n return `\\x00CODE${idx}\\x00`;\n });\n\n // Escape HTML in non-code portions\n processed = escapeHtml(processed);\n\n // Images: ![alt](url)\n processed = processed.replace(\n /!\\[([^\\]]*)\\]\\(([^)\\s]+)(?:\\s+&quot;[^&]*&quot;)?\\)/g,\n (_m, alt: string, url: string) =>\n `<img src=\"${url}\" alt=\"${alt || 'image'}\" style=\"max-width:100%;\">`\n );\n\n // Links: [label](url) → <a href=\"url\">label</a>\n processed = processed.replace(\n /\\[([^\\]]+)\\]\\(([^)\\s]+)(?:\\s+&quot;[^&]*&quot;)?\\)/g,\n (_m, label: string, url: string) => `<a href=\"${url}\" style=\"color:#0066cc;\">${label}</a>`\n );\n\n // Bold: **text** or __text__\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/__([^_]+)__/g, '<strong>$1</strong>');\n\n // Italic: *text* (but not inside bold)\n processed = processed.replace(/(?<!\\*)\\*([^*]+)\\*(?!\\*)/g, '<em>$1</em>');\n\n // Strikethrough: ~~text~~\n processed = processed.replace(/~~([^~]+)~~/g, '<del>$1</del>');\n\n // Restore code spans\n processed = processed.replace(\n /\\x00CODE(\\d+)\\x00/g,\n (_m, idx: string) => codeSpans[parseInt(idx)]\n );\n\n return processed;\n}\n\n/**\n * Wrap body HTML in a complete email HTML template with inline CSS.\n */\nexport function wrapInEmailTemplate(bodyHtml: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n<body style=\"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.5;color:#333;max-width:600px;margin:0 auto;padding:16px;\">\n${bodyHtml}\n</body>\n</html>`;\n}\n\n/**\n * Format text as a plain-text email quote (prepend \"> \" to each line).\n */\nexport function formatEmailQuote(text: string): string {\n if (!text) return '';\n return text\n .split(/\\r?\\n/)\n .map(l => `> ${l}`)\n .join('\\n');\n}\n\n/**\n * Add \"Re: \" prefix to subject if not already present.\n */\nexport function addRePrefix(subject: string): string {\n if (!subject) return 'Re:';\n if (/^Re:/i.test(subject.trim())) return subject.trim();\n return `Re: ${subject.trim()}`;\n}\n\n/**\n * Main entry point: convert Markdown to email HTML body (not wrapped in template).\n */\nexport function formatEmailText(text: string): string {\n return markdownToEmailHtml(text);\n}\n","/**\n * Email Frontend for Visor workflows.\n *\n * Mirrors the TelegramFrontend pattern:\n * - Sends AI replies as threaded emails (In-Reply-To, References headers)\n * - Converts Markdown to email HTML format\n * - No reaction equivalent (CheckScheduled is a no-op)\n */\nimport type { Frontend, FrontendContext } from './host';\nimport { EmailClient, type EmailSendOptions } from '../email/client';\nimport { formatEmailText, wrapInEmailTemplate, addRePrefix } from '../email/markdown';\nimport {\n formatUserFacingExecutionMessage,\n summarizeUserFacingIssues,\n} from '../utils/user-facing-error';\n\ntype EmailFrontendConfig = {\n send?: {\n type?: string;\n host?: string;\n port?: number;\n auth?: { user?: string; pass?: string };\n secure?: boolean;\n from?: string;\n api_key?: string;\n };\n};\n\nexport class EmailFrontend implements Frontend {\n public readonly name = 'email';\n private subs: Array<{ unsubscribe(): void }> = [];\n private cfg: EmailFrontendConfig;\n private errorNotified: boolean = false;\n\n constructor(config?: EmailFrontendConfig) {\n this.cfg = config || {};\n }\n\n start(ctx: FrontendContext): void {\n const bus = ctx.eventBus;\n\n try {\n ctx.logger.info(`[email-frontend] started`);\n } catch {}\n\n // CheckCompleted: send reply email\n this.subs.push(\n bus.on('CheckCompleted', async (env: any) => {\n const ev = (env && env.payload) || env;\n await this.maybePostDirectReply(ctx, ev.checkId, ev.result).catch(() => {});\n })\n );\n\n // CheckErrored: send error email\n this.subs.push(\n bus.on('CheckErrored', async (env: any) => {\n const ev = (env && env.payload) || env;\n const message = ev?.error?.message || 'Execution error';\n await this.maybePostError(ctx, 'Check failed', message, ev?.checkId).catch(() => {});\n })\n );\n\n // Shutdown: send fatal error email\n this.subs.push(\n bus.on('Shutdown', async (env: any) => {\n const ev = (env && env.payload) || env;\n const message = ev?.error?.message || 'Fatal error';\n await this.maybePostError(ctx, 'Run failed', message).catch(() => {});\n })\n );\n\n // CheckScheduled: no-op for email (no reaction equivalent)\n // StateTransition: no-op for email\n }\n\n stop(): void {\n for (const s of this.subs) s.unsubscribe();\n this.subs = [];\n }\n\n private getEmailClient(ctx: FrontendContext): EmailClient | undefined {\n // Prefer injected client (for tests or shared runner context)\n const injected = (ctx as any).emailClient;\n if (injected) return injected;\n // Lazy-create from config\n try {\n const emailConfig = (ctx as any).webhookContext?.webhookData?.get('/bots/email/message');\n const sendCfg = this.cfg.send || (emailConfig as any)?.sendConfig;\n if (sendCfg || process.env.EMAIL_SMTP_HOST || process.env.RESEND_API_KEY) {\n return new EmailClient({\n send: sendCfg || {\n type: process.env.RESEND_API_KEY ? 'resend' : 'smtp',\n },\n });\n }\n } catch {}\n return undefined;\n }\n\n private getInboundEmailPayload(ctx: FrontendContext): any | null {\n try {\n const endpoint = '/bots/email/message';\n return (ctx as any).webhookContext?.webhookData?.get(endpoint) || null;\n } catch {\n return null;\n }\n }\n\n private async maybePostError(\n ctx: FrontendContext,\n title: string,\n message: string,\n checkId?: string\n ): Promise<void> {\n if (this.errorNotified) return;\n const client = this.getEmailClient(ctx);\n if (!client) return;\n const payload = this.getInboundEmailPayload(ctx);\n const ev: any = payload?.event;\n if (!ev?.from) return;\n\n let text = `${title}`;\n if (checkId) text += `\\nCheck: ${checkId}`;\n if (message) text += `\\n${formatUserFacingExecutionMessage(message)}`;\n\n const sendOpts: EmailSendOptions = {\n to: ev.from,\n subject: ev.subject ? addRePrefix(ev.subject) : `Visor: ${title}`,\n text,\n html: wrapInEmailTemplate(\n `<p><strong>${title}</strong></p><p>${formatUserFacingExecutionMessage(message)}</p>`\n ),\n };\n\n // Thread the reply\n if (ev.messageId) {\n sendOpts.inReplyTo = ev.messageId;\n sendOpts.references = ev.references ? [...ev.references, ev.messageId] : [ev.messageId];\n }\n\n await client.sendEmail(sendOpts);\n this.errorNotified = true;\n }\n\n private async maybePostDirectReply(\n ctx: FrontendContext,\n checkId: string,\n result: { output?: any; content?: string }\n ): Promise<void> {\n try {\n const cfg: any = ctx.config || {};\n const checkCfg: any = cfg.checks?.[checkId];\n if (!checkCfg) return;\n\n const providerType = (checkCfg.type as string) || '';\n const isAi = providerType === 'ai';\n const isLogChat = providerType === 'log' && checkCfg.group === 'chat';\n const isWorkflow = providerType === 'workflow';\n if (!isAi && !isLogChat && !isWorkflow) return;\n if (checkCfg.criticality === 'internal') return;\n\n // For AI checks, only post simple schemas\n if (isAi) {\n const schema = checkCfg.schema;\n if (typeof schema === 'string') {\n const simpleSchemas = ['code-review', 'markdown', 'text', 'plain'];\n if (!simpleSchemas.includes(schema)) return;\n }\n }\n\n const client = this.getEmailClient(ctx);\n if (!client) return;\n\n const payload = this.getInboundEmailPayload(ctx);\n const ev: any = payload?.event;\n if (!ev?.from) {\n ctx.logger.warn(`[email-frontend] skip posting reply for ${checkId}: missing from address`);\n return;\n }\n\n // Extract text (same logic as TelegramFrontend/SlackFrontend)\n const out: any = (result as any)?.output;\n let text: string | undefined;\n if (out && typeof out.text === 'string' && out.text.trim().length > 0) {\n text = out.text.trim();\n } else if (isAi && typeof checkCfg.schema === 'string') {\n if (\n typeof (result as any)?.content === 'string' &&\n (result as any).content.trim().length > 0\n ) {\n text = (result as any).content.trim();\n }\n } else if (isLogChat && typeof (result as any)?.logOutput === 'string') {\n const raw = (result as any).logOutput;\n if (raw.trim().length > 0) text = raw.trim();\n }\n\n // Append raw output\n if (out && typeof out._rawOutput === 'string' && out._rawOutput.trim().length > 0) {\n text = (text || '') + '\\n\\n' + out._rawOutput.trim();\n }\n\n if (!text) {\n const issueSummary = summarizeUserFacingIssues((result as any)?.issues || []);\n if (issueSummary) {\n text = issueSummary;\n this.errorNotified = true;\n }\n }\n\n if (!text) {\n ctx.logger.info(`[email-frontend] skip posting reply for ${checkId}: no renderable text`);\n return;\n }\n\n // Normalize literal \\n escape sequences\n text = text.replace(/\\\\n/g, '\\n');\n\n const htmlBody = formatEmailText(text);\n const sendOpts: EmailSendOptions = {\n to: ev.from,\n subject: ev.subject ? addRePrefix(ev.subject) : `Re: Visor response`,\n text,\n html: wrapInEmailTemplate(htmlBody),\n };\n\n // Thread the reply\n if (ev.messageId) {\n sendOpts.inReplyTo = ev.messageId;\n sendOpts.references = ev.references ? [...ev.references, ev.messageId] : [ev.messageId];\n }\n\n const sendResult = await client.sendEmail(sendOpts);\n\n if (!sendResult.ok) {\n ctx.logger.warn(\n `[email-frontend] failed to send reply for ${checkId}: ${sendResult.error}`\n );\n return;\n }\n ctx.logger.info(\n `[email-frontend] sent reply for ${checkId} to ${ev.from} (messageId=${sendResult.messageId})`\n );\n } catch (err) {\n try {\n ctx.logger.warn(\n `[email-frontend] maybePostDirectReply failed for ${checkId}: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n } catch {}\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  FailureConditionEvaluator,
3
3
  init_failure_condition_evaluator
4
- } from "./chunk-5TXIAPRA.mjs";
5
- import "./chunk-A4WHMRK2.mjs";
6
- import "./chunk-NEZY2MXM.mjs";
4
+ } from "./chunk-S3GSZRYC.mjs";
5
+ import "./chunk-YETG675X.mjs";
6
+ import "./chunk-B2LQT6QU.mjs";
7
7
  import "./chunk-FWWLD555.mjs";
8
8
  import "./chunk-25IC7KXZ.mjs";
9
9
  import "./chunk-LW3INISN.mjs";
@@ -15,4 +15,4 @@ init_failure_condition_evaluator();
15
15
  export {
16
16
  FailureConditionEvaluator
17
17
  };
18
- //# sourceMappingURL=failure-condition-evaluator-ZBOSD574.mjs.map
18
+ //# sourceMappingURL=failure-condition-evaluator-66PWLV3D.mjs.map
@@ -5,12 +5,12 @@ import {
5
5
  import {
6
6
  failure_condition_evaluator_exports,
7
7
  init_failure_condition_evaluator
8
- } from "./chunk-5TXIAPRA.mjs";
9
- import "./chunk-A4WHMRK2.mjs";
8
+ } from "./chunk-S3GSZRYC.mjs";
9
+ import "./chunk-YETG675X.mjs";
10
10
  import {
11
11
  generateShortHumanId,
12
12
  init_human_id
13
- } from "./chunk-NEZY2MXM.mjs";
13
+ } from "./chunk-B2LQT6QU.mjs";
14
14
  import "./chunk-FWWLD555.mjs";
15
15
  import "./chunk-25IC7KXZ.mjs";
16
16
  import "./chunk-LW3INISN.mjs";
@@ -1391,4 +1391,4 @@ init_github_frontend();
1391
1391
  export {
1392
1392
  GitHubFrontend
1393
1393
  };
1394
- //# sourceMappingURL=github-frontend-4WHT5JEU.mjs.map
1394
+ //# sourceMappingURL=github-frontend-BBFKCY4M.mjs.map
@@ -24,28 +24,28 @@ var init_host = __esm({
24
24
  const { NdjsonSink } = await import("./ndjson-sink-FD2PSXGD.mjs");
25
25
  this.frontends.push(new NdjsonSink(spec.config));
26
26
  } else if (spec.name === "github") {
27
- const { GitHubFrontend } = await import("./github-frontend-4WHT5JEU.mjs");
27
+ const { GitHubFrontend } = await import("./github-frontend-BBFKCY4M.mjs");
28
28
  this.frontends.push(new GitHubFrontend());
29
29
  } else if (spec.name === "slack") {
30
- const { SlackFrontend } = await import("./slack-frontend-K3TPGERM.mjs");
30
+ const { SlackFrontend } = await import("./slack-frontend-JMX5MUVZ.mjs");
31
31
  this.frontends.push(new SlackFrontend(spec.config));
32
32
  } else if (spec.name === "tui") {
33
33
  const { TuiFrontend } = await import("./tui-frontend-T56PZB67.mjs");
34
34
  this.frontends.push(new TuiFrontend(spec.config));
35
35
  } else if (spec.name === "telegram") {
36
- const { TelegramFrontend } = await import("./telegram-frontend-5UA77YAT.mjs");
36
+ const { TelegramFrontend } = await import("./telegram-frontend-NLX2ZHS4.mjs");
37
37
  this.frontends.push(new TelegramFrontend(spec.config));
38
38
  } else if (spec.name === "email") {
39
- const { EmailFrontend } = await import("./email-frontend-P7QE4UUJ.mjs");
39
+ const { EmailFrontend } = await import("./email-frontend-AE5TYWNC.mjs");
40
40
  this.frontends.push(new EmailFrontend(spec.config));
41
41
  } else if (spec.name === "whatsapp") {
42
- const { WhatsAppFrontend } = await import("./whatsapp-frontend-72XEIUIR.mjs");
42
+ const { WhatsAppFrontend } = await import("./whatsapp-frontend-3EMMNC7R.mjs");
43
43
  this.frontends.push(new WhatsAppFrontend(spec.config));
44
44
  } else if (spec.name === "teams") {
45
- const { TeamsFrontend } = await import("./teams-frontend-6RRW533K.mjs");
45
+ const { TeamsFrontend } = await import("./teams-frontend-6MDAN7OR.mjs");
46
46
  this.frontends.push(new TeamsFrontend(spec.config));
47
47
  } else if (spec.name === "a2a") {
48
- const { A2AFrontend } = await import("./a2a-frontend-L3TQ7QQ6.mjs");
48
+ const { A2AFrontend } = await import("./a2a-frontend-XCQ4CQUF.mjs");
49
49
  this.frontends.push(new A2AFrontend(spec.config));
50
50
  } else {
51
51
  this.log.warn(`[FrontendsHost] Unknown frontend '${spec.name}', skipping`);
@@ -84,4 +84,4 @@ export {
84
84
  FrontendsHost,
85
85
  isActiveFrontend
86
86
  };
87
- //# sourceMappingURL=host-FKR7H26C.mjs.map
87
+ //# sourceMappingURL=host-UQRZDLT7.mjs.map
@@ -0,0 +1,13 @@
1
+ import {
2
+ OAuth2TokenCache,
3
+ init_oauth2_token_cache
4
+ } from "./chunk-PGBV3VZB.mjs";
5
+ import "./chunk-7QI6F66G.mjs";
6
+ import "./chunk-6E625R3C.mjs";
7
+ import "./chunk-B2OUZAWY.mjs";
8
+ import "./chunk-J7LXIPZS.mjs";
9
+ init_oauth2_token_cache();
10
+ export {
11
+ OAuth2TokenCache
12
+ };
13
+ //# sourceMappingURL=oauth2-token-cache-OS7WHLDI.mjs.map
@@ -4,10 +4,10 @@ import {
4
4
  evaluateTransitions,
5
5
  handleRouting,
6
6
  init_routing
7
- } from "./chunk-4UMDSYC7.mjs";
8
- import "./chunk-5TXIAPRA.mjs";
9
- import "./chunk-A4WHMRK2.mjs";
10
- import "./chunk-NEZY2MXM.mjs";
7
+ } from "./chunk-VS3JE2DL.mjs";
8
+ import "./chunk-S3GSZRYC.mjs";
9
+ import "./chunk-YETG675X.mjs";
10
+ import "./chunk-B2LQT6QU.mjs";
11
11
  import "./chunk-FWWLD555.mjs";
12
12
  import "./chunk-4HIWZA6M.mjs";
13
13
  import "./chunk-25IC7KXZ.mjs";
@@ -23,4 +23,4 @@ export {
23
23
  evaluateTransitions,
24
24
  handleRouting
25
25
  };
26
- //# sourceMappingURL=routing-IB2PXYFC.mjs.map
26
+ //# sourceMappingURL=routing-Q647KUMO.mjs.map
@@ -4,22 +4,25 @@ import {
4
4
  handleScheduleAction,
5
5
  init_schedule_tool,
6
6
  isScheduleTool
7
- } from "./chunk-NPOVLLKH.mjs";
7
+ } from "./chunk-TGQBEM3Y.mjs";
8
8
  import "./chunk-YSOIR46P.mjs";
9
- import "./chunk-PDQTEBOJ.mjs";
10
- import "./chunk-WZQMTD7W.mjs";
11
- import "./chunk-TSX3YS3F.mjs";
9
+ import "./chunk-QT766ZLD.mjs";
10
+ import "./chunk-2LLKENYD.mjs";
11
+ import "./chunk-TL3ZTYFY.mjs";
12
+ import "./chunk-PGBV3VZB.mjs";
13
+ import "./chunk-HW4MPCOW.mjs";
14
+ import "./chunk-7QI6F66G.mjs";
12
15
  import "./chunk-VPPBOKBQ.mjs";
13
16
  import "./chunk-B7BVQM5K.mjs";
14
- import "./chunk-XXAEN5KU.mjs";
17
+ import "./chunk-77AKSSW2.mjs";
15
18
  import "./chunk-ZNKL6ESZ.mjs";
16
19
  import "./chunk-4ZLYHSN4.mjs";
17
- import "./chunk-XX6WT332.mjs";
20
+ import "./chunk-YTG5DN72.mjs";
18
21
  import "./chunk-KWTCTEFT.mjs";
19
- import "./chunk-4UMDSYC7.mjs";
20
- import "./chunk-5TXIAPRA.mjs";
21
- import "./chunk-A4WHMRK2.mjs";
22
- import "./chunk-NEZY2MXM.mjs";
22
+ import "./chunk-VS3JE2DL.mjs";
23
+ import "./chunk-S3GSZRYC.mjs";
24
+ import "./chunk-YETG675X.mjs";
25
+ import "./chunk-B2LQT6QU.mjs";
23
26
  import "./chunk-FWWLD555.mjs";
24
27
  import "./chunk-4HIWZA6M.mjs";
25
28
  import "./chunk-25IC7KXZ.mjs";
@@ -35,4 +38,4 @@ export {
35
38
  handleScheduleAction,
36
39
  isScheduleTool
37
40
  };
38
- //# sourceMappingURL=schedule-tool-LB33KL2W.mjs.map
41
+ //# sourceMappingURL=schedule-tool-WMGSM6IT.mjs.map
@@ -6,22 +6,25 @@ import {
6
6
  extractSlackContext,
7
7
  init_schedule_tool_handler,
8
8
  isScheduleToolCall
9
- } from "./chunk-NPOVLLKH.mjs";
9
+ } from "./chunk-TGQBEM3Y.mjs";
10
10
  import "./chunk-YSOIR46P.mjs";
11
- import "./chunk-PDQTEBOJ.mjs";
12
- import "./chunk-WZQMTD7W.mjs";
13
- import "./chunk-TSX3YS3F.mjs";
11
+ import "./chunk-QT766ZLD.mjs";
12
+ import "./chunk-2LLKENYD.mjs";
13
+ import "./chunk-TL3ZTYFY.mjs";
14
+ import "./chunk-PGBV3VZB.mjs";
15
+ import "./chunk-HW4MPCOW.mjs";
16
+ import "./chunk-7QI6F66G.mjs";
14
17
  import "./chunk-VPPBOKBQ.mjs";
15
18
  import "./chunk-B7BVQM5K.mjs";
16
- import "./chunk-XXAEN5KU.mjs";
19
+ import "./chunk-77AKSSW2.mjs";
17
20
  import "./chunk-ZNKL6ESZ.mjs";
18
21
  import "./chunk-4ZLYHSN4.mjs";
19
- import "./chunk-XX6WT332.mjs";
22
+ import "./chunk-YTG5DN72.mjs";
20
23
  import "./chunk-KWTCTEFT.mjs";
21
- import "./chunk-4UMDSYC7.mjs";
22
- import "./chunk-5TXIAPRA.mjs";
23
- import "./chunk-A4WHMRK2.mjs";
24
- import "./chunk-NEZY2MXM.mjs";
24
+ import "./chunk-VS3JE2DL.mjs";
25
+ import "./chunk-S3GSZRYC.mjs";
26
+ import "./chunk-YETG675X.mjs";
27
+ import "./chunk-B2LQT6QU.mjs";
25
28
  import "./chunk-FWWLD555.mjs";
26
29
  import "./chunk-4HIWZA6M.mjs";
27
30
  import "./chunk-25IC7KXZ.mjs";
@@ -39,4 +42,4 @@ export {
39
42
  extractSlackContext,
40
43
  isScheduleToolCall
41
44
  };
42
- //# sourceMappingURL=schedule-tool-handler-KYWZHKSS.mjs.map
45
+ //# sourceMappingURL=schedule-tool-handler-JMDHCGZ2.mjs.map
@@ -838,6 +838,18 @@ interface CheckConfig {
838
838
  failure_conditions?: FailureConditions;
839
839
  /** Tags for categorizing and filtering checks (e.g., ["local", "fast", "security"]) */
840
840
  tags?: string[];
841
+ /**
842
+ * Debounce window in milliseconds. When set, multiple invocations of this
843
+ * step (across concurrent engine instances) within the window are coalesced
844
+ * — only the last invocation actually executes after the window expires.
845
+ * Useful for steps that should run once after a burst of triggers settles.
846
+ *
847
+ * The debounce key defaults to the step's fully-qualified check ID.
848
+ * Use `debounce_key` to group different steps under the same debounce.
849
+ */
850
+ debounce?: number;
851
+ /** Custom debounce key. Steps sharing the same key share the same debounce window. */
852
+ debounce_key?: string;
841
853
  /**
842
854
  * Operational criticality of this step. Drives default safety policies
843
855
  * (contracts, retries, loop budgets) at load time. Behavior can still be
@@ -1538,8 +1550,8 @@ interface SlackMessageTrigger {
1538
1550
  interface StaticCronJob {
1539
1551
  /** Cron expression (e.g., "0 9 * * 1" for every Monday at 9am) */
1540
1552
  schedule: string;
1541
- /** Workflow/check ID to run */
1542
- workflow: string;
1553
+ /** Workflow/check ID to run. Omit to treat inputs.text as a user message through the full pipeline. */
1554
+ workflow?: string;
1543
1555
  /** Optional workflow inputs */
1544
1556
  inputs?: Record<string, unknown>;
1545
1557
  /** Output destination configuration */
package/dist/sdk/sdk.d.ts CHANGED
@@ -838,6 +838,18 @@ interface CheckConfig {
838
838
  failure_conditions?: FailureConditions;
839
839
  /** Tags for categorizing and filtering checks (e.g., ["local", "fast", "security"]) */
840
840
  tags?: string[];
841
+ /**
842
+ * Debounce window in milliseconds. When set, multiple invocations of this
843
+ * step (across concurrent engine instances) within the window are coalesced
844
+ * — only the last invocation actually executes after the window expires.
845
+ * Useful for steps that should run once after a burst of triggers settles.
846
+ *
847
+ * The debounce key defaults to the step's fully-qualified check ID.
848
+ * Use `debounce_key` to group different steps under the same debounce.
849
+ */
850
+ debounce?: number;
851
+ /** Custom debounce key. Steps sharing the same key share the same debounce window. */
852
+ debounce_key?: string;
841
853
  /**
842
854
  * Operational criticality of this step. Drives default safety policies
843
855
  * (contracts, retries, loop budgets) at load time. Behavior can still be
@@ -1538,8 +1550,8 @@ interface SlackMessageTrigger {
1538
1550
  interface StaticCronJob {
1539
1551
  /** Cron expression (e.g., "0 9 * * 1" for every Monday at 9am) */
1540
1552
  schedule: string;
1541
- /** Workflow/check ID to run */
1542
- workflow: string;
1553
+ /** Workflow/check ID to run. Omit to treat inputs.text as a user message through the full pipeline. */
1554
+ workflow?: string;
1543
1555
  /** Optional workflow inputs */
1544
1556
  inputs?: Record<string, unknown>;
1545
1557
  /** Output destination configuration */