botmux 2.33.0 → 2.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/README.en.md +12 -1
  2. package/README.md +45 -1
  3. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  4. package/dist/adapters/cli/claude-code.js +11 -0
  5. package/dist/adapters/cli/claude-code.js.map +1 -1
  6. package/dist/cli/bots-list-output.d.ts +21 -0
  7. package/dist/cli/bots-list-output.d.ts.map +1 -0
  8. package/dist/cli/bots-list-output.js +23 -0
  9. package/dist/cli/bots-list-output.js.map +1 -0
  10. package/dist/cli/workflow.d.ts +13 -0
  11. package/dist/cli/workflow.d.ts.map +1 -0
  12. package/dist/cli/workflow.js +781 -0
  13. package/dist/cli/workflow.js.map +1 -0
  14. package/dist/cli.js +69 -14
  15. package/dist/cli.js.map +1 -1
  16. package/dist/core/command-handler.d.ts.map +1 -1
  17. package/dist/core/command-handler.js +219 -6
  18. package/dist/core/command-handler.js.map +1 -1
  19. package/dist/core/session-manager.d.ts +6 -1
  20. package/dist/core/session-manager.d.ts.map +1 -1
  21. package/dist/core/session-manager.js +22 -12
  22. package/dist/core/session-manager.js.map +1 -1
  23. package/dist/core/worker-pool.d.ts +13 -0
  24. package/dist/core/worker-pool.d.ts.map +1 -1
  25. package/dist/core/worker-pool.js +100 -6
  26. package/dist/core/worker-pool.js.map +1 -1
  27. package/dist/daemon.d.ts +3 -0
  28. package/dist/daemon.d.ts.map +1 -1
  29. package/dist/daemon.js +884 -3
  30. package/dist/daemon.js.map +1 -1
  31. package/dist/dashboard/auth.d.ts +36 -0
  32. package/dist/dashboard/auth.d.ts.map +1 -1
  33. package/dist/dashboard/auth.js +22 -0
  34. package/dist/dashboard/auth.js.map +1 -1
  35. package/dist/dashboard/web/app.js +20 -1
  36. package/dist/dashboard/web/app.js.map +1 -1
  37. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  38. package/dist/dashboard/web/i18n.js +356 -0
  39. package/dist/dashboard/web/i18n.js.map +1 -1
  40. package/dist/dashboard/web/workflow-catalog.d.ts +2 -0
  41. package/dist/dashboard/web/workflow-catalog.d.ts.map +1 -0
  42. package/dist/dashboard/web/workflow-catalog.js +323 -0
  43. package/dist/dashboard/web/workflow-catalog.js.map +1 -0
  44. package/dist/dashboard/web/workflows.d.ts +2 -0
  45. package/dist/dashboard/web/workflows.d.ts.map +1 -0
  46. package/dist/dashboard/web/workflows.js +1618 -0
  47. package/dist/dashboard/web/workflows.js.map +1 -0
  48. package/dist/dashboard/workflow-api.d.ts +23 -0
  49. package/dist/dashboard/workflow-api.d.ts.map +1 -0
  50. package/dist/dashboard/workflow-api.js +463 -0
  51. package/dist/dashboard/workflow-api.js.map +1 -0
  52. package/dist/dashboard-web/app.js +494 -199
  53. package/dist/dashboard-web/index.html +1 -0
  54. package/dist/dashboard-web/style.css +160 -6
  55. package/dist/dashboard-web/terminal-replay.html +227 -0
  56. package/dist/dashboard.js +29 -12
  57. package/dist/dashboard.js.map +1 -1
  58. package/dist/i18n/en.d.ts.map +1 -1
  59. package/dist/i18n/en.js +12 -0
  60. package/dist/i18n/en.js.map +1 -1
  61. package/dist/i18n/zh.d.ts.map +1 -1
  62. package/dist/i18n/zh.js +12 -0
  63. package/dist/i18n/zh.js.map +1 -1
  64. package/dist/im/lark/card-handler.d.ts +3 -0
  65. package/dist/im/lark/card-handler.d.ts.map +1 -1
  66. package/dist/im/lark/card-handler.js +27 -1
  67. package/dist/im/lark/card-handler.js.map +1 -1
  68. package/dist/im/lark/client.d.ts +19 -2
  69. package/dist/im/lark/client.d.ts.map +1 -1
  70. package/dist/im/lark/client.js +21 -2
  71. package/dist/im/lark/client.js.map +1 -1
  72. package/dist/im/lark/workflow-card-handler.d.ts +50 -0
  73. package/dist/im/lark/workflow-card-handler.d.ts.map +1 -0
  74. package/dist/im/lark/workflow-card-handler.js +152 -0
  75. package/dist/im/lark/workflow-card-handler.js.map +1 -0
  76. package/dist/im/lark/workflow-cards.d.ts +46 -0
  77. package/dist/im/lark/workflow-cards.d.ts.map +1 -0
  78. package/dist/im/lark/workflow-cards.js +226 -0
  79. package/dist/im/lark/workflow-cards.js.map +1 -0
  80. package/dist/im/lark/workflow-progress-card.d.ts +76 -0
  81. package/dist/im/lark/workflow-progress-card.d.ts.map +1 -0
  82. package/dist/im/lark/workflow-progress-card.js +279 -0
  83. package/dist/im/lark/workflow-progress-card.js.map +1 -0
  84. package/dist/im/lark/workflow-slash-command.d.ts +92 -0
  85. package/dist/im/lark/workflow-slash-command.d.ts.map +1 -0
  86. package/dist/im/lark/workflow-slash-command.js +185 -0
  87. package/dist/im/lark/workflow-slash-command.js.map +1 -0
  88. package/dist/services/group-creator.d.ts.map +1 -1
  89. package/dist/services/group-creator.js +17 -4
  90. package/dist/services/group-creator.js.map +1 -1
  91. package/dist/services/groups-store.d.ts +11 -0
  92. package/dist/services/groups-store.d.ts.map +1 -1
  93. package/dist/services/groups-store.js +26 -0
  94. package/dist/services/groups-store.js.map +1 -1
  95. package/dist/services/jsonl-cursor.d.ts +12 -0
  96. package/dist/services/jsonl-cursor.d.ts.map +1 -0
  97. package/dist/services/jsonl-cursor.js +45 -0
  98. package/dist/services/jsonl-cursor.js.map +1 -0
  99. package/dist/services/schedule-store.d.ts +35 -0
  100. package/dist/services/schedule-store.d.ts.map +1 -1
  101. package/dist/services/schedule-store.js +108 -1
  102. package/dist/services/schedule-store.js.map +1 -1
  103. package/dist/skills/definitions.d.ts.map +1 -1
  104. package/dist/skills/definitions.js +399 -0
  105. package/dist/skills/definitions.js.map +1 -1
  106. package/dist/types.d.ts +4 -0
  107. package/dist/types.d.ts.map +1 -1
  108. package/dist/utils/cli-usage-limit.d.ts.map +1 -1
  109. package/dist/utils/cli-usage-limit.js +4 -0
  110. package/dist/utils/cli-usage-limit.js.map +1 -1
  111. package/dist/worker.js +118 -14
  112. package/dist/worker.js.map +1 -1
  113. package/dist/workflows/attempt-resume.d.ts +114 -0
  114. package/dist/workflows/attempt-resume.d.ts.map +1 -0
  115. package/dist/workflows/attempt-resume.js +385 -0
  116. package/dist/workflows/attempt-resume.js.map +1 -0
  117. package/dist/workflows/attempt-terminal.d.ts +21 -0
  118. package/dist/workflows/attempt-terminal.d.ts.map +1 -0
  119. package/dist/workflows/attempt-terminal.js +7 -0
  120. package/dist/workflows/attempt-terminal.js.map +1 -0
  121. package/dist/workflows/blob.d.ts +27 -0
  122. package/dist/workflows/blob.d.ts.map +1 -0
  123. package/dist/workflows/blob.js +39 -0
  124. package/dist/workflows/blob.js.map +1 -0
  125. package/dist/workflows/cancel-run.d.ts +45 -0
  126. package/dist/workflows/cancel-run.d.ts.map +1 -0
  127. package/dist/workflows/cancel-run.js +99 -0
  128. package/dist/workflows/cancel-run.js.map +1 -0
  129. package/dist/workflows/cancel.d.ts +111 -0
  130. package/dist/workflows/cancel.d.ts.map +1 -0
  131. package/dist/workflows/cancel.js +120 -0
  132. package/dist/workflows/cancel.js.map +1 -0
  133. package/dist/workflows/catalog.d.ts +60 -0
  134. package/dist/workflows/catalog.d.ts.map +1 -0
  135. package/dist/workflows/catalog.js +119 -0
  136. package/dist/workflows/catalog.js.map +1 -0
  137. package/dist/workflows/cold-attach.d.ts +30 -0
  138. package/dist/workflows/cold-attach.d.ts.map +1 -0
  139. package/dist/workflows/cold-attach.js +40 -0
  140. package/dist/workflows/cold-attach.js.map +1 -0
  141. package/dist/workflows/cold-scan.d.ts +21 -0
  142. package/dist/workflows/cold-scan.d.ts.map +1 -0
  143. package/dist/workflows/cold-scan.js +70 -0
  144. package/dist/workflows/cold-scan.js.map +1 -0
  145. package/dist/workflows/daemon-spawn.d.ts +117 -0
  146. package/dist/workflows/daemon-spawn.d.ts.map +1 -0
  147. package/dist/workflows/daemon-spawn.js +551 -0
  148. package/dist/workflows/daemon-spawn.js.map +1 -0
  149. package/dist/workflows/definition.d.ts +1309 -0
  150. package/dist/workflows/definition.d.ts.map +1 -0
  151. package/dist/workflows/definition.js +334 -0
  152. package/dist/workflows/definition.js.map +1 -0
  153. package/dist/workflows/effect-input.d.ts +4 -0
  154. package/dist/workflows/effect-input.d.ts.map +1 -0
  155. package/dist/workflows/effect-input.js +18 -0
  156. package/dist/workflows/effect-input.js.map +1 -0
  157. package/dist/workflows/events/append.d.ts +77 -0
  158. package/dist/workflows/events/append.d.ts.map +1 -0
  159. package/dist/workflows/events/append.js +214 -0
  160. package/dist/workflows/events/append.js.map +1 -0
  161. package/dist/workflows/events/idempotency.d.ts +77 -0
  162. package/dist/workflows/events/idempotency.d.ts.map +1 -0
  163. package/dist/workflows/events/idempotency.js +116 -0
  164. package/dist/workflows/events/idempotency.js.map +1 -0
  165. package/dist/workflows/events/index.d.ts +7 -0
  166. package/dist/workflows/events/index.d.ts.map +1 -0
  167. package/dist/workflows/events/index.js +7 -0
  168. package/dist/workflows/events/index.js.map +1 -0
  169. package/dist/workflows/events/payloads.d.ts +917 -0
  170. package/dist/workflows/events/payloads.d.ts.map +1 -0
  171. package/dist/workflows/events/payloads.js +337 -0
  172. package/dist/workflows/events/payloads.js.map +1 -0
  173. package/dist/workflows/events/replay.d.ts +238 -0
  174. package/dist/workflows/events/replay.d.ts.map +1 -0
  175. package/dist/workflows/events/replay.js +608 -0
  176. package/dist/workflows/events/replay.js.map +1 -0
  177. package/dist/workflows/events/schema.d.ts +5242 -0
  178. package/dist/workflows/events/schema.d.ts.map +1 -0
  179. package/dist/workflows/events/schema.js +295 -0
  180. package/dist/workflows/events/schema.js.map +1 -0
  181. package/dist/workflows/events/types.d.ts +34 -0
  182. package/dist/workflows/events/types.d.ts.map +1 -0
  183. package/dist/workflows/events/types.js +2 -0
  184. package/dist/workflows/events/types.js.map +1 -0
  185. package/dist/workflows/fanout.d.ts +36 -0
  186. package/dist/workflows/fanout.d.ts.map +1 -0
  187. package/dist/workflows/fanout.js +114 -0
  188. package/dist/workflows/fanout.js.map +1 -0
  189. package/dist/workflows/hostExecutors/botmux-schedule.d.ts +41 -0
  190. package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -0
  191. package/dist/workflows/hostExecutors/botmux-schedule.js +121 -0
  192. package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -0
  193. package/dist/workflows/hostExecutors/feishu-im.d.ts +12 -0
  194. package/dist/workflows/hostExecutors/feishu-im.d.ts.map +1 -0
  195. package/dist/workflows/hostExecutors/feishu-im.js +49 -0
  196. package/dist/workflows/hostExecutors/feishu-im.js.map +1 -0
  197. package/dist/workflows/hostExecutors/feishu-reply.d.ts +24 -0
  198. package/dist/workflows/hostExecutors/feishu-reply.d.ts.map +1 -0
  199. package/dist/workflows/hostExecutors/feishu-reply.js +88 -0
  200. package/dist/workflows/hostExecutors/feishu-reply.js.map +1 -0
  201. package/dist/workflows/hostExecutors/feishu-send.d.ts +23 -0
  202. package/dist/workflows/hostExecutors/feishu-send.d.ts.map +1 -0
  203. package/dist/workflows/hostExecutors/feishu-send.js +124 -0
  204. package/dist/workflows/hostExecutors/feishu-send.js.map +1 -0
  205. package/dist/workflows/hostExecutors/index.d.ts +8 -0
  206. package/dist/workflows/hostExecutors/index.d.ts.map +1 -0
  207. package/dist/workflows/hostExecutors/index.js +8 -0
  208. package/dist/workflows/hostExecutors/index.js.map +1 -0
  209. package/dist/workflows/hostExecutors/protocol.d.ts +42 -0
  210. package/dist/workflows/hostExecutors/protocol.d.ts.map +1 -0
  211. package/dist/workflows/hostExecutors/protocol.js +181 -0
  212. package/dist/workflows/hostExecutors/protocol.js.map +1 -0
  213. package/dist/workflows/hostExecutors/registry.d.ts +10 -0
  214. package/dist/workflows/hostExecutors/registry.d.ts.map +1 -0
  215. package/dist/workflows/hostExecutors/registry.js +36 -0
  216. package/dist/workflows/hostExecutors/registry.js.map +1 -0
  217. package/dist/workflows/hostExecutors/types.d.ts +78 -0
  218. package/dist/workflows/hostExecutors/types.d.ts.map +1 -0
  219. package/dist/workflows/hostExecutors/types.js +2 -0
  220. package/dist/workflows/hostExecutors/types.js.map +1 -0
  221. package/dist/workflows/loader.d.ts +16 -0
  222. package/dist/workflows/loader.d.ts.map +1 -0
  223. package/dist/workflows/loader.js +56 -0
  224. package/dist/workflows/loader.js.map +1 -0
  225. package/dist/workflows/loop.d.ts +50 -0
  226. package/dist/workflows/loop.d.ts.map +1 -0
  227. package/dist/workflows/loop.js +350 -0
  228. package/dist/workflows/loop.js.map +1 -0
  229. package/dist/workflows/ops-projection.d.ts +168 -0
  230. package/dist/workflows/ops-projection.d.ts.map +1 -0
  231. package/dist/workflows/ops-projection.js +707 -0
  232. package/dist/workflows/ops-projection.js.map +1 -0
  233. package/dist/workflows/orchestrator.d.ts +107 -0
  234. package/dist/workflows/orchestrator.d.ts.map +1 -0
  235. package/dist/workflows/orchestrator.js +197 -0
  236. package/dist/workflows/orchestrator.js.map +1 -0
  237. package/dist/workflows/output-binding.d.ts +70 -0
  238. package/dist/workflows/output-binding.d.ts.map +1 -0
  239. package/dist/workflows/output-binding.js +265 -0
  240. package/dist/workflows/output-binding.js.map +1 -0
  241. package/dist/workflows/params.d.ts +61 -0
  242. package/dist/workflows/params.d.ts.map +1 -0
  243. package/dist/workflows/params.js +195 -0
  244. package/dist/workflows/params.js.map +1 -0
  245. package/dist/workflows/resume.d.ts +263 -0
  246. package/dist/workflows/resume.d.ts.map +1 -0
  247. package/dist/workflows/resume.js +808 -0
  248. package/dist/workflows/resume.js.map +1 -0
  249. package/dist/workflows/run-id.d.ts +2 -0
  250. package/dist/workflows/run-id.d.ts.map +1 -0
  251. package/dist/workflows/run-id.js +7 -0
  252. package/dist/workflows/run-id.js.map +1 -0
  253. package/dist/workflows/run-init.d.ts +48 -0
  254. package/dist/workflows/run-init.d.ts.map +1 -0
  255. package/dist/workflows/run-init.js +99 -0
  256. package/dist/workflows/run-init.js.map +1 -0
  257. package/dist/workflows/runs-dir.d.ts +4 -0
  258. package/dist/workflows/runs-dir.d.ts.map +1 -0
  259. package/dist/workflows/runs-dir.js +15 -0
  260. package/dist/workflows/runs-dir.js.map +1 -0
  261. package/dist/workflows/runtime.d.ts +211 -0
  262. package/dist/workflows/runtime.d.ts.map +1 -0
  263. package/dist/workflows/runtime.js +594 -0
  264. package/dist/workflows/runtime.js.map +1 -0
  265. package/dist/workflows/spawn-bot.d.ts +165 -0
  266. package/dist/workflows/spawn-bot.d.ts.map +1 -0
  267. package/dist/workflows/spawn-bot.js +215 -0
  268. package/dist/workflows/spawn-bot.js.map +1 -0
  269. package/dist/workflows/system.d.ts +49 -0
  270. package/dist/workflows/system.d.ts.map +1 -0
  271. package/dist/workflows/system.js +48 -0
  272. package/dist/workflows/system.js.map +1 -0
  273. package/dist/workflows/trigger-run.d.ts +70 -0
  274. package/dist/workflows/trigger-run.d.ts.map +1 -0
  275. package/dist/workflows/trigger-run.js +88 -0
  276. package/dist/workflows/trigger-run.js.map +1 -0
  277. package/dist/workflows/wait.d.ts +120 -0
  278. package/dist/workflows/wait.d.ts.map +1 -0
  279. package/dist/workflows/wait.js +181 -0
  280. package/dist/workflows/wait.js.map +1 -0
  281. package/package.json +3 -3
@@ -0,0 +1,181 @@
1
+ import { writeJsonBlob } from '../blob.js';
2
+ import { computeInputHash, deriveIdempotencyKey } from '../events/idempotency.js';
3
+ // ─── Public API ─────────────────────────────────────────────────────────────
4
+ /**
5
+ * Drive the side-effecting protocol for one attempt (events doc v0.1.2
6
+ * §2.3, §4.3). Writes three events in order:
7
+ *
8
+ * 1. `effectAttempted` — written **before** invoking the provider so a
9
+ * crash mid-call leaves a dangling intent that resume can reconcile.
10
+ * 2. provider invocation (via `executor.invoke`).
11
+ * 3. `activitySucceeded` OR `activityFailed` — terminal event for this
12
+ * attempt; carries `externalRefs` on success or classified error on
13
+ * failure.
14
+ *
15
+ * The protocol does NOT write `attemptCreated/leaseSigned/activityRunning`
16
+ * — those are the scheduler/worker layer's responsibility. This function
17
+ * assumes the caller has already advanced the activity to `running`.
18
+ *
19
+ * The protocol does NOT do retry/backoff — that's the scheduler's job
20
+ * (Step 7+). A failed invocation is reported via `ok: false` and the
21
+ * caller decides whether to spawn a new `attemptCreated`.
22
+ *
23
+ * Idempotency contract:
24
+ * - `idempotencyKey` is deterministic per attempt (5-tuple hash), so
25
+ * re-running the same attempt with the same input produces the same
26
+ * uuid → Feishu/schedule provider returns the original ref.
27
+ * - `inputHash` is recorded for the resume path to detect attempt
28
+ * mutability violations (Step 7). This function doesn't enforce
29
+ * immutability across calls — Step 7 reads recorded inputHash and
30
+ * fails if a future attempt re-derives a different one.
31
+ */
32
+ export async function executeSideEffect(ctx, input, executor) {
33
+ const idempotencyKey = deriveIdempotencyKey({
34
+ workflowId: ctx.workflowId,
35
+ revisionId: ctx.revisionId,
36
+ runId: ctx.runId,
37
+ nodeId: ctx.nodeId,
38
+ attemptId: ctx.attemptId,
39
+ });
40
+ const inputHash = computeInputHash(executor.canonicalInput(input));
41
+ // 1. effectAttempted — written BEFORE invoking the provider so a crash
42
+ // mid-call leaves a dangling effectAttempted for resume to reconcile.
43
+ await ctx.log.append({
44
+ runId: ctx.runId,
45
+ type: 'effectAttempted',
46
+ actor: 'hostExecutor',
47
+ payload: {
48
+ activityId: ctx.activityId,
49
+ attemptId: ctx.attemptId,
50
+ idempotencyKey,
51
+ inputHash,
52
+ idempotencyTtlMs: executor.idempotencyTtlMs,
53
+ provider: executor.provider,
54
+ },
55
+ });
56
+ // 2. provider invocation
57
+ try {
58
+ const { output, externalRefs } = await executor.invoke(input, idempotencyKey);
59
+ // 3a. activitySucceeded. outputRef points at a real JSON blob
60
+ // `{ output, externalRefs }` so dashboard / CLI show / reconcile
61
+ // evidence can inspect the full provider response without
62
+ // replaying events. We keep `externalRefs` on the event payload
63
+ // too — replay/reconciler reads it without touching disk.
64
+ //
65
+ // Non-plain-JSON outputs (Date, Map, Set, Buffer, BigInt,
66
+ // function) are rejected here so they fall through the same
67
+ // classifier path as a provider crash. Executors must return
68
+ // plain JSON-serializable values; silently coercing a Date to
69
+ // `{}` would corrupt the audit trail.
70
+ assertJsonPlain(output, 'output');
71
+ assertJsonPlain(externalRefs, 'externalRefs');
72
+ const outputRef = await writeJsonBlob(ctx.log, { output, externalRefs });
73
+ const successEvent = (await ctx.log.append({
74
+ runId: ctx.runId,
75
+ type: 'activitySucceeded',
76
+ actor: 'hostExecutor',
77
+ payload: {
78
+ activityId: ctx.activityId,
79
+ attemptId: ctx.attemptId,
80
+ outputRef,
81
+ externalRefs,
82
+ },
83
+ }));
84
+ return { ok: true, event: successEvent, output, externalRefs };
85
+ }
86
+ catch (err) {
87
+ // 3b. activityFailed. Map via the executor's classifier when
88
+ // present; default to UnknownProviderError/manual (codex round 2
89
+ // — TTL/unknown failures need human resolution, not silent retry).
90
+ const classification = executor.classifyError?.(err) ?? defaultClassification(err);
91
+ // Truncate uniformly — protects against custom classifiers that
92
+ // return long messages (e.g. dumping a full provider response).
93
+ const safeMessage = truncateMessage(classification.errorMessage);
94
+ const failedEvent = (await ctx.log.append({
95
+ runId: ctx.runId,
96
+ type: 'activityFailed',
97
+ actor: 'hostExecutor',
98
+ payload: {
99
+ activityId: ctx.activityId,
100
+ attemptId: ctx.attemptId,
101
+ error: {
102
+ errorCode: classification.errorCode,
103
+ errorClass: classification.errorClass,
104
+ errorMessage: safeMessage,
105
+ },
106
+ },
107
+ }));
108
+ return {
109
+ ok: false,
110
+ event: failedEvent,
111
+ error: { ...classification, errorMessage: safeMessage },
112
+ };
113
+ }
114
+ }
115
+ // ─── Helpers ────────────────────────────────────────────────────────────────
116
+ /**
117
+ * Error-message truncation budget. The schema bound is 4096 (events doc
118
+ * §3.3), but the envelope payload also has to fit `INLINE_PAYLOAD_MAX_BYTES`
119
+ * (4096) total — so a 4096-char message alone would overflow the event
120
+ * envelope cap after JSON encoding + other fields. Truncate to leave
121
+ * headroom; large error bodies should be written to a stackRef blob.
122
+ */
123
+ const ERROR_MESSAGE_MAX_CHARS = 2048;
124
+ function truncateMessage(msg) {
125
+ return msg.length > ERROR_MESSAGE_MAX_CHARS
126
+ ? msg.slice(0, ERROR_MESSAGE_MAX_CHARS - 3) + '...'
127
+ : msg;
128
+ }
129
+ function defaultClassification(err) {
130
+ const msg = err instanceof Error ? err.message : String(err);
131
+ return {
132
+ errorCode: 'UnknownProviderError',
133
+ errorClass: 'manual',
134
+ errorMessage: truncateMessage(msg),
135
+ };
136
+ }
137
+ /**
138
+ * Reject non-plain-JSON values before they reach `writeJsonBlob`, where
139
+ * `canonicalJsonStringify` would silently coerce a Date / Map / Set into
140
+ * `{}`. Path-prefixed error messages so the classifier can surface
141
+ * which field tripped it.
142
+ */
143
+ function assertJsonPlain(value, path) {
144
+ if (value === null)
145
+ return;
146
+ const t = typeof value;
147
+ if (t === 'string' || t === 'number' || t === 'boolean' || t === 'undefined') {
148
+ // `undefined` is JSON-omitted, not a serialization failure — only
149
+ // reject the explicitly hostile types below.
150
+ return;
151
+ }
152
+ if (t === 'bigint') {
153
+ throw new Error(`hostExecutor output not JSON-serializable at ${path}: BigInt`);
154
+ }
155
+ if (t === 'function' || t === 'symbol') {
156
+ throw new Error(`hostExecutor output not JSON-serializable at ${path}: ${t}`);
157
+ }
158
+ if (value instanceof Date) {
159
+ throw new Error(`hostExecutor output not JSON-serializable at ${path}: Date (use .toISOString() string)`);
160
+ }
161
+ if (value instanceof Map || value instanceof Set) {
162
+ throw new Error(`hostExecutor output not JSON-serializable at ${path}: ${value.constructor.name}`);
163
+ }
164
+ if (Buffer.isBuffer(value) || ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
165
+ throw new Error(`hostExecutor output not JSON-serializable at ${path}: binary buffer`);
166
+ }
167
+ if (Array.isArray(value)) {
168
+ value.forEach((v, i) => assertJsonPlain(v, `${path}[${i}]`));
169
+ return;
170
+ }
171
+ const obj = value;
172
+ const proto = Object.getPrototypeOf(obj);
173
+ if (proto !== Object.prototype && proto !== null) {
174
+ const ctorName = obj.constructor?.name ?? 'unknown';
175
+ throw new Error(`hostExecutor output not JSON-serializable at ${path}: non-plain object (${ctorName})`);
176
+ }
177
+ for (const [k, v] of Object.entries(obj)) {
178
+ assertJsonPlain(v, `${path}.${k}`);
179
+ }
180
+ }
181
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/workflows/hostExecutors/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ProviderReconciler } from '../resume.js';
2
+ import type { SideEffectingExecutor } from './types.js';
3
+ export type RegisteredHostExecutor<Input = unknown, Output = unknown> = {
4
+ executor: SideEffectingExecutor<Input, Output>;
5
+ parseInput(input: unknown): Input;
6
+ };
7
+ export type HostExecutorRegistry = Map<string, RegisteredHostExecutor>;
8
+ export declare function createDefaultHostExecutorRegistry(): HostExecutorRegistry;
9
+ export declare function createDefaultProviderReconcilers(): Map<string, ProviderReconciler>;
10
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/workflows/hostExecutors/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAevD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI;IACtE,QAAQ,EAAE,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC/C,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;AAEvE,wBAAgB,iCAAiC,IAAI,oBAAoB,CAwBxE;AAED,wBAAgB,gCAAgC,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAKlF"}
@@ -0,0 +1,36 @@
1
+ import { botmuxScheduleExecutor, botmuxScheduleReconciler, parseScheduleInput, } from './botmux-schedule.js';
2
+ import { feishuSendExecutor, parseFeishuSendInput, } from './feishu-send.js';
3
+ import { feishuReplyExecutor, parseFeishuReplyInput, } from './feishu-reply.js';
4
+ import { feishuImReconciler } from './feishu-im.js';
5
+ export function createDefaultHostExecutorRegistry() {
6
+ return new Map([
7
+ [
8
+ 'botmux-schedule',
9
+ {
10
+ executor: botmuxScheduleExecutor,
11
+ parseInput: parseScheduleInput,
12
+ },
13
+ ],
14
+ [
15
+ 'feishu-send',
16
+ {
17
+ executor: feishuSendExecutor,
18
+ parseInput: parseFeishuSendInput,
19
+ },
20
+ ],
21
+ [
22
+ 'feishu-reply',
23
+ {
24
+ executor: feishuReplyExecutor,
25
+ parseInput: parseFeishuReplyInput,
26
+ },
27
+ ],
28
+ ]);
29
+ }
30
+ export function createDefaultProviderReconcilers() {
31
+ return new Map([
32
+ [botmuxScheduleReconciler.provider, botmuxScheduleReconciler],
33
+ [feishuImReconciler.provider, feishuImReconciler],
34
+ ]);
35
+ }
36
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/workflows/hostExecutors/registry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUpD,MAAM,UAAU,iCAAiC;IAC/C,OAAO,IAAI,GAAG,CAAC;QACb;YACE,iBAAiB;YACjB;gBACE,QAAQ,EAAE,sBAAsB;gBAChC,UAAU,EAAE,kBAAkB;aACE;SACnC;QACD;YACE,aAAa;YACb;gBACE,QAAQ,EAAE,kBAAkB;gBAC5B,UAAU,EAAE,oBAAoB;aACA;SACnC;QACD;YACE,cAAc;YACd;gBACE,QAAQ,EAAE,mBAAmB;gBAC7B,UAAU,EAAE,qBAAqB;aACD;SACnC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gCAAgC;IAC9C,OAAO,IAAI,GAAG,CAAC;QACb,CAAC,wBAAwB,CAAC,QAAQ,EAAE,wBAAwB,CAAC;QAC7D,CAAC,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,CAAC;KAClD,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,78 @@
1
+ import type { EventLog } from '../events/append.js';
2
+ import type { ErrorClass, ErrorCode } from '../events/payloads.js';
3
+ /**
4
+ * Runtime context handed to every hostExecutor invocation. The caller
5
+ * (workflow scheduler/worker) is responsible for already having written:
6
+ * - `attemptCreated` (with this `nodeId/activityId/attemptId`)
7
+ * - `leaseSigned`
8
+ * - `activityRunning`
9
+ * before invoking the side-effect protocol. This context only needs the
10
+ * tuple required to derive `idempotencyKey` plus the event log handle so
11
+ * the protocol can record its 3 events (`effectAttempted`,
12
+ * `activitySucceeded`/`activityFailed`).
13
+ */
14
+ export type HostExecutorContext = {
15
+ log: EventLog;
16
+ runId: string;
17
+ workflowId: string;
18
+ revisionId: string;
19
+ nodeId: string;
20
+ activityId: string;
21
+ attemptId: string;
22
+ };
23
+ /**
24
+ * Classified executor error. Executors that can give precise error codes
25
+ * (Feishu 230011 etc.) return a typed result; everything else falls back
26
+ * to `UnknownProviderError` / `manual` (events doc v0.1.2 §3.3).
27
+ */
28
+ export type ExecutorErrorClassification = {
29
+ errorCode: ErrorCode;
30
+ errorClass: ErrorClass;
31
+ /** Human-readable detail; truncated to 4KB upstream. */
32
+ errorMessage: string;
33
+ };
34
+ /**
35
+ * A side-effecting hostExecutor (send / reply / schedule in v0). Pure
36
+ * executors (transform / bots / history / quoted / sub-agent) have a
37
+ * separate interface in `pure.ts` because they skip `effectAttempted`.
38
+ */
39
+ export interface SideEffectingExecutor<Input, Output> {
40
+ /** Identifier embedded in `effectAttempted.provider`. */
41
+ readonly provider: string;
42
+ /**
43
+ * Provider TTL. Feeds `effectAttempted.idempotencyTtlMs` and the
44
+ * resume reconciler's TTL-vs-manual decision (events doc §4.3.1).
45
+ */
46
+ readonly idempotencyTtlMs: number;
47
+ /**
48
+ * Convert the typed `Input` into the canonical shape that's hashed
49
+ * into `effectAttempted.inputHash`. Codex round 2 / 4 invariant: this
50
+ * MUST include every field that participates in the external effect
51
+ * (e.g. for Feishu reply: `receive_id`, `root_message_id`, `msg_type`,
52
+ * `content`) so that retries can detect input drift.
53
+ */
54
+ canonicalInput(input: Input): unknown;
55
+ /**
56
+ * Invoke the provider. `idempotencyKey` is the runtime-derived
57
+ * dedupe token (≤ 50 chars) that callers should forward to the
58
+ * provider's idempotency knob (Feishu uuid / schedule task id).
59
+ */
60
+ invoke(input: Input, idempotencyKey: string): Promise<{
61
+ output: Output;
62
+ /**
63
+ * Provider-returned identifiers stored in
64
+ * `activitySucceeded.externalRefs`. Type-specific (send/reply →
65
+ * `{ messageId }`, schedule → `{ taskId }`).
66
+ */
67
+ externalRefs: Record<string, unknown>;
68
+ }>;
69
+ /**
70
+ * Map an `invoke` error to an event-typed error. Returning `null`
71
+ * (or omitting the method) falls back to the protocol default:
72
+ * `{ UnknownProviderError, manual }`.
73
+ * Codex round 2: TTL-class errors are `manual` (need human resolution),
74
+ * lease/worker/network errors stay `retryable`.
75
+ */
76
+ classifyError?(err: unknown): ExecutorErrorClassification | null;
77
+ }
78
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/workflows/hostExecutors/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,qBAAqB,CAAC,KAAK,EAAE,MAAM;IAClD,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC;;;;;;OAMG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC;IAEtC;;;;OAIG;IACH,MAAM,CACJ,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf;;;;WAIG;QACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvC,CAAC,CAAC;IAEH;;;;;;OAMG;IACH,aAAa,CAAC,CAAC,GAAG,EAAE,OAAO,GAAG,2BAA2B,GAAG,IAAI,CAAC;CAClE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/workflows/hostExecutors/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { type WorkflowDefinition } from './definition.js';
2
+ export type RunChatBinding = {
3
+ chatId: string;
4
+ larkAppId: string;
5
+ };
6
+ type RunFileOptions = {
7
+ runDir?: string;
8
+ runsDir?: string;
9
+ };
10
+ export declare function workflowDefinitionSearchPaths(workflowId: string): string[];
11
+ export declare function loadWorkflowDefinition(workflowId: string): Promise<WorkflowDefinition>;
12
+ export declare function snapshotWorkflowDefinition(runId: string, def: WorkflowDefinition, opts?: RunFileOptions): Promise<string>;
13
+ export declare function writeRunChatBinding(runId: string, binding: RunChatBinding, opts?: RunFileOptions): Promise<string>;
14
+ export declare function readRunChatBinding(runId: string, opts?: RunFileOptions): Promise<RunChatBinding>;
15
+ export {};
16
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/workflows/loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAM1E;AAED,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkB5F;AAED,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,kBAAkB,EACvB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,cAAc,EACvB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,cAAc,CAAC,CASzB"}
@@ -0,0 +1,56 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { canonicalJsonStringify, parseWorkflowDefinition, } from './definition.js';
4
+ import { ensureRunDir } from './runs-dir.js';
5
+ export function workflowDefinitionSearchPaths(workflowId) {
6
+ const home = process.env.HOME;
7
+ return [
8
+ join(process.cwd(), 'workflows', `${workflowId}.workflow.json`),
9
+ join(home ?? '', '.botmux', 'workflows', `${workflowId}.workflow.json`),
10
+ ];
11
+ }
12
+ export async function loadWorkflowDefinition(workflowId) {
13
+ const paths = workflowDefinitionSearchPaths(workflowId);
14
+ for (const path of paths) {
15
+ try {
16
+ const raw = await fs.readFile(path, 'utf-8');
17
+ return parseWorkflowDefinition(JSON.parse(raw));
18
+ }
19
+ catch (err) {
20
+ if (err.code === 'ENOENT')
21
+ continue;
22
+ throw new Error(`Failed to load workflow '${workflowId}' from ${path}: ${err instanceof Error ? err.message : String(err)}`);
23
+ }
24
+ }
25
+ throw new Error(`Workflow '${workflowId}' not found. Looked in:\n${paths.map((p) => `- ${p}`).join('\n')}`);
26
+ }
27
+ export async function snapshotWorkflowDefinition(runId, def, opts = {}) {
28
+ const dir = await getOrEnsureRunDir(runId, opts);
29
+ const path = join(dir, 'workflow.json');
30
+ await fs.writeFile(path, canonicalJsonStringify(def), 'utf-8');
31
+ return path;
32
+ }
33
+ export async function writeRunChatBinding(runId, binding, opts = {}) {
34
+ const dir = await getOrEnsureRunDir(runId, opts);
35
+ const path = join(dir, 'chat-binding.json');
36
+ await fs.writeFile(path, JSON.stringify(binding, null, 2), 'utf-8');
37
+ return path;
38
+ }
39
+ export async function readRunChatBinding(runId, opts = {}) {
40
+ const dir = await getOrEnsureRunDir(runId, opts);
41
+ const path = join(dir, 'chat-binding.json');
42
+ const raw = await fs.readFile(path, 'utf-8');
43
+ const parsed = JSON.parse(raw);
44
+ if (!parsed.chatId || !parsed.larkAppId) {
45
+ throw new Error(`Invalid workflow chat binding at ${path}`);
46
+ }
47
+ return { chatId: parsed.chatId, larkAppId: parsed.larkAppId };
48
+ }
49
+ async function getOrEnsureRunDir(runId, opts) {
50
+ if (opts.runDir) {
51
+ await fs.mkdir(opts.runDir, { recursive: true });
52
+ return opts.runDir;
53
+ }
54
+ return ensureRunDir(runId, opts.runsDir);
55
+ }
56
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/workflows/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Orchestrator loop runner.
3
+ *
4
+ * Drives `decideNextActions → dispatch* → replay → repeat` until either
5
+ * the run reaches a terminal status or the orchestrator returns no
6
+ * actions (which on a non-terminal run means we're paused on an open
7
+ * `waitCreated`).
8
+ *
9
+ * Per-tick dispatch model (v0.1.3+):
10
+ * 1. Split ready actions into `dispatch*` (gate / work) and `complete*`
11
+ * (settle node / run). The two phases have different concurrency
12
+ * semantics — dispatch can race, settles must not.
13
+ * 2. Within the dispatch phase: cap concurrency by `defaults.maxConcurrency`
14
+ * (default 4) and enforce per-bot serialization (one in-flight subagent
15
+ * per bot within a tick). Deferred dispatches just stay in the next
16
+ * tick's ready set; no separate scheduling state needed.
17
+ * 3. Run dispatches via `Promise.allSettled` so a sibling throwing doesn't
18
+ * starve the rest. After settle, replay fresh and patch any non-terminal
19
+ * activity with an `activityFailed` (errorClass=fatal, errorCode=
20
+ * WorkerCrashed; closest fit in the existing enum — see payloads.ts) —
21
+ * but NEVER write a second terminal if the dispatch already wrote one
22
+ * before throwing. If a dispatch throws BEFORE writing `attemptCreated`,
23
+ * we have no attempt to attach the failure to; the tick returns
24
+ * `no-progress` rather than re-dispatching the same action forever.
25
+ * 4. Settle actions (`completeNode*` / `completeRun*`) run sequentially so
26
+ * event log order stays readable and `completeRun*` is never racy.
27
+ *
28
+ * Re-entry: external events (e.g. `waitResolved` written by the lark
29
+ * card handler) don't drive this loop — the caller is responsible for
30
+ * invoking `runLoop` again when it knows new events have landed. See
31
+ * `src/workflows/fanout.ts` (Slice D-4) for the daemon-side trigger.
32
+ */
33
+ import { type Snapshot } from './events/replay.js';
34
+ import { type WorkflowRuntimeContext } from './runtime.js';
35
+ export type RunLoopStopReason = 'terminal' | 'awaiting-wait' | 'no-progress' | 'max-ticks';
36
+ export type RunLoopResult = {
37
+ reason: RunLoopStopReason;
38
+ ticks: number;
39
+ lastSnapshot: Snapshot;
40
+ };
41
+ export type RunLoopOptions = {
42
+ /**
43
+ * Defensive cap on tick count. A correctly modeled workflow with N
44
+ * nodes terminates in O(N) ticks; the cap exists to keep buggy
45
+ * orchestrator output from spinning forever. Default 1000.
46
+ */
47
+ maxTicks?: number;
48
+ };
49
+ export declare function runLoop(ctx: WorkflowRuntimeContext, options?: RunLoopOptions): Promise<RunLoopResult>;
50
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/workflows/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAQH,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAQL,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAStB,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,eAAe,GACf,aAAa,GACb,WAAW,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,QAAQ,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,OAAO,CAC3B,GAAG,EAAE,sBAAsB,EAC3B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CA4KxB"}