@rubytech/create-maxy-code 0.1.602 → 0.1.604

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 (296) hide show
  1. package/dist/__tests__/email-sampler-unit.test.js +22 -0
  2. package/dist/index.js +3 -0
  3. package/dist/port-resolution.js +9 -1
  4. package/package.json +1 -1
  5. package/payload/platform/lib/routine-templates/dist/roster.d.ts +17 -1
  6. package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
  7. package/payload/platform/lib/routine-templates/dist/roster.js +8 -0
  8. package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
  9. package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +26 -1
  10. package/payload/platform/lib/routine-templates/src/roster.ts +26 -1
  11. package/payload/platform/lib/telegram-store-read/dist/index.d.ts +59 -0
  12. package/payload/platform/lib/telegram-store-read/dist/index.d.ts.map +1 -0
  13. package/payload/platform/lib/telegram-store-read/dist/index.js +219 -0
  14. package/payload/platform/lib/telegram-store-read/dist/index.js.map +1 -0
  15. package/payload/platform/lib/telegram-store-read/src/__tests__/fold.test.ts +124 -0
  16. package/payload/platform/lib/telegram-store-read/src/index.ts +262 -0
  17. package/payload/platform/lib/telegram-store-read/tsconfig.json +9 -0
  18. package/payload/platform/lib/telegram-store-read/vitest.config.ts +9 -0
  19. package/payload/platform/neo4j/schema.cypher +7 -0
  20. package/payload/platform/package.json +2 -2
  21. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +51 -4
  22. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
  23. package/payload/platform/plugins/docs/references/outlook-guide.md +21 -2
  24. package/payload/platform/plugins/docs/references/telegram-guide.md +29 -1
  25. package/payload/platform/plugins/email/PLUGIN.md +10 -1
  26. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js +30 -0
  27. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js.map +1 -1
  28. package/payload/platform/plugins/email/mcp/dist/sampler/main.js +49 -3
  29. package/payload/platform/plugins/email/mcp/dist/sampler/main.js.map +1 -1
  30. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts +5 -0
  31. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts.map +1 -1
  32. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js +10 -5
  33. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js.map +1 -1
  34. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js +11 -0
  35. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js.map +1 -1
  36. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +8 -0
  38. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  39. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts +2 -0
  40. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts.map +1 -0
  41. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js +324 -0
  42. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js.map +1 -0
  43. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts +2 -0
  44. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts.map +1 -0
  45. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js +102 -0
  46. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js.map +1 -0
  47. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts +2 -0
  48. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts.map +1 -0
  49. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js +125 -0
  50. package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js.map +1 -0
  51. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts +2 -0
  52. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts.map +1 -0
  53. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js +109 -0
  54. package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js.map +1 -0
  55. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts +25 -0
  56. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts.map +1 -0
  57. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js +94 -0
  58. package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js.map +1 -0
  59. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts +41 -0
  60. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts.map +1 -0
  61. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js +122 -0
  62. package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js.map +1 -0
  63. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts +73 -0
  64. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts.map +1 -0
  65. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js +162 -0
  66. package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js.map +1 -0
  67. package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
  68. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  69. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts +2 -0
  70. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts.map +1 -0
  71. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js +90 -0
  72. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js.map +1 -0
  73. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +26 -4
  74. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
  75. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts +78 -0
  76. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts.map +1 -0
  77. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js +76 -0
  78. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js.map +1 -0
  79. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +8 -0
  80. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
  81. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +9 -1
  82. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
  83. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +15 -0
  84. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -1
  85. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +12 -1
  86. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  87. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +34 -1
  88. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  89. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +9 -1
  90. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  91. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +116 -4
  92. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
  93. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +60 -2
  94. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
  95. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +101 -4
  96. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
  97. package/payload/platform/plugins/telegram/PLUGIN.md +1 -1
  98. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.d.ts +2 -0
  99. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.d.ts.map +1 -0
  100. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.js +157 -0
  101. package/payload/platform/plugins/telegram/mcp/dist/__tests__/messages.test.js.map +1 -0
  102. package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin.test.js +2 -2
  103. package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin.test.js.map +1 -1
  104. package/payload/platform/plugins/telegram/mcp/dist/index.js +32 -34
  105. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  106. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js +1 -1
  107. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js.map +1 -1
  108. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.d.ts +27 -0
  109. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.d.ts.map +1 -0
  110. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.js +152 -0
  111. package/payload/platform/plugins/telegram/mcp/dist/tools/messages.js.map +1 -0
  112. package/payload/platform/plugins/telegram/skills/build/SKILL.md +1 -1
  113. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +15 -1
  114. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -1
  115. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  116. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  117. package/payload/server/public/activity.html +6 -6
  118. package/payload/server/public/agents.html +5 -5
  119. package/payload/server/public/assets/{AdminLoginScreens-CaQqLuxZ.js → AdminLoginScreens-DI5bNlX8.js} +1 -1
  120. package/payload/server/public/assets/AdminLoginScreens-DI5bNlX8.js.br +0 -0
  121. package/payload/server/public/assets/AdminLoginScreens-DI5bNlX8.js.gz +0 -0
  122. package/payload/server/public/assets/{AdminShell-D8WTrqem.js → AdminShell-B-iX9ahJ.js} +1 -1
  123. package/payload/server/public/assets/AdminShell-B-iX9ahJ.js.br +0 -0
  124. package/payload/server/public/assets/AdminShell-B-iX9ahJ.js.gz +0 -0
  125. package/payload/server/public/assets/{activity-B3fiJrC2.js → activity-CqgFwANo.js} +1 -1
  126. package/payload/server/public/assets/activity-CqgFwANo.js.br +0 -0
  127. package/payload/server/public/assets/activity-CqgFwANo.js.gz +0 -0
  128. package/payload/server/public/assets/{admin-ouF-DflP.js → admin-K63n6ybW.js} +1 -1
  129. package/payload/server/public/assets/admin-K63n6ybW.js.br +0 -0
  130. package/payload/server/public/assets/admin-K63n6ybW.js.gz +0 -0
  131. package/payload/server/public/assets/{agents-C8RSXHdh.js → agents-cue5Zf8X.js} +1 -1
  132. package/payload/server/public/assets/agents-cue5Zf8X.js.br +0 -0
  133. package/payload/server/public/assets/agents-cue5Zf8X.js.gz +0 -0
  134. package/payload/server/public/assets/{browser-Dbv6-Rag.js → browser-CqDBcKwU.js} +1 -1
  135. package/payload/server/public/assets/browser-CqDBcKwU.js.br +0 -0
  136. package/payload/server/public/assets/browser-CqDBcKwU.js.gz +0 -0
  137. package/payload/server/public/assets/{calendar-vJjtsH9n.js → calendar-BgzuW5Rt.js} +1 -1
  138. package/payload/server/public/assets/calendar-BgzuW5Rt.js.br +0 -0
  139. package/payload/server/public/assets/calendar-BgzuW5Rt.js.gz +0 -0
  140. package/payload/server/public/assets/chat-HYZViu2u.js +1 -0
  141. package/payload/server/public/assets/chat-HYZViu2u.js.br +3 -0
  142. package/payload/server/public/assets/chat-HYZViu2u.js.gz +0 -0
  143. package/payload/server/public/assets/chevron-left-C5FXH9r_.js +1 -0
  144. package/payload/server/public/assets/chevron-left-C5FXH9r_.js.br +0 -0
  145. package/payload/server/public/assets/clock-DxPtyejC.js +1 -0
  146. package/payload/server/public/assets/clock-DxPtyejC.js.br +0 -0
  147. package/payload/server/public/assets/clock-DxPtyejC.js.gz +0 -0
  148. package/payload/server/public/assets/{copy-DyG7sC5o.js → copy-BNhZ0flH.js} +1 -1
  149. package/payload/server/public/assets/copy-BNhZ0flH.js.br +0 -0
  150. package/payload/server/public/assets/copy-BNhZ0flH.js.gz +0 -0
  151. package/payload/server/public/assets/data-kCBB8Z4Z.js +1 -0
  152. package/payload/server/public/assets/data-kCBB8Z4Z.js.br +0 -0
  153. package/payload/server/public/assets/data-kCBB8Z4Z.js.gz +0 -0
  154. package/payload/server/public/assets/{field-Bx6pM-vq.js → field-X4OVA3vx.js} +1 -1
  155. package/payload/server/public/assets/field-X4OVA3vx.js.br +0 -0
  156. package/payload/server/public/assets/field-X4OVA3vx.js.gz +0 -0
  157. package/payload/server/public/assets/{file-text-CpHWsMGe.js → file-text-BddO_2EI.js} +1 -1
  158. package/payload/server/public/assets/file-text-BddO_2EI.js.br +0 -0
  159. package/payload/server/public/assets/file-text-BddO_2EI.js.gz +0 -0
  160. package/payload/server/public/assets/{graph-DjOywuv_.js → graph-l7tzHqvm.js} +1 -1
  161. package/payload/server/public/assets/graph-l7tzHqvm.js.br +0 -0
  162. package/payload/server/public/assets/graph-l7tzHqvm.js.gz +0 -0
  163. package/payload/server/public/assets/{graph-labels-CGWtqa-m.js → graph-labels-CtFFq5W2.js} +1 -1
  164. package/payload/server/public/assets/graph-labels-CtFFq5W2.js.br +0 -0
  165. package/payload/server/public/assets/graph-labels-CtFFq5W2.js.gz +0 -0
  166. package/payload/server/public/assets/jsx-runtime-bq0g4NlA.css +1 -0
  167. package/payload/server/public/assets/jsx-runtime-bq0g4NlA.css.br +0 -0
  168. package/payload/server/public/assets/jsx-runtime-bq0g4NlA.css.gz +0 -0
  169. package/payload/server/public/assets/{operator-_DN0RF1R.js → operator-Dg-dwf7a.js} +1 -1
  170. package/payload/server/public/assets/operator-Dg-dwf7a.js.br +7 -0
  171. package/payload/server/public/assets/operator-Dg-dwf7a.js.gz +0 -0
  172. package/payload/server/public/assets/{page-DI4qQIK0.js → page-Ci1bfIbs.js} +1 -1
  173. package/payload/server/public/assets/page-Ci1bfIbs.js.br +0 -0
  174. package/payload/server/public/assets/page-Ci1bfIbs.js.gz +0 -0
  175. package/payload/server/public/assets/{page-zCwgrs8m.js → page-Y9JmFq0Q.js} +1 -1
  176. package/payload/server/public/assets/page-Y9JmFq0Q.js.br +0 -0
  177. package/payload/server/public/assets/page-Y9JmFq0Q.js.gz +0 -0
  178. package/payload/server/public/assets/play-BSZVGpQT.js +1 -0
  179. package/payload/server/public/assets/play-BSZVGpQT.js.br +0 -0
  180. package/payload/server/public/assets/play-BSZVGpQT.js.gz +0 -0
  181. package/payload/server/public/assets/{public-DDVWBNSH.js → public-m66FAza_.js} +1 -1
  182. package/payload/server/public/assets/public-m66FAza_.js.br +0 -0
  183. package/payload/server/public/assets/public-m66FAza_.js.gz +0 -0
  184. package/payload/server/public/assets/{rotate-ccw-xTwkf-m7.js → rotate-ccw-DTOJmOxB.js} +1 -1
  185. package/payload/server/public/assets/rotate-ccw-DTOJmOxB.js.br +0 -0
  186. package/payload/server/public/assets/rotate-ccw-DTOJmOxB.js.gz +0 -0
  187. package/payload/server/public/assets/{routines-Bu5MdNmG.js → routines-6fxZNacQ.js} +1 -1
  188. package/payload/server/public/assets/routines-6fxZNacQ.js.br +0 -0
  189. package/payload/server/public/assets/routines-6fxZNacQ.js.gz +0 -0
  190. package/payload/server/public/assets/{skills-DRunh5vy.js → skills-51mqx-s5.js} +1 -1
  191. package/payload/server/public/assets/skills-51mqx-s5.js.br +0 -0
  192. package/payload/server/public/assets/skills-51mqx-s5.js.gz +0 -0
  193. package/payload/server/public/assets/{tasks-DI2fznvd.js → tasks-D4y-Cwa3.js} +1 -1
  194. package/payload/server/public/assets/tasks-D4y-Cwa3.js.br +0 -0
  195. package/payload/server/public/assets/tasks-D4y-Cwa3.js.gz +0 -0
  196. package/payload/server/public/assets/{triangle-alert-B6CHZeUf.js → triangle-alert-BzCjDFts.js} +1 -1
  197. package/payload/server/public/assets/triangle-alert-BzCjDFts.js.br +0 -0
  198. package/payload/server/public/assets/triangle-alert-BzCjDFts.js.gz +0 -0
  199. package/payload/server/public/assets/{useCopyFeedback-6rU2IEPk.js → useCopyFeedback-BG7h37Rx.js} +1 -1
  200. package/payload/server/public/assets/useCopyFeedback-BG7h37Rx.js.br +2 -0
  201. package/payload/server/public/assets/useCopyFeedback-BG7h37Rx.js.gz +0 -0
  202. package/payload/server/public/assets/{useMediaQuery-D7A5Bzs3.js → useMediaQuery-CqwktQr_.js} +1 -1
  203. package/payload/server/public/assets/useMediaQuery-CqwktQr_.js.br +0 -0
  204. package/payload/server/public/assets/{useMediaQuery-D7A5Bzs3.js.gz → useMediaQuery-CqwktQr_.js.gz} +0 -0
  205. package/payload/server/public/assets/{useVoiceRecorder-CptrerVA.js → useVoiceRecorder-CAZcUc1s.js} +1 -1
  206. package/payload/server/public/assets/useVoiceRecorder-CAZcUc1s.js.br +0 -0
  207. package/payload/server/public/assets/useVoiceRecorder-CAZcUc1s.js.gz +0 -0
  208. package/payload/server/public/assets/{wrench-DyX4C8aY.js → wrench-B2WKLLQG.js} +1 -1
  209. package/payload/server/public/assets/wrench-B2WKLLQG.js.br +0 -0
  210. package/payload/server/public/assets/wrench-B2WKLLQG.js.gz +0 -0
  211. package/payload/server/public/browser.html +5 -5
  212. package/payload/server/public/calendar.html +8 -8
  213. package/payload/server/public/chat.html +14 -14
  214. package/payload/server/public/data.html +12 -12
  215. package/payload/server/public/field.html +3 -3
  216. package/payload/server/public/graph.html +10 -10
  217. package/payload/server/public/index.html +14 -14
  218. package/payload/server/public/operator.html +16 -16
  219. package/payload/server/public/public.html +14 -14
  220. package/payload/server/public/routines.html +8 -8
  221. package/payload/server/public/skills.html +6 -6
  222. package/payload/server/public/tasks.html +7 -7
  223. package/payload/server/server.js +500 -325
  224. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts +0 -16
  225. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts.map +0 -1
  226. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js +0 -68
  227. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js.map +0 -1
  228. package/payload/server/public/assets/AdminLoginScreens-CaQqLuxZ.js.br +0 -0
  229. package/payload/server/public/assets/AdminLoginScreens-CaQqLuxZ.js.gz +0 -0
  230. package/payload/server/public/assets/AdminShell-D8WTrqem.js.br +0 -0
  231. package/payload/server/public/assets/AdminShell-D8WTrqem.js.gz +0 -0
  232. package/payload/server/public/assets/activity-B3fiJrC2.js.br +0 -0
  233. package/payload/server/public/assets/activity-B3fiJrC2.js.gz +0 -0
  234. package/payload/server/public/assets/admin-ouF-DflP.js.br +0 -0
  235. package/payload/server/public/assets/admin-ouF-DflP.js.gz +0 -0
  236. package/payload/server/public/assets/agents-C8RSXHdh.js.br +0 -0
  237. package/payload/server/public/assets/agents-C8RSXHdh.js.gz +0 -0
  238. package/payload/server/public/assets/browser-Dbv6-Rag.js.br +0 -0
  239. package/payload/server/public/assets/browser-Dbv6-Rag.js.gz +0 -0
  240. package/payload/server/public/assets/calendar-vJjtsH9n.js.br +0 -0
  241. package/payload/server/public/assets/calendar-vJjtsH9n.js.gz +0 -0
  242. package/payload/server/public/assets/chat-cqL4qPUy.js +0 -1
  243. package/payload/server/public/assets/chat-cqL4qPUy.js.br +0 -1
  244. package/payload/server/public/assets/chat-cqL4qPUy.js.gz +0 -0
  245. package/payload/server/public/assets/chevron-left-DB98DSG3.js +0 -1
  246. package/payload/server/public/assets/chevron-left-DB98DSG3.js.br +0 -0
  247. package/payload/server/public/assets/clock-4YwsYe4L.js +0 -1
  248. package/payload/server/public/assets/clock-4YwsYe4L.js.br +0 -0
  249. package/payload/server/public/assets/clock-4YwsYe4L.js.gz +0 -0
  250. package/payload/server/public/assets/copy-DyG7sC5o.js.br +0 -0
  251. package/payload/server/public/assets/copy-DyG7sC5o.js.gz +0 -0
  252. package/payload/server/public/assets/data-BAzLtx9C.js +0 -1
  253. package/payload/server/public/assets/data-BAzLtx9C.js.br +0 -0
  254. package/payload/server/public/assets/data-BAzLtx9C.js.gz +0 -0
  255. package/payload/server/public/assets/field-Bx6pM-vq.js.br +0 -0
  256. package/payload/server/public/assets/field-Bx6pM-vq.js.gz +0 -0
  257. package/payload/server/public/assets/file-text-CpHWsMGe.js.br +0 -0
  258. package/payload/server/public/assets/file-text-CpHWsMGe.js.gz +0 -0
  259. package/payload/server/public/assets/graph-DjOywuv_.js.br +0 -0
  260. package/payload/server/public/assets/graph-DjOywuv_.js.gz +0 -0
  261. package/payload/server/public/assets/graph-labels-CGWtqa-m.js.br +0 -0
  262. package/payload/server/public/assets/graph-labels-CGWtqa-m.js.gz +0 -0
  263. package/payload/server/public/assets/jsx-runtime-D75_aR1J.css +0 -1
  264. package/payload/server/public/assets/jsx-runtime-D75_aR1J.css.br +0 -0
  265. package/payload/server/public/assets/jsx-runtime-D75_aR1J.css.gz +0 -0
  266. package/payload/server/public/assets/operator-_DN0RF1R.js.br +0 -0
  267. package/payload/server/public/assets/operator-_DN0RF1R.js.gz +0 -0
  268. package/payload/server/public/assets/page-DI4qQIK0.js.br +0 -0
  269. package/payload/server/public/assets/page-DI4qQIK0.js.gz +0 -0
  270. package/payload/server/public/assets/page-zCwgrs8m.js.br +0 -0
  271. package/payload/server/public/assets/page-zCwgrs8m.js.gz +0 -0
  272. package/payload/server/public/assets/play-CHQ5a9yh.js +0 -1
  273. package/payload/server/public/assets/play-CHQ5a9yh.js.br +0 -0
  274. package/payload/server/public/assets/play-CHQ5a9yh.js.gz +0 -0
  275. package/payload/server/public/assets/public-DDVWBNSH.js.br +0 -0
  276. package/payload/server/public/assets/public-DDVWBNSH.js.gz +0 -0
  277. package/payload/server/public/assets/rotate-ccw-xTwkf-m7.js.br +0 -0
  278. package/payload/server/public/assets/rotate-ccw-xTwkf-m7.js.gz +0 -0
  279. package/payload/server/public/assets/routines-Bu5MdNmG.js.br +0 -0
  280. package/payload/server/public/assets/routines-Bu5MdNmG.js.gz +0 -0
  281. package/payload/server/public/assets/skills-DRunh5vy.js.br +0 -0
  282. package/payload/server/public/assets/skills-DRunh5vy.js.gz +0 -0
  283. package/payload/server/public/assets/tasks-DI2fznvd.js.br +0 -0
  284. package/payload/server/public/assets/tasks-DI2fznvd.js.gz +0 -0
  285. package/payload/server/public/assets/triangle-alert-B6CHZeUf.js.br +0 -0
  286. package/payload/server/public/assets/triangle-alert-B6CHZeUf.js.gz +0 -0
  287. package/payload/server/public/assets/useCopyFeedback-6rU2IEPk.js.br +0 -2
  288. package/payload/server/public/assets/useCopyFeedback-6rU2IEPk.js.gz +0 -0
  289. package/payload/server/public/assets/useMediaQuery-D7A5Bzs3.js.br +0 -0
  290. package/payload/server/public/assets/useVoiceRecorder-CptrerVA.js.br +0 -0
  291. package/payload/server/public/assets/useVoiceRecorder-CptrerVA.js.gz +0 -0
  292. package/payload/server/public/assets/wrench-DyX4C8aY.js.br +0 -0
  293. package/payload/server/public/assets/wrench-DyX4C8aY.js.gz +0 -0
  294. /package/payload/server/public/assets/{jsx-runtime-B2Q1UOSJ.js → jsx-runtime-UK6hgBWO.js} +0 -0
  295. /package/payload/server/public/assets/{jsx-runtime-B2Q1UOSJ.js.br → jsx-runtime-UK6hgBWO.js.br} +0 -0
  296. /package/payload/server/public/assets/{jsx-runtime-B2Q1UOSJ.js.gz → jsx-runtime-UK6hgBWO.js.gz} +0 -0
@@ -0,0 +1,324 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { sampleOutlookMailbox, } from "../sampler/sample-outlook-mailbox.js";
4
+ const TARGET = {
5
+ accountId: "acct-1",
6
+ mailbox: "a@example.com",
7
+ mailboxKey: "guid-1",
8
+ pathPrefix: "/me",
9
+ via: null,
10
+ };
11
+ const NOW = Date.parse("2026-08-13T12:00:00Z");
12
+ function listed(id, receivedDateTime) {
13
+ return { id, receivedDateTime };
14
+ }
15
+ function body(id, receivedDateTime, text = "full body") {
16
+ return {
17
+ id,
18
+ subject: "subject",
19
+ from: "sender@example.com",
20
+ fromName: "Sender",
21
+ to: ["a@example.com"],
22
+ cc: [],
23
+ conversationId: "conv-1",
24
+ body: text,
25
+ receivedDateTime,
26
+ };
27
+ }
28
+ function harness(over = {}) {
29
+ const lines = [];
30
+ const writes = [];
31
+ let stored = null;
32
+ const deps = {
33
+ list: async () => ({ items: [], nextCursor: null }),
34
+ fetchBody: async (_t, id) => body(id, "2026-08-13T09:00:00Z"),
35
+ write: async (m) => {
36
+ writes.push(m);
37
+ return { threadsDispatched: 1, threadsSkipped: 0, unresolvedAddresses: [] };
38
+ },
39
+ readCursor: () => stored,
40
+ writeCursor: (_t, c) => {
41
+ stored = c;
42
+ },
43
+ log: (l) => lines.push(l),
44
+ now: () => NOW,
45
+ ...over,
46
+ };
47
+ return {
48
+ deps,
49
+ lines,
50
+ writes,
51
+ get stored() {
52
+ return stored;
53
+ },
54
+ setStored(c) {
55
+ stored = c;
56
+ },
57
+ };
58
+ }
59
+ test("the first cycle asks for the last 7 days", async () => {
60
+ const seen = [];
61
+ const h = harness({
62
+ list: async (_t, since) => {
63
+ seen.push(since);
64
+ return { items: [], nextCursor: null };
65
+ },
66
+ });
67
+ await sampleOutlookMailbox(h.deps, TARGET);
68
+ assert.deepEqual(seen, [new Date(NOW - 7 * 24 * 60 * 60 * 1000).toISOString()]);
69
+ });
70
+ test("a later cycle asks from the stored instant", async () => {
71
+ const seen = [];
72
+ const h = harness({
73
+ list: async (_t, since) => {
74
+ seen.push(since);
75
+ return { items: [], nextCursor: null };
76
+ },
77
+ });
78
+ h.setStored({ newestReceivedAt: "2026-08-13T09:00:00Z", idsAtNewest: ["id-1"] });
79
+ await sampleOutlookMailbox(h.deps, TARGET);
80
+ assert.deepEqual(seen, ["2026-08-13T09:00:00Z"]);
81
+ });
82
+ test("nothing newer is a no-op that writes nothing and leaves the cursor alone", async () => {
83
+ const h = harness({
84
+ list: async () => ({ items: [listed("id-1", "2026-08-13T09:00:00Z")], nextCursor: null }),
85
+ });
86
+ h.setStored({ newestReceivedAt: "2026-08-13T09:00:00Z", idsAtNewest: ["id-1"] });
87
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
88
+ assert.equal(r.fetched, 0);
89
+ assert.equal(h.writes.length, 0);
90
+ assert.deepEqual(h.stored, { newestReceivedAt: "2026-08-13T09:00:00Z", idsAtNewest: ["id-1"] });
91
+ assert.ok(h.lines.some((l) => l === "op=sample mailbox=a@example.com provider=outlook fetched=0 cursor=2026-08-13T09:00:00Z"), h.lines.join("\n"));
92
+ });
93
+ test("messages above the cursor are written once and the cursor advances", async () => {
94
+ const h = harness({
95
+ list: async () => ({
96
+ items: [listed("id-2", "2026-08-13T10:00:00Z"), listed("id-1", "2026-08-13T09:00:00Z")],
97
+ nextCursor: null,
98
+ }),
99
+ fetchBody: async (_t, id) => body(id, id === "id-2" ? "2026-08-13T10:00:00Z" : "2026-08-13T09:00:00Z"),
100
+ });
101
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
102
+ assert.equal(r.fetched, 2);
103
+ assert.equal(h.writes.length, 1, "one write for the whole batch");
104
+ assert.equal(h.writes[0].length, 2);
105
+ assert.deepEqual(h.stored, {
106
+ newestReceivedAt: "2026-08-13T10:00:00Z",
107
+ idsAtNewest: ["id-2"],
108
+ });
109
+ assert.ok(h.lines.some((l) => l === "op=sample mailbox=a@example.com provider=outlook fetched=2 threads=1 skipped=0 cursor=2026-08-13T10:00:00Z"), h.lines.join("\n"));
110
+ });
111
+ test("a sibling arriving at the cursor instant is ingested and joins the exclusion set", async () => {
112
+ const h = harness({
113
+ list: async () => ({
114
+ items: [listed("id-1b", "2026-08-13T09:00:00Z"), listed("id-1", "2026-08-13T09:00:00Z")],
115
+ nextCursor: null,
116
+ }),
117
+ fetchBody: async (_t, id) => body(id, "2026-08-13T09:00:00Z"),
118
+ });
119
+ h.setStored({ newestReceivedAt: "2026-08-13T09:00:00Z", idsAtNewest: ["id-1"] });
120
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
121
+ assert.equal(r.fetched, 1, "only the unseen sibling");
122
+ assert.equal(h.writes[0].length, 1);
123
+ assert.equal(h.writes[0][0].messageId, "id-1b");
124
+ assert.deepEqual(h.stored, {
125
+ newestReceivedAt: "2026-08-13T09:00:00Z",
126
+ idsAtNewest: ["id-1", "id-1b"],
127
+ });
128
+ });
129
+ test("a second cycle over the same listing re-ingests nothing", async () => {
130
+ const items = [listed("id-2", "2026-08-13T10:00:00Z"), listed("id-1", "2026-08-13T09:00:00Z")];
131
+ const h = harness({
132
+ list: async () => ({ items, nextCursor: null }),
133
+ fetchBody: async (_t, id) => body(id, id === "id-2" ? "2026-08-13T10:00:00Z" : "2026-08-13T09:00:00Z"),
134
+ });
135
+ await sampleOutlookMailbox(h.deps, TARGET);
136
+ // The second cycle's list is filtered `ge cursor`, so only the boundary
137
+ // message comes back — and it is excluded by id.
138
+ const h2 = harness({
139
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
140
+ });
141
+ h2.setStored(h.stored);
142
+ const r2 = await sampleOutlookMailbox(h2.deps, TARGET);
143
+ assert.equal(r2.fetched, 0);
144
+ assert.equal(h2.writes.length, 0);
145
+ });
146
+ test("a write failure leaves the cursor unadvanced", async () => {
147
+ const h = harness({
148
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
149
+ fetchBody: async (_t, id) => body(id, "2026-08-13T10:00:00Z"),
150
+ write: async () => {
151
+ throw new Error("neo4j down");
152
+ },
153
+ });
154
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
155
+ assert.equal(r.error, "neo4j down");
156
+ assert.equal(h.stored, null);
157
+ assert.ok(h.lines.some((l) => l === "op=sample-error mailbox=a@example.com provider=outlook detail=neo4j down"), h.lines.join("\n"));
158
+ });
159
+ test("a list failure writes nothing and leaves the cursor unadvanced", async () => {
160
+ const h = harness({
161
+ list: async () => {
162
+ throw new Error("graph 503");
163
+ },
164
+ });
165
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
166
+ assert.equal(r.error, "graph 503");
167
+ assert.equal(h.writes.length, 0);
168
+ assert.equal(h.stored, null);
169
+ });
170
+ test("a body-fetch failure writes nothing and leaves the cursor unadvanced", async () => {
171
+ const h = harness({
172
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
173
+ fetchBody: async () => {
174
+ throw new Error("graph 404");
175
+ },
176
+ });
177
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
178
+ assert.equal(r.error, "graph 404");
179
+ assert.equal(h.writes.length, 0);
180
+ assert.equal(h.stored, null);
181
+ });
182
+ test("every page is fetched before anything is written", async () => {
183
+ const h = harness({
184
+ list: async (_t, _since, cursor) => cursor
185
+ ? { items: [listed("id-1", "2026-08-13T09:00:00Z")], nextCursor: null }
186
+ : { items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: "next-link" },
187
+ fetchBody: async (_t, id) => body(id, id === "id-2" ? "2026-08-13T10:00:00Z" : "2026-08-13T09:00:00Z"),
188
+ });
189
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
190
+ assert.equal(r.fetched, 2);
191
+ assert.equal(h.writes.length, 1, "one write, after both pages");
192
+ assert.equal(h.stored?.newestReceivedAt, "2026-08-13T10:00:00Z");
193
+ });
194
+ test("a continuation page is requested with the cursor and no since filter", async () => {
195
+ const calls = [];
196
+ const h = harness({
197
+ list: async (_t, since, cursor) => {
198
+ calls.push({ since, cursor });
199
+ return cursor
200
+ ? { items: [], nextCursor: null }
201
+ : { items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: "next-link" };
202
+ },
203
+ fetchBody: async (_t, id) => body(id, "2026-08-13T10:00:00Z"),
204
+ });
205
+ await sampleOutlookMailbox(h.deps, TARGET);
206
+ assert.equal(calls.length, 2);
207
+ assert.equal(calls[1].cursor, "next-link");
208
+ assert.equal(calls[1].since, undefined, "a nextLink already encodes the filter");
209
+ });
210
+ test("a delegated mailbox names its delegator on the sample line", async () => {
211
+ const h = harness();
212
+ await sampleOutlookMailbox(h.deps, {
213
+ ...TARGET,
214
+ mailbox: "shared@example.com",
215
+ pathPrefix: "/users/shared%40example.com",
216
+ via: "a@example.com",
217
+ });
218
+ assert.ok(h.lines.some((l) => l ===
219
+ "op=sample mailbox=shared@example.com provider=outlook via=a@example.com fetched=0 cursor=none"), h.lines.join("\n"));
220
+ });
221
+ test("the full body is written with no truncation", async () => {
222
+ const long = "x".repeat(4000);
223
+ const h = harness({
224
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
225
+ fetchBody: async (_t, id) => body(id, "2026-08-13T10:00:00Z", long),
226
+ });
227
+ await sampleOutlookMailbox(h.deps, TARGET);
228
+ assert.equal(h.writes[0][0].bodyText.length, 4000);
229
+ });
230
+ test("the written record carries the envelope the archive dispatcher groups on", async () => {
231
+ const h = harness({
232
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
233
+ fetchBody: async (_t, id) => body(id, "2026-08-13T10:00:00Z"),
234
+ });
235
+ await sampleOutlookMailbox(h.deps, TARGET);
236
+ assert.deepEqual(h.writes[0][0], {
237
+ messageId: "id-2",
238
+ conversationId: "conv-1",
239
+ fromAddress: "sender@example.com",
240
+ fromName: "Sender",
241
+ toAddresses: ["a@example.com"],
242
+ ccAddresses: [],
243
+ subject: "subject",
244
+ bodyText: "full body",
245
+ receivedDateTime: "2026-08-13T10:00:00Z",
246
+ accountId: "acct-1",
247
+ });
248
+ });
249
+ test("a later message with finer fractional precision still wins the cursor", async () => {
250
+ // Raw string comparison puts "...00.5Z" BEFORE "...00Z" because '.' precedes
251
+ // 'Z'. If the cursor were chosen that way, id-late would never be excluded and
252
+ // would be re-fetched and re-written on every cycle for ever.
253
+ const h = harness({
254
+ list: async () => ({
255
+ items: [
256
+ listed("id-late", "2026-08-13T09:00:00.5Z"),
257
+ listed("id-early", "2026-08-13T09:00:00Z"),
258
+ ],
259
+ nextCursor: null,
260
+ }),
261
+ fetchBody: async (_t, id) => body(id, id === "id-late" ? "2026-08-13T09:00:00.5Z" : "2026-08-13T09:00:00Z"),
262
+ });
263
+ await sampleOutlookMailbox(h.deps, TARGET);
264
+ assert.deepEqual(h.stored, {
265
+ newestReceivedAt: "2026-08-13T09:00:00.5Z",
266
+ idsAtNewest: ["id-late"],
267
+ });
268
+ });
269
+ test("the same instant in two spellings is one instant for the exclusion set", async () => {
270
+ const h = harness({
271
+ readCursor: () => ({ newestReceivedAt: "2026-08-13T09:00:00.000Z", idsAtNewest: ["id-1"] }),
272
+ list: async () => ({ items: [listed("id-2", "2026-08-13T09:00:00Z")], nextCursor: null }),
273
+ fetchBody: async (_t, id) => body(id, "2026-08-13T09:00:00Z"),
274
+ });
275
+ await sampleOutlookMailbox(h.deps, TARGET);
276
+ // Same instant, different spelling: id-1 must be carried, not discarded.
277
+ assert.deepEqual(h.stored?.idsAtNewest, ["id-1", "id-2"]);
278
+ });
279
+ test("the cursor never moves backwards when a fetched instant disagrees with its listing", async () => {
280
+ const h = harness({
281
+ readCursor: () => ({ newestReceivedAt: "2026-08-13T10:00:00Z", idsAtNewest: ["id-1"] }),
282
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
283
+ fetchBody: async (_t, id) => body(id, "2026-08-13T08:00:00Z"),
284
+ });
285
+ await sampleOutlookMailbox(h.deps, TARGET);
286
+ assert.equal(h.stored?.newestReceivedAt, "2026-08-13T10:00:00Z");
287
+ });
288
+ test("an all-skipped write reports the skip and names the unresolved addresses", async () => {
289
+ const h = harness({
290
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
291
+ fetchBody: async (_t, id) => body(id, "2026-08-13T10:00:00Z"),
292
+ write: async () => ({
293
+ threadsDispatched: 0,
294
+ threadsSkipped: 1,
295
+ unresolvedAddresses: ["stranger@example.com"],
296
+ }),
297
+ });
298
+ await sampleOutlookMailbox(h.deps, TARGET);
299
+ // fetched=1 alone would state that a message was sampled while nothing
300
+ // reached the graph, and the cursor advances past it either way.
301
+ assert.ok(h.lines.some((l) => l ===
302
+ "op=sample mailbox=a@example.com provider=outlook fetched=1 threads=0 skipped=1 cursor=2026-08-13T10:00:00Z"), h.lines.join("\n"));
303
+ assert.ok(h.lines.some((l) => l ===
304
+ "op=sample-unresolved mailbox=a@example.com provider=outlook threads=1 addresses=stranger@example.com"), h.lines.join("\n"));
305
+ });
306
+ test("a fully resolved write emits no unresolved line", async () => {
307
+ const h = harness({
308
+ list: async () => ({ items: [listed("id-2", "2026-08-13T10:00:00Z")], nextCursor: null }),
309
+ fetchBody: async (_t, id) => body(id, "2026-08-13T10:00:00Z"),
310
+ });
311
+ await sampleOutlookMailbox(h.deps, TARGET);
312
+ assert.ok(!h.lines.some((l) => l.includes("op=sample-unresolved")), h.lines.join("\n"));
313
+ });
314
+ test("an unparseable instant with no stored cursor leaves the cursor unwritten", async () => {
315
+ const h = harness({
316
+ list: async () => ({ items: [listed("id-2", "not-a-date")], nextCursor: null }),
317
+ fetchBody: async (_t, id) => body(id, "not-a-date"),
318
+ });
319
+ const r = await sampleOutlookMailbox(h.deps, TARGET);
320
+ assert.equal(r.error, "no-parseable-instant");
321
+ assert.equal(h.stored, null, "a NaN cursor is worse than re-reading the window");
322
+ assert.ok(h.lines.some((l) => l.includes("detail=no-parseable-instant")), h.lines.join("\n"));
323
+ });
324
+ //# sourceMappingURL=sample-outlook-mailbox.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-outlook-mailbox.test.js","sourceRoot":"","sources":["../../src/__tests__/sample-outlook-mailbox.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sampler-cursor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampler-cursor.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sampler-cursor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, readFileSync, statSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { readCursor, writeCursor } from "../sampler/cursor.js";
7
+ function tmp() {
8
+ return mkdtempSync(join(tmpdir(), "outlook-cursor-"));
9
+ }
10
+ function pathFor(dir, accountId) {
11
+ return join(dir, accountId, "secrets", "outlook", "sampler-cursors.json");
12
+ }
13
+ test("a mailbox with no cursor reads null", () => {
14
+ assert.equal(readCursor(tmp(), "acct-1", "a@example.com"), null);
15
+ });
16
+ test("a written cursor reads back for that mailbox only", () => {
17
+ const dir = tmp();
18
+ writeCursor(dir, "acct-1", "a@example.com", {
19
+ newestReceivedAt: "2026-08-13T09:00:00Z",
20
+ idsAtNewest: ["id-1"],
21
+ });
22
+ assert.deepEqual(readCursor(dir, "acct-1", "a@example.com"), {
23
+ newestReceivedAt: "2026-08-13T09:00:00Z",
24
+ idsAtNewest: ["id-1"],
25
+ });
26
+ assert.equal(readCursor(dir, "acct-1", "b@example.com"), null);
27
+ });
28
+ test("a second mailbox's write preserves the first", () => {
29
+ const dir = tmp();
30
+ writeCursor(dir, "acct-1", "a@example.com", {
31
+ newestReceivedAt: "2026-08-13T09:00:00Z",
32
+ idsAtNewest: ["id-1"],
33
+ });
34
+ writeCursor(dir, "acct-1", "b@example.com", {
35
+ newestReceivedAt: "2026-08-13T10:00:00Z",
36
+ idsAtNewest: ["id-2"],
37
+ });
38
+ assert.equal(readCursor(dir, "acct-1", "a@example.com")?.newestReceivedAt, "2026-08-13T09:00:00Z");
39
+ assert.equal(readCursor(dir, "acct-1", "b@example.com")?.newestReceivedAt, "2026-08-13T10:00:00Z");
40
+ });
41
+ test("a second account's cursors are a separate file", () => {
42
+ const dir = tmp();
43
+ writeCursor(dir, "acct-1", "a@example.com", {
44
+ newestReceivedAt: "2026-08-13T09:00:00Z",
45
+ idsAtNewest: [],
46
+ });
47
+ assert.equal(readCursor(dir, "acct-2", "a@example.com"), null);
48
+ });
49
+ test("the mailbox key is case- and whitespace-insensitive", () => {
50
+ const dir = tmp();
51
+ writeCursor(dir, "acct-1", " A@Example.com ", {
52
+ newestReceivedAt: "2026-08-13T09:00:00Z",
53
+ idsAtNewest: [],
54
+ });
55
+ assert.ok(readCursor(dir, "acct-1", "a@example.com"));
56
+ });
57
+ test("the cursor file is written 0600 and holds the mailbox key", () => {
58
+ const dir = tmp();
59
+ writeCursor(dir, "acct-1", "a@example.com", {
60
+ newestReceivedAt: "2026-08-13T09:00:00Z",
61
+ idsAtNewest: [],
62
+ });
63
+ const path = pathFor(dir, "acct-1");
64
+ assert.equal(statSync(path).mode & 0o777, 0o600);
65
+ assert.ok(Object.hasOwn(JSON.parse(readFileSync(path, "utf-8")), "a@example.com"));
66
+ });
67
+ test("an unparseable cursor file reads as no cursor rather than throwing", () => {
68
+ const dir = tmp();
69
+ writeCursor(dir, "acct-1", "a@example.com", {
70
+ newestReceivedAt: "2026-08-13T09:00:00Z",
71
+ idsAtNewest: [],
72
+ });
73
+ writeFileSync(pathFor(dir, "acct-1"), "{not json");
74
+ assert.equal(readCursor(dir, "acct-1", "a@example.com"), null);
75
+ });
76
+ test("an entry with no instant reads as no cursor", () => {
77
+ const dir = tmp();
78
+ writeCursor(dir, "acct-1", "a@example.com", {
79
+ newestReceivedAt: "2026-08-13T09:00:00Z",
80
+ idsAtNewest: [],
81
+ });
82
+ writeFileSync(pathFor(dir, "acct-1"), JSON.stringify({ "a@example.com": { idsAtNewest: [] } }));
83
+ assert.equal(readCursor(dir, "acct-1", "a@example.com"), null);
84
+ });
85
+ test("an entry with no id list reads as an empty exclusion set", () => {
86
+ const dir = tmp();
87
+ writeCursor(dir, "acct-1", "a@example.com", {
88
+ newestReceivedAt: "2026-08-13T09:00:00Z",
89
+ idsAtNewest: [],
90
+ });
91
+ writeFileSync(pathFor(dir, "acct-1"), JSON.stringify({ "a@example.com": { newestReceivedAt: "2026-08-13T09:00:00Z" } }));
92
+ assert.deepEqual(readCursor(dir, "acct-1", "a@example.com")?.idsAtNewest, []);
93
+ });
94
+ test("an inherited property name is not read as a stored cursor", () => {
95
+ const dir = tmp();
96
+ writeCursor(dir, "acct-1", "a@example.com", {
97
+ newestReceivedAt: "2026-08-13T09:00:00Z",
98
+ idsAtNewest: [],
99
+ });
100
+ assert.equal(readCursor(dir, "acct-1", "constructor"), null);
101
+ });
102
+ //# sourceMappingURL=sampler-cursor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampler-cursor.test.js","sourceRoot":"","sources":["../../src/__tests__/sampler-cursor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sampler-enumerate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampler-enumerate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sampler-enumerate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { TokenStore } from "../auth/token-store.js";
7
+ import { DelegatedStore } from "../auth/delegated-store.js";
8
+ import { censusLine, enumerateSampleableMailboxes } from "../sampler/enumerate.js";
9
+ const ACCT = "11111111-2222-3333-4444-555555555555";
10
+ const ACCT_B = "99999999-8888-7777-6666-555555555555";
11
+ function tmp() {
12
+ return mkdtempSync(join(tmpdir(), "outlook-enum-"));
13
+ }
14
+ /** A provisioned account is a UUID directory holding a parseable account.json. */
15
+ function provision(dir, accountId) {
16
+ mkdirSync(join(dir, accountId), { recursive: true });
17
+ writeFileSync(join(dir, accountId, "account.json"), JSON.stringify({ accountId }));
18
+ }
19
+ function connect(dir, accountId, graphUserId, mail) {
20
+ new TokenStore(accountId, dir, graphUserId).store("access", "refresh", 3600, {
21
+ graphUserId,
22
+ mail,
23
+ scopes: ["Mail.Read"],
24
+ });
25
+ }
26
+ test("an absent accounts dir enumerates nothing", () => {
27
+ const dir = join(tmp(), "absent");
28
+ assert.deepEqual(enumerateSampleableMailboxes(dir), { sampleable: [], skipped: [], accounts: 0 });
29
+ });
30
+ test("a signed-in mailbox is sampleable with the /me prefix", () => {
31
+ const dir = tmp();
32
+ provision(dir, ACCT);
33
+ connect(dir, ACCT, "guid-1", "a@example.com");
34
+ const { sampleable, skipped } = enumerateSampleableMailboxes(dir);
35
+ assert.deepEqual(skipped, []);
36
+ assert.deepEqual(sampleable, [
37
+ {
38
+ accountId: ACCT,
39
+ mailbox: "a@example.com",
40
+ mailboxKey: "guid-1",
41
+ pathPrefix: "/me",
42
+ via: null,
43
+ },
44
+ ]);
45
+ });
46
+ test("a directory with no account.json is not a provisioned account", () => {
47
+ const dir = tmp();
48
+ connect(dir, ACCT, "guid-1", "a@example.com");
49
+ assert.deepEqual(enumerateSampleableMailboxes(dir).sampleable, []);
50
+ });
51
+ test("a non-UUID directory name is not a provisioned account", () => {
52
+ const dir = tmp();
53
+ provision(dir, "not-a-uuid");
54
+ connect(dir, "not-a-uuid", "guid-1", "a@example.com");
55
+ assert.deepEqual(enumerateSampleableMailboxes(dir).sampleable, []);
56
+ });
57
+ test("every provisioned account is enumerated", () => {
58
+ const dir = tmp();
59
+ provision(dir, ACCT);
60
+ provision(dir, ACCT_B);
61
+ connect(dir, ACCT, "guid-1", "a@example.com");
62
+ connect(dir, ACCT_B, "guid-2", "b@example.com");
63
+ const boxes = enumerateSampleableMailboxes(dir).sampleable.map((m) => m.mailbox).sort();
64
+ assert.deepEqual(boxes, ["a@example.com", "b@example.com"]);
65
+ });
66
+ test("a delegated mailbox is sampleable through its delegator's prefix", () => {
67
+ const dir = tmp();
68
+ provision(dir, ACCT);
69
+ connect(dir, ACCT, "guid-1", "a@example.com");
70
+ new DelegatedStore(ACCT, dir).add("shared@example.com", "guid-1", 1);
71
+ const { sampleable } = enumerateSampleableMailboxes(dir);
72
+ const shared = sampleable.find((m) => m.mailbox === "shared@example.com");
73
+ assert.deepEqual(shared, {
74
+ accountId: ACCT,
75
+ mailbox: "shared@example.com",
76
+ mailboxKey: "guid-1",
77
+ pathPrefix: `/users/${encodeURIComponent("shared@example.com")}`,
78
+ via: "a@example.com",
79
+ });
80
+ });
81
+ test("a delegated record whose delegator is gone is skipped with a reason", () => {
82
+ const dir = tmp();
83
+ provision(dir, ACCT);
84
+ new DelegatedStore(ACCT, dir).add("shared@example.com", "guid-missing", 1);
85
+ const { sampleable, skipped } = enumerateSampleableMailboxes(dir);
86
+ assert.deepEqual(sampleable, []);
87
+ assert.equal(skipped.length, 1);
88
+ assert.equal(skipped[0].mailbox, "shared@example.com");
89
+ assert.match(skipped[0].reason, /delegator-missing/);
90
+ });
91
+ test("a mailbox with a blank email is skipped, never sampled", () => {
92
+ const dir = tmp();
93
+ provision(dir, ACCT);
94
+ connect(dir, ACCT, "guid-2", null);
95
+ const { sampleable, skipped } = enumerateSampleableMailboxes(dir);
96
+ assert.deepEqual(sampleable, []);
97
+ assert.equal(skipped.length, 1);
98
+ assert.match(skipped[0].reason, /blank-email/);
99
+ });
100
+ test("an account with no outlook mailboxes contributes nothing", () => {
101
+ const dir = tmp();
102
+ provision(dir, ACCT);
103
+ // The account IS walked; it simply holds no mailbox. `accounts: 1` is what
104
+ // separates that from an accountsDir that resolved nowhere.
105
+ assert.deepEqual(enumerateSampleableMailboxes(dir), { sampleable: [], skipped: [], accounts: 1 });
106
+ });
107
+ test("the census is emitted with zeros when nothing is connected", () => {
108
+ const dir = tmp();
109
+ provision(dir, ACCT);
110
+ // The guarantee: an install with no Outlook mailbox still says so. Silence
111
+ // here would be indistinguishable from the arm never running.
112
+ assert.equal(censusLine(enumerateSampleableMailboxes(dir)), "op=sample-census provider=outlook accounts=1 mailboxes=0 delegated=0 skipped=0");
113
+ });
114
+ test("the census counts an absent accounts dir as zero accounts", () => {
115
+ assert.equal(censusLine(enumerateSampleableMailboxes(join(tmp(), "absent"))), "op=sample-census provider=outlook accounts=0 mailboxes=0 delegated=0 skipped=0");
116
+ });
117
+ test("the census separates delegated mailboxes from signed-in ones", () => {
118
+ const dir = tmp();
119
+ provision(dir, ACCT);
120
+ connect(dir, ACCT, "guid-1", "a@example.com");
121
+ new DelegatedStore(ACCT, dir).add("shared@example.com", "guid-1", 1);
122
+ new DelegatedStore(ACCT, dir).add("orphan@example.com", "guid-missing", 1);
123
+ assert.equal(censusLine(enumerateSampleableMailboxes(dir)), "op=sample-census provider=outlook accounts=1 mailboxes=2 delegated=1 skipped=1");
124
+ });
125
+ //# sourceMappingURL=sampler-enumerate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampler-enumerate.test.js","sourceRoot":"","sources":["../../src/__tests__/sampler-enumerate.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAEnF,MAAM,IAAI,GAAG,sCAAsC,CAAC;AACpD,MAAM,MAAM,GAAG,sCAAsC,CAAC;AAEtD,SAAS,GAAG;IACV,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,kFAAkF;AAClF,SAAS,SAAS,CAAC,GAAW,EAAE,SAAiB;IAC/C,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,OAAO,CAAC,GAAW,EAAE,SAAiB,EAAE,WAAmB,EAAE,IAAmB;IACvF,IAAI,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;QAC3E,WAAW;QACX,IAAI;QACJ,MAAM,EAAE,CAAC,WAAW,CAAC;KACtB,CAAC,CAAC;AACL,CAAC;AAED,IAAI,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClC,MAAM,CAAC,SAAS,CAAC,4BAA4B,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;AACpG,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACjE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE;QAC3B;YACE,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,KAAK;YACjB,GAAG,EAAE,IAAI;SACV;KACF,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+DAA+D,EAAE,GAAG,EAAE;IACzE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,MAAM,CAAC,SAAS,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;IAClE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IACtD,MAAM,CAAC,SAAS,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACnD,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACxF,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAC5E,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,IAAI,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,oBAAoB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACrE,MAAM,EAAE,UAAU,EAAE,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,oBAAoB,CAAC,CAAC;IAC1E,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;QACvB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,oBAAoB;QAC7B,UAAU,EAAE,QAAQ;QACpB,UAAU,EAAE,UAAU,kBAAkB,CAAC,oBAAoB,CAAC,EAAE;QAChE,GAAG,EAAE,eAAe;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,GAAG,EAAE;IAC/E,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,IAAI,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,oBAAoB,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAC3E,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACvD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;IAClE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACpE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,2EAA2E;IAC3E,4DAA4D;IAC5D,MAAM,CAAC,SAAS,CAAC,4BAA4B,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;AACpG,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,GAAG,EAAE;IACtE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,CAAC,KAAK,CACV,UAAU,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC,EAC7C,gFAAgF,CACjF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;IACrE,MAAM,CAAC,KAAK,CACV,UAAU,CAAC,4BAA4B,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,EAC/D,gFAAgF,CACjF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8DAA8D,EAAE,GAAG,EAAE;IACxE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC9C,IAAI,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,oBAAoB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACrE,IAAI,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,oBAAoB,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,CACV,UAAU,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC,EAC7C,gFAAgF,CACjF,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runOutlookArm(log: (line: string) => void): Promise<void>;
2
+ //# sourceMappingURL=arm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arm.d.ts","sourceRoot":"","sources":["../../src/sampler/arm.ts"],"names":[],"mappings":"AA8DA,wBAAsB,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE9E"}