@k2b/cloud 0.6.0-rc.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 (540) hide show
  1. package/README.md +98 -0
  2. package/package.json +128 -0
  3. package/public/logo.svg +1 -0
  4. package/scripts/app-favicon.test.ts +49 -0
  5. package/scripts/app-favicon.ts +51 -0
  6. package/scripts/build.ts +205 -0
  7. package/scripts/preload.ts +164 -0
  8. package/scripts/sync-recovery-smoke.ts +200 -0
  9. package/src/_internal/app-favicon.ts +2 -0
  10. package/src/_internal/app-presentation.ts +61 -0
  11. package/src/_internal/app-workspace-state.ts +24 -0
  12. package/src/_internal/bounded-json.ts +47 -0
  13. package/src/_internal/build-metadata.ts +9 -0
  14. package/src/_internal/capabilities.ts +1118 -0
  15. package/src/_internal/define-app.ts +801 -0
  16. package/src/_internal/heartbeat.ts +167 -0
  17. package/src/_internal/help-catalog.ts +241 -0
  18. package/src/_internal/help.ts +95 -0
  19. package/src/_internal/nats-connection.ts +34 -0
  20. package/src/_internal/page-responses.ts +40 -0
  21. package/src/_internal/process-sync.ts +117 -0
  22. package/src/_internal/readiness.ts +3 -0
  23. package/src/_internal/registry-validation.ts +136 -0
  24. package/src/_internal/registry-watch.ts +52 -0
  25. package/src/_internal/registry.ts +338 -0
  26. package/src/_internal/runtime-compatibility.ts +64 -0
  27. package/src/_internal/runtime-context.ts +84 -0
  28. package/src/_internal/runtime-watcher.ts +78 -0
  29. package/src/_internal/static-assets.ts +86 -0
  30. package/src/_internal/status-preserving-ssr.ts +49 -0
  31. package/src/access/PermissionEditor.tsx +486 -0
  32. package/src/access/ResourceApiKeys.tsx +271 -0
  33. package/src/access/messages.ts +121 -0
  34. package/src/access/ui.ts +16 -0
  35. package/src/account/Avatar.tsx +28 -0
  36. package/src/account/EntitySearch.tsx +363 -0
  37. package/src/account/avatar-upload-dialog.tsx +197 -0
  38. package/src/account/avatar-upload.ts +149 -0
  39. package/src/account/ui.ts +3 -0
  40. package/src/ai/admin.ts +47 -0
  41. package/src/ai/approval-routes.ts +130 -0
  42. package/src/ai/approvals.ts +139 -0
  43. package/src/ai/assistant-models.ts +61 -0
  44. package/src/ai/attachments.ts +40 -0
  45. package/src/ai/browser.ts +92 -0
  46. package/src/ai/capabilities.ts +714 -0
  47. package/src/ai/capability-execution.ts +151 -0
  48. package/src/ai/chat/blocks.render.test.tsx +1108 -0
  49. package/src/ai/chat/blocks.tsx +730 -0
  50. package/src/ai/chat/builtin-tools.tsx +428 -0
  51. package/src/ai/chat/capability-table.tsx +87 -0
  52. package/src/ai/chat/composer-adapter.ts +169 -0
  53. package/src/ai/chat/file-tools.tsx +81 -0
  54. package/src/ai/chat/message-actions.tsx +370 -0
  55. package/src/ai/chat/message-utils.ts +479 -0
  56. package/src/ai/chat/messages.ts +43 -0
  57. package/src/ai/chat/presentation.tsx +395 -0
  58. package/src/ai/chat/primitives.tsx +3 -0
  59. package/src/ai/chat/tool-disclosure.tsx +41 -0
  60. package/src/ai/chat/turn-navigator-utils.ts +28 -0
  61. package/src/ai/chat/turn-navigator.tsx +164 -0
  62. package/src/ai/chat/user-message.tsx +149 -0
  63. package/src/ai/chat/visual-tools.tsx +435 -0
  64. package/src/ai/chat/web-tools.tsx +202 -0
  65. package/src/ai/chat-task-contracts.ts +113 -0
  66. package/src/ai/chat-tasks.ts +952 -0
  67. package/src/ai/client/controller.ts +1211 -0
  68. package/src/ai/client/file-source.ts +95 -0
  69. package/src/ai/client/live-connection.ts +140 -0
  70. package/src/ai/client/projection.ts +178 -0
  71. package/src/ai/client/transport.ts +111 -0
  72. package/src/ai/compaction.ts +182 -0
  73. package/src/ai/credentials.ts +124 -0
  74. package/src/ai/default-tool-contracts.ts +108 -0
  75. package/src/ai/default-tools.ts +127 -0
  76. package/src/ai/enrich.ts +280 -0
  77. package/src/ai/executor.ts +1624 -0
  78. package/src/ai/fetch-file-tool.ts +313 -0
  79. package/src/ai/file-context.ts +92 -0
  80. package/src/ai/file-media-type.ts +28 -0
  81. package/src/ai/file-mount.ts +16 -0
  82. package/src/ai/file-tools.ts +566 -0
  83. package/src/ai/files-store.ts +390 -0
  84. package/src/ai/firecrawl-tools.ts +305 -0
  85. package/src/ai/grids-skill.ts +126 -0
  86. package/src/ai/http.ts +265 -0
  87. package/src/ai/index.ts +337 -0
  88. package/src/ai/kit-skill.ts +22 -0
  89. package/src/ai/limits.ts +5 -0
  90. package/src/ai/live-events.ts +289 -0
  91. package/src/ai/live-messages.ts +45 -0
  92. package/src/ai/live-outbox.ts +102 -0
  93. package/src/ai/live-routes.ts +412 -0
  94. package/src/ai/live.ts +2 -0
  95. package/src/ai/maintenance.ts +302 -0
  96. package/src/ai/markdown-pdf-tool.ts +95 -0
  97. package/src/ai/memories.ts +605 -0
  98. package/src/ai/memory-learning-runs.ts +222 -0
  99. package/src/ai/memory-learning.ts +619 -0
  100. package/src/ai/memory-tool.ts +120 -0
  101. package/src/ai/memory-workflow-evidence.ts +158 -0
  102. package/src/ai/migrate.ts +2082 -0
  103. package/src/ai/model-access-migrate.ts +30 -0
  104. package/src/ai/model-access.ts +191 -0
  105. package/src/ai/personal-agent.ts +6 -0
  106. package/src/ai/prefs.ts +72 -0
  107. package/src/ai/project-tool.ts +94 -0
  108. package/src/ai/projects-routes.ts +277 -0
  109. package/src/ai/projects.ts +902 -0
  110. package/src/ai/protocol.ts +279 -0
  111. package/src/ai/provider.ts +73 -0
  112. package/src/ai/public-projection.ts +25 -0
  113. package/src/ai/resource-markers.ts +31 -0
  114. package/src/ai/resource-refs.ts +70 -0
  115. package/src/ai/routes.ts +1131 -0
  116. package/src/ai/runtime-tools.ts +39 -0
  117. package/src/ai/runtime.ts +544 -0
  118. package/src/ai/settings.ts +529 -0
  119. package/src/ai/short-id.ts +45 -0
  120. package/src/ai/skill-catalog.ts +73 -0
  121. package/src/ai/skill-format.ts +145 -0
  122. package/src/ai/skill-seeds.ts +430 -0
  123. package/src/ai/skill-tool.ts +81 -0
  124. package/src/ai/skills-routes.ts +143 -0
  125. package/src/ai/skills.ts +934 -0
  126. package/src/ai/solid.ts +27 -0
  127. package/src/ai/store.ts +3113 -0
  128. package/src/ai/stream.ts +308 -0
  129. package/src/ai/structured-runs.ts +66 -0
  130. package/src/ai/structured.ts +186 -0
  131. package/src/ai/system-prompt.ts +170 -0
  132. package/src/ai/task-prompt.ts +22 -0
  133. package/src/ai/timeline.ts +148 -0
  134. package/src/ai/tool-audit.ts +177 -0
  135. package/src/ai/tool-result-budget.ts +16 -0
  136. package/src/ai/tools.ts +155 -0
  137. package/src/ai/types.ts +967 -0
  138. package/src/ai/ui.tsx +39 -0
  139. package/src/ai/usage-migrate.ts +81 -0
  140. package/src/ai/usage.ts +315 -0
  141. package/src/ai/validate.ts +54 -0
  142. package/src/ai/vision-tool.ts +79 -0
  143. package/src/api/accounts-entities.ts +174 -0
  144. package/src/api/admin-ai-projects.ts +74 -0
  145. package/src/api/admin-ai-skills.ts +76 -0
  146. package/src/api/admin-ai-usage.ts +42 -0
  147. package/src/api/admin-core-settings.ts +508 -0
  148. package/src/api/admin-identity.ts +148 -0
  149. package/src/api/admin-lifecycle.ts +206 -0
  150. package/src/api/admin-linux-identities.ts +66 -0
  151. package/src/api/announcements.ts +131 -0
  152. package/src/api/app-approval.ts +129 -0
  153. package/src/api/apps.ts +51 -0
  154. package/src/api/auth/schemas.ts +54 -0
  155. package/src/api/auth.ts +370 -0
  156. package/src/api/capabilities.ts +658 -0
  157. package/src/api/help-messages.ts +19 -0
  158. package/src/api/help.ts +78 -0
  159. package/src/api/index.ts +108 -0
  160. package/src/api/mcp.ts +744 -0
  161. package/src/api/me-rail.ts +45 -0
  162. package/src/api/me.ts +753 -0
  163. package/src/api/search/schemas.ts +79 -0
  164. package/src/api/search.bench.ts +185 -0
  165. package/src/api/search.ts +407 -0
  166. package/src/api/sync-ops.ts +79 -0
  167. package/src/api/widgets.ts +143 -0
  168. package/src/browser/CloudResourceSearch.behavior.test.tsx +74 -0
  169. package/src/browser/CloudResourceSearch.tsx +791 -0
  170. package/src/browser/app-approval-vault.ts +305 -0
  171. package/src/browser/app-approval.ts +234 -0
  172. package/src/browser/live-websocket.ts +268 -0
  173. package/src/browser/locale-preference.ts +25 -0
  174. package/src/browser/notification-target.ts +27 -0
  175. package/src/browser/notification-timeout.ts +14 -0
  176. package/src/browser/notifications.ts +181 -0
  177. package/src/browser/resource-clipboard.ts +70 -0
  178. package/src/browser/resource-picker.tsx +39 -0
  179. package/src/browser/resource-search-messages.ts +55 -0
  180. package/src/browser/resource-search.ts +27 -0
  181. package/src/capabilities/client.ts +149 -0
  182. package/src/capabilities/response.ts +39 -0
  183. package/src/capabilities/server.ts +215 -0
  184. package/src/capabilities/signals.ts +4 -0
  185. package/src/capabilities/testing.ts +12 -0
  186. package/src/capabilities/types.ts +32 -0
  187. package/src/cli/access.ts +499 -0
  188. package/src/cli/account.ts +382 -0
  189. package/src/cli/admin/account-administration.ts +45 -0
  190. package/src/cli/admin/account-categories.ts +49 -0
  191. package/src/cli/admin/ai-usage.ts +118 -0
  192. package/src/cli/admin/app-sign-in.ts +49 -0
  193. package/src/cli/admin/data.ts +343 -0
  194. package/src/cli/admin/documentation.ts +34 -0
  195. package/src/cli/admin/gateway.ts +155 -0
  196. package/src/cli/admin/index.ts +61 -0
  197. package/src/cli/admin/instance.ts +250 -0
  198. package/src/cli/admin/jobs.ts +223 -0
  199. package/src/cli/admin/legal.ts +122 -0
  200. package/src/cli/admin/linux.ts +53 -0
  201. package/src/cli/admin/logs.ts +324 -0
  202. package/src/cli/admin/metrics.ts +142 -0
  203. package/src/cli/admin/nats.ts +167 -0
  204. package/src/cli/admin/notifications.ts +516 -0
  205. package/src/cli/admin/shared.ts +113 -0
  206. package/src/cli/admin/sync.ts +188 -0
  207. package/src/cli/admin/telemetry.ts +314 -0
  208. package/src/cli/admin/webhooks.ts +222 -0
  209. package/src/cli/admin/workflows.ts +367 -0
  210. package/src/cli/apps.ts +40 -0
  211. package/src/cli/capabilities.ts +239 -0
  212. package/src/cli/commands.ts +604 -0
  213. package/src/cli/index.ts +61 -0
  214. package/src/cli/locale.ts +31 -0
  215. package/src/cli/output.ts +58 -0
  216. package/src/clients/core.ts +20 -0
  217. package/src/config/env.ts +54 -0
  218. package/src/config/index.ts +6 -0
  219. package/src/contracts/account-categories.ts +62 -0
  220. package/src/contracts/announcements.ts +121 -0
  221. package/src/contracts/app-approval.ts +197 -0
  222. package/src/contracts/app.ts +162 -0
  223. package/src/contracts/capabilities.ts +484 -0
  224. package/src/contracts/index.ts +14 -0
  225. package/src/contracts/notification-live.ts +66 -0
  226. package/src/contracts/notification-types.ts +235 -0
  227. package/src/contracts/posix.ts +69 -0
  228. package/src/contracts/profile.ts +85 -0
  229. package/src/contracts/rail-preferences.ts +53 -0
  230. package/src/contracts/registry.ts +110 -0
  231. package/src/contracts/resource-clipboard.ts +33 -0
  232. package/src/contracts/settings-types.ts +98 -0
  233. package/src/contracts/shared.ts +408 -0
  234. package/src/contracts/user-notifications.ts +101 -0
  235. package/src/contracts/widgets.ts +183 -0
  236. package/src/desktop/index.ts +704 -0
  237. package/src/desktop/solid.tsx +938 -0
  238. package/src/index.ts +58 -0
  239. package/src/server/actor.ts +41 -0
  240. package/src/server/api/index.ts +2 -0
  241. package/src/server/api/respond.ts +96 -0
  242. package/src/server/api-client.ts +54 -0
  243. package/src/server/app-context.ts +39 -0
  244. package/src/server/help.ts +187 -0
  245. package/src/server/index.ts +89 -0
  246. package/src/server/locale.ts +55 -0
  247. package/src/server/middleware/auth.ts +386 -0
  248. package/src/server/middleware/index.ts +28 -0
  249. package/src/server/middleware/invocation.ts +55 -0
  250. package/src/server/middleware/middleware.ts +65 -0
  251. package/src/server/middleware/openapi.ts +126 -0
  252. package/src/server/middleware/rate-limit.ts +125 -0
  253. package/src/server/middleware/request-logger.ts +41 -0
  254. package/src/server/middleware/route-template.ts +46 -0
  255. package/src/server/middleware/runtime.ts +22 -0
  256. package/src/server/middleware/settings.ts +55 -0
  257. package/src/server/middleware/validator.ts +49 -0
  258. package/src/server/middleware/workload.ts +22 -0
  259. package/src/server/ratelimit.ts +151 -0
  260. package/src/server/request-cookies.ts +18 -0
  261. package/src/server/services/access.ts +644 -0
  262. package/src/server/services/freeipa/client.ts +137 -0
  263. package/src/server/services/freeipa/index.ts +9 -0
  264. package/src/server/services/freeipa/session.ts +123 -0
  265. package/src/server/services/freeipa/test-certificates.ts +44 -0
  266. package/src/server/services/freeipa/tls.ts +44 -0
  267. package/src/server/services/freeipa/transport.ts +116 -0
  268. package/src/server/services/freeipa/util.ts +59 -0
  269. package/src/server/services/geo.ts +198 -0
  270. package/src/server/services/index.ts +48 -0
  271. package/src/server/services/pagination.ts +22 -0
  272. package/src/server/services/services.ts +13 -0
  273. package/src/server/time.ts +33 -0
  274. package/src/services/account-category-policy.ts +51 -0
  275. package/src/services/account-lifecycle/audit.ts +41 -0
  276. package/src/services/account-lifecycle/index.ts +940 -0
  277. package/src/services/account-lifecycle/ipa-backfill.ts +152 -0
  278. package/src/services/account-lifecycle/notification-sender.ts +13 -0
  279. package/src/services/account-lifecycle/scheduler.ts +506 -0
  280. package/src/services/account-model.ts +22 -0
  281. package/src/services/accounts/app.ts +1671 -0
  282. package/src/services/accounts/authz.ts +44 -0
  283. package/src/services/accounts/avatar.ts +120 -0
  284. package/src/services/accounts/base-group.ts +11 -0
  285. package/src/services/accounts/base-user.ts +46 -0
  286. package/src/services/accounts/duplicate-emails.ts +82 -0
  287. package/src/services/accounts/entities.ts +622 -0
  288. package/src/services/accounts/group-sql.ts +106 -0
  289. package/src/services/accounts/groups.ts +272 -0
  290. package/src/services/accounts/index.ts +14 -0
  291. package/src/services/accounts/ipa-data.ts +66 -0
  292. package/src/services/accounts/lifecycle.ts +2 -0
  293. package/src/services/accounts/local-groups.ts +499 -0
  294. package/src/services/accounts/model.ts +129 -0
  295. package/src/services/accounts/notification-sender.ts +31 -0
  296. package/src/services/accounts/posix.ts +386 -0
  297. package/src/services/accounts/request-policy.ts +11 -0
  298. package/src/services/accounts/switching.ts +126 -0
  299. package/src/services/accounts/users.ts +745 -0
  300. package/src/services/announcements/index.ts +224 -0
  301. package/src/services/app-approval.ts +498 -0
  302. package/src/services/audit/index.ts +438 -0
  303. package/src/services/auth-flows/index.ts +15 -0
  304. package/src/services/auth-flows/ipa.ts +197 -0
  305. package/src/services/auth-flows/magic-link.ts +185 -0
  306. package/src/services/auth-flows/notification-sender.ts +10 -0
  307. package/src/services/auth-flows/password-reset.ts +268 -0
  308. package/src/services/auth-flows/proxy-return.ts +49 -0
  309. package/src/services/document-extraction.ts +148 -0
  310. package/src/services/freeipa-config.ts +179 -0
  311. package/src/services/gateway.ts +186 -0
  312. package/src/services/identity/constants.ts +18 -0
  313. package/src/services/identity/index.ts +52 -0
  314. package/src/services/identity/invocation-actor.ts +120 -0
  315. package/src/services/identity/invocation-authority.ts +53 -0
  316. package/src/services/identity/invocation-operations.ts +15 -0
  317. package/src/services/identity/invocation-token.ts +276 -0
  318. package/src/services/identity/key-config.ts +41 -0
  319. package/src/services/identity/key-ring.ts +530 -0
  320. package/src/services/identity/metrics.ts +29 -0
  321. package/src/services/identity/routes.ts +18 -0
  322. package/src/services/identity/runtime-config.ts +88 -0
  323. package/src/services/identity/session-token.ts +152 -0
  324. package/src/services/identity/signer-refresh.ts +44 -0
  325. package/src/services/identity/workload-auth.ts +64 -0
  326. package/src/services/index.ts +187 -0
  327. package/src/services/ipa/auth.ts +216 -0
  328. package/src/services/ipa/connection.ts +57 -0
  329. package/src/services/ipa/effective-groups.ts +70 -0
  330. package/src/services/ipa/groups.ts +722 -0
  331. package/src/services/ipa/guard.ts +17 -0
  332. package/src/services/ipa/index.ts +17 -0
  333. package/src/services/ipa/posix.ts +19 -0
  334. package/src/services/ipa/profile.ts +132 -0
  335. package/src/services/ipa/runtime.ts +28 -0
  336. package/src/services/ipa/search.ts +154 -0
  337. package/src/services/ipa/service-account.ts +15 -0
  338. package/src/services/ipa/sync-planning.ts +100 -0
  339. package/src/services/ipa/sync.ts +862 -0
  340. package/src/services/ipa/users.ts +806 -0
  341. package/src/services/legal-consent.ts +76 -0
  342. package/src/services/logging/index.ts +477 -0
  343. package/src/services/logging/redaction.ts +20 -0
  344. package/src/services/logging/trace.ts +1231 -0
  345. package/src/services/mandates/index.ts +855 -0
  346. package/src/services/mandates/policy.ts +85 -0
  347. package/src/services/network-security.ts +31 -0
  348. package/src/services/notifications/batches.ts +722 -0
  349. package/src/services/notifications/browser.ts +252 -0
  350. package/src/services/notifications/catalog.ts +113 -0
  351. package/src/services/notifications/channels.ts +104 -0
  352. package/src/services/notifications/dispatcher.ts +139 -0
  353. package/src/services/notifications/email.ts +118 -0
  354. package/src/services/notifications/index.ts +633 -0
  355. package/src/services/notifications/live.ts +50 -0
  356. package/src/services/notifications/observability.ts +407 -0
  357. package/src/services/notifications/platform.ts +421 -0
  358. package/src/services/notifications/runtime.ts +120 -0
  359. package/src/services/notifications/user.ts +248 -0
  360. package/src/services/notifications/web-push-transport.ts +135 -0
  361. package/src/services/oauth-tokens.ts +209 -0
  362. package/src/services/outbox.ts +187 -0
  363. package/src/services/pdf/gotenberg.ts +290 -0
  364. package/src/services/pdf/index.ts +43 -0
  365. package/src/services/pdf/markdown.ts +209 -0
  366. package/src/services/pdf/template-preview.ts +122 -0
  367. package/src/services/postgres.ts +76 -0
  368. package/src/services/providers/index.ts +27 -0
  369. package/src/services/providers/local/auth.ts +51 -0
  370. package/src/services/providers/local/index.ts +4 -0
  371. package/src/services/providers/local/users.ts +263 -0
  372. package/src/services/rail-preferences.ts +27 -0
  373. package/src/services/runtime-lifecycle.ts +191 -0
  374. package/src/services/secrets.ts +10 -0
  375. package/src/services/service-account-credentials.ts +891 -0
  376. package/src/services/service-accounts.ts +184 -0
  377. package/src/services/session/index.ts +236 -0
  378. package/src/services/session/test-fixture.ts +18 -0
  379. package/src/services/session/user.ts +144 -0
  380. package/src/services/settings/api.ts +61 -0
  381. package/src/services/settings/app.ts +86 -0
  382. package/src/services/settings/core-settings.ts +796 -0
  383. package/src/services/settings/crypto.ts +69 -0
  384. package/src/services/settings/defaults.ts +374 -0
  385. package/src/services/settings/index.ts +215 -0
  386. package/src/services/settings/namespace.ts +9 -0
  387. package/src/services/settings/snapshot.ts +49 -0
  388. package/src/services/settings/store.ts +241 -0
  389. package/src/services/settings/templates.ts +4 -0
  390. package/src/services/sync-ops.ts +403 -0
  391. package/src/services/topic-cursor.ts +22 -0
  392. package/src/services/weather/forecast.ts +323 -0
  393. package/src/services/weather/geo.ts +119 -0
  394. package/src/services/weather/index.ts +67 -0
  395. package/src/services/weather/location.ts +24 -0
  396. package/src/services/weather/locations.ts +133 -0
  397. package/src/services/weather/migrate.ts +45 -0
  398. package/src/services/weather/settings.ts +66 -0
  399. package/src/services/weather/short-id.ts +57 -0
  400. package/src/services/weather/types.ts +61 -0
  401. package/src/services/weather/ui.ts +50 -0
  402. package/src/services/webauthn.ts +385 -0
  403. package/src/shared/account-action-notice.ts +70 -0
  404. package/src/shared/account-display.ts +15 -0
  405. package/src/shared/account-session.ts +15 -0
  406. package/src/shared/ai-platform-prompt.ts +134 -0
  407. package/src/shared/ai-usage.ts +49 -0
  408. package/src/shared/app-presentation.ts +48 -0
  409. package/src/shared/app-url.ts +12 -0
  410. package/src/shared/branding.ts +14 -0
  411. package/src/shared/capability-messages.ts +70 -0
  412. package/src/shared/email-html.ts +54 -0
  413. package/src/shared/format.ts +91 -0
  414. package/src/shared/help.ts +68 -0
  415. package/src/shared/icons.ts +400 -0
  416. package/src/shared/index.ts +54 -0
  417. package/src/shared/locale.ts +48 -0
  418. package/src/shared/login-method.ts +44 -0
  419. package/src/shared/markdown/client.ts +130 -0
  420. package/src/shared/markdown/extensions/code.ts +105 -0
  421. package/src/shared/markdown/extensions/guided-help.ts +100 -0
  422. package/src/shared/markdown/extensions/images.ts +79 -0
  423. package/src/shared/markdown/extensions/info-blocks.ts +97 -0
  424. package/src/shared/markdown/extensions/katex.ts +120 -0
  425. package/src/shared/markdown/extensions/links.ts +43 -0
  426. package/src/shared/markdown/extensions/mark.ts +48 -0
  427. package/src/shared/markdown/extensions/sub-sup.ts +60 -0
  428. package/src/shared/markdown/extensions/tables.ts +109 -0
  429. package/src/shared/markdown/extensions/task-list.ts +53 -0
  430. package/src/shared/markdown/formula.ts +1187 -0
  431. package/src/shared/markdown/index.ts +193 -0
  432. package/src/shared/markdown/shared.ts +36 -0
  433. package/src/shared/mock-cover.ts +130 -0
  434. package/src/shared/network-address.ts +106 -0
  435. package/src/shared/redirect.ts +56 -0
  436. package/src/shared/template-rendering.ts +140 -0
  437. package/src/shared/theme.ts +68 -0
  438. package/src/shared/time.ts +13 -0
  439. package/src/ssr/AdminLayout.tsx +53 -0
  440. package/src/ssr/AdminSidebar.tsx +50 -0
  441. package/src/ssr/AppLaunchpad.island.tsx +236 -0
  442. package/src/ssr/AppWorkspaceController.island.tsx +21 -0
  443. package/src/ssr/BrowserNotifications.island.tsx +135 -0
  444. package/src/ssr/GlobalAnnouncements.island.tsx +142 -0
  445. package/src/ssr/GlobalSearchDialog.behavior.test.tsx +96 -0
  446. package/src/ssr/GlobalSearchDialog.tsx +35 -0
  447. package/src/ssr/GlobalSearchHelpDialog.tsx +104 -0
  448. package/src/ssr/GlobalSearchTrigger.island.tsx +55 -0
  449. package/src/ssr/HotkeysHelpRail.island.tsx +55 -0
  450. package/src/ssr/Layout.render.test.tsx +148 -0
  451. package/src/ssr/Layout.tsx +292 -0
  452. package/src/ssr/LayoutBreadcrumbs.island.tsx +44 -0
  453. package/src/ssr/LayoutFooter.tsx +22 -0
  454. package/src/ssr/LayoutHeader.tsx +81 -0
  455. package/src/ssr/LayoutHelp.tsx +869 -0
  456. package/src/ssr/LayoutPreferences.island.tsx +36 -0
  457. package/src/ssr/LayoutRail.tsx +58 -0
  458. package/src/ssr/MinimalLayout.tsx +46 -0
  459. package/src/ssr/PageError.tsx +29 -0
  460. package/src/ssr/ProfilePreferences.island.tsx +92 -0
  461. package/src/ssr/RailApps.island.tsx +61 -0
  462. package/src/ssr/RailEditor.tsx +293 -0
  463. package/src/ssr/RegisteredHelpDocuments.island.tsx +3 -0
  464. package/src/ssr/TimezoneCookie.island.tsx +23 -0
  465. package/src/ssr/admin-active-link.ts +47 -0
  466. package/src/ssr/admin-navigation.ts +78 -0
  467. package/src/ssr/app-appearance.ts +23 -0
  468. package/src/ssr/app-navigation.ts +41 -0
  469. package/src/ssr/help-messages.ts +104 -0
  470. package/src/ssr/index.ts +14 -0
  471. package/src/ssr/islands/SearchBar.island.tsx +80 -0
  472. package/src/ssr/islands/index.ts +16 -0
  473. package/src/ssr/layout-context.ts +17 -0
  474. package/src/ssr/layout-help-markdown.ts +9 -0
  475. package/src/ssr/layout-help-navigation.ts +24 -0
  476. package/src/ssr/layout-help-url.ts +5 -0
  477. package/src/ssr/layout-runtime.ts +22 -0
  478. package/src/ssr/page-error-messages.ts +25 -0
  479. package/src/ssr/platform-messages.ts +135 -0
  480. package/src/ssr/preference-controller.ts +44 -0
  481. package/src/ssr/profile-preferences-messages.ts +29 -0
  482. package/src/ssr/rail-context.ts +21 -0
  483. package/src/ssr/rail-messages.ts +66 -0
  484. package/src/ssr/rail-navigation.ts +60 -0
  485. package/src/ssr/runtime.ts +31 -0
  486. package/src/ssr/url-filter.ts +127 -0
  487. package/src/styles/base-popover.css +36 -0
  488. package/src/styles/effects.css +851 -0
  489. package/src/styles/global.css +268 -0
  490. package/src/styles/input.css +58 -0
  491. package/src/styles/tokens.css +230 -0
  492. package/src/styles/utilities-buttons.css +405 -0
  493. package/src/styles/utilities-data.css +33 -0
  494. package/src/styles/utilities-feedback.css +232 -0
  495. package/src/styles/utilities-layout.css +603 -0
  496. package/src/styles/utilities-markdown-editor.css +525 -0
  497. package/src/styles/utilities-markdown-table.css +234 -0
  498. package/src/styles/utilities-navigation.css +1054 -0
  499. package/src/types/ambient.d.ts +24 -0
  500. package/src/workflows/ai/index.ts +17 -0
  501. package/src/workflows/ai/runtime.ts +286 -0
  502. package/src/workflows/ai/store.ts +314 -0
  503. package/src/workflows/ai/types.ts +111 -0
  504. package/src/workflows/ai-actions.ts +269 -0
  505. package/src/workflows/authoring.ts +88 -0
  506. package/src/workflows/builtins.ts +193 -0
  507. package/src/workflows/contracts.ts +280 -0
  508. package/src/workflows/definition.ts +334 -0
  509. package/src/workflows/editor.ts +113 -0
  510. package/src/workflows/index.ts +71 -0
  511. package/src/workflows/language/binder.ts +45 -0
  512. package/src/workflows/language/canonical.ts +29 -0
  513. package/src/workflows/language/compiler.ts +396 -0
  514. package/src/workflows/language/expressions.ts +34 -0
  515. package/src/workflows/language/index.ts +20 -0
  516. package/src/workflows/language/references.ts +55 -0
  517. package/src/workflows/language/schema.ts +134 -0
  518. package/src/workflows/language/strict-yaml.ts +131 -0
  519. package/src/workflows/manifest.ts +24 -0
  520. package/src/workflows/module.ts +12 -0
  521. package/src/workflows/runtime/coordinator.ts +115 -0
  522. package/src/workflows/runtime/executor.ts +1003 -0
  523. package/src/workflows/runtime/index.ts +60 -0
  524. package/src/workflows/runtime/instant.ts +8 -0
  525. package/src/workflows/runtime/ports.ts +213 -0
  526. package/src/workflows/runtime/schedule.ts +203 -0
  527. package/src/workflows/runtime/trigger.ts +37 -0
  528. package/src/workflows/runtime/wake.ts +13 -0
  529. package/src/workflows/store/actions.ts +438 -0
  530. package/src/workflows/store/budget.ts +145 -0
  531. package/src/workflows/store/definitions.ts +345 -0
  532. package/src/workflows/store/events.ts +383 -0
  533. package/src/workflows/store/index.ts +107 -0
  534. package/src/workflows/store/observability.ts +594 -0
  535. package/src/workflows/store/runs.ts +975 -0
  536. package/src/workflows/store/transaction.ts +23 -0
  537. package/src/workflows/store/worker.ts +439 -0
  538. package/src/workflows/testing/conformance.ts +72 -0
  539. package/src/workflows/testing/index.ts +11 -0
  540. package/src/workflows/testing/process-fixtures.ts +275 -0
@@ -0,0 +1,60 @@
1
+ export type {
2
+ WorkflowCoordinatorClaim,
3
+ WorkflowCoordinatorExecution,
4
+ WorkflowCoordinatorFinishState,
5
+ WorkflowCoordinatorLeaseState,
6
+ WorkflowCoordinatorPort,
7
+ WorkflowCoordinatorReleaseState,
8
+ WorkflowCoordinatorResult,
9
+ } from "./coordinator";
10
+ export { coordinateWorkflowExecution } from "./coordinator";
11
+ export {
12
+ DEFAULT_MAX_LOOP_ITEMS,
13
+ dryRunWorkflowPlan,
14
+ executeWorkflowPlan,
15
+ WorkflowLeaseLostError,
16
+ WorkflowRetryableStepError,
17
+ } from "./executor";
18
+ export type {
19
+ WorkflowActionStep,
20
+ WorkflowDryRunActionContext,
21
+ WorkflowDryRunActionHandler,
22
+ WorkflowDryRunActionPort,
23
+ WorkflowDryRunIssue,
24
+ WorkflowDryRunOptions,
25
+ WorkflowDryRunResult,
26
+ WorkflowExecuteActionContext,
27
+ WorkflowExecuteActionHandler,
28
+ WorkflowExecuteActionPort,
29
+ WorkflowExecuteOptions,
30
+ WorkflowExecutionClock,
31
+ WorkflowExecutionResult,
32
+ WorkflowHeartbeatOutcome,
33
+ WorkflowRestoredStep,
34
+ WorkflowRuntimeRepositoryPort,
35
+ WorkflowRuntimeRunIdentity,
36
+ WorkflowRuntimeStepIdentity,
37
+ WorkflowRuntimeStepResult,
38
+ WorkflowTraceEvent,
39
+ WorkflowTracePort,
40
+ WorkflowValueResolution,
41
+ WorkflowValueResolverPort,
42
+ WorkflowVariableScope,
43
+ } from "./ports";
44
+ export type {
45
+ WorkflowSchedule,
46
+ WorkflowScheduleReconciliation,
47
+ WorkflowScheduleReconciliationPort,
48
+ WorkflowScheduleRegistration,
49
+ } from "./schedule";
50
+ export {
51
+ createWorkflowScheduleRegistration,
52
+ normalizeWorkflowSchedule,
53
+ planWorkflowScheduleReconciliation,
54
+ reconcileWorkflowSchedules,
55
+ workflowScheduleRegistrationId,
56
+ workflowScheduleSlotKey,
57
+ } from "./schedule";
58
+ export { evaluateWorkflowTriggerInputs } from "./trigger";
59
+ export type { WorkflowRunWake } from "./wake";
60
+ export { wakeWorkflowRunBestEffort } from "./wake";
@@ -0,0 +1,8 @@
1
+ export const normalizeWorkflowInstant = (name: string, value: string): string => {
2
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/u.test(value)) {
3
+ throw new Error(`${name} must be an ISO date-time with a timezone`);
4
+ }
5
+ const timestamp = Date.parse(value);
6
+ if (!Number.isFinite(timestamp)) throw new Error(`${name} must be an ISO date-time with a timezone`);
7
+ return new Date(timestamp).toISOString();
8
+ };
@@ -0,0 +1,213 @@
1
+ import type {
2
+ WorkflowBoundPlan,
3
+ WorkflowDependency,
4
+ WorkflowInvocation,
5
+ WorkflowInvocationMode,
6
+ WorkflowIrStep,
7
+ WorkflowJsonValue,
8
+ WorkflowPlanningIssue,
9
+ WorkflowPlanningOutcome,
10
+ WorkflowRunState,
11
+ WorkflowStepOutcome,
12
+ } from "../contracts";
13
+
14
+ export type WorkflowActionStep = Extract<WorkflowIrStep, { kind: "action" }>;
15
+
16
+ export type WorkflowRuntimeRunIdentity = {
17
+ runId: string;
18
+ executionGeneration: number;
19
+ mode: WorkflowInvocationMode;
20
+ workflowId: string;
21
+ sourceHash: string;
22
+ idempotencyKey: string;
23
+ };
24
+
25
+ export type WorkflowRuntimeStepIdentity = WorkflowRuntimeRunIdentity & {
26
+ key: string;
27
+ sourcePath: Array<string | number>;
28
+ iterationPath: number[];
29
+ path: Array<string | number>;
30
+ kind: WorkflowIrStep["kind"];
31
+ action?: string;
32
+ };
33
+
34
+ export type WorkflowHeartbeatOutcome = { state: "active" } | { state: "stale" } | { state: "canceled"; message?: string };
35
+
36
+ export type WorkflowRestoredStep =
37
+ | { mode: "execute"; outcome: Exclude<WorkflowStepOutcome, { state: "waiting" }> }
38
+ | { mode: "dryRun"; outcome: WorkflowPlanningOutcome };
39
+
40
+ export type WorkflowRuntimeStepResult =
41
+ | { mode: "execute"; outcome: WorkflowStepOutcome }
42
+ | { mode: "dryRun"; outcome: WorkflowPlanningOutcome };
43
+
44
+ export interface WorkflowRuntimeRepositoryPort {
45
+ heartbeat(run: WorkflowRuntimeRunIdentity): Promise<WorkflowHeartbeatOutcome>;
46
+ restoreStepOutcome(step: WorkflowRuntimeStepIdentity): Promise<WorkflowRestoredStep | null>;
47
+ startStep(step: WorkflowRuntimeStepIdentity): Promise<void>;
48
+ finishStep(step: WorkflowRuntimeStepIdentity, result: WorkflowRuntimeStepResult): Promise<void>;
49
+ parkStep(step: WorkflowRuntimeStepIdentity, dependency: WorkflowDependency): Promise<void>;
50
+ }
51
+
52
+ export interface WorkflowVariableScope {
53
+ get(name: string): WorkflowJsonValue | undefined;
54
+ has(name: string): boolean;
55
+ set(name: string, value: WorkflowJsonValue): void;
56
+ snapshot?(): Record<string, WorkflowJsonValue>;
57
+ }
58
+
59
+ export type WorkflowValueResolution =
60
+ | { state: "resolved"; value: WorkflowJsonValue }
61
+ | { state: "missing" }
62
+ | { state: "waiting"; dependency: WorkflowDependency };
63
+
64
+ export interface WorkflowExecutionClock {
65
+ now(): string;
66
+ }
67
+
68
+ type WorkflowActionContextBase<Mode extends WorkflowInvocationMode> = {
69
+ mode: Mode;
70
+ run: WorkflowRuntimeRunIdentity & { mode: Mode };
71
+ step: WorkflowRuntimeStepIdentity & { mode: Mode };
72
+ plan: WorkflowBoundPlan;
73
+ invocation: WorkflowInvocation & { mode: Mode };
74
+ variables: WorkflowVariableScope;
75
+ evaluate(value: WorkflowJsonValue, path?: Array<string | number>): Promise<WorkflowJsonValue>;
76
+ resolveReference(reference: string, path?: Array<string | number>): Promise<WorkflowJsonValue | undefined>;
77
+ heartbeat(): Promise<void>;
78
+ };
79
+
80
+ export type WorkflowExecuteActionContext = WorkflowActionContextBase<"execute">;
81
+ export type WorkflowDryRunActionContext = WorkflowActionContextBase<"dryRun">;
82
+
83
+ export type WorkflowExecuteActionHandler = {
84
+ execute(context: WorkflowExecuteActionContext, step: WorkflowActionStep): Promise<WorkflowStepOutcome>;
85
+ restoreCompleted?(
86
+ context: WorkflowExecuteActionContext,
87
+ step: WorkflowActionStep,
88
+ outcome: Extract<WorkflowStepOutcome, { state: "completed" }>,
89
+ ): Promise<void> | void;
90
+ };
91
+
92
+ export type WorkflowDryRunActionHandler = {
93
+ plan(context: WorkflowDryRunActionContext, step: WorkflowActionStep): Promise<WorkflowPlanningOutcome>;
94
+ restoreCompleted?(
95
+ context: WorkflowDryRunActionContext,
96
+ step: WorkflowActionStep,
97
+ outcome: Extract<WorkflowPlanningOutcome, { state: "planned" }>,
98
+ ): Promise<void> | void;
99
+ };
100
+
101
+ export interface WorkflowExecuteActionPort {
102
+ get(action: string): WorkflowExecuteActionHandler | undefined;
103
+ }
104
+
105
+ export interface WorkflowDryRunActionPort {
106
+ get(action: string): WorkflowDryRunActionHandler | undefined;
107
+ }
108
+
109
+ /**
110
+ * What an observer is told about a run's progress.
111
+ *
112
+ * The run-level events bracket the step-level ones: a worker claimed this run,
113
+ * and it settled this way. An app that streams progress to a browser needs both
114
+ * ends — without `run.started` a queued run appears to sit still until its first
115
+ * step reports, and without `run.finished` a run that failed before any step
116
+ * never announces that it stopped.
117
+ *
118
+ * Deliberately thin: the transition and which run it happened to. Whoever
119
+ * publishes re-reads the run, because the row is the truth and an event that
120
+ * carried a copy of it would be one more thing to keep in step.
121
+ */
122
+ export type WorkflowTraceEvent =
123
+ | { type: "run.started"; run: WorkflowRuntimeRunIdentity }
124
+ | { type: "step.started"; step: WorkflowRuntimeStepIdentity }
125
+ | { type: "step.restored"; step: WorkflowRuntimeStepIdentity; restored: WorkflowRestoredStep }
126
+ | { type: "step.waiting"; step: WorkflowRuntimeStepIdentity; dependency: WorkflowDependency }
127
+ | { type: "step.finished"; step: WorkflowRuntimeStepIdentity; result: WorkflowRuntimeStepResult }
128
+ | { type: "run.canceled"; run: WorkflowRuntimeRunIdentity; message?: string }
129
+ | { type: "run.finished"; run: WorkflowRuntimeRunIdentity; state: WorkflowRunState | "released" };
130
+
131
+ export interface WorkflowTracePort {
132
+ emit(event: WorkflowTraceEvent): Promise<void> | void;
133
+ }
134
+
135
+ export interface WorkflowValueResolverPort {
136
+ resolve(input: {
137
+ reference: string;
138
+ path: Array<string | number>;
139
+ plan: WorkflowBoundPlan;
140
+ invocation: WorkflowInvocation;
141
+ variables: WorkflowVariableScope;
142
+ fallback: () => WorkflowJsonValue | undefined;
143
+ }): Promise<WorkflowValueResolution>;
144
+ }
145
+
146
+ type WorkflowRuntimeOptionsBase = {
147
+ runId: string;
148
+ executionGeneration: number;
149
+ plan: WorkflowBoundPlan;
150
+ invocation: WorkflowInvocation;
151
+ repository: WorkflowRuntimeRepositoryPort;
152
+ clock: WorkflowExecutionClock;
153
+ trace?: WorkflowTracePort;
154
+ values?: WorkflowValueResolverPort;
155
+ maxLoopItems?: number;
156
+ initialVariables?: Record<string, WorkflowJsonValue>;
157
+ };
158
+
159
+ export type WorkflowExecuteOptions = Omit<WorkflowRuntimeOptionsBase, "invocation"> & {
160
+ invocation: WorkflowInvocation & { mode: "execute" };
161
+ actions: WorkflowExecuteActionPort;
162
+ };
163
+
164
+ export type WorkflowDryRunOptions = Omit<WorkflowRuntimeOptionsBase, "invocation"> & {
165
+ invocation: WorkflowInvocation & { mode: "dryRun" };
166
+ actions: WorkflowDryRunActionPort;
167
+ };
168
+
169
+ export type WorkflowExecutionResult =
170
+ | { state: "succeeded"; output?: WorkflowJsonValue; message?: string }
171
+ | { state: "waiting"; dependency: Extract<WorkflowStepOutcome, { state: "waiting" }>["dependency"]; step: WorkflowRuntimeStepIdentity }
172
+ | { state: "failed"; error: Extract<WorkflowStepOutcome, { state: "failed" }>["error"]; step: WorkflowRuntimeStepIdentity }
173
+ | {
174
+ state: "needs_attention";
175
+ error: Extract<WorkflowStepOutcome, { state: "needs_attention" }>["error"];
176
+ step: WorkflowRuntimeStepIdentity;
177
+ }
178
+ | { state: "canceled"; message?: string; step?: WorkflowRuntimeStepIdentity };
179
+
180
+ export type WorkflowDryRunIssue = Omit<WorkflowPlanningIssue, "step"> & {
181
+ step: WorkflowRuntimeStepIdentity;
182
+ };
183
+
184
+ export type WorkflowDryRunResult =
185
+ | { state: "planned"; output?: WorkflowJsonValue; effects: WorkflowJsonValue[] }
186
+ | {
187
+ state: "terminal";
188
+ status: "succeeded" | "failed";
189
+ message?: string;
190
+ effects: WorkflowJsonValue[];
191
+ issues?: WorkflowDryRunIssue[];
192
+ }
193
+ | {
194
+ state: "unsupported";
195
+ reason: string;
196
+ effects: WorkflowJsonValue[];
197
+ step: WorkflowRuntimeStepIdentity;
198
+ issues: WorkflowDryRunIssue[];
199
+ }
200
+ | {
201
+ state: "indeterminate";
202
+ reason: string;
203
+ effects: WorkflowJsonValue[];
204
+ step: WorkflowRuntimeStepIdentity;
205
+ issues: WorkflowDryRunIssue[];
206
+ }
207
+ | {
208
+ state: "canceled";
209
+ message?: string;
210
+ effects: WorkflowJsonValue[];
211
+ step?: WorkflowRuntimeStepIdentity;
212
+ issues?: WorkflowDryRunIssue[];
213
+ };
@@ -0,0 +1,203 @@
1
+ import type { WorkflowRevision } from "../contracts";
2
+ import { normalizeWorkflowInstant } from "./instant";
3
+
4
+ const opaqueKey = (prefix: string, parts: readonly string[]): string =>
5
+ `${prefix}:${parts.map((part) => `${part.length}:${part}`).join("")}`;
6
+
7
+ const CRON_FIELDS = [
8
+ { name: "minute", min: 0, max: 59 },
9
+ { name: "hour", min: 0, max: 23 },
10
+ { name: "day-of-month", min: 1, max: 31 },
11
+ { name: "month", min: 1, max: 12 },
12
+ { name: "day-of-week", min: 0, max: 7 },
13
+ ] as const;
14
+
15
+ const cronError = (field: (typeof CRON_FIELDS)[number], value: string): Error => new Error(`cron ${field.name} field is invalid: ${value}`);
16
+
17
+ const cronNumber = (value: string, field: (typeof CRON_FIELDS)[number]): number => {
18
+ if (!/^\d+$/u.test(value)) throw cronError(field, value);
19
+ const number = Number(value);
20
+ if (!Number.isSafeInteger(number) || number < field.min || number > field.max) throw cronError(field, value);
21
+ return number;
22
+ };
23
+
24
+ type CronFieldValues = { any: boolean; values: Set<number> };
25
+
26
+ const normalizeCronValue = (value: number, field: (typeof CRON_FIELDS)[number]): number =>
27
+ field.name === "day-of-week" && value === 7 ? 0 : value;
28
+
29
+ const validateCronItem = (item: string, field: (typeof CRON_FIELDS)[number]): number[] => {
30
+ const stepParts = item.split("/");
31
+ if (stepParts.length > 2) throw cronError(field, item);
32
+ const [base = "", step] = stepParts;
33
+ const rangeParts = base.split("-");
34
+ if (rangeParts.length > 2) throw cronError(field, item);
35
+
36
+ const stepNumber = step === undefined ? 1 : Number(step);
37
+ if (step !== undefined && (!/^\d+$/u.test(step) || !Number.isSafeInteger(stepNumber) || stepNumber < 1)) {
38
+ throw cronError(field, item);
39
+ }
40
+
41
+ let start: number = field.min;
42
+ let end: number = field.max;
43
+ if (base !== "*") {
44
+ const [startText = "", endText] = rangeParts;
45
+ start = cronNumber(startText, field);
46
+ end = endText === undefined ? start : cronNumber(endText, field);
47
+ }
48
+
49
+ const normalizedStart = normalizeCronValue(start, field);
50
+ const normalizedEnd = normalizeCronValue(end, field);
51
+ const values: number[] = [];
52
+ if (field.name === "day-of-week" && start !== end && normalizedStart > normalizedEnd) {
53
+ for (let value = normalizedStart; value <= field.max; value += stepNumber) values.push(normalizeCronValue(value, field));
54
+ for (let value = field.min; value <= normalizedEnd; value += stepNumber) values.push(normalizeCronValue(value, field));
55
+ return values;
56
+ }
57
+ if (normalizedStart > normalizedEnd) throw cronError(field, item);
58
+ for (let value = normalizedStart; value <= normalizedEnd; value += stepNumber) values.push(normalizeCronValue(value, field));
59
+ return values;
60
+ };
61
+
62
+ const validateCronField = (value: string, field: (typeof CRON_FIELDS)[number]): CronFieldValues => {
63
+ const items = value.split(",");
64
+ if (items.some((item) => item.length === 0)) throw cronError(field, value);
65
+ const values = new Set(items.flatMap((item) => validateCronItem(item, field)));
66
+ if (values.size === 0) throw cronError(field, value);
67
+ return { any: value === "*", values };
68
+ };
69
+
70
+ const assertReachableCalendarDate = (fields: readonly CronFieldValues[]): void => {
71
+ const dayOfMonth = fields[2]!;
72
+ const month = fields[3]!;
73
+ const dayOfWeek = fields[4]!;
74
+ if (dayOfMonth.any || !dayOfWeek.any) return;
75
+ const maxDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
76
+ const reachable = [...month.values].some((value) => [...dayOfMonth.values].some((day) => day <= maxDays[value - 1]!));
77
+ if (!reachable) throw new Error("cron has no reachable calendar date");
78
+ };
79
+
80
+ export type WorkflowSchedule = {
81
+ cron: string;
82
+ timezone: string;
83
+ };
84
+
85
+ export type WorkflowScheduleRegistration = {
86
+ id: string;
87
+ namespace: string;
88
+ workflowId: string;
89
+ triggerId: string;
90
+ revision: WorkflowRevision;
91
+ schedule: WorkflowSchedule;
92
+ };
93
+
94
+ export const normalizeWorkflowSchedule = (schedule: WorkflowSchedule): WorkflowSchedule => {
95
+ const fields = schedule.cron.trim().split(/\s+/u);
96
+ if (fields.length !== 5 || fields.some((field) => field.length === 0)) {
97
+ throw new Error("cron must contain exactly five fields");
98
+ }
99
+ const parsedFields = fields.map((value, index) => validateCronField(value, CRON_FIELDS[index]!));
100
+ assertReachableCalendarDate(parsedFields);
101
+
102
+ const timezone = schedule.timezone.trim();
103
+ if (!timezone) throw new Error("timezone must be an IANA timezone");
104
+ let normalizedTimezone: string;
105
+ try {
106
+ normalizedTimezone = new Intl.DateTimeFormat("en-US", { timeZone: timezone }).resolvedOptions().timeZone;
107
+ } catch {
108
+ throw new Error(`timezone must be an IANA timezone: ${timezone}`);
109
+ }
110
+ return { cron: fields.join(" "), timezone: normalizedTimezone };
111
+ };
112
+
113
+ export const workflowScheduleRegistrationId = (input: {
114
+ namespace: string;
115
+ workflowId: string;
116
+ triggerId: string;
117
+ revision: WorkflowRevision;
118
+ }): string => opaqueKey("workflow-schedule", [input.namespace, input.workflowId, input.triggerId]);
119
+
120
+ export const createWorkflowScheduleRegistration = (
121
+ input: Omit<WorkflowScheduleRegistration, "id" | "schedule"> & WorkflowSchedule,
122
+ ): WorkflowScheduleRegistration => ({
123
+ id: workflowScheduleRegistrationId(input),
124
+ namespace: input.namespace,
125
+ workflowId: input.workflowId,
126
+ triggerId: input.triggerId,
127
+ revision: input.revision,
128
+ schedule: normalizeWorkflowSchedule(input),
129
+ });
130
+
131
+ export const workflowScheduleSlotKey = (registrationId: string, slot: string): string => {
132
+ return opaqueKey("workflow-schedule-slot", [registrationId, normalizeWorkflowInstant("slot", slot)]);
133
+ };
134
+
135
+ export type WorkflowScheduleReconciliation = {
136
+ create: WorkflowScheduleRegistration[];
137
+ update: Array<{ current: WorkflowScheduleRegistration; desired: WorkflowScheduleRegistration }>;
138
+ remove: WorkflowScheduleRegistration[];
139
+ };
140
+
141
+ const registrationMap = (
142
+ name: "current" | "desired",
143
+ registrations: readonly WorkflowScheduleRegistration[],
144
+ ): Map<string, WorkflowScheduleRegistration> => {
145
+ const result = new Map<string, WorkflowScheduleRegistration>();
146
+ for (const registration of registrations) {
147
+ if (result.has(registration.id)) throw new Error(`${name} schedules contain duplicate id ${registration.id}`);
148
+ result.set(registration.id, registration);
149
+ }
150
+ return result;
151
+ };
152
+
153
+ const schedulesMatch = (left: WorkflowSchedule, right: WorkflowSchedule): boolean => {
154
+ try {
155
+ const normalizedLeft = normalizeWorkflowSchedule(left);
156
+ const normalizedRight = normalizeWorkflowSchedule(right);
157
+ return normalizedLeft.cron === normalizedRight.cron && normalizedLeft.timezone === normalizedRight.timezone;
158
+ } catch {
159
+ return false;
160
+ }
161
+ };
162
+
163
+ export const planWorkflowScheduleReconciliation = (
164
+ desired: readonly WorkflowScheduleRegistration[],
165
+ current: readonly WorkflowScheduleRegistration[],
166
+ ): WorkflowScheduleReconciliation => {
167
+ const desiredById = registrationMap("desired", desired);
168
+ const currentById = registrationMap("current", current);
169
+ const create = desired.filter((registration) => !currentById.has(registration.id)).sort((a, b) => a.id.localeCompare(b.id));
170
+ const update = desired
171
+ .flatMap((registration) => {
172
+ const existing = currentById.get(registration.id);
173
+ return existing && (existing.revision !== registration.revision || !schedulesMatch(existing.schedule, registration.schedule))
174
+ ? [{ current: existing, desired: registration }]
175
+ : [];
176
+ })
177
+ .sort((a, b) => a.desired.id.localeCompare(b.desired.id));
178
+ const remove = current.filter((registration) => !desiredById.has(registration.id)).sort((a, b) => a.id.localeCompare(b.id));
179
+ return { create, update, remove };
180
+ };
181
+
182
+ export interface WorkflowScheduleReconciliationPort {
183
+ create(registration: WorkflowScheduleRegistration): Promise<void>;
184
+ update(current: WorkflowScheduleRegistration, desired: WorkflowScheduleRegistration): Promise<void>;
185
+ register(registration: WorkflowScheduleRegistration): Promise<void>;
186
+ remove(registration: WorkflowScheduleRegistration): Promise<void>;
187
+ }
188
+
189
+ export const reconcileWorkflowSchedules = async (input: {
190
+ desired: readonly WorkflowScheduleRegistration[];
191
+ current: readonly WorkflowScheduleRegistration[];
192
+ port: WorkflowScheduleReconciliationPort;
193
+ }): Promise<WorkflowScheduleReconciliation> => {
194
+ const plan = planWorkflowScheduleReconciliation(input.desired, input.current);
195
+ const changed = new Set([...plan.create.map((registration) => registration.id), ...plan.update.map((item) => item.desired.id)]);
196
+ for (const registration of plan.create) await input.port.create(registration);
197
+ for (const item of plan.update) await input.port.update(item.current, item.desired);
198
+ for (const registration of input.desired.filter((item) => !changed.has(item.id)).sort((a, b) => a.id.localeCompare(b.id))) {
199
+ await input.port.register(registration);
200
+ }
201
+ for (const registration of plan.remove) await input.port.remove(registration);
202
+ return plan;
203
+ };
@@ -0,0 +1,37 @@
1
+ import type { WorkflowJsonValue } from "../contracts";
2
+ import { parseWorkflowValueString } from "../language";
3
+ import { readWorkflowValuePath } from "../language/references";
4
+
5
+ const readTriggerPath = (values: Record<string, WorkflowJsonValue>, reference: string): WorkflowJsonValue | undefined => {
6
+ const segments = reference.split(".");
7
+ if (segments.shift() !== "trigger") return undefined;
8
+ return readWorkflowValuePath(values, segments);
9
+ };
10
+
11
+ const evaluateTriggerValue = (
12
+ value: WorkflowJsonValue,
13
+ values: Record<string, WorkflowJsonValue>,
14
+ occurredAt: string,
15
+ ): WorkflowJsonValue => {
16
+ if (typeof value === "string") {
17
+ const parsed = parseWorkflowValueString(value);
18
+ if (parsed.kind === "literal") return value;
19
+ if (parsed.kind === "invalid") throw new Error(`invalid workflow trigger expression "${value}"`);
20
+ if (parsed.expression.kind === "now") return occurredAt;
21
+ const resolved = readTriggerPath(values, parsed.expression.reference);
22
+ if (resolved === undefined) throw new Error(`workflow trigger value "${parsed.expression.reference}" is unavailable`);
23
+ return resolved;
24
+ }
25
+ if (Array.isArray(value)) return value.map((item) => evaluateTriggerValue(item, values, occurredAt));
26
+ if (value !== null && typeof value === "object") {
27
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, evaluateTriggerValue(item, values, occurredAt)]));
28
+ }
29
+ return value;
30
+ };
31
+
32
+ export const evaluateWorkflowTriggerInputs = (
33
+ values: Record<string, WorkflowJsonValue>,
34
+ bindings: Record<string, WorkflowJsonValue>,
35
+ occurredAt: string,
36
+ ): Record<string, WorkflowJsonValue> =>
37
+ Object.fromEntries(Object.entries(bindings).map(([name, value]) => [name, evaluateTriggerValue(value, values, occurredAt)]));
@@ -0,0 +1,13 @@
1
+ export type WorkflowRunWake = (runId: string) => Promise<void>;
2
+
3
+ export const wakeWorkflowRunBestEffort = async (input: {
4
+ runId: string;
5
+ wake: WorkflowRunWake;
6
+ onError(error: unknown): void;
7
+ }): Promise<void> => {
8
+ try {
9
+ await input.wake(input.runId);
10
+ } catch (error) {
11
+ input.onError(error);
12
+ }
13
+ };