@anchrd/intel 0.59.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 (364) hide show
  1. package/README.md +496 -0
  2. package/bin/intel.mjs +134 -0
  3. package/dist/adapters/cloudflare/cloudflare-flow-workflow.d.ts +42 -0
  4. package/dist/adapters/cloudflare/cloudflare-flow-workflow.js +89 -0
  5. package/dist/adapters/cloudflare/cloudflare.d.ts +29 -0
  6. package/dist/adapters/cloudflare/cloudflare.js +416 -0
  7. package/dist/adapters/cloudflare/cloudflare.types.d.ts +31 -0
  8. package/dist/adapters/cloudflare/cloudflare.types.js +1 -0
  9. package/dist/adapters/content/content.d.ts +3 -0
  10. package/dist/adapters/content/content.js +128 -0
  11. package/dist/adapters/content/content.types.d.ts +38 -0
  12. package/dist/adapters/content/content.types.js +1 -0
  13. package/dist/adapters/db/db-audit.d.ts +62 -0
  14. package/dist/adapters/db/db-audit.js +150 -0
  15. package/dist/adapters/db/db-boards.d.ts +6 -0
  16. package/dist/adapters/db/db-boards.js +324 -0
  17. package/dist/adapters/db/db-feed.d.ts +30 -0
  18. package/dist/adapters/db/db-feed.js +276 -0
  19. package/dist/adapters/db/db-flows.d.ts +42 -0
  20. package/dist/adapters/db/db-flows.js +1311 -0
  21. package/dist/adapters/db/db-grants.d.ts +133 -0
  22. package/dist/adapters/db/db-grants.js +269 -0
  23. package/dist/adapters/db/db-indexing.d.ts +3 -0
  24. package/dist/adapters/db/db-indexing.js +200 -0
  25. package/dist/adapters/db/db-oauth.d.ts +3 -0
  26. package/dist/adapters/db/db-oauth.js +26 -0
  27. package/dist/adapters/db/db-prompts.d.ts +46 -0
  28. package/dist/adapters/db/db-prompts.js +144 -0
  29. package/dist/adapters/db/db.d.ts +6 -0
  30. package/dist/adapters/db/db.js +1687 -0
  31. package/dist/adapters/db/db.types.d.ts +16 -0
  32. package/dist/adapters/db/db.types.js +1 -0
  33. package/dist/adapters/document-converter/document-converter.d.ts +2 -0
  34. package/dist/adapters/document-converter/document-converter.js +26 -0
  35. package/dist/adapters/document-converter/document-converter.types.d.ts +17 -0
  36. package/dist/adapters/document-converter/document-converter.types.js +1 -0
  37. package/dist/adapters/flow-runtime/flow-runtime.d.ts +3 -0
  38. package/dist/adapters/flow-runtime/flow-runtime.js +22 -0
  39. package/dist/adapters/flow-runtime/flow-runtime.types.d.ts +19 -0
  40. package/dist/adapters/flow-runtime/flow-runtime.types.js +1 -0
  41. package/dist/adapters/index-queue/index-queue.d.ts +10 -0
  42. package/dist/adapters/index-queue/index-queue.js +12 -0
  43. package/dist/adapters/index-queue/index-queue.types.d.ts +11 -0
  44. package/dist/adapters/index-queue/index-queue.types.js +1 -0
  45. package/dist/adapters/json-schema/json-schema.d.ts +2 -0
  46. package/dist/adapters/json-schema/json-schema.js +77 -0
  47. package/dist/adapters/openid/openid.d.ts +5 -0
  48. package/dist/adapters/openid/openid.js +301 -0
  49. package/dist/adapters/portal-tokens/portal-tokens.d.ts +8 -0
  50. package/dist/adapters/portal-tokens/portal-tokens.js +79 -0
  51. package/dist/adapters/remote-tools/remote-tools.d.ts +5 -0
  52. package/dist/adapters/remote-tools/remote-tools.js +129 -0
  53. package/dist/adapters/semantic-index/semantic-index.d.ts +2 -0
  54. package/dist/adapters/semantic-index/semantic-index.js +139 -0
  55. package/dist/adapters/semantic-index/semantic-index.types.d.ts +56 -0
  56. package/dist/adapters/semantic-index/semantic-index.types.js +1 -0
  57. package/dist/adapters/session-cookie/session-cookie.d.ts +5 -0
  58. package/dist/adapters/session-cookie/session-cookie.js +87 -0
  59. package/dist/adapters/tool-source-policy/tool-source-policy.d.ts +1 -0
  60. package/dist/adapters/tool-source-policy/tool-source-policy.js +22 -0
  61. package/dist/audit/audit.d.ts +2 -0
  62. package/dist/audit/audit.js +87 -0
  63. package/dist/audit/audit.types.d.ts +23 -0
  64. package/dist/audit/audit.types.js +1 -0
  65. package/dist/auth/auth.d.ts +2 -0
  66. package/dist/auth/auth.js +284 -0
  67. package/dist/auth/auth.types.d.ts +108 -0
  68. package/dist/auth/auth.types.js +1 -0
  69. package/dist/boards/boards.d.ts +44 -0
  70. package/dist/boards/boards.js +447 -0
  71. package/dist/boards/boards.types.d.ts +117 -0
  72. package/dist/boards/boards.types.js +1 -0
  73. package/dist/build/build.d.ts +2 -0
  74. package/dist/build/build.js +192 -0
  75. package/dist/build/build.types.d.ts +17 -0
  76. package/dist/build/build.types.js +1 -0
  77. package/dist/bundle/bundle.d.ts +4 -0
  78. package/dist/bundle/bundle.js +1194 -0
  79. package/dist/bundle/bundle.types.d.ts +33 -0
  80. package/dist/bundle/bundle.types.js +1 -0
  81. package/dist/cli/cli.d.ts +4 -0
  82. package/dist/cli/cli.js +262 -0
  83. package/dist/cli/cli.types.d.ts +14 -0
  84. package/dist/cli/cli.types.js +1 -0
  85. package/dist/contract/audit.d.ts +50 -0
  86. package/dist/contract/audit.js +72 -0
  87. package/dist/contract/board.d.ts +150 -0
  88. package/dist/contract/board.js +262 -0
  89. package/dist/contract/bundle.d.ts +147 -0
  90. package/dist/contract/bundle.js +139 -0
  91. package/dist/contract/contract.d.ts +112 -0
  92. package/dist/contract/contract.js +143 -0
  93. package/dist/contract/feed.d.ts +126 -0
  94. package/dist/contract/feed.js +149 -0
  95. package/dist/contract/flow-run.d.ts +346 -0
  96. package/dist/contract/flow-run.js +194 -0
  97. package/dist/contract/flow.d.ts +1057 -0
  98. package/dist/contract/flow.js +552 -0
  99. package/dist/contract/node.d.ts +551 -0
  100. package/dist/contract/node.js +456 -0
  101. package/dist/contract/share.d.ts +216 -0
  102. package/dist/contract/share.js +134 -0
  103. package/dist/contract/table.d.ts +171 -0
  104. package/dist/contract/table.js +117 -0
  105. package/dist/contract/tool.d.ts +122 -0
  106. package/dist/contract/tool.js +172 -0
  107. package/dist/feed/feed.d.ts +2 -0
  108. package/dist/feed/feed.js +77 -0
  109. package/dist/feed/feed.types.d.ts +23 -0
  110. package/dist/feed/feed.types.js +1 -0
  111. package/dist/flows/flows.d.ts +41 -0
  112. package/dist/flows/flows.js +2216 -0
  113. package/dist/flows/flows.types.d.ts +339 -0
  114. package/dist/flows/flows.types.js +1 -0
  115. package/dist/http/http.d.ts +9 -0
  116. package/dist/http/http.js +874 -0
  117. package/dist/http/http.types.d.ts +22 -0
  118. package/dist/http/http.types.js +1 -0
  119. package/dist/indexing/indexing.d.ts +6 -0
  120. package/dist/indexing/indexing.js +239 -0
  121. package/dist/indexing/indexing.types.d.ts +11 -0
  122. package/dist/indexing/indexing.types.js +1 -0
  123. package/dist/intel/intel.d.ts +3 -0
  124. package/dist/intel/intel.js +194 -0
  125. package/dist/intel/intel.types.d.ts +24 -0
  126. package/dist/intel/intel.types.js +1 -0
  127. package/dist/mcp/mcp.d.ts +2 -0
  128. package/dist/mcp/mcp.js +1292 -0
  129. package/dist/mcp/mcp.types.d.ts +25 -0
  130. package/dist/mcp/mcp.types.js +1 -0
  131. package/dist/nodes/document-links/document-links.d.ts +20 -0
  132. package/dist/nodes/document-links/document-links.js +57 -0
  133. package/dist/nodes/nodes.d.ts +2 -0
  134. package/dist/nodes/nodes.js +1667 -0
  135. package/dist/nodes/nodes.types.d.ts +511 -0
  136. package/dist/nodes/nodes.types.js +1 -0
  137. package/dist/prepare/prepare.d.ts +4 -0
  138. package/dist/prepare/prepare.js +16 -0
  139. package/dist/prepare/prepare.types.d.ts +9 -0
  140. package/dist/prepare/prepare.types.js +1 -0
  141. package/dist/prompts/prompts.d.ts +2 -0
  142. package/dist/prompts/prompts.js +65 -0
  143. package/dist/prompts/prompts.types.d.ts +71 -0
  144. package/dist/prompts/prompts.types.js +1 -0
  145. package/dist/shared/callers/callers.d.ts +28 -0
  146. package/dist/shared/callers/callers.js +30 -0
  147. package/dist/shared/csv/csv.d.ts +13 -0
  148. package/dist/shared/csv/csv.js +85 -0
  149. package/dist/shared/document-text/document-text.d.ts +21 -0
  150. package/dist/shared/document-text/document-text.js +31 -0
  151. package/dist/shared/gate-authorization/gate-authorization.d.ts +5 -0
  152. package/dist/shared/gate-authorization/gate-authorization.js +26 -0
  153. package/dist/shared/grant-expiry/grant-expiry.d.ts +19 -0
  154. package/dist/shared/grant-expiry/grant-expiry.js +26 -0
  155. package/dist/shared/intel-error/intel-error.d.ts +22 -0
  156. package/dist/shared/intel-error/intel-error.js +27 -0
  157. package/dist/shared/plain-title/plain-title.d.ts +16 -0
  158. package/dist/shared/plain-title/plain-title.js +45 -0
  159. package/dist/shared/problem-details/problem-details.d.ts +30 -0
  160. package/dist/shared/problem-details/problem-details.js +18 -0
  161. package/dist/shared/report-unexpected-error/report-unexpected-error.d.ts +1 -0
  162. package/dist/shared/report-unexpected-error/report-unexpected-error.js +37 -0
  163. package/dist/shared/safe-return-path/safe-return-path.d.ts +2 -0
  164. package/dist/shared/safe-return-path/safe-return-path.js +11 -0
  165. package/dist/shared/sha256/sha256.d.ts +2 -0
  166. package/dist/shared/sha256/sha256.js +14 -0
  167. package/dist/tools/tool-servers/tool-servers.d.ts +46 -0
  168. package/dist/tools/tool-servers/tool-servers.js +177 -0
  169. package/dist/tools/tools.d.ts +2 -0
  170. package/dist/tools/tools.js +207 -0
  171. package/dist/tools/tools.types.d.ts +56 -0
  172. package/dist/tools/tools.types.js +1 -0
  173. package/examples/branding/favicon.svg +5 -0
  174. package/examples/branding/logo.svg +5 -0
  175. package/examples/branding/theme.css +16 -0
  176. package/examples/dev.vars.example +7 -0
  177. package/examples/intel.json +9 -0
  178. package/migrations/0000_intel_foundation.sql +203 -0
  179. package/migrations/0001_portal_native_tools.sql +21 -0
  180. package/migrations/0002_flows_in_the_knowledge_tree.sql +34 -0
  181. package/migrations/0003_folder_permissions.sql +211 -0
  182. package/migrations/0004_subflow_runs.sql +14 -0
  183. package/migrations/0005_flow_node_cleanup.sql +28 -0
  184. package/migrations/0005_tables_in_the_knowledge_tree.sql +68 -0
  185. package/migrations/0006_links_are_written_in_the_text.sql +20 -0
  186. package/migrations/0007_no_node_waits.sql +69 -0
  187. package/migrations/0008_three_layers.sql +130 -0
  188. package/migrations/0009_no_context_policy.sql +48 -0
  189. package/migrations/0010_no_run_waits_a_year.sql +27 -0
  190. package/migrations/0011_one_name_for_the_tree.sql +53 -0
  191. package/migrations/0012_table_snapshots.sql +29 -0
  192. package/migrations/0017_a_vector_per_card.sql +38 -0
  193. package/migrations/0018_no_context_policy_at_last.sql +97 -0
  194. package/migrations/0019_one_name_for_the_grants.sql +52 -0
  195. package/migrations/0020_cascade_purge_replay.sql +11 -0
  196. package/migrations/0021_a_flow_carries_its_own_grant.sql +44 -0
  197. package/migrations/0022_a_cursor_over_the_journal.sql +14 -0
  198. package/migrations/0023_a_board_and_its_tasks.sql +116 -0
  199. package/migrations/0024_the_archive_is_a_column.sql +33 -0
  200. package/migrations/0025_archiving_takes_the_subtree.sql +29 -0
  201. package/migrations/0026_one_feed_over_two_kinds.sql +23 -0
  202. package/migrations/0027_the_runs_of_every_flow.sql +27 -0
  203. package/migrations/0028_a_prompt_name_over_two_kinds.sql +70 -0
  204. package/package.json +118 -0
  205. package/src/contract/CLAUDE.md +152 -0
  206. package/src/contract/README.md +102 -0
  207. package/src/contract/audit.ts +85 -0
  208. package/src/contract/board.ts +306 -0
  209. package/src/contract/bundle.ts +157 -0
  210. package/src/contract/contract.ts +161 -0
  211. package/src/contract/feed.ts +165 -0
  212. package/src/contract/flow-run.ts +241 -0
  213. package/src/contract/flow.ts +675 -0
  214. package/src/contract/node.ts +583 -0
  215. package/src/contract/share.ts +196 -0
  216. package/src/contract/table.ts +178 -0
  217. package/src/contract/tool.ts +202 -0
  218. package/ui/README.md +110 -0
  219. package/ui/components.json +21 -0
  220. package/ui/index.html +13 -0
  221. package/ui/package.json +11 -0
  222. package/ui/scripts/lint-tokens.mjs +187 -0
  223. package/ui/src/access-summary/access-summary.tsx +385 -0
  224. package/ui/src/app/action-slot/action-slot.tsx +27 -0
  225. package/ui/src/app/app-sidebar/app-sidebar.tsx +71 -0
  226. package/ui/src/app/app-tree/app-tree.tsx +1175 -0
  227. package/ui/src/app/app.tsx +87 -0
  228. package/ui/src/app/header-search/header-search.tsx +294 -0
  229. package/ui/src/app/reindex-dialog/reindex-dialog.tsx +79 -0
  230. package/ui/src/app/settings-dialog/settings-dialog.tsx +135 -0
  231. package/ui/src/app/sidebar-preferences/sidebar-preferences.ts +68 -0
  232. package/ui/src/app/sidebar-preferences/sidebar-preferences.types.ts +15 -0
  233. package/ui/src/app/sidebar-resize-handle/sidebar-resize-handle.tsx +86 -0
  234. package/ui/src/app/tree-expansion/tree-expansion.ts +107 -0
  235. package/ui/src/app/tree-expansion/tree-expansion.types.ts +31 -0
  236. package/ui/src/app/tree-move/tree-move.tsx +427 -0
  237. package/ui/src/app/tree-reveal/tree-reveal.ts +64 -0
  238. package/ui/src/app/tree-reveal/tree-reveal.types.ts +16 -0
  239. package/ui/src/app/user-footer/user-footer.tsx +188 -0
  240. package/ui/src/app/view-menu/view-menu.tsx +115 -0
  241. package/ui/src/app-root/app-root.tsx +109 -0
  242. package/ui/src/app-root/app-root.types.ts +27 -0
  243. package/ui/src/archive/archive.tsx +417 -0
  244. package/ui/src/attachment-detail/attachment-detail.ts +52 -0
  245. package/ui/src/attachment-viewer/attachment-viewer.tsx +166 -0
  246. package/ui/src/blocknote-view/blocknote-view.tsx +30 -0
  247. package/ui/src/board/board-assignee/board-assignee-picker.tsx +132 -0
  248. package/ui/src/board/board-assignee/board-assignee.ts +48 -0
  249. package/ui/src/board/board-assignee/board-assignee.tsx +75 -0
  250. package/ui/src/board/board-chip/board-chip.tsx +46 -0
  251. package/ui/src/board/board-crumbs/board-crumbs.ts +56 -0
  252. package/ui/src/board/board-crumbs/board-crumbs.tsx +111 -0
  253. package/ui/src/board/board-data/board-data.ts +195 -0
  254. package/ui/src/board/board-data/board-data.types.ts +38 -0
  255. package/ui/src/board/board-dates/board-dates.ts +40 -0
  256. package/ui/src/board/board-dates/board-dates.tsx +105 -0
  257. package/ui/src/board/board-kanban/board-kanban.ts +162 -0
  258. package/ui/src/board/board-kanban/board-kanban.tsx +680 -0
  259. package/ui/src/board/board-open-task/board-open-task.ts +32 -0
  260. package/ui/src/board/board-panel/board-panel.tsx +259 -0
  261. package/ui/src/board/board-settings/board-settings.tsx +226 -0
  262. package/ui/src/board/board-status/board-status.tsx +60 -0
  263. package/ui/src/board/board-stripes/board-stripes.ts +128 -0
  264. package/ui/src/board/board-table/board-table.ts +53 -0
  265. package/ui/src/board/board-table/board-table.tsx +610 -0
  266. package/ui/src/board/board-task/board-task.ts +108 -0
  267. package/ui/src/board/board-task/board-task.tsx +335 -0
  268. package/ui/src/board/board-title-row/board-title-row.tsx +66 -0
  269. package/ui/src/branding/branding.tsx +17 -0
  270. package/ui/src/branding/custom-logo.ts +1 -0
  271. package/ui/src/branding/favicon.default.svg +5 -0
  272. package/ui/src/branding/favicon.svg +5 -0
  273. package/ui/src/components/ui/avatar.tsx +39 -0
  274. package/ui/src/components/ui/button.tsx +64 -0
  275. package/ui/src/components/ui/collapsible.tsx +20 -0
  276. package/ui/src/components/ui/command.tsx +160 -0
  277. package/ui/src/components/ui/dialog.tsx +143 -0
  278. package/ui/src/components/ui/dropdown-menu.tsx +187 -0
  279. package/ui/src/components/ui/input.tsx +21 -0
  280. package/ui/src/components/ui/popover.tsx +41 -0
  281. package/ui/src/components/ui/select.tsx +163 -0
  282. package/ui/src/components/ui/separator.tsx +26 -0
  283. package/ui/src/components/ui/sheet.tsx +136 -0
  284. package/ui/src/components/ui/sidebar.tsx +693 -0
  285. package/ui/src/components/ui/skeleton.tsx +13 -0
  286. package/ui/src/components/ui/switch.tsx +25 -0
  287. package/ui/src/components/ui/table.tsx +82 -0
  288. package/ui/src/components/ui/tabs.tsx +52 -0
  289. package/ui/src/components/ui/tooltip.tsx +51 -0
  290. package/ui/src/data/intel-data-provider/intel-data-provider.ts +685 -0
  291. package/ui/src/data/intel-data-provider/intel-data-provider.types.ts +266 -0
  292. package/ui/src/data/query-client.ts +18 -0
  293. package/ui/src/data/request-refusal/refusal-notice.tsx +36 -0
  294. package/ui/src/data/request-refusal/request-refusal.ts +51 -0
  295. package/ui/src/data/sign-in/sign-in.ts +97 -0
  296. package/ui/src/data/sign-in/sign-in.types.ts +15 -0
  297. package/ui/src/document-link/document-link.tsx +114 -0
  298. package/ui/src/document-markdown/document-markdown.ts +195 -0
  299. package/ui/src/editor-schema/editor-schema.ts +23 -0
  300. package/ui/src/entry-picker/entry-picker.tsx +238 -0
  301. package/ui/src/feed/feed.tsx +344 -0
  302. package/ui/src/file-preview/file-preview-view.tsx +496 -0
  303. package/ui/src/file-preview/file-preview.tsx +28 -0
  304. package/ui/src/file-preview/pdf-file-preview.tsx +5 -0
  305. package/ui/src/file-preview/presentation-file-preview.tsx +21 -0
  306. package/ui/src/file-preview/spreadsheet-file-preview.tsx +5 -0
  307. package/ui/src/file-preview/word-file-preview.tsx +5 -0
  308. package/ui/src/flow-runs/flow-runs.tsx +238 -0
  309. package/ui/src/flows/flows.tsx +1646 -0
  310. package/ui/src/flows/node-icon/node-icon.ts +34 -0
  311. package/ui/src/flows/node-palette/node-palette.tsx +214 -0
  312. package/ui/src/flows/node-palette/node-palette.types.ts +15 -0
  313. package/ui/src/folder-contents/folder-contents.tsx +321 -0
  314. package/ui/src/folder-index/folder-index.ts +55 -0
  315. package/ui/src/frontmatter/frontmatter.tsx +193 -0
  316. package/ui/src/graph-pane/graph-pane.tsx +53 -0
  317. package/ui/src/hooks/use-mobile.ts +19 -0
  318. package/ui/src/i18n/custom.json +4 -0
  319. package/ui/src/i18n/de.json +609 -0
  320. package/ui/src/i18n/en.json +609 -0
  321. package/ui/src/i18n/es.json +609 -0
  322. package/ui/src/i18n/i18n-context.tsx +65 -0
  323. package/ui/src/i18n/i18n-languages/i18n-languages.ts +83 -0
  324. package/ui/src/i18n/i18n.ts +32 -0
  325. package/ui/src/i18n/i18n.types.ts +49 -0
  326. package/ui/src/kind-icon.ts +97 -0
  327. package/ui/src/lib/utils.ts +6 -0
  328. package/ui/src/main.tsx +68 -0
  329. package/ui/src/modal/modal.tsx +53 -0
  330. package/ui/src/node-details/node-details.tsx +545 -0
  331. package/ui/src/node-editor/node-editor.tsx +304 -0
  332. package/ui/src/node-graph/graph-notice.tsx +21 -0
  333. package/ui/src/node-graph/node-graph.ts +214 -0
  334. package/ui/src/node-graph/node-graph.tsx +295 -0
  335. package/ui/src/node-import/node-import.tsx +418 -0
  336. package/ui/src/node-save-error.ts +46 -0
  337. package/ui/src/node-source/node-source.tsx +128 -0
  338. package/ui/src/node-table/node-table.tsx +107 -0
  339. package/ui/src/nodes/nodes.tsx +240 -0
  340. package/ui/src/rename-resource/rename-resource.ts +80 -0
  341. package/ui/src/resolved-names/resolved-names.tsx +67 -0
  342. package/ui/src/resource-error.ts +33 -0
  343. package/ui/src/resource-menu/resource-menu.tsx +1156 -0
  344. package/ui/src/router/router-context.ts +6 -0
  345. package/ui/src/router/router.tsx +67 -0
  346. package/ui/src/router/router.types.ts +8 -0
  347. package/ui/src/router/selection-search.ts +88 -0
  348. package/ui/src/save-button/save-button.tsx +94 -0
  349. package/ui/src/section-hint/section-hint.tsx +40 -0
  350. package/ui/src/sign-in-refused/sign-in-refused.tsx +35 -0
  351. package/ui/src/styles.css +189 -0
  352. package/ui/src/table-columns/table-columns.tsx +379 -0
  353. package/ui/src/theme/custom.css +1 -0
  354. package/ui/src/theme/theme-context.tsx +89 -0
  355. package/ui/src/theme/theme.ts +70 -0
  356. package/ui/src/time/relative-time.tsx +41 -0
  357. package/ui/src/time/time-context.tsx +78 -0
  358. package/ui/src/time/time.ts +165 -0
  359. package/ui/src/title-row/title-row.tsx +185 -0
  360. package/ui/src/tools/tools.tsx +546 -0
  361. package/ui/src/user-name/user-name.ts +61 -0
  362. package/ui/src/verbatim/verbatim.tsx +68 -0
  363. package/ui/tsconfig.json +17 -0
  364. package/ui/vite.config.ts +129 -0
@@ -0,0 +1,161 @@
1
+ import { z } from "zod";
2
+
3
+ export const IntelId = z.string().min(1).max(128);
4
+ export const IsoDateTime = z.iso.datetime({ offset: true });
5
+
6
+ // ⚠️ One described primitive rather than the same sentence on twenty-odd fields (#398). The word
7
+ // `idempotencyKey` means exactly the same thing everywhere it appears, and a reader who learns it
8
+ // once at `node_create` should not have to re-read it at `flow_publish`. Twenty copies of one
9
+ // sentence is also twenty places for it to drift, and `tools/list` would carry every copy.
10
+ //
11
+ // The description says what the caller has to DO, because that is the part a model gets wrong: it
12
+ // invents a fresh key on the retry and creates the thing twice.
13
+ export const IdempotencyKey = z
14
+ .string()
15
+ .min(8)
16
+ .max(200)
17
+ .describe(
18
+ "A caller-chosen key that makes this call safe to retry: repeating the same key returns the first result instead of doing the work twice. Reuse the SAME key when retrying one attempt, and a new one for a genuinely new call.",
19
+ );
20
+
21
+ /**
22
+ * The short name a document or a published flow is offered under as a slash command (#775).
23
+ *
24
+ * ⚠️ One described primitive rather than the same sentence in two files, for the reason
25
+ * `IdempotencyKey` above gives: a document and a flow take the same kind of name out of the same
26
+ * catalogue, and a copy would be a second place for one sentence to drift. It sits here rather than
27
+ * in `node.ts` because `flow.ts` states it too, and this is the file both may read.
28
+ *
29
+ * ⚠️ The refusal spells the GRAMMAR, not the verdict. Zod's own `Invalid` tells a caller who sent
30
+ * `CRM Outreach` that something was wrong and not what would have worked, and the one thing they
31
+ * need is that the answer is `crm-outreach`.
32
+ *
33
+ * ⚠️ Uniqueness is NOT in this schema and cannot be: it is a question about the whole installation,
34
+ * across documents and flows at once, and it is answered where the write happens. A name another
35
+ * node or flow already holds is refused by name there, never quietly turned into a second one.
36
+ */
37
+ export const PromptName = z
38
+ .string()
39
+ .regex(/^[a-z0-9-]{1,40}$/, {
40
+ error:
41
+ "A prompt name is 1 to 40 characters of lowercase letters, digits and hyphens, and nothing else: `crm-outreach`.",
42
+ })
43
+ .describe(
44
+ "The slash command this is offered under, written without the leading slash: `crm-outreach` reaches a client as `/crm-outreach`. Lowercase letters, digits and hyphens only, and unique over every document and flow in the installation — a name one of them already holds is refused and names its holder, never silently changed into another one.",
45
+ );
46
+
47
+ /**
48
+ * The version a write is made against, in the one form every writer of versioned content takes it.
49
+ *
50
+ * ⚠️ It lived beside the two node writers until #459 and moved here when the flow graph became the
51
+ * third — the point at which the repository stops copying and names the thing. It could not simply
52
+ * be imported: `flow.ts` may not depend on `node.ts` (the graph is `table → node`, `flow-run →
53
+ * flow`, and everything → here), and a copy would have been a second place for one sentence to
54
+ * drift, which is exactly what `IdempotencyKey` above exists to avoid.
55
+ *
56
+ * ⚠️ Nullable and required are not the same thing, and here they stand together (#437). `null` is
57
+ * how something that has no version yet is addressed, and it is the only way to write its first
58
+ * content; leaving the field out says nothing at all and is refused. Whoever leaves it out is
59
+ * almost always holding a node or a flow created one call earlier, and the plain type error they
60
+ * used to get — "expected string, received undefined" — reads as "this field must be an id", about
61
+ * a field that cannot have one yet. Both refusals therefore name both ways instead.
62
+ *
63
+ * ⚠️ It stays required once a version exists, and that is what it is for: a mismatch is answered
64
+ * with a `409` rather than by overwriting somebody else's newer version. Making it `optional()` to
65
+ * smooth the first write is the repair that breaks the guard — an absent field would then have to
66
+ * mean "there is none", and the forgetful caller silently replaces the newest one.
67
+ *
68
+ * ⚠️ The bounds remain `IntelId`'s. The repeated `min(1)` adds no rule — it only puts the sentence
69
+ * on the second value that gets tried after `undefined`, the empty string.
70
+ *
71
+ * ⚠️ The sentence says what the field TAKES, not what the caller did wrong. It answers a wrong type
72
+ * as well as an absent field, and "is required" would be false about the first — which would be
73
+ * this same ticket one corner further on. A value that is merely too long keeps Zod's own `Too
74
+ * big`: that one is already a true statement about what was sent.
75
+ *
76
+ * ⚠️ The JSON Schema it produces is the one `IntelId.nullable()` produced — an `anyOf` of the
77
+ * bounded string and `null`, still `required` — so nothing on the MCP surface moves when a field
78
+ * changes over to it.
79
+ */
80
+ export function baseVersion(rule: string) {
81
+ return z.union([IntelId.min(1, { error: rule }), z.null()], { error: rule });
82
+ }
83
+
84
+ // The languages whose UI catalog ships inside the surface. They live here rather than only in the UI
85
+ // because `intel build` has to know them: a built-in language may be chosen as `ui.defaultLanguage`
86
+ // without the customer listing a copy under `ui.languages` that would rot at every UI update.
87
+ //
88
+ // ⚠️ The list is a claim about the contents of packages/intel/ui/src/i18n and cannot be checked here.
89
+ // `i18n.unit.ts` compares it against the catalogs actually built in; a language listed here without
90
+ // a file gives a red run there instead of a UI that starts on a catalog which does not exist.
91
+ export const UI_LANGUAGES = ["en", "de", "es"] as const;
92
+ export type UiLanguage = (typeof UI_LANGUAGES)[number];
93
+
94
+ /**
95
+ * A set of things the reader is only partly entitled to see: the ones they may see BY NAME, the
96
+ * rest as a NUMBER (ADR-0004 §3). Never the titles of the rest, in any field, ever — a warning or a
97
+ * refusal must not become a way of reading the tree.
98
+ *
99
+ * ⚠️ It lives here rather than in `share.ts` because two domains state it: a grant says what it
100
+ * does not reach (`UnreadableNodes`), and a refusal says who is still calling in
101
+ * (`ProblemDetails.callers`, #448). `contract.ts` may not import from `share.ts` — the graph
102
+ * between these files has to stay acyclic — and a copy would be a second place for one rule to
103
+ * drift, which is what `IdempotencyKey` and `baseVersion` above exist against.
104
+ */
105
+ export const NamedOrCounted = z.strictObject({
106
+ titles: z.array(z.string().min(1).max(240)),
107
+ hidden: z.number().int().nonnegative(),
108
+ });
109
+ export type NamedOrCounted = z.infer<typeof NamedOrCounted>;
110
+
111
+ /**
112
+ * ⚠️ `callers` is the one member here that is not about every problem, and it is deliberate (#448).
113
+ * RFC 9457 allows extension members for exactly this: `folder_execute_in_use` refuses to narrow a
114
+ * library folder while flows from outside still call into it, and the CALLERS are the only thing
115
+ * that makes the refusal actionable. They used to exist only inside `detail` — an English sentence
116
+ * built on the server — so a German or Spanish surface could do nothing but print it verbatim, and
117
+ * no surface could shorten it or link the titles.
118
+ *
119
+ * The split is the point: the server decides WHAT is named and what is only counted, because that
120
+ * is an authorization answer nobody else can give; the surface decides how the sentence READS,
121
+ * because that is a language answer no server can give.
122
+ *
123
+ * `detail` keeps its sentence rather than emptying out — MCP hands a model prose and has nothing to
124
+ * formulate with, and an empty `detail` beside a new field would be the worst of the three states.
125
+ * It is absent on every other problem, so a reader must not treat its presence as guaranteed.
126
+ */
127
+ export const ProblemDetails = z.strictObject({
128
+ type: z.string(),
129
+ status: z.number().int().min(400).max(599),
130
+ title: z.string(),
131
+ detail: z.string().optional(),
132
+ instance: z.string().optional(),
133
+ code: z.string().optional(),
134
+ callers: NamedOrCounted.optional(),
135
+ });
136
+ export type ProblemDetails = z.infer<typeof ProblemDetails>;
137
+
138
+ // Who the caller is, as Gate resolved it from the bearer: no token, and no capability list.
139
+ //
140
+ // ⚠️ `isAdmin` is the one exception, and it is a DRAWING instruction rather than a permission
141
+ // (#416). MCP hides what a caller may not do by never registering the tool, so a model never sees a
142
+ // door it cannot open; the browser has no equivalent and would have to offer an admin action to
143
+ // everybody and answer with a 403. One boolean is what the shell needs to not do that.
144
+ //
145
+ // Two things keep it from becoming a capability list by degrees: it says what the shell may DRAW,
146
+ // never what the server may do — every door still asks Gate itself — and it is one field with one
147
+ // consumer. A second one is a second reason, written down when it exists.
148
+ export const SessionUser = z.strictObject({
149
+ id: IntelId,
150
+ email: z.email(),
151
+ name: z.string().min(1).max(240).nullable(),
152
+ isAdmin: z.boolean(),
153
+ });
154
+ export type SessionUser = z.infer<typeof SessionUser>;
155
+
156
+ // One reference, never a list. The old `knowledge` node carried up to a hundred, plus a retrieval
157
+ // mode and a query that nothing read — three things in one, and the last two describing a retrieval
158
+ // Intel does not perform (D24: the agent fetches, Intel does not put anything into a context).
159
+ // Splitting by kind is what makes "exactly one" sayable at all, and it lets the editor filter the
160
+ // picker by what the node is for.
161
+ export const LinkConfiguration = z.strictObject({ resourceId: IntelId });
@@ -0,0 +1,165 @@
1
+ import { z } from "zod";
2
+ import { IntelId, IsoDateTime } from "./contract.ts";
3
+
4
+ // What a person did, in the words a person would use. This is a POSITIVE LIST and not the set of
5
+ // actions the journal carries (#740).
6
+ //
7
+ // ⚠️ Two omissions are the point of the list, not an oversight. `node.version` is written by the
8
+ // same batch as `node.save`, so admitting both would show every edit twice — and because this feed
9
+ // does not group anything yet, twice means two cards. `node.link` and `node.import` are machine
10
+ // traces of a save rather than something anybody did.
11
+ //
12
+ // ⚠️ And it stays a positive list. "Everything except" would silently admit whatever the next
13
+ // migration starts writing, on a surface whose whole job is to be readable.
14
+ export const FeedAction = z.enum([
15
+ "node.create",
16
+ "node.save",
17
+ "node.update",
18
+ "node.append",
19
+ "node.archive",
20
+ // ⚠️ The one event whose node no longer exists when it is read. Its visibility runs over the
21
+ // surviving folder, from `parentId` in the metadata, and its title comes from there too — the row
22
+ // it would have been read from is gone (#645).
23
+ "node.purge",
24
+ "node.share",
25
+ "node.revoke",
26
+ // The flow half (#763). Twelve kinds are written; these are the ones a person did rather than a
27
+ // machine bookkeeping step.
28
+ //
29
+ // ⚠️ **`flows.run` is deliberately NOT here, and its two siblings are** (#767, Jacks Entscheidung
30
+ // 2026-08-24). A run writes up to three events, and an agent runs often — without summarising,
31
+ // which #742 struck, twenty runs on one morning would be sixty cards and every human entry would
32
+ // lie buried under them.
33
+ //
34
+ // The END was chosen over the START, and not because it is cheaper: a finished run carries BOTH
35
+ // pieces — that it ran *and* how it went — while a start carries half of one. A run that hangs or
36
+ // fails looks exactly like one that sailed through, and that is the case somebody opens the feed
37
+ // for. What it costs is that a long run is invisible until it ends; that is the deliberate price
38
+ // of needing no merge over the run id, which is the only way a start-card could later be updated.
39
+ //
40
+ // ⚠️ These two are the only actions in this list written against `resource_type = 'flow-run'`,
41
+ // with the RUN's id — which is why `feedResourceTypeOf` exists below and why the query needs a
42
+ // third visibility walk (run → flow → folder) and a title read from the flow.
43
+ "flows.complete",
44
+ "flows.cancel",
45
+ "flows.create",
46
+ "flows.save",
47
+ "flows.update",
48
+ "flows.publish",
49
+ "flows.unpublish",
50
+ "flows.archive",
51
+ "flows.share",
52
+ "flows.revoke",
53
+ // ⚠️ The flow-side twin of `node.purge`, and it carries the same two consequences: its row is
54
+ // gone when the card is read, so both its visibility and its title come from the metadata of the
55
+ // event itself (#763, D73).
56
+ "flows.purge",
57
+ ]);
58
+ export type FeedAction = z.infer<typeof FeedAction>;
59
+
60
+ /**
61
+ * What an entry is about. Derived from the action rather than carried separately: the two can then
62
+ * never disagree, and a reader that has to draw a flow differently from a document does not depend
63
+ * on a second field being filled in correctly.
64
+ */
65
+ export function feedKindOf(action: FeedAction): "node" | "flow" {
66
+ return action.startsWith("flows.") ? "flow" : "node";
67
+ }
68
+
69
+ /**
70
+ * Which `resource_type` the journal wrote an action against — a different question from
71
+ * `feedKindOf`, and the two answers disagree on purpose for exactly two actions (#767).
72
+ *
73
+ * A card about a finished run is a card about a **flow**: that is what it names, that is where it
74
+ * links, and `feedKindOf` says so. But the ROW it was written as carries `flow-run` and the run's
75
+ * id, so the query has to find it under a third kind and walk run → flow → folder to decide whether
76
+ * it may be seen.
77
+ *
78
+ * ⚠️ Derived here rather than written out beside the SQL. A second list that has to agree with this
79
+ * one is a second list too many — the same reason `NODE_ACTIONS` and `FLOW_ACTIONS` are filtered
80
+ * out of `FeedAction.options` instead of being typed again.
81
+ */
82
+ export function feedResourceTypeOf(action: FeedAction): "node" | "flow" | "flow-run" {
83
+ if (action === "flows.complete" || action === "flows.cancel") return "flow-run";
84
+ return feedKindOf(action);
85
+ }
86
+
87
+ // One step on the way down to the node, from the root. It carries the id as well as the title
88
+ // because the surface links each step, and two folders may share a name.
89
+ export const FeedPathSegment = z.strictObject({
90
+ id: IntelId,
91
+ title: z.string().min(1),
92
+ });
93
+ export type FeedPathSegment = z.infer<typeof FeedPathSegment>;
94
+
95
+ // One card's worth of journal.
96
+ //
97
+ // ⚠️ `resourceTitle` and `path` are read from `nodes` or `flows` at query time, so they are TODAY's
98
+ // title and today's place — not the ones the thing had when the event happened. That is the right
99
+ // answer for a feed (the reader wants to find it now) and the wrong one for an audit trail, which is
100
+ // one more reason these are two doors and not one.
101
+ //
102
+ // ⚠️ The fields say `resource` and not `node` because half of them are not nodes (#763). Which half
103
+ // is answered by `feedKindOf(action)` and by nothing on the card — a second field saying "flow"
104
+ // beside an action that already says `flows.publish` is a second truth, and two truths disagree.
105
+ //
106
+ // `metadata` is whatever the write site recorded, untyped on purpose: a schema per action would
107
+ // have to be kept in step with eleven write sites and would go stale in silence. What the surface
108
+ // needs from it today is `sequence` on a `node.save`, which is the version number behind the card's
109
+ // button.
110
+ export const FeedEvent = z.strictObject({
111
+ id: IntelId,
112
+ actorId: z.string().min(1),
113
+ action: FeedAction,
114
+ resourceId: IntelId,
115
+ resourceTitle: z.string().min(1),
116
+ path: z.array(FeedPathSegment),
117
+ metadata: z.record(z.string(), z.unknown()),
118
+ occurredAt: IsoDateTime,
119
+ });
120
+ export type FeedEvent = z.infer<typeof FeedEvent>;
121
+
122
+ // ⚠️ Opaque BY CONTRACT, like the audit cursor and for the same reason: it is a PAIR
123
+ // (`occurredAt`, `id`), and a timestamp alone cannot separate two events written in the same
124
+ // millisecond — the normal case inside one batch. A reader continuing on the timestamp alone skips
125
+ // the second one with no error and no log.
126
+ //
127
+ // ⚠️ It is deliberately NOT interchangeable with an audit cursor, although both encode the same
128
+ // pair. The two doors walk the journal in opposite directions, so handing one's position to the
129
+ // other reads on from the wrong end — and would look like a feed that suddenly starts at the
130
+ // beginning of time rather than like a mistake. The encoding therefore carries its own marker and
131
+ // the other door's cursor is refused.
132
+ export const FeedCursor = z.string().min(1).max(400);
133
+
134
+ export const FeedListRequest = z.strictObject({
135
+ actor: z
136
+ .string()
137
+ .min(1)
138
+ .optional()
139
+ .describe(
140
+ "Show only what this person or agent did. Omit it for everybody whose work you may see anyway.",
141
+ ),
142
+ before: FeedCursor.optional().describe(
143
+ "Where to continue: the `nextCursor` of a previous answer, passed back unchanged. Omit it to start at the most recent event. Do not build one — it is opaque on purpose, and a cursor from `audit_list` is refused rather than followed backwards.",
144
+ ),
145
+ limit: z
146
+ .number()
147
+ .int()
148
+ .min(1)
149
+ .max(100)
150
+ .default(30)
151
+ .describe("How many events to return at most. The answer may be shorter."),
152
+ });
153
+ export type FeedListRequest = z.infer<typeof FeedListRequest>;
154
+
155
+ // `nextCursor` is present exactly when another page may exist, and it is the cursor of the LAST
156
+ // returned row.
157
+ //
158
+ // ⚠️ Present does not promise the next page is non-empty: the rows a reader may see can shrink
159
+ // between calls. Treating "cursor present" as "there is more" is fair; treating an empty answer as
160
+ // "you have reached the beginning of the journal" is not.
161
+ export const FeedListResponse = z.strictObject({
162
+ events: z.array(FeedEvent),
163
+ nextCursor: FeedCursor.nullable(),
164
+ });
165
+ export type FeedListResponse = z.infer<typeof FeedListResponse>;
@@ -0,0 +1,241 @@
1
+ import { z } from "zod";
2
+ import { IdempotencyKey, IntelId, IsoDateTime } from "./contract.ts";
3
+ import { FlowNode, FlowNodeId } from "./flow.ts";
4
+
5
+ // ⚠️ No `waiting`. It was written for the approval node and never set by anything — the two places
6
+ // that tested for it only ever saw `running` (#73). The column's CHECK constraint still allows the
7
+ // value, deliberately: rewriting it means rebuilding the table in D1 for a value nothing writes,
8
+ // and migration 0007 turns any row that somehow carries it into `failed` rather than leave a status
9
+ // the contract cannot parse.
10
+ export const FlowRunStatus = z.enum(["queued", "running", "completed", "failed", "cancelled"]);
11
+ export type FlowRunStatus = z.infer<typeof FlowRunStatus>;
12
+ export const FlowRun = z.strictObject({
13
+ id: IntelId,
14
+ flowId: IntelId,
15
+ versionId: IntelId,
16
+ status: FlowRunStatus,
17
+ currentNodeId: FlowNodeId.nullable(),
18
+ input: z.record(z.string(), z.unknown()),
19
+ output: z.unknown().nullable(),
20
+ error: z.string().max(2_000).nullable(),
21
+ initiatedBy: IntelId,
22
+ // The subflow node this run was called from, and the run that node belongs to. A called run is a
23
+ // run of its own: it has its own version, its own steps and its own authorization, and only these
24
+ // two fields say where its result goes back to.
25
+ parentRunId: IntelId.nullable().default(null),
26
+ parentNodeId: FlowNodeId.nullable().default(null),
27
+ createdAt: IsoDateTime,
28
+ updatedAt: IsoDateTime,
29
+ completedAt: IsoDateTime.nullable(),
30
+ });
31
+ export type FlowRun = z.infer<typeof FlowRun>;
32
+
33
+ // Which step of which flow is running, outermost caller first. Readable rather than reconstructed
34
+ // from `parentRunId` by whoever is looking (#17).
35
+ export const FlowRunTrailEntry = z.strictObject({
36
+ runId: IntelId,
37
+ flowId: IntelId,
38
+ flowTitle: z.string().min(1).max(240),
39
+ nodeId: FlowNodeId.nullable(),
40
+ nodeLabel: z.string().max(160).nullable(),
41
+ });
42
+ export type FlowRunTrailEntry = z.infer<typeof FlowRunTrailEntry>;
43
+
44
+ export const FlowRunStep = z.strictObject({
45
+ run: FlowRun,
46
+ node: FlowNode.nullable(),
47
+ trail: z.array(FlowRunTrailEntry).default([]),
48
+ });
49
+ export type FlowRunStep = z.infer<typeof FlowRunStep>;
50
+ export const StartFlowRunInput = z.strictObject({
51
+ flowId: IntelId.describe(
52
+ "Flow to run. It has to be published; the run takes the published version, not the newest one.",
53
+ ),
54
+ input: z
55
+ .record(z.string(), z.unknown())
56
+ .default({})
57
+ .describe(
58
+ "The values the flow's trigger node declares. An empty object is right for a flow that asks for nothing.",
59
+ ),
60
+ // Present when this run is the call a subflow node makes. It names a place, never a permission:
61
+ // the callee's `execute` is asked of the user exactly as it is for a run they start themselves,
62
+ // and the parent run must be the caller's own and standing on that very node.
63
+ parent: z
64
+ .strictObject({
65
+ runId: IntelId.describe("The calling run."),
66
+ nodeId: FlowNodeId.describe("The subflow node in that run which is making the call."),
67
+ })
68
+ .nullable()
69
+ .default(null)
70
+ .describe(
71
+ "Leave at `null`. It is set only when a subflow node makes this call, and it names a place rather than a permission: the callee's `execute` is still asked of the user.",
72
+ ),
73
+ idempotencyKey: IdempotencyKey,
74
+ });
75
+ export type StartFlowRunInput = z.infer<typeof StartFlowRunInput>;
76
+ export const GetFlowRunInput = z.strictObject({
77
+ runId: IntelId.describe(
78
+ "Run to read. A run has an address of its own because it outlives its flow; the id comes from flow_run_start or flow_run_list.",
79
+ ),
80
+ });
81
+ export type GetFlowRunInput = z.infer<typeof GetFlowRunInput>;
82
+ // Ending a run on purpose (#145). Until this existed the only way off a parked manual step was
83
+ // `completeStep` with `outcome: "failed"` — which recorded a step failure that never happened.
84
+ // Cancelling records nothing into the step history: the run ends, the history stays true.
85
+ export const CancelFlowRunInput = z.strictObject({
86
+ runId: IntelId.describe(
87
+ "Run to end on purpose. This is the way off a run parked on a manual step — it records nothing into the step history, unlike completing the step as `failed`, which would report a failure that never happened.",
88
+ ),
89
+ idempotencyKey: IdempotencyKey,
90
+ });
91
+ export type CancelFlowRunInput = z.infer<typeof CancelFlowRunInput>;
92
+ export const CompleteFlowRunStepInput = z.strictObject({
93
+ runId: IntelId.describe("Run that is waiting."),
94
+ nodeId: FlowNodeId.describe(
95
+ "The node the run is standing on, from flow_run_get. Answering any other node is refused: this completes the step that is waiting, not a step of one's choosing.",
96
+ ),
97
+ outcome: z
98
+ .enum(["completed", "failed"])
99
+ .describe("Whether the step is done or could not be done. `failed` ends the run at this node."),
100
+ branch: z
101
+ .string()
102
+ .min(1)
103
+ .max(120)
104
+ .nullable()
105
+ .default(null)
106
+ .describe(
107
+ "Which way out of a branching node the run takes, by the label on the edge. `null` for a node with one way out.",
108
+ ),
109
+ output: z
110
+ .unknown()
111
+ .nullable()
112
+ .default(null)
113
+ .describe(
114
+ "What the step produced, for the nodes after it to read. `null` when it produced nothing.",
115
+ ),
116
+ error: z
117
+ .string()
118
+ .max(2_000)
119
+ .nullable()
120
+ .default(null)
121
+ .describe(
122
+ 'Why it could not be done. Belongs with `outcome: "failed"` and is what the run\'s failure will say.',
123
+ ),
124
+ idempotencyKey: IdempotencyKey,
125
+ });
126
+ export type CompleteFlowRunStepInput = z.infer<typeof CompleteFlowRunStepInput>;
127
+
128
+ // Why a run started. Derived when it is read and deliberately not a column: `subflow` when the run
129
+ // is the call another run made, otherwise the mode of the trigger node in the immutable version the
130
+ // run took. A stored copy would be a second answer that could disagree with the graph that ran.
131
+ //
132
+ // ⚠️ `webhook` and `schedule` stood here until #39 took them out of the trigger node. Being derived
133
+ // rather than stored is exactly what makes that safe: no run carries a trigger of its own, so once
134
+ // the 0005 migration has rewritten every stored trigger to `manual`, there is nowhere left for the
135
+ // old values to come from. Had this been a column, the enum would have had to keep reading them or
136
+ // every old run would have failed to parse the moment somebody opened the list.
137
+ export const FlowRunTrigger = z.enum(["manual", "subflow"]);
138
+ export type FlowRunTrigger = z.infer<typeof FlowRunTrigger>;
139
+
140
+ // Which step ended a run, and why, in the words the failure already used (#20).
141
+ //
142
+ // ⚠️ A call that failed carries its reason in the *called* run, and that run is a run of its own
143
+ // with its own authorization. `calledRunId` is therefore filled only when the asking user may see
144
+ // that run through the very rule every other run answer uses; otherwise the failure is named by the
145
+ // calling step alone — the caller's own label — and `detail` says no more than that it did not
146
+ // finish. Naming a callee's step or document here would be the leak #17, #19 and #20 each closed.
147
+ export const FlowRunFailure = z.strictObject({
148
+ nodeId: FlowNodeId,
149
+ nodeLabel: z.string().max(160),
150
+ detail: z.string().max(2_000),
151
+ calledRunId: IntelId.nullable(),
152
+ });
153
+ export type FlowRunFailure = z.infer<typeof FlowRunFailure>;
154
+
155
+ // One run as a list shows it: what it did, never what it produced.
156
+ //
157
+ // ⚠️ Neither `input` nor `output` is in here, on purpose. A run reaches its nodes and its tools
158
+ // with the rights of whoever started it, so its result is a way to content the next reader of this
159
+ // list may have no claim to. Whoever wants a result asks for the run itself, where the same rule
160
+ // decides again.
161
+ export const FlowRunSummary = z.strictObject({
162
+ id: IntelId,
163
+ flowId: IntelId,
164
+ // The version the run took. Together with the run's stored input it is what a later "run this
165
+ // again with the old data" would need; replaying is a separate ticket, this only keeps it possible.
166
+ versionId: IntelId,
167
+ status: FlowRunStatus,
168
+ trigger: FlowRunTrigger,
169
+ startedAt: IsoDateTime,
170
+ completedAt: IsoDateTime.nullable(),
171
+ durationMs: z.number().int().nonnegative().nullable(),
172
+ initiatedBy: IntelId,
173
+ parentRunId: IntelId.nullable(),
174
+ failure: FlowRunFailure.nullable(),
175
+ });
176
+ export type FlowRunSummary = z.infer<typeof FlowRunSummary>;
177
+
178
+ // One filter and nothing else: "only the failed ones" is the question asked in almost every case,
179
+ // and every further facet is a report rather than a search for a fault.
180
+ export const ListFlowRunsInput = z.strictObject({
181
+ /**
182
+ * ⚠️ `nullable` since #774, and the null case is the point rather than a convenience.
183
+ *
184
+ * With a flow named, this answers "what did THIS flow do". Without one it answers "did anything
185
+ * run at all" — the question somebody actually has, and the one that used to take one call per
186
+ * flow. An installation with sixteen flows made that sixteen calls, so in practice nobody asked
187
+ * it and a working agent was indistinguishable from a silent one.
188
+ *
189
+ * The visibility does not change with it: `runVisible` decides per ROW either way — their own
190
+ * runs, plus every run of a flow they may read.
191
+ */
192
+ flowId: IntelId.nullable()
193
+ .default(null)
194
+ .describe(
195
+ "Flow whose runs to list, newest first. `null` lists the runs of every flow you may read — the answer to `did anything run`, which otherwise takes one call per flow. Each row carries its flowId; the titles come from flow_list in one call.",
196
+ ),
197
+ failedOnly: z.boolean().default(false).describe("List only the runs that failed."),
198
+ limit: z.number().int().min(1).max(50).default(20).describe("How many runs per page."),
199
+ // The `nextCursor` of the previous page. Keyset rather than an offset, because runs arrive while
200
+ // someone reads and an offset would skip or repeat rows exactly when a flow is busy.
201
+ cursor: z
202
+ .string()
203
+ .min(1)
204
+ .max(400)
205
+ .nullable()
206
+ .default(null)
207
+ .describe(
208
+ "The `nextCursor` of the previous page, or `null` for the first. It is a keyset rather than an offset, so runs arriving while someone reads neither skip nor repeat a row.",
209
+ ),
210
+ });
211
+ export type ListFlowRunsInput = z.infer<typeof ListFlowRunsInput>;
212
+
213
+ export const FlowRunList = z.strictObject({
214
+ items: z.array(FlowRunSummary),
215
+ nextCursor: z.string().max(400).nullable(),
216
+ });
217
+ export type FlowRunList = z.infer<typeof FlowRunList>;
218
+
219
+ // One completed step of one run. `detail` is the step's own error text; an output is absent for the
220
+ // same reason it is absent from the summary.
221
+ export const FlowRunStepRecord = z.strictObject({
222
+ nodeId: FlowNodeId,
223
+ nodeLabel: z.string().max(160),
224
+ outcome: z.enum(["completed", "failed"]),
225
+ branch: z.string().max(120).nullable(),
226
+ detail: z.string().max(2_000).nullable(),
227
+ calledRunId: IntelId.nullable(),
228
+ completedAt: IsoDateTime,
229
+ });
230
+ export type FlowRunStepRecord = z.infer<typeof FlowRunStepRecord>;
231
+
232
+ // What one run did, step by step, oldest first, with the call chain it belongs to (#17). The trail
233
+ // is what makes a nested run readable: which step of which flow this run is.
234
+ export const FlowRunHistory = z.strictObject({
235
+ runId: IntelId,
236
+ flowId: IntelId,
237
+ status: FlowRunStatus,
238
+ steps: z.array(FlowRunStepRecord),
239
+ trail: z.array(FlowRunTrailEntry),
240
+ });
241
+ export type FlowRunHistory = z.infer<typeof FlowRunHistory>;