@probelabs/visor 0.1.186-ee → 0.1.187-ee

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 (194) 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/agent-protocol/task-live-update-slack.d.ts +10 -0
  5. package/dist/agent-protocol/task-live-update-slack.d.ts.map +1 -1
  6. package/dist/agent-protocol/task-live-updates.d.ts +10 -0
  7. package/dist/agent-protocol/task-live-updates.d.ts.map +1 -1
  8. package/dist/agent-protocol/tasks-cli-handler.d.ts.map +1 -1
  9. package/dist/agent-protocol/trace-serializer.d.ts +43 -1
  10. package/dist/agent-protocol/trace-serializer.d.ts.map +1 -1
  11. package/dist/agent-protocol/track-execution.d.ts.map +1 -1
  12. package/dist/ai-review-service.d.ts +22 -1
  13. package/dist/ai-review-service.d.ts.map +1 -1
  14. package/dist/cli-main.d.ts +1 -0
  15. package/dist/cli-main.d.ts.map +1 -1
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/defaults/assistant.yaml +31 -0
  18. package/dist/defaults/code-talk.yaml +32 -0
  19. package/dist/defaults/skills/code-explorer.yaml +6 -0
  20. package/dist/docs/telemetry-setup.md +18 -2
  21. package/dist/email/polling-runner.d.ts +1 -0
  22. package/dist/email/polling-runner.d.ts.map +1 -1
  23. package/dist/frontends/email-frontend.d.ts.map +1 -1
  24. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  25. package/dist/frontends/teams-frontend.d.ts.map +1 -1
  26. package/dist/frontends/telegram-frontend.d.ts.map +1 -1
  27. package/dist/frontends/whatsapp-frontend.d.ts.map +1 -1
  28. package/dist/generated/config-schema.d.ts +16 -8
  29. package/dist/generated/config-schema.d.ts.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +7658 -1460
  33. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  34. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  35. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
  36. package/dist/providers/script-check-provider.d.ts.map +1 -1
  37. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  38. package/dist/runners/mcp-server-runner.d.ts.map +1 -1
  39. package/dist/scheduler/scheduler.d.ts.map +1 -1
  40. package/dist/sdk/a2a-frontend-7EGXSULE.mjs +1751 -0
  41. package/dist/sdk/a2a-frontend-7EGXSULE.mjs.map +1 -0
  42. package/dist/sdk/{a2a-frontend-OI4OVSKC.mjs → a2a-frontend-QVKJ7MVW.mjs} +3 -3
  43. package/dist/sdk/{check-provider-registry-TQR32QBD.mjs → check-provider-registry-IGNTM4MW.mjs} +5 -5
  44. package/dist/sdk/{check-provider-registry-7T2AEWLU.mjs → check-provider-registry-QUUL6JI2.mjs} +14 -11
  45. package/dist/sdk/chunk-2LLKENYD.mjs +33 -0
  46. package/dist/sdk/chunk-2LLKENYD.mjs.map +1 -0
  47. package/dist/sdk/{chunk-XX6WT332.mjs → chunk-6DDNEBZ7.mjs} +2 -1
  48. package/dist/sdk/{chunk-XX6WT332.mjs.map → chunk-6DDNEBZ7.mjs.map} +1 -1
  49. package/dist/sdk/chunk-6LQEODDA.mjs +391 -0
  50. package/dist/sdk/chunk-6LQEODDA.mjs.map +1 -0
  51. package/dist/sdk/chunk-77AKSSW2.mjs +175 -0
  52. package/dist/sdk/chunk-77AKSSW2.mjs.map +1 -0
  53. package/dist/sdk/chunk-7QI6F66G.mjs +145 -0
  54. package/dist/sdk/chunk-7QI6F66G.mjs.map +1 -0
  55. package/dist/sdk/{chunk-UM7LGO2P.mjs → chunk-BBLBZVWC.mjs} +3 -3
  56. package/dist/sdk/chunk-BVEATT5V.mjs +2495 -0
  57. package/dist/sdk/chunk-BVEATT5V.mjs.map +1 -0
  58. package/dist/sdk/{chunk-SRU5TFNY.mjs → chunk-D6O5SCPC.mjs} +2 -1
  59. package/dist/sdk/{chunk-SRU5TFNY.mjs.map → chunk-D6O5SCPC.mjs.map} +1 -1
  60. package/dist/sdk/chunk-H2ZWNJJO.mjs +204 -0
  61. package/dist/sdk/chunk-H2ZWNJJO.mjs.map +1 -0
  62. package/dist/sdk/{chunk-TAOGXCWT.mjs → chunk-HMVD3AEC.mjs} +16 -16
  63. package/dist/sdk/{chunk-LWH6CVLZ.mjs → chunk-HQCCT6WP.mjs} +570 -259
  64. package/dist/sdk/chunk-HQCCT6WP.mjs.map +1 -0
  65. package/dist/sdk/chunk-HW4MPCOW.mjs +691 -0
  66. package/dist/sdk/chunk-HW4MPCOW.mjs.map +1 -0
  67. package/dist/sdk/chunk-PGBV3VZB.mjs +122 -0
  68. package/dist/sdk/chunk-PGBV3VZB.mjs.map +1 -0
  69. package/dist/sdk/chunk-PZADRRLX.mjs +739 -0
  70. package/dist/sdk/chunk-PZADRRLX.mjs.map +1 -0
  71. package/dist/sdk/chunk-QT766ZLD.mjs +217 -0
  72. package/dist/sdk/chunk-QT766ZLD.mjs.map +1 -0
  73. package/dist/sdk/chunk-RQDLVMER.mjs +1507 -0
  74. package/dist/sdk/chunk-RQDLVMER.mjs.map +1 -0
  75. package/dist/sdk/chunk-TL3ZTYFY.mjs +141 -0
  76. package/dist/sdk/chunk-TL3ZTYFY.mjs.map +1 -0
  77. package/dist/sdk/{chunk-YBXNG75V.mjs → chunk-YTG5DN72.mjs} +103 -28
  78. package/dist/sdk/chunk-YTG5DN72.mjs.map +1 -0
  79. package/dist/sdk/chunk-YU3VR5SZ.mjs +749 -0
  80. package/dist/sdk/chunk-YU3VR5SZ.mjs.map +1 -0
  81. package/dist/sdk/chunk-ZCBVXBKG.mjs +1150 -0
  82. package/dist/sdk/chunk-ZCBVXBKG.mjs.map +1 -0
  83. package/dist/sdk/{config-BCYAVJ5S.mjs → config-BI5ZXG6D.mjs} +2 -2
  84. package/dist/sdk/{config-TVU5RWR5.mjs → config-H5IOLBFA.mjs} +2 -2
  85. package/dist/sdk/{dist-PN5UHL6A.mjs → dist-YLO6HUFD.mjs} +238 -65
  86. package/dist/sdk/dist-YLO6HUFD.mjs.map +1 -0
  87. package/dist/sdk/{email-frontend-6JU4L33L.mjs → email-frontend-6O454VL5.mjs} +18 -3
  88. package/dist/sdk/{email-frontend-ECHQCFTR.mjs.map → email-frontend-6O454VL5.mjs.map} +1 -1
  89. package/dist/sdk/{email-frontend-ECHQCFTR.mjs → email-frontend-JE7H3LBC.mjs} +2 -2
  90. package/dist/sdk/failure-condition-evaluator-7WHZUYDC.mjs +18 -0
  91. package/dist/sdk/github-frontend-RGK4DPRI.mjs +1394 -0
  92. package/dist/sdk/github-frontend-RGK4DPRI.mjs.map +1 -0
  93. package/dist/sdk/{host-RM6UJEPP.mjs → host-UZESVA6Z.mjs} +8 -8
  94. package/dist/sdk/{host-OJSMCLKK.mjs → host-YWXWROIE.mjs} +6 -6
  95. package/dist/sdk/oauth2-token-cache-OS7WHLDI.mjs +13 -0
  96. package/dist/sdk/{routing-NNQQSLWA.mjs → routing-PHHRW2C7.mjs} +2 -2
  97. package/dist/sdk/routing-TYXT3STD.mjs +26 -0
  98. package/dist/sdk/{schedule-tool-7IQI6MID.mjs → schedule-tool-ITD445EO.mjs} +5 -5
  99. package/dist/sdk/{schedule-tool-25C5NMDG.mjs → schedule-tool-ODMIDBMT.mjs} +14 -11
  100. package/dist/sdk/{schedule-tool-handler-IYBNJLTV.mjs → schedule-tool-handler-5WPHFBOG.mjs} +5 -5
  101. package/dist/sdk/{schedule-tool-handler-VWGTVSB6.mjs → schedule-tool-handler-IQSKBFLS.mjs} +14 -11
  102. package/dist/sdk/schedule-tool-handler-IQSKBFLS.mjs.map +1 -0
  103. package/dist/sdk/sdk.d.mts +14 -2
  104. package/dist/sdk/sdk.d.ts +14 -2
  105. package/dist/sdk/sdk.js +1926 -642
  106. package/dist/sdk/sdk.js.map +1 -1
  107. package/dist/sdk/sdk.mjs +13 -10
  108. package/dist/sdk/sdk.mjs.map +1 -1
  109. package/dist/sdk/session-registry-CENXWIFR.mjs +12 -0
  110. package/dist/sdk/session-registry-CENXWIFR.mjs.map +1 -0
  111. package/dist/sdk/{slack-frontend-K3TPGERM.mjs → slack-frontend-H7PX5GE7.mjs} +2 -2
  112. package/dist/sdk/slack-frontend-JMX5MUVZ.mjs +1015 -0
  113. package/dist/sdk/slack-frontend-JMX5MUVZ.mjs.map +1 -0
  114. package/dist/sdk/task-evaluator-4QG4CYQA.mjs +264 -0
  115. package/dist/sdk/task-evaluator-4QG4CYQA.mjs.map +1 -0
  116. package/dist/sdk/teams-frontend-6MDAN7OR.mjs +355 -0
  117. package/dist/sdk/teams-frontend-6MDAN7OR.mjs.map +1 -0
  118. package/dist/sdk/{teams-frontend-6RRW533K.mjs → teams-frontend-HCT4MTY4.mjs} +2 -2
  119. package/dist/sdk/telegram-frontend-NLX2ZHS4.mjs +599 -0
  120. package/dist/sdk/telegram-frontend-NLX2ZHS4.mjs.map +1 -0
  121. package/dist/sdk/{telegram-frontend-5UA77YAT.mjs → telegram-frontend-YQRYDKPN.mjs} +2 -2
  122. package/dist/sdk/trace-helpers-AM2QE5UZ.mjs +31 -0
  123. package/dist/sdk/trace-helpers-AM2QE5UZ.mjs.map +1 -0
  124. package/dist/sdk/trace-serializer-4TOIAVQL.mjs +32 -0
  125. package/dist/sdk/trace-serializer-4TOIAVQL.mjs.map +1 -0
  126. package/dist/sdk/{track-execution-3CHMGEPH.mjs → track-execution-BULXL2XD.mjs} +2 -2
  127. package/dist/sdk/track-execution-VJJVJH6K.mjs +320 -0
  128. package/dist/sdk/track-execution-VJJVJH6K.mjs.map +1 -0
  129. package/dist/sdk/utcp-check-provider-WDTSQ7DZ.mjs +17 -0
  130. package/dist/sdk/utcp-check-provider-WDTSQ7DZ.mjs.map +1 -0
  131. package/dist/sdk/whatsapp-frontend-3EMMNC7R.mjs +451 -0
  132. package/dist/sdk/whatsapp-frontend-3EMMNC7R.mjs.map +1 -0
  133. package/dist/sdk/{workflow-check-provider-FOWDJUO3.mjs → workflow-check-provider-OVZDCL4E.mjs} +5 -5
  134. package/dist/sdk/workflow-check-provider-OVZDCL4E.mjs.map +1 -0
  135. package/dist/sdk/{workflow-check-provider-MRP3C2NC.mjs → workflow-check-provider-XOWQYWTC.mjs} +14 -11
  136. package/dist/sdk/workflow-check-provider-XOWQYWTC.mjs.map +1 -0
  137. package/dist/session-registry.d.ts +2 -7
  138. package/dist/session-registry.d.ts.map +1 -1
  139. package/dist/slack/client.d.ts +8 -0
  140. package/dist/slack/client.d.ts.map +1 -1
  141. package/dist/slack/markdown.d.ts.map +1 -1
  142. package/dist/slack/slack-output-adapter.d.ts.map +1 -1
  143. package/dist/slack/socket-runner.d.ts +1 -0
  144. package/dist/slack/socket-runner.d.ts.map +1 -1
  145. package/dist/state-machine/dispatch/debounce-manager.d.ts +44 -0
  146. package/dist/state-machine/dispatch/debounce-manager.d.ts.map +1 -0
  147. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
  148. package/dist/state-machine-execution-engine.d.ts +1 -0
  149. package/dist/state-machine-execution-engine.d.ts.map +1 -1
  150. package/dist/teams/webhook-runner.d.ts +1 -0
  151. package/dist/teams/webhook-runner.d.ts.map +1 -1
  152. package/dist/telegram/polling-runner.d.ts +1 -0
  153. package/dist/telegram/polling-runner.d.ts.map +1 -1
  154. package/dist/types/config.d.ts +14 -2
  155. package/dist/types/config.d.ts.map +1 -1
  156. package/dist/utils/child-process-error-handler.d.ts +19 -0
  157. package/dist/utils/child-process-error-handler.d.ts.map +1 -0
  158. package/dist/utils/user-facing-error.d.ts +4 -0
  159. package/dist/utils/user-facing-error.d.ts.map +1 -0
  160. package/dist/utils/workspace-manager.d.ts +5 -0
  161. package/dist/utils/workspace-manager.d.ts.map +1 -1
  162. package/dist/utils/worktree-cleanup.d.ts +28 -0
  163. package/dist/utils/worktree-cleanup.d.ts.map +1 -1
  164. package/dist/utils/worktree-manager.d.ts +6 -0
  165. package/dist/utils/worktree-manager.d.ts.map +1 -1
  166. package/dist/whatsapp/webhook-runner.d.ts +1 -0
  167. package/dist/whatsapp/webhook-runner.d.ts.map +1 -1
  168. package/dist/workflow-executor.d.ts +7 -0
  169. package/dist/workflow-executor.d.ts.map +1 -1
  170. package/package.json +3 -3
  171. package/dist/sdk/chunk-LWH6CVLZ.mjs.map +0 -1
  172. package/dist/sdk/chunk-YBXNG75V.mjs.map +0 -1
  173. package/dist/sdk/dist-PN5UHL6A.mjs.map +0 -1
  174. /package/dist/sdk/{a2a-frontend-OI4OVSKC.mjs.map → a2a-frontend-QVKJ7MVW.mjs.map} +0 -0
  175. /package/dist/sdk/{check-provider-registry-7T2AEWLU.mjs.map → check-provider-registry-IGNTM4MW.mjs.map} +0 -0
  176. /package/dist/sdk/{check-provider-registry-TQR32QBD.mjs.map → check-provider-registry-QUUL6JI2.mjs.map} +0 -0
  177. /package/dist/sdk/{chunk-UM7LGO2P.mjs.map → chunk-BBLBZVWC.mjs.map} +0 -0
  178. /package/dist/sdk/{chunk-TAOGXCWT.mjs.map → chunk-HMVD3AEC.mjs.map} +0 -0
  179. /package/dist/sdk/{config-BCYAVJ5S.mjs.map → config-BI5ZXG6D.mjs.map} +0 -0
  180. /package/dist/sdk/{config-TVU5RWR5.mjs.map → config-H5IOLBFA.mjs.map} +0 -0
  181. /package/dist/sdk/{email-frontend-6JU4L33L.mjs.map → email-frontend-JE7H3LBC.mjs.map} +0 -0
  182. /package/dist/sdk/{routing-NNQQSLWA.mjs.map → failure-condition-evaluator-7WHZUYDC.mjs.map} +0 -0
  183. /package/dist/sdk/{host-OJSMCLKK.mjs.map → host-UZESVA6Z.mjs.map} +0 -0
  184. /package/dist/sdk/{host-RM6UJEPP.mjs.map → host-YWXWROIE.mjs.map} +0 -0
  185. /package/dist/sdk/{schedule-tool-25C5NMDG.mjs.map → oauth2-token-cache-OS7WHLDI.mjs.map} +0 -0
  186. /package/dist/sdk/{schedule-tool-7IQI6MID.mjs.map → routing-PHHRW2C7.mjs.map} +0 -0
  187. /package/dist/sdk/{schedule-tool-handler-IYBNJLTV.mjs.map → routing-TYXT3STD.mjs.map} +0 -0
  188. /package/dist/sdk/{schedule-tool-handler-VWGTVSB6.mjs.map → schedule-tool-ITD445EO.mjs.map} +0 -0
  189. /package/dist/sdk/{workflow-check-provider-FOWDJUO3.mjs.map → schedule-tool-ODMIDBMT.mjs.map} +0 -0
  190. /package/dist/sdk/{workflow-check-provider-MRP3C2NC.mjs.map → schedule-tool-handler-5WPHFBOG.mjs.map} +0 -0
  191. /package/dist/sdk/{slack-frontend-K3TPGERM.mjs.map → slack-frontend-H7PX5GE7.mjs.map} +0 -0
  192. /package/dist/sdk/{teams-frontend-6RRW533K.mjs.map → teams-frontend-HCT4MTY4.mjs.map} +0 -0
  193. /package/dist/sdk/{telegram-frontend-5UA77YAT.mjs.map → telegram-frontend-YQRYDKPN.mjs.map} +0 -0
  194. /package/dist/sdk/{track-execution-3CHMGEPH.mjs.map → track-execution-BULXL2XD.mjs.map} +0 -0
@@ -0,0 +1,451 @@
1
+ import {
2
+ formatUserFacingExecutionMessage,
3
+ init_user_facing_error,
4
+ summarizeUserFacingIssues
5
+ } from "./chunk-TL3ZTYFY.mjs";
6
+ import {
7
+ __esm
8
+ } from "./chunk-J7LXIPZS.mjs";
9
+
10
+ // src/whatsapp/markdown.ts
11
+ function markdownToWhatsApp(text) {
12
+ if (!text || typeof text !== "string") return "";
13
+ const lines = text.split(/\r?\n/);
14
+ const result = [];
15
+ let inCodeBlock = false;
16
+ let codeLines = [];
17
+ for (let i = 0; i < lines.length; i++) {
18
+ const trimmed = lines[i].trimStart();
19
+ if (/^```/.test(trimmed)) {
20
+ if (!inCodeBlock) {
21
+ inCodeBlock = true;
22
+ codeLines = [];
23
+ } else {
24
+ result.push("```" + codeLines.join("\n") + "```");
25
+ inCodeBlock = false;
26
+ codeLines = [];
27
+ }
28
+ continue;
29
+ }
30
+ if (inCodeBlock) {
31
+ codeLines.push(lines[i]);
32
+ continue;
33
+ }
34
+ const line = lines[i];
35
+ const headerMatch = /^(#{1,6})\s+(.+)$/.exec(line.trimStart());
36
+ if (headerMatch) {
37
+ result.push(`*${convertInline(headerMatch[2].trim())}*`);
38
+ continue;
39
+ }
40
+ if (/^[-*_]{3,}\s*$/.test(trimmed)) {
41
+ result.push("---");
42
+ continue;
43
+ }
44
+ const bulletMatch = /^(\s*)([-*])\s+(.+)$/.exec(line);
45
+ if (bulletMatch) {
46
+ result.push(`${bulletMatch[1]}- ${convertInline(bulletMatch[3])}`);
47
+ continue;
48
+ }
49
+ const numMatch = /^(\s*)(\d+\.)\s+(.+)$/.exec(line);
50
+ if (numMatch) {
51
+ result.push(`${numMatch[1]}${numMatch[2]} ${convertInline(numMatch[3])}`);
52
+ continue;
53
+ }
54
+ const bqMatch = /^>\s?(.*)$/.exec(trimmed);
55
+ if (bqMatch) {
56
+ result.push(`> ${convertInline(bqMatch[1])}`);
57
+ continue;
58
+ }
59
+ result.push(convertInline(line));
60
+ }
61
+ if (inCodeBlock && codeLines.length > 0) {
62
+ result.push("```" + codeLines.join("\n") + "```");
63
+ }
64
+ return result.join("\n");
65
+ }
66
+ function convertInline(line) {
67
+ const codeSpans = [];
68
+ let processed = line.replace(/`([^`]+)`/g, (_m, code) => {
69
+ const idx = codeSpans.length;
70
+ codeSpans.push("```" + code + "```");
71
+ return `\0CODE${idx}\0`;
72
+ });
73
+ processed = processed.replace(
74
+ /!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
75
+ (_m, alt, url) => `${alt || "image"} (${url})`
76
+ );
77
+ processed = processed.replace(
78
+ /\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
79
+ (_m, label, url) => `${label} (${url})`
80
+ );
81
+ const boldSpans = [];
82
+ processed = processed.replace(/\*\*([^*]+)\*\*/g, (_m, content) => {
83
+ const idx = boldSpans.length;
84
+ boldSpans.push(`*${content}*`);
85
+ return `\0BOLD${idx}\0`;
86
+ });
87
+ processed = processed.replace(/__([^_]+)__/g, (_m, content) => {
88
+ const idx = boldSpans.length;
89
+ boldSpans.push(`*${content}*`);
90
+ return `\0BOLD${idx}\0`;
91
+ });
92
+ processed = processed.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, "_$1_");
93
+ processed = processed.replace(/~~([^~]+)~~/g, "~$1~");
94
+ processed = processed.replace(
95
+ /\x00BOLD(\d+)\x00/g,
96
+ (_m, idx) => boldSpans[parseInt(idx)]
97
+ );
98
+ processed = processed.replace(
99
+ /\x00CODE(\d+)\x00/g,
100
+ (_m, idx) => codeSpans[parseInt(idx)]
101
+ );
102
+ return processed;
103
+ }
104
+ function chunkText(text, limit = 4096) {
105
+ if (text.length <= limit) return [text];
106
+ const chunks = [];
107
+ const lines = text.split("\n");
108
+ let current = "";
109
+ for (const line of lines) {
110
+ const candidate = current ? current + "\n" + line : line;
111
+ if (candidate.length > limit) {
112
+ if (current) {
113
+ chunks.push(current);
114
+ current = line;
115
+ } else {
116
+ let remaining = line;
117
+ while (remaining.length > limit) {
118
+ chunks.push(remaining.slice(0, limit));
119
+ remaining = remaining.slice(limit);
120
+ }
121
+ current = remaining;
122
+ }
123
+ } else {
124
+ current = candidate;
125
+ }
126
+ }
127
+ if (current) chunks.push(current);
128
+ return chunks;
129
+ }
130
+ function formatWhatsAppText(text) {
131
+ return markdownToWhatsApp(text);
132
+ }
133
+ var init_markdown = __esm({
134
+ "src/whatsapp/markdown.ts"() {
135
+ "use strict";
136
+ }
137
+ });
138
+
139
+ // src/whatsapp/client.ts
140
+ import { createHmac } from "crypto";
141
+ var WhatsAppClient;
142
+ var init_client = __esm({
143
+ "src/whatsapp/client.ts"() {
144
+ "use strict";
145
+ init_markdown();
146
+ WhatsAppClient = class {
147
+ accessToken;
148
+ phoneNumberId;
149
+ appSecret;
150
+ verifyToken;
151
+ baseUrl;
152
+ constructor(opts) {
153
+ if (!opts.accessToken || typeof opts.accessToken !== "string") {
154
+ throw new Error("WhatsAppClient: accessToken is required");
155
+ }
156
+ if (!opts.phoneNumberId || typeof opts.phoneNumberId !== "string") {
157
+ throw new Error("WhatsAppClient: phoneNumberId is required");
158
+ }
159
+ this.accessToken = opts.accessToken;
160
+ this.phoneNumberId = opts.phoneNumberId;
161
+ this.appSecret = opts.appSecret;
162
+ this.verifyToken = opts.verifyToken;
163
+ const version = opts.apiVersion || "v21.0";
164
+ this.baseUrl = `https://graph.facebook.com/${version}/${this.phoneNumberId}`;
165
+ }
166
+ /** Get the Phone Number ID */
167
+ getPhoneNumberId() {
168
+ return this.phoneNumberId;
169
+ }
170
+ /**
171
+ * Send a text message. Auto-chunks at 4096 characters.
172
+ */
173
+ async sendMessage(opts) {
174
+ const chunks = chunkText(opts.text, 4096);
175
+ let lastResult = { ok: false, error: "No chunks to send" };
176
+ for (const chunk of chunks) {
177
+ const body = {
178
+ messaging_product: "whatsapp",
179
+ to: opts.to,
180
+ type: "text",
181
+ text: { body: chunk }
182
+ };
183
+ if (opts.replyToMessageId) {
184
+ body.context = { message_id: opts.replyToMessageId };
185
+ }
186
+ try {
187
+ const resp = await fetch(`${this.baseUrl}/messages`, {
188
+ method: "POST",
189
+ headers: {
190
+ "Content-Type": "application/json",
191
+ Authorization: `Bearer ${this.accessToken}`
192
+ },
193
+ body: JSON.stringify(body)
194
+ });
195
+ const data = await resp.json();
196
+ if (!resp.ok) {
197
+ const errMsg = data?.error?.message || `HTTP ${resp.status}`;
198
+ return { ok: false, error: errMsg };
199
+ }
200
+ const msgId = data?.messages?.[0]?.id;
201
+ lastResult = { ok: true, messageId: msgId };
202
+ } catch (err) {
203
+ return {
204
+ ok: false,
205
+ error: err instanceof Error ? err.message : String(err)
206
+ };
207
+ }
208
+ }
209
+ return lastResult;
210
+ }
211
+ /**
212
+ * Mark a message as read (send read receipt).
213
+ */
214
+ async markAsRead(messageId) {
215
+ try {
216
+ const resp = await fetch(`${this.baseUrl}/messages`, {
217
+ method: "POST",
218
+ headers: {
219
+ "Content-Type": "application/json",
220
+ Authorization: `Bearer ${this.accessToken}`
221
+ },
222
+ body: JSON.stringify({
223
+ messaging_product: "whatsapp",
224
+ status: "read",
225
+ message_id: messageId
226
+ })
227
+ });
228
+ if (!resp.ok) {
229
+ const data = await resp.json();
230
+ return {
231
+ ok: false,
232
+ error: data?.error?.message || `HTTP ${resp.status}`
233
+ };
234
+ }
235
+ return { ok: true };
236
+ } catch (err) {
237
+ return {
238
+ ok: false,
239
+ error: err instanceof Error ? err.message : String(err)
240
+ };
241
+ }
242
+ }
243
+ /**
244
+ * Verify webhook signature (HMAC-SHA256 with X-Hub-Signature-256).
245
+ * Returns true if valid or if no appSecret is configured (skip verification).
246
+ */
247
+ verifyWebhookSignature(rawBody, signatureHeader) {
248
+ if (!this.appSecret) return true;
249
+ if (!signatureHeader) return false;
250
+ const expected = "sha256=" + createHmac("sha256", this.appSecret).update(rawBody).digest("hex");
251
+ return signatureHeader === expected;
252
+ }
253
+ /**
254
+ * Verify GET challenge-response for webhook subscription.
255
+ */
256
+ verifyChallenge(params) {
257
+ const mode = params["hub.mode"];
258
+ const token = params["hub.verify_token"];
259
+ const challenge = params["hub.challenge"];
260
+ if (mode === "subscribe" && token === this.verifyToken) {
261
+ return { ok: true, challenge };
262
+ }
263
+ return { ok: false };
264
+ }
265
+ };
266
+ }
267
+ });
268
+
269
+ // src/frontends/whatsapp-frontend.ts
270
+ var WhatsAppFrontend;
271
+ var init_whatsapp_frontend = __esm({
272
+ "src/frontends/whatsapp-frontend.ts"() {
273
+ init_client();
274
+ init_markdown();
275
+ init_user_facing_error();
276
+ WhatsAppFrontend = class {
277
+ name = "whatsapp";
278
+ subs = [];
279
+ cfg;
280
+ errorNotified = false;
281
+ constructor(config) {
282
+ this.cfg = config || {};
283
+ }
284
+ start(ctx) {
285
+ const bus = ctx.eventBus;
286
+ try {
287
+ ctx.logger.info(`[whatsapp-frontend] started`);
288
+ } catch {
289
+ }
290
+ this.subs.push(
291
+ bus.on("CheckCompleted", async (env) => {
292
+ const ev = env && env.payload || env;
293
+ await this.maybePostDirectReply(ctx, ev.checkId, ev.result).catch(() => {
294
+ });
295
+ })
296
+ );
297
+ this.subs.push(
298
+ bus.on("CheckErrored", async (env) => {
299
+ const ev = env && env.payload || env;
300
+ const message = ev?.error?.message || "Execution error";
301
+ await this.maybePostError(ctx, "Check failed", message, ev?.checkId).catch(() => {
302
+ });
303
+ })
304
+ );
305
+ this.subs.push(
306
+ bus.on("Shutdown", async (env) => {
307
+ const ev = env && env.payload || env;
308
+ const message = ev?.error?.message || "Fatal error";
309
+ await this.maybePostError(ctx, "Run failed", message).catch(() => {
310
+ });
311
+ })
312
+ );
313
+ }
314
+ stop() {
315
+ for (const s of this.subs) s.unsubscribe();
316
+ this.subs = [];
317
+ }
318
+ getWhatsApp(ctx) {
319
+ const injected = ctx.whatsapp || ctx.whatsappClient;
320
+ if (injected) return injected;
321
+ try {
322
+ const token = this.cfg.accessToken || process.env.WHATSAPP_ACCESS_TOKEN;
323
+ const phoneId = this.cfg.phoneNumberId || process.env.WHATSAPP_PHONE_NUMBER_ID;
324
+ if (typeof token === "string" && token.trim() && typeof phoneId === "string" && phoneId.trim()) {
325
+ return new WhatsAppClient({
326
+ accessToken: token.trim(),
327
+ phoneNumberId: phoneId.trim()
328
+ });
329
+ }
330
+ } catch {
331
+ }
332
+ return void 0;
333
+ }
334
+ getInboundWhatsAppPayload(ctx) {
335
+ try {
336
+ const endpoint = "/bots/whatsapp/message";
337
+ return ctx.webhookContext?.webhookData?.get(endpoint) || null;
338
+ } catch {
339
+ return null;
340
+ }
341
+ }
342
+ async maybePostError(ctx, title, message, checkId) {
343
+ if (this.errorNotified) return;
344
+ const whatsapp = this.getWhatsApp(ctx);
345
+ if (!whatsapp) return;
346
+ const payload = this.getInboundWhatsAppPayload(ctx);
347
+ const ev = payload?.event;
348
+ const from = ev?.from;
349
+ if (!from) return;
350
+ let text = `${title}`;
351
+ if (checkId) text += `
352
+ Check: ${checkId}`;
353
+ if (message) text += `
354
+ ${formatUserFacingExecutionMessage(message)}`;
355
+ await whatsapp.sendMessage({
356
+ to: from,
357
+ text,
358
+ replyToMessageId: ev?.message_id
359
+ });
360
+ this.errorNotified = true;
361
+ }
362
+ async maybePostDirectReply(ctx, checkId, result) {
363
+ try {
364
+ const cfg = ctx.config || {};
365
+ const checkCfg = cfg.checks?.[checkId];
366
+ if (!checkCfg) return;
367
+ const providerType = checkCfg.type || "";
368
+ const isAi = providerType === "ai";
369
+ const isLogChat = providerType === "log" && checkCfg.group === "chat";
370
+ const isWorkflow = providerType === "workflow";
371
+ if (!isAi && !isLogChat && !isWorkflow) return;
372
+ if (checkCfg.criticality === "internal") return;
373
+ if (isAi) {
374
+ const schema = checkCfg.schema;
375
+ if (typeof schema === "string") {
376
+ const simpleSchemas = ["code-review", "markdown", "text", "plain"];
377
+ if (!simpleSchemas.includes(schema)) return;
378
+ }
379
+ }
380
+ const whatsapp = this.getWhatsApp(ctx);
381
+ if (!whatsapp) return;
382
+ const payload = this.getInboundWhatsAppPayload(ctx);
383
+ const ev = payload?.event;
384
+ const from = ev?.from;
385
+ if (!from) {
386
+ ctx.logger.warn(
387
+ `[whatsapp-frontend] skip posting reply for ${checkId}: missing from number`
388
+ );
389
+ return;
390
+ }
391
+ const out = result?.output;
392
+ let text;
393
+ if (out && typeof out.text === "string" && out.text.trim().length > 0) {
394
+ text = out.text.trim();
395
+ } else if (isAi && typeof checkCfg.schema === "string") {
396
+ if (typeof result?.content === "string" && result.content.trim().length > 0) {
397
+ text = result.content.trim();
398
+ }
399
+ } else if (isLogChat && typeof result?.logOutput === "string") {
400
+ const raw = result.logOutput;
401
+ if (raw.trim().length > 0) text = raw.trim();
402
+ }
403
+ if (out && typeof out._rawOutput === "string" && out._rawOutput.trim().length > 0) {
404
+ text = (text || "") + "\n\n" + out._rawOutput.trim();
405
+ }
406
+ if (!text) {
407
+ const issueSummary = summarizeUserFacingIssues(result?.issues || []);
408
+ if (issueSummary) {
409
+ text = issueSummary;
410
+ this.errorNotified = true;
411
+ }
412
+ }
413
+ if (!text) {
414
+ ctx.logger.info(
415
+ `[whatsapp-frontend] skip posting reply for ${checkId}: no renderable text`
416
+ );
417
+ return;
418
+ }
419
+ text = text.replace(/\\n/g, "\n");
420
+ const formattedText = formatWhatsAppText(text);
421
+ const postResult = await whatsapp.sendMessage({
422
+ to: from,
423
+ text: formattedText,
424
+ replyToMessageId: ev?.message_id
425
+ });
426
+ if (!postResult.ok) {
427
+ ctx.logger.warn(
428
+ `[whatsapp-frontend] failed to post reply for ${checkId}: ${postResult.error}`
429
+ );
430
+ return;
431
+ }
432
+ ctx.logger.info(
433
+ `[whatsapp-frontend] posted reply for ${checkId} to ${from} (messageId=${postResult.messageId})`
434
+ );
435
+ } catch (err) {
436
+ try {
437
+ ctx.logger.warn(
438
+ `[whatsapp-frontend] maybePostDirectReply failed for ${checkId}: ${err instanceof Error ? err.message : String(err)}`
439
+ );
440
+ } catch {
441
+ }
442
+ }
443
+ }
444
+ };
445
+ }
446
+ });
447
+ init_whatsapp_frontend();
448
+ export {
449
+ WhatsAppFrontend
450
+ };
451
+ //# sourceMappingURL=whatsapp-frontend-3EMMNC7R.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/whatsapp/markdown.ts","../../src/whatsapp/client.ts","../../src/frontends/whatsapp-frontend.ts"],"sourcesContent":["// Lightweight Markdown → WhatsApp formatter.\n// Converts common Markdown output from AI steps to WhatsApp-compatible text.\n//\n// Supported conversions:\n// - # Header / ## Header → *Header* (bold, no header support)\n// - **bold** / __bold__ → *bold*\n// - *italic* → _italic_\n// - ~~strike~~ → ~strike~\n// - `code` → ```code```\n// - ```block``` → ```block``` (preserved)\n// - [label](url) → label (url)\n// - > blockquote → > blockquote (preserved, WhatsApp renders this)\n//\n// WhatsApp text messages have a 4096 character limit.\n\n/**\n * Convert Markdown text to WhatsApp-compatible format.\n * Processes line-by-line, respecting fenced code blocks.\n */\nexport function markdownToWhatsApp(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 codeLines: string[] = [];\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 inCodeBlock = true;\n codeLines = [];\n } else {\n // Close code block\n result.push('```' + codeLines.join('\\n') + '```');\n inCodeBlock = false;\n codeLines = [];\n }\n continue;\n }\n if (inCodeBlock) {\n codeLines.push(lines[i]);\n continue;\n }\n\n const line = lines[i];\n\n // Headers: # Header → *Header* (bold)\n const headerMatch = /^(#{1,6})\\s+(.+)$/.exec(line.trimStart());\n if (headerMatch) {\n result.push(`*${convertInline(headerMatch[2].trim())}*`);\n continue;\n }\n\n // Horizontal rules\n if (/^[-*_]{3,}\\s*$/.test(trimmed)) {\n result.push('---');\n continue;\n }\n\n // Bullet lists: \"- item\" or \"* item\" preserved\n const bulletMatch = /^(\\s*)([-*])\\s+(.+)$/.exec(line);\n if (bulletMatch) {\n result.push(`${bulletMatch[1]}- ${convertInline(bulletMatch[3])}`);\n continue;\n }\n\n // Numbered lists: preserve as-is but convert inline\n const numMatch = /^(\\s*)(\\d+\\.)\\s+(.+)$/.exec(line);\n if (numMatch) {\n result.push(`${numMatch[1]}${numMatch[2]} ${convertInline(numMatch[3])}`);\n continue;\n }\n\n // Blockquotes: > text — preserved (WhatsApp renders these)\n const bqMatch = /^>\\s?(.*)$/.exec(trimmed);\n if (bqMatch) {\n result.push(`> ${convertInline(bqMatch[1])}`);\n continue;\n }\n\n // Regular line: apply inline conversions\n result.push(convertInline(line));\n }\n\n // Close any unclosed code block\n if (inCodeBlock && codeLines.length > 0) {\n result.push('```' + codeLines.join('\\n') + '```');\n }\n\n return result.join('\\n');\n}\n\n/**\n * Apply inline Markdown conversions to a single line.\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('```' + code + '```');\n return `\\x00CODE${idx}\\x00`;\n });\n\n // Images: ![alt](url) → alt (url)\n processed = processed.replace(\n /!\\[([^\\]]*)\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)/g,\n (_m, alt: string, url: string) => `${alt || 'image'} (${url})`\n );\n\n // Links: [label](url) → label (url)\n processed = processed.replace(\n /\\[([^\\]]+)\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)/g,\n (_m, label: string, url: string) => `${label} (${url})`\n );\n\n // Bold: **text** or __text__ → *text* (protect with placeholders first)\n const boldSpans: string[] = [];\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, (_m, content: string) => {\n const idx = boldSpans.length;\n boldSpans.push(`*${content}*`);\n return `\\x00BOLD${idx}\\x00`;\n });\n processed = processed.replace(/__([^_]+)__/g, (_m, content: string) => {\n const idx = boldSpans.length;\n boldSpans.push(`*${content}*`);\n return `\\x00BOLD${idx}\\x00`;\n });\n\n // Italic: *text* → _text_ (bold already protected)\n processed = processed.replace(/(?<!\\*)\\*([^*]+)\\*(?!\\*)/g, '_$1_');\n\n // Strikethrough: ~~text~~ → ~text~\n processed = processed.replace(/~~([^~]+)~~/g, '~$1~');\n\n // Restore bold spans\n processed = processed.replace(\n /\\x00BOLD(\\d+)\\x00/g,\n (_m, idx: string) => boldSpans[parseInt(idx)]\n );\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 * Chunk text into segments no larger than limit, splitting at newlines.\n */\nexport function chunkText(text: string, limit: number = 4096): string[] {\n if (text.length <= limit) return [text];\n\n const chunks: string[] = [];\n const lines = text.split('\\n');\n let current = '';\n\n for (const line of lines) {\n const candidate = current ? current + '\\n' + line : line;\n if (candidate.length > limit) {\n if (current) {\n chunks.push(current);\n current = line;\n } else {\n // Single line exceeds limit — force split\n let remaining = line;\n while (remaining.length > limit) {\n chunks.push(remaining.slice(0, limit));\n remaining = remaining.slice(limit);\n }\n current = remaining;\n }\n } else {\n current = candidate;\n }\n }\n if (current) chunks.push(current);\n\n return chunks;\n}\n\n/**\n * Main entry point: convert Markdown to WhatsApp format.\n */\nexport function formatWhatsAppText(text: string): string {\n return markdownToWhatsApp(text);\n}\n","// WhatsApp Cloud API client.\n// Wraps Graph API calls behind a clean interface.\n// Uses fetch directly (no npm dependency — Meta's official SDK is archived).\n\nimport { createHmac } from 'crypto';\nimport { chunkText } from './markdown';\n\nexport interface WhatsAppSendResult {\n ok: boolean;\n messageId?: string; // wamid.* format\n error?: string;\n}\n\nexport interface WhatsAppMessageStatus {\n ok: boolean;\n error?: string;\n}\n\nexport interface WhatsAppClientOptions {\n accessToken: string;\n phoneNumberId: string;\n appSecret?: string;\n verifyToken?: string;\n apiVersion?: string; // default 'v21.0'\n}\n\nexport class WhatsAppClient {\n private accessToken: string;\n private phoneNumberId: string;\n private appSecret?: string;\n private verifyToken?: string;\n private baseUrl: string;\n\n constructor(opts: WhatsAppClientOptions) {\n if (!opts.accessToken || typeof opts.accessToken !== 'string') {\n throw new Error('WhatsAppClient: accessToken is required');\n }\n if (!opts.phoneNumberId || typeof opts.phoneNumberId !== 'string') {\n throw new Error('WhatsAppClient: phoneNumberId is required');\n }\n this.accessToken = opts.accessToken;\n this.phoneNumberId = opts.phoneNumberId;\n this.appSecret = opts.appSecret;\n this.verifyToken = opts.verifyToken;\n const version = opts.apiVersion || 'v21.0';\n this.baseUrl = `https://graph.facebook.com/${version}/${this.phoneNumberId}`;\n }\n\n /** Get the Phone Number ID */\n getPhoneNumberId(): string {\n return this.phoneNumberId;\n }\n\n /**\n * Send a text message. Auto-chunks at 4096 characters.\n */\n async sendMessage(opts: {\n to: string;\n text: string;\n replyToMessageId?: string;\n }): Promise<WhatsAppSendResult> {\n const chunks = chunkText(opts.text, 4096);\n let lastResult: WhatsAppSendResult = { ok: false, error: 'No chunks to send' };\n\n for (const chunk of chunks) {\n const body: any = {\n messaging_product: 'whatsapp',\n to: opts.to,\n type: 'text',\n text: { body: chunk },\n };\n\n // Add quoted reply context\n if (opts.replyToMessageId) {\n body.context = { message_id: opts.replyToMessageId };\n }\n\n try {\n const resp = await fetch(`${this.baseUrl}/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.accessToken}`,\n },\n body: JSON.stringify(body),\n });\n\n const data = await resp.json();\n\n if (!resp.ok) {\n const errMsg = (data as any)?.error?.message || `HTTP ${resp.status}`;\n return { ok: false, error: errMsg };\n }\n\n const msgId = (data as any)?.messages?.[0]?.id;\n lastResult = { ok: true, messageId: msgId };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n return lastResult;\n }\n\n /**\n * Mark a message as read (send read receipt).\n */\n async markAsRead(messageId: string): Promise<WhatsAppMessageStatus> {\n try {\n const resp = await fetch(`${this.baseUrl}/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.accessToken}`,\n },\n body: JSON.stringify({\n messaging_product: 'whatsapp',\n status: 'read',\n message_id: messageId,\n }),\n });\n\n if (!resp.ok) {\n const data = await resp.json();\n return {\n ok: false,\n error: (data as any)?.error?.message || `HTTP ${resp.status}`,\n };\n }\n\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n /**\n * Verify webhook signature (HMAC-SHA256 with X-Hub-Signature-256).\n * Returns true if valid or if no appSecret is configured (skip verification).\n */\n verifyWebhookSignature(rawBody: string, signatureHeader: string): boolean {\n if (!this.appSecret) return true; // no secret = skip verification\n if (!signatureHeader) return false;\n\n const expected = 'sha256=' + createHmac('sha256', this.appSecret).update(rawBody).digest('hex');\n\n return signatureHeader === expected;\n }\n\n /**\n * Verify GET challenge-response for webhook subscription.\n */\n verifyChallenge(params: Record<string, string>): {\n ok: boolean;\n challenge?: string;\n } {\n const mode = params['hub.mode'];\n const token = params['hub.verify_token'];\n const challenge = params['hub.challenge'];\n\n if (mode === 'subscribe' && token === this.verifyToken) {\n return { ok: true, challenge };\n }\n\n return { ok: false };\n }\n}\n","/**\n * WhatsApp Frontend for Visor workflows.\n *\n * Mirrors the TelegramFrontend pattern:\n * - Sends AI replies as WhatsApp text messages\n * - Converts Markdown to WhatsApp format\n * - No reaction equivalent (CheckScheduled is a no-op)\n */\nimport type { Frontend, FrontendContext } from './host';\nimport { WhatsAppClient } from '../whatsapp/client';\nimport { formatWhatsAppText } from '../whatsapp/markdown';\nimport {\n formatUserFacingExecutionMessage,\n summarizeUserFacingIssues,\n} from '../utils/user-facing-error';\n\ntype WhatsAppFrontendConfig = {\n accessToken?: string;\n phoneNumberId?: string;\n};\n\nexport class WhatsAppFrontend implements Frontend {\n public readonly name = 'whatsapp';\n private subs: Array<{ unsubscribe(): void }> = [];\n private cfg: WhatsAppFrontendConfig;\n private errorNotified: boolean = false;\n\n constructor(config?: WhatsAppFrontendConfig) {\n this.cfg = config || {};\n }\n\n start(ctx: FrontendContext): void {\n const bus = ctx.eventBus;\n\n try {\n ctx.logger.info(`[whatsapp-frontend] started`);\n } catch {}\n\n // CheckCompleted: post AI replies\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: post error notice\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: post error\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 (WhatsApp has no reaction equivalent)\n // StateTransition: no-op\n }\n\n stop(): void {\n for (const s of this.subs) s.unsubscribe();\n this.subs = [];\n }\n\n private getWhatsApp(ctx: FrontendContext): WhatsAppClient | undefined {\n // Prefer injected client (for tests or shared runner context)\n const injected = (ctx as any).whatsapp || (ctx as any).whatsappClient;\n if (injected) return injected;\n // Lazy-create from env or frontend config\n try {\n const token = this.cfg.accessToken || process.env.WHATSAPP_ACCESS_TOKEN;\n const phoneId = this.cfg.phoneNumberId || process.env.WHATSAPP_PHONE_NUMBER_ID;\n if (\n typeof token === 'string' &&\n token.trim() &&\n typeof phoneId === 'string' &&\n phoneId.trim()\n ) {\n return new WhatsAppClient({\n accessToken: token.trim(),\n phoneNumberId: phoneId.trim(),\n });\n }\n } catch {}\n return undefined;\n }\n\n private getInboundWhatsAppPayload(ctx: FrontendContext): any | null {\n try {\n const endpoint = '/bots/whatsapp/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 whatsapp = this.getWhatsApp(ctx);\n if (!whatsapp) return;\n const payload = this.getInboundWhatsAppPayload(ctx);\n const ev: any = payload?.event;\n const from = ev?.from;\n if (!from) return;\n\n let text = `${title}`;\n if (checkId) text += `\\nCheck: ${checkId}`;\n if (message) text += `\\n${formatUserFacingExecutionMessage(message)}`;\n\n await whatsapp.sendMessage({\n to: from,\n text,\n replyToMessageId: ev?.message_id,\n });\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 whatsapp = this.getWhatsApp(ctx);\n if (!whatsapp) return;\n\n const payload = this.getInboundWhatsAppPayload(ctx);\n const ev: any = payload?.event;\n const from = ev?.from;\n if (!from) {\n ctx.logger.warn(\n `[whatsapp-frontend] skip posting reply for ${checkId}: missing from number`\n );\n return;\n }\n\n // Extract text (same logic as Telegram/Email/Slack frontends)\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(\n `[whatsapp-frontend] skip posting reply for ${checkId}: no renderable text`\n );\n return;\n }\n\n // Normalize literal \\n escape sequences\n text = text.replace(/\\\\n/g, '\\n');\n\n const formattedText = formatWhatsAppText(text);\n const postResult = await whatsapp.sendMessage({\n to: from,\n text: formattedText,\n replyToMessageId: ev?.message_id,\n });\n\n if (!postResult.ok) {\n ctx.logger.warn(\n `[whatsapp-frontend] failed to post reply for ${checkId}: ${postResult.error}`\n );\n return;\n }\n ctx.logger.info(\n `[whatsapp-frontend] posted reply for ${checkId} to ${from} (messageId=${postResult.messageId})`\n );\n } catch (err) {\n try {\n ctx.logger.warn(\n `[whatsapp-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,8 +1,8 @@
1
1
  import {
2
2
  WorkflowCheckProvider,
3
3
  init_workflow_check_provider
4
- } from "./chunk-TAOGXCWT.mjs";
5
- import "./chunk-YSOIR46P.mjs";
4
+ } from "./chunk-HMVD3AEC.mjs";
5
+ import "./chunk-H2ZWNJJO.mjs";
6
6
  import "./chunk-PDQTEBOJ.mjs";
7
7
  import "./chunk-WZQMTD7W.mjs";
8
8
  import "./chunk-TSX3YS3F.mjs";
@@ -11,9 +11,9 @@ import "./chunk-B7BVQM5K.mjs";
11
11
  import "./chunk-XXAEN5KU.mjs";
12
12
  import "./chunk-ZNKL6ESZ.mjs";
13
13
  import "./chunk-4ZLYHSN4.mjs";
14
- import "./chunk-YBXNG75V.mjs";
14
+ import "./chunk-6DDNEBZ7.mjs";
15
15
  import "./chunk-KWTCTEFT.mjs";
16
- import "./chunk-UM7LGO2P.mjs";
16
+ import "./chunk-RQDLVMER.mjs";
17
17
  import "./chunk-7XKHFRPN.mjs";
18
18
  import "./chunk-QLT42TX7.mjs";
19
19
  import "./chunk-PUHU6UY6.mjs";
@@ -29,4 +29,4 @@ init_workflow_check_provider();
29
29
  export {
30
30
  WorkflowCheckProvider
31
31
  };
32
- //# sourceMappingURL=workflow-check-provider-FOWDJUO3.mjs.map
32
+ //# sourceMappingURL=workflow-check-provider-OVZDCL4E.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,22 +1,25 @@
1
1
  import {
2
2
  WorkflowCheckProvider,
3
3
  init_workflow_check_provider
4
- } from "./chunk-LWH6CVLZ.mjs";
4
+ } from "./chunk-HQCCT6WP.mjs";
5
5
  import "./chunk-YSOIR46P.mjs";
6
- import "./chunk-PDQTEBOJ.mjs";
7
- import "./chunk-WZQMTD7W.mjs";
8
- import "./chunk-TSX3YS3F.mjs";
6
+ import "./chunk-QT766ZLD.mjs";
7
+ import "./chunk-2LLKENYD.mjs";
8
+ import "./chunk-TL3ZTYFY.mjs";
9
+ import "./chunk-PGBV3VZB.mjs";
10
+ import "./chunk-HW4MPCOW.mjs";
11
+ import "./chunk-7QI6F66G.mjs";
9
12
  import "./chunk-VPPBOKBQ.mjs";
10
13
  import "./chunk-B7BVQM5K.mjs";
11
- import "./chunk-XXAEN5KU.mjs";
14
+ import "./chunk-77AKSSW2.mjs";
12
15
  import "./chunk-ZNKL6ESZ.mjs";
13
16
  import "./chunk-4ZLYHSN4.mjs";
14
- import "./chunk-XX6WT332.mjs";
17
+ import "./chunk-YTG5DN72.mjs";
15
18
  import "./chunk-KWTCTEFT.mjs";
16
- import "./chunk-UM7LGO2P.mjs";
17
- import "./chunk-7XKHFRPN.mjs";
18
- import "./chunk-QLT42TX7.mjs";
19
- import "./chunk-PUHU6UY6.mjs";
19
+ import "./chunk-BBLBZVWC.mjs";
20
+ import "./chunk-PZADRRLX.mjs";
21
+ import "./chunk-ZCBVXBKG.mjs";
22
+ import "./chunk-6LQEODDA.mjs";
20
23
  import "./chunk-FWWLD555.mjs";
21
24
  import "./chunk-4HIWZA6M.mjs";
22
25
  import "./chunk-25IC7KXZ.mjs";
@@ -29,4 +32,4 @@ init_workflow_check_provider();
29
32
  export {
30
33
  WorkflowCheckProvider
31
34
  };
32
- //# sourceMappingURL=workflow-check-provider-MRP3C2NC.mjs.map
35
+ //# sourceMappingURL=workflow-check-provider-XOWQYWTC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -13,7 +13,6 @@ interface TracedProbeAgent extends ProbeAgent {
13
13
  export declare class SessionRegistry {
14
14
  private static instance;
15
15
  private sessions;
16
- private exitHandlerRegistered;
17
16
  private constructor();
18
17
  /**
19
18
  * Get the singleton instance of SessionRegistry
@@ -30,11 +29,11 @@ export declare class SessionRegistry {
30
29
  /**
31
30
  * Remove a session from the registry
32
31
  */
33
- unregisterSession(sessionId: string): void;
32
+ unregisterSession(sessionId: string): Promise<void>;
34
33
  /**
35
34
  * Clear all sessions (useful for cleanup)
36
35
  */
37
- clearAllSessions(): void;
36
+ clearAllSessions(): Promise<void>;
38
37
  /**
39
38
  * Get all active session IDs
40
39
  */
@@ -52,9 +51,5 @@ export declare class SessionRegistry {
52
51
  * - Copying agent configuration
53
52
  */
54
53
  cloneSession(sourceSessionId: string, newSessionId: string, checkName?: string): Promise<ProbeAgent | undefined>;
55
- /**
56
- * Register process exit handlers to cleanup sessions on exit
57
- */
58
- private registerExitHandlers;
59
54
  }
60
55
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/session-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;GAEG;AACH,UAAU,gBAAiB,SAAQ,UAAU;IAC3C,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,qBAAqB,CAAS;IAEtC,OAAO;IAKP;;OAEG;WACW,WAAW,IAAI,eAAe;IAO5C;;OAEG;IACI,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAKxE;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAQlE;;OAEG;IACI,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmBjD;;OAEG;IACI,gBAAgB,IAAI,IAAI;IAmB/B;;OAEG;IACI,mBAAmB,IAAI,MAAM,EAAE;IAItC;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C;;;;;;;OAOG;IACU,YAAY,CACvB,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAkElC;;OAEG;IACH,OAAO,CAAC,oBAAoB;CA8C7B"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/session-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;GAEG;AACH,UAAU,gBAAiB,SAAQ,UAAU;IAC3C,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAA4C;IAE5D,OAAO;IAEP;;OAEG;WACW,WAAW,IAAI,eAAe;IAO5C;;OAEG;IACI,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAKxE;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAQlE;;OAEG;IACU,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhE;;OAEG;IACU,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B9C;;OAEG;IACI,mBAAmB,IAAI,MAAM,EAAE;IAItC;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C;;;;;;;OAOG;IACU,YAAY,CACvB,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;CAoEnC"}
@@ -70,6 +70,8 @@ export declare class SlackClient {
70
70
  }>;
71
71
  };
72
72
  getBotUserId(): Promise<string>;
73
+ /** The bot's bot_id (from auth.test), used to detect own bot_message events */
74
+ _botId?: string;
73
75
  /**
74
76
  * Fetch user info from Slack API.
75
77
  * Returns user profile including guest status flags, email, display name, and timezone.
@@ -94,6 +96,12 @@ export declare class SlackClient {
94
96
  * Open a DM channel with a user.
95
97
  * Returns the DM channel ID.
96
98
  */
99
+ /**
100
+ * Resolve a channel name (e.g. "function-cve-alerts") to a channel ID.
101
+ * Uses conversations.list with pagination. Results are cached for the process lifetime.
102
+ */
103
+ private channelNameCache;
104
+ resolveChannelName(name: string): Promise<string | undefined>;
97
105
  openDM(userId: string): Promise<{
98
106
  ok: boolean;
99
107
  channel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/slack/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/slack/client.ts"],"names":[],"mappings":"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"}