@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,967 @@
1
+ import type {
2
+ ContentPart,
3
+ DoneReason,
4
+ InboundEvent,
5
+ Input,
6
+ LoopAggregate,
7
+ Message,
8
+ Provider,
9
+ SessionStore,
10
+ Tool,
11
+ ToolContext,
12
+ } from "@k2b/nessi";
13
+ import type { Usage } from "@k2b/nessi/ai";
14
+ import type { z } from "zod";
15
+ import type { CapabilityActionReview, CloudResourceRef } from "../contracts/capabilities";
16
+ import type { RequestActor } from "../server";
17
+ import type { AiTurnBlock } from "./protocol";
18
+
19
+ export const AI_MODEL_CAPABILITIES = ["streaming", "tools", "vision"] as const;
20
+ export type AiModelCapability = (typeof AI_MODEL_CAPABILITIES)[number];
21
+
22
+ export const AI_IMAGE_MEDIA_TYPES = ["image/png", "image/jpeg", "image/jpg", "image/webp", "image/gif"] as const;
23
+ export type AiImageMediaType = (typeof AI_IMAGE_MEDIA_TYPES)[number];
24
+ export const isAiImageMediaType = (value: string): value is AiImageMediaType =>
25
+ AI_IMAGE_MEDIA_TYPES.some((mediaType) => mediaType === value);
26
+
27
+ export type AiProviderId = "openai" | "openrouter" | "anthropic" | "mistral" | "gemini" | "ollama" | "vllm" | "openai-compatible";
28
+
29
+ export const AI_DATA_BOUNDARIES = ["hosted", "private"] as const;
30
+ export type AiDataBoundary = (typeof AI_DATA_BOUNDARIES)[number];
31
+ /** @deprecated Use AiDataBoundary. */
32
+ export type AiDataPolicy = AiDataBoundary;
33
+
34
+ export type AiModelProfile = {
35
+ id: string;
36
+ label: string;
37
+ provider: AiProviderId;
38
+ model: string;
39
+ enabled: boolean;
40
+ /** Small logo (data URL, hard-compressed) shown in the admin card and the composer model picker. */
41
+ image?: string;
42
+ capabilities: AiModelCapability[];
43
+ dataBoundary: AiDataBoundary;
44
+ baseURL?: string;
45
+ contextWindow?: number;
46
+ temperature?: number;
47
+ maxOutputTokens?: number;
48
+ /** Maximum deferred tools retained per conversation. Missing or <= 0 keeps all loaded tools. */
49
+ maxLoadedTools?: number;
50
+ /** Tool-using model rounds per chat turn. Missing or <= 0 is unlimited. */
51
+ maxToolRounds?: number;
52
+ creditsPerInputToken?: number;
53
+ creditsPerOutputToken?: number;
54
+ };
55
+
56
+ export type AiPublicModelProfile = Pick<
57
+ AiModelProfile,
58
+ "id" | "label" | "provider" | "model" | "image" | "capabilities" | "dataBoundary" | "contextWindow"
59
+ >;
60
+
61
+ export type AiUserContentPart = ContentPart;
62
+
63
+ export type AiSettingsErrorCode =
64
+ | "ai_disabled"
65
+ | "invalid_model_profiles"
66
+ | "missing_default_model"
67
+ | "default_model_disabled"
68
+ | "missing_provider_credential"
69
+ | "model_policy_mismatch"
70
+ | "model_access_denied";
71
+
72
+ export type AiSettingsError = {
73
+ code: AiSettingsErrorCode;
74
+ message: string;
75
+ fields?: Record<string, string>;
76
+ };
77
+
78
+ export type AiSettingsState =
79
+ | {
80
+ ok: true;
81
+ enabled: boolean;
82
+ defaultModelId: string;
83
+ visionModelId?: string;
84
+ globalInstructions: string;
85
+ compactionInstructions: string;
86
+ maxToolResultChars: number;
87
+ firecrawlConfigured: boolean;
88
+ profiles: AiModelProfile[];
89
+ }
90
+ | {
91
+ ok: false;
92
+ enabled: boolean;
93
+ defaultModelId: string;
94
+ visionModelId?: string;
95
+ globalInstructions: string;
96
+ compactionInstructions: string;
97
+ maxToolResultChars: number;
98
+ firecrawlConfigured: boolean;
99
+ profiles: AiModelProfile[];
100
+ error: AiSettingsError;
101
+ };
102
+
103
+ export type AiModelPolicy =
104
+ | { kind: "platform-default"; allowedDataBoundaries?: AiDataBoundary[]; requiredCapabilities?: AiModelCapability[] }
105
+ | { kind: "locked"; modelId: string; allowedDataBoundaries?: AiDataBoundary[]; requiredCapabilities?: AiModelCapability[] }
106
+ | {
107
+ kind: "selectable";
108
+ defaultModelId?: string;
109
+ allowedModelIds?: string[];
110
+ allowedDataBoundaries?: AiDataBoundary[];
111
+ requiredCapabilities?: AiModelCapability[];
112
+ };
113
+
114
+ export type AiResolvedModel = {
115
+ profile: AiModelProfile;
116
+ provider: Provider;
117
+ };
118
+
119
+ export type AiDraftContentPart =
120
+ | { type: "text"; text: string }
121
+ | { type: "resource"; ref: CloudResourceRef; title?: string; icon?: string; href?: string }
122
+ | { type: "file"; path: string; mediaType: string; size: number; version: number };
123
+
124
+ export type AiConversationDraft = {
125
+ content: AiDraftContentPart[];
126
+ revision: number;
127
+ updatedAt: string | null;
128
+ };
129
+
130
+ export type AiConversationFieldSource = "default" | "auto" | "user";
131
+ export type AiConversationTitleSource = AiConversationFieldSource;
132
+ export type AiConversationRunStatus = "idle" | "queued" | "running" | "needs_attention" | "failed";
133
+ export type AiConversationStatusFilter = Exclude<AiConversationRunStatus, "idle" | "queued"> | "unread";
134
+
135
+ export type AiConversation = {
136
+ id: string;
137
+ shortId: string;
138
+ title: string;
139
+ /** Who set the current title — enrichment never overwrites a user-chosen title. */
140
+ titleSource: AiConversationFieldSource;
141
+ /** User-visible description. Kept fresh by the enrichment job until the user edits it. */
142
+ description: string;
143
+ /** Who wrote the current description — enrichment never overwrites a user-authored one. */
144
+ descriptionSource: AiConversationFieldSource;
145
+ /** AI-generated keywords for search. */
146
+ keywords: string[];
147
+ pinnedAt: string | null;
148
+ archivedAt: string | null;
149
+ runStatus: AiConversationRunStatus;
150
+ /** Error from the latest turn when `runStatus` is `failed`. */
151
+ runError: string | null;
152
+ unreadCompletion: boolean;
153
+ /** Optional shared project context; the conversation itself remains private to its owner. */
154
+ projectId: string | null;
155
+ /** Mutable pending user message. It is not part of model context until a turn consumes it. */
156
+ draft: AiConversationDraft;
157
+ createdByUserId: string | null;
158
+ /** Application that explicitly launched this chat through `launchAssistant`; null for direct Assistant chats. */
159
+ launchedByAppId?: string | null;
160
+ /** Immutable tool ceiling for this conversation; null means unrestricted discovery. */
161
+ allowedTools?: string[] | null;
162
+ createdAt: string;
163
+ updatedAt: string;
164
+ };
165
+
166
+ export const AI_MESSAGE_FEEDBACK_REASONS = [
167
+ "incorrect",
168
+ "did_not_follow_request",
169
+ "incomplete",
170
+ "poor_tool_choice",
171
+ "too_slow",
172
+ "other",
173
+ ] as const;
174
+ export type AiMessageFeedbackReason = (typeof AI_MESSAGE_FEEDBACK_REASONS)[number];
175
+
176
+ export type AiMessageFeedback = {
177
+ rating: "up" | "down";
178
+ reasons: AiMessageFeedbackReason[];
179
+ comment: string | null;
180
+ updatedAt: string;
181
+ };
182
+
183
+ export type AiEnrichmentRunStatus = "ok" | "failed" | "skipped";
184
+ export type AiEnrichmentTrigger = "scheduled" | "manual";
185
+
186
+ /** One recorded enrichment attempt for a conversation — user-visible in chat settings. */
187
+ export type AiEnrichmentRun = {
188
+ id: string;
189
+ conversationId: string;
190
+ status: AiEnrichmentRunStatus;
191
+ trigger: AiEnrichmentTrigger;
192
+ modelProfileId: string | null;
193
+ /** nessi structured mode of the successful call: native | fallback | repair. */
194
+ mode: string | null;
195
+ durationMs: number | null;
196
+ titleUpdated: boolean;
197
+ keywordsCount: number;
198
+ error: string | null;
199
+ createdAt: string;
200
+ };
201
+
202
+ /** Current index state of one conversation, for the chat settings UI. */
203
+ export type AiEnrichmentStatus = {
204
+ enrichedAt: string | null;
205
+ /** Content changed since the last enrichment (or never enriched). */
206
+ dirty: boolean;
207
+ enrichFailCount: number;
208
+ /** Current AI-generated search keywords. */
209
+ keywords: string[];
210
+ };
211
+
212
+ export type AiEnrichmentOverviewRun = AiEnrichmentRun & {
213
+ conversationTitle: string;
214
+ };
215
+
216
+ export type AiEnrichmentOverview = {
217
+ totalConversations: number;
218
+ dirtyConversations: number;
219
+ failedConversations: number;
220
+ oldestDirtyAt: string | null;
221
+ lastRunAt: string | null;
222
+ avgDurationMs: number | null;
223
+ failedRuns24h: number;
224
+ totalRuns24h: number;
225
+ errorRate24h: number;
226
+ recentRuns: AiEnrichmentOverviewRun[];
227
+ };
228
+
229
+ export type AiEnrichmentCandidate = AiConversation & {
230
+ /**
231
+ * The conversation's updated_at exactly as stored (Postgres microsecond
232
+ * precision, via ::text). Written back as enriched_at — the ISO `updatedAt`
233
+ * field is millisecond-truncated and would leave the chat dirty forever.
234
+ */
235
+ dirtyAsOf: string;
236
+ /** Consecutive failed enrichment attempts (drives the retry backoff). */
237
+ enrichFailCount: number;
238
+ };
239
+
240
+ export type AiConversationPage = {
241
+ items: AiConversation[];
242
+ total: number;
243
+ page: number;
244
+ perPage: number;
245
+ hasNext: boolean;
246
+ };
247
+
248
+ export type AiConversationProjectUpdateResult =
249
+ | { ok: true; conversation: AiConversation }
250
+ | { ok: false; reason: "not_found" | "active_turn" };
251
+
252
+ export type AiStoredMessage = {
253
+ id: string;
254
+ shortId: string;
255
+ conversationId: string;
256
+ seq: number;
257
+ kind: "message" | "summary";
258
+ message: Message;
259
+ loopId: string | null;
260
+ modelProfileId: string | null;
261
+ providerModel: string | null;
262
+ usage: Usage | null;
263
+ stopReason: string | null;
264
+ loopAggregate: LoopAggregate | null;
265
+ loopDoneReason: DoneReason | null;
266
+ /**
267
+ * Set once compaction archived this message out of the model context.
268
+ * Archived messages stay visible in the chat; only the model stops seeing them.
269
+ */
270
+ compactedAt: string | null;
271
+ /** UI metadata (e.g. how many messages a compaction summary replaced). */
272
+ meta: {
273
+ compactedCount?: number;
274
+ steerId?: string;
275
+ agentMessage?: {
276
+ id: string;
277
+ sourceChatId: string;
278
+ sourceTurnId: string;
279
+ sourceTitle: string;
280
+ sourceHref?: string;
281
+ };
282
+ scheduledTask?: {
283
+ taskId: string;
284
+ occurrenceId: string;
285
+ scheduledFor: string;
286
+ trigger: "scheduled" | "manual";
287
+ };
288
+ toolPresentations?: Record<string, AiToolPresentation>;
289
+ toolOutcomes?: Record<string, "rejected">;
290
+ } | null;
291
+ /** Private owner feedback for this rendered assistant response. Never enters model context. */
292
+ feedback?: AiMessageFeedback | null;
293
+ createdAt: string;
294
+ };
295
+
296
+ /** Lightweight navigation anchor for one user message in a long conversation. */
297
+ export type AiConversationTimelineEntry = {
298
+ id: string;
299
+ seq: number;
300
+ loopId: string | null;
301
+ userPreview: string;
302
+ assistantPreview: string;
303
+ isSteer: boolean;
304
+ inputFileCount: number;
305
+ outputFileCount: number;
306
+ toolCount: number;
307
+ createdAt: string;
308
+ };
309
+
310
+ export type AiTurnStatus = "queued" | "running" | "waiting_for_action" | "completed" | "failed" | "aborted";
311
+
312
+ export type AiTurnSteerStatus = "pending" | "consumed" | "discarded";
313
+
314
+ export type AiTurnSteer = {
315
+ id: string;
316
+ conversationId: string;
317
+ turnId: string;
318
+ seq: number;
319
+ clientRequestId: string;
320
+ text: string;
321
+ status: AiTurnSteerStatus;
322
+ messageId: string | null;
323
+ createdAt: string;
324
+ consumedAt: string | null;
325
+ };
326
+
327
+ export type AiTurnSteerEnqueueResult = { ok: true; steer: AiTurnSteer } | { ok: false; reason: "not_found" | "not_chat" | "not_active" };
328
+
329
+ export type AiTurnCompletionResult = "completed" | "pending_steering" | "lost";
330
+
331
+ export type AiTurnFinalizedEvent = {
332
+ conversationId: string;
333
+ turnId: string;
334
+ status: "completed" | "failed" | "aborted";
335
+ kind: AiTurnRunConfig["kind"] | null;
336
+ };
337
+
338
+ export type AiTurn = {
339
+ id: string;
340
+ shortId: string;
341
+ conversationId: string;
342
+ status: AiTurnStatus;
343
+ attempt: number;
344
+ modelProfileId: string | null;
345
+ createdAt: string;
346
+ completedAt: string | null;
347
+ error: string | null;
348
+ };
349
+
350
+ export type AiInterChatMessage = {
351
+ id: string;
352
+ shortId: string;
353
+ sourceConversationId: string;
354
+ sourceChatId: string;
355
+ sourceTitle: string;
356
+ sourceTurnId: string;
357
+ sourceTurnShortId: string;
358
+ sourceCallId: string;
359
+ targetConversationId: string;
360
+ targetChatId: string;
361
+ targetTitle: string;
362
+ actorUserId: string;
363
+ text: string;
364
+ status: "pending" | "delivered" | "failed";
365
+ targetTurnId: string | null;
366
+ targetTurnShortId: string | null;
367
+ targetMessageId: string | null;
368
+ error: string | null;
369
+ createdAt: string;
370
+ deliveredAt: string | null;
371
+ };
372
+
373
+ export type AiPendingTurnAction =
374
+ | {
375
+ type: "approval_request";
376
+ turnId: string;
377
+ conversationId: string;
378
+ callId: string;
379
+ name: string;
380
+ args: unknown;
381
+ message?: string;
382
+ review?: CapabilityActionReview;
383
+ allowAlways: boolean;
384
+ }
385
+ | {
386
+ type: "frontend_tool";
387
+ turnId: string;
388
+ conversationId: string;
389
+ callId: string;
390
+ name: string;
391
+ args: unknown;
392
+ mode: AiFrontendToolMode;
393
+ };
394
+
395
+ export type AiTurnAbortRequest =
396
+ | { found: false }
397
+ | {
398
+ found: true;
399
+ status: AiTurnStatus;
400
+ /** True when no live lease exists — the caller must finalize the turn itself. */
401
+ ownerless: boolean;
402
+ };
403
+
404
+ export type AiPendingTurnActionRecord = {
405
+ turnId: string;
406
+ conversationId: string;
407
+ callId: string;
408
+ kind: "approval" | "custom_approval" | "client_tool";
409
+ status: "pending" | "resolved" | "aborted";
410
+ name: string;
411
+ args: unknown;
412
+ message?: string;
413
+ review?: CapabilityActionReview;
414
+ approvalScope: string;
415
+ allowAlways: boolean;
416
+ frontendMode?: AiFrontendToolMode;
417
+ resolvedEvent: InboundEvent | null;
418
+ };
419
+
420
+ export type AiTurnToolSource = { kind: "none" } | { kind: "default"; appTools?: boolean };
421
+
422
+ export type AiClientToolId = "local_bash";
423
+
424
+ /** Immutable project instructions and context manifest captured for one turn. */
425
+ export type AiProjectPromptSnapshot = {
426
+ /** Public readable Project ID. Resolve it once before using internal Project services. */
427
+ id: string;
428
+ name: string;
429
+ revision: number;
430
+ instructions: string;
431
+ context: string;
432
+ references: CloudResourceRef[];
433
+ defaultModelProfileId: string | null;
434
+ };
435
+
436
+ export type AiProjectFileToolStat = {
437
+ path: string;
438
+ mediaType: string;
439
+ size: number;
440
+ updatedAt: string;
441
+ };
442
+
443
+ export type AiProjectFileToolContent = AiProjectFileToolStat & { bytes: Uint8Array };
444
+
445
+ /** Current-authority, read-only Project file access mounted into AI file tools. */
446
+ export type AiProjectFileToolSource = {
447
+ list: () => Promise<AiProjectFileToolStat[]>;
448
+ read: (path: string) => Promise<AiProjectFileToolContent | null>;
449
+ };
450
+
451
+ export type AiSkillFileToolStat = {
452
+ path: string;
453
+ mediaType: string;
454
+ size: number;
455
+ updatedAt: string;
456
+ };
457
+
458
+ export type AiSkillFileToolContent = AiSkillFileToolStat & { bytes: Uint8Array };
459
+
460
+ /** Permission-checked, immutable loaded-skill snapshots mounted below /skills. */
461
+ export type AiSkillFileToolSource = {
462
+ list: () => Promise<AiSkillFileToolStat[]>;
463
+ read: (path: string) => Promise<AiSkillFileToolContent | null>;
464
+ };
465
+
466
+ export type AiConversationResourceRef = {
467
+ ref: CloudResourceRef;
468
+ title: string | null;
469
+ preview: string | null;
470
+ icon: string | null;
471
+ href: string | null;
472
+ firstSeenAt: string;
473
+ lastSeenAt: string;
474
+ sourceTurnId: string | null;
475
+ sourceCallId: string | null;
476
+ };
477
+
478
+ export type AiConversationResourceObservation = {
479
+ ref: CloudResourceRef;
480
+ title?: string;
481
+ preview?: string;
482
+ icon?: string;
483
+ href?: string;
484
+ };
485
+
486
+ export type AiConversationResourceOccurrence = AiConversationResourceRef & {
487
+ chat: Pick<AiConversation, "shortId" | "title" | "updatedAt">;
488
+ };
489
+
490
+ export type AiConversationSourceKind = "web" | "file" | "resource" | "activity";
491
+
492
+ export type AiConversationSource = {
493
+ kind: AiConversationSourceKind;
494
+ key: string;
495
+ title: string;
496
+ preview: string | null;
497
+ icon: string;
498
+ href: string | null;
499
+ path: string | null;
500
+ mediaType: string | null;
501
+ size: number | null;
502
+ ref: CloudResourceRef | null;
503
+ occurrences: number;
504
+ firstSeenAt: string;
505
+ lastSeenAt: string;
506
+ sourceTurnId: string | null;
507
+ sourceCallId: string | null;
508
+ };
509
+
510
+ export type AiConversationSourceObservation = {
511
+ kind: "web" | "activity";
512
+ key: string;
513
+ title: string;
514
+ preview?: string;
515
+ icon?: string;
516
+ href?: string;
517
+ };
518
+
519
+ export type AiConversationFileSnapshotEntry = {
520
+ path: string;
521
+ size: number;
522
+ mediaType: string;
523
+ origin: "user" | "assistant";
524
+ updatedAt: string;
525
+ version?: number;
526
+ };
527
+
528
+ export type AiConversationFileSnapshot = {
529
+ attached: AiConversationFileSnapshotEntry[];
530
+ available: AiConversationFileSnapshotEntry[];
531
+ total: number;
532
+ };
533
+
534
+ export type AiChatTurnRunConfig = {
535
+ /** Server-owned marker: model grants apply only to interactive Assistant chat. */
536
+ assistantChat?: true;
537
+ kind?: "chat";
538
+ input: Input;
539
+ /** Stable public ID exposed as runtime context, not instructions. */
540
+ chatId?: string;
541
+ actor?: RequestActor;
542
+ /** Request locale persisted with the turn so async execution keeps the caller preference. */
543
+ locale?: string;
544
+ modelPolicy?: AiModelPolicy;
545
+ requestedModelId?: string;
546
+ /** Optional instructions that apply only to this turn. */
547
+ systemPrompt?: string;
548
+ project?: AiProjectPromptSnapshot;
549
+ files?: AiConversationFileSnapshot;
550
+ /** Whether this turn's materialized tools can inspect referenced images. */
551
+ canInspectAttachedImages?: boolean;
552
+ clientToolIds?: AiClientToolId[];
553
+ toolSource?: AiTurnToolSource;
554
+ toolApprovalContext?: {
555
+ actorUserId: string;
556
+ };
557
+ /** Durable Core-owned authority for a scheduled chat task. */
558
+ mandate?: {
559
+ id: string;
560
+ revision: number;
561
+ };
562
+ };
563
+
564
+ export type AiCompactionTurnRunConfig = {
565
+ kind: "compact";
566
+ actor?: RequestActor;
567
+ modelPolicy?: AiModelPolicy;
568
+ requestedModelId?: string;
569
+ };
570
+
571
+ export type AiTurnRunConfig = AiChatTurnRunConfig | AiCompactionTurnRunConfig;
572
+
573
+ export type AiTurnClaim = {
574
+ turn: AiTurn;
575
+ runConfig: AiTurnRunConfig | null;
576
+ /** Live blocks persisted by a previous attempt (continuation base), if any. */
577
+ liveBlocks: AiTurnBlock[] | null;
578
+ /** Highest wire seq of the previous attempt; the new attempt continues from here. */
579
+ liveSeq: number;
580
+ };
581
+
582
+ export type AiTurnSweepAction = { conversationId: string; turnId: string };
583
+ /** A turn finalized by the sweep, with the wire coordinates for its turn_finished event. */
584
+ export type AiTurnFinalizedAction = AiTurnSweepAction & { attempt: number; seq: number };
585
+
586
+ export type AiTurnSweepResult = {
587
+ /** Lease-expired or stale-queued turns that need (re-)enqueueing. */
588
+ requeued: AiTurnSweepAction[];
589
+ /** Turns finalized as failed (deadline exceeded); turn_finished must be published. */
590
+ failed: (AiTurnFinalizedAction & { error: string })[];
591
+ /** Turns finalized as aborted (cancel requested or waiting deadline); turn_finished must be published. */
592
+ aborted: AiTurnFinalizedAction[];
593
+ };
594
+
595
+ export type AiConversationService = {
596
+ createConversation(input: {
597
+ ownerUserId: string;
598
+ title?: string;
599
+ description?: string;
600
+ projectId?: string;
601
+ draft?: AiDraftContentPart[];
602
+ preloadTools?: string[];
603
+ allowedTools?: string[];
604
+ launchedByAppId?: string;
605
+ }): Promise<AiConversation>;
606
+ forkConversation(input: {
607
+ sourceConversationId: string;
608
+ throughSeq: number;
609
+ ownerUserId: string;
610
+ title?: string;
611
+ }): Promise<AiConversation>;
612
+ listConversations(input: {
613
+ ownerUserId: string;
614
+ search?: string;
615
+ refs?: CloudResourceRef[];
616
+ archived?: boolean;
617
+ status?: AiConversationStatusFilter;
618
+ projectId?: string;
619
+ unassigned?: boolean;
620
+ limit?: number;
621
+ }): Promise<AiConversation[]>;
622
+ listSidebarConversations(input: { ownerUserId: string; unassignedLimit?: number; perProjectLimit?: number }): Promise<AiConversation[]>;
623
+ listConversationsPage(input: {
624
+ ownerUserId: string;
625
+ search?: string;
626
+ archived?: boolean;
627
+ status?: AiConversationStatusFilter;
628
+ projectId?: string;
629
+ unassigned?: boolean;
630
+ page: number;
631
+ perPage: number;
632
+ }): Promise<AiConversationPage>;
633
+ getConversation(input: { conversationId: string; ownerUserId?: string }): Promise<AiConversation | null>;
634
+ getConversationByShortId(input: { shortId: string; ownerUserId?: string; archived?: boolean }): Promise<AiConversation | null>;
635
+ saveDraft(input: {
636
+ conversationId: string;
637
+ ownerUserId: string;
638
+ expectedRevision: number;
639
+ content: AiDraftContentPart[];
640
+ }): Promise<{ ok: true; draft: AiConversationDraft } | { ok: false; reason: "not_found" | "conflict" }>;
641
+ getLoadedTools(input: { conversationId: string }): Promise<string[]>;
642
+ loadTools(input: {
643
+ conversationId: string;
644
+ names: string[];
645
+ maxLoadedTools?: number;
646
+ }): Promise<{ loaded: string[]; alreadyLoaded: string[]; evicted: string[] }>;
647
+ indexConversationResources(input: {
648
+ conversationId: string;
649
+ turnId?: string;
650
+ callId?: string;
651
+ resources: AiConversationResourceObservation[];
652
+ }): Promise<void>;
653
+ listConversationResources(input: {
654
+ conversationId: string;
655
+ search?: string;
656
+ before?: string;
657
+ limit?: number;
658
+ }): Promise<{ resources: AiConversationResourceRef[]; nextCursor?: string }>;
659
+ listUserConversationResources(input: {
660
+ ownerUserId: string;
661
+ search?: string;
662
+ before?: string;
663
+ limit?: number;
664
+ }): Promise<{ resources: AiConversationResourceOccurrence[]; nextCursor?: string }>;
665
+ indexConversationSource(input: {
666
+ conversationId: string;
667
+ turnId?: string;
668
+ callId?: string;
669
+ source: AiConversationSourceObservation;
670
+ }): Promise<void>;
671
+ listConversationSources(input: {
672
+ conversationId: string;
673
+ search?: string;
674
+ before?: string;
675
+ limit?: number;
676
+ }): Promise<{ sources: AiConversationSource[]; nextCursor?: string }>;
677
+ getCapabilityInvocationOrigin(input: { idempotencyKey: string; toolName: string }): Promise<{
678
+ conversationId: string;
679
+ conversationShortId: string;
680
+ turnId: string;
681
+ turnShortId: string;
682
+ callId: string;
683
+ } | null>;
684
+ createInterChatMessage(input: {
685
+ sourceConversationId: string;
686
+ sourceTurnId: string;
687
+ sourceCallId: string;
688
+ targetChatId: string;
689
+ actorUserId: string;
690
+ text: string;
691
+ idempotencyKey: string;
692
+ }): Promise<{ ok: true; message: AiInterChatMessage } | { ok: false; reason: "not_found" | "same_chat" | "recursive" }>;
693
+ listPendingInterChatMessages(input?: { targetConversationId?: string; limit?: number }): Promise<AiInterChatMessage[]>;
694
+ failInterChatMessage(input: { messageId: string; error: string }): Promise<boolean>;
695
+ deliverInterChatMessage(input: {
696
+ messageId: string;
697
+ modelProfileId: string;
698
+ runConfig: AiChatTurnRunConfig;
699
+ userMessage: Message;
700
+ sourceHref?: string;
701
+ }): Promise<
702
+ { delivered: false; reason: "not_found" | "busy" | "failed" } | { delivered: true; message: AiInterChatMessage; turn: AiTurn }
703
+ >;
704
+ updateConversationMetadata(input: {
705
+ conversationId: string;
706
+ ownerUserId?: string;
707
+ title: string;
708
+ description?: string;
709
+ pinned?: boolean;
710
+ }): Promise<AiConversation | null>;
711
+ setConversationProject(input: {
712
+ conversationId: string;
713
+ ownerUserId?: string;
714
+ projectId: string | null;
715
+ }): Promise<AiConversationProjectUpdateResult>;
716
+ setConversationPinned(input: { conversationId: string; ownerUserId?: string; pinned: boolean }): Promise<AiConversation | null>;
717
+ archiveConversation(input: { conversationId: string; ownerUserId?: string }): Promise<boolean>;
718
+ restoreConversation(input: { conversationId: string; ownerUserId?: string }): Promise<AiConversation | null>;
719
+ markConversationViewed(input: { conversationId: string; ownerUserId?: string }): Promise<boolean>;
720
+ /**
721
+ * Conversations whose content changed since the last enrichment (no active
722
+ * turn, has messages, failure backoff elapsed). Oldest first. With
723
+ * `conversationId` (manual reindex) the dirty and backoff checks are skipped.
724
+ */
725
+ listEnrichmentCandidates(input: { limit: number; conversationId?: string }): Promise<AiEnrichmentCandidate[]>;
726
+ /**
727
+ * Store enrichment results and clear the failure backoff. `dirtyAsOf` is the
728
+ * candidate's exact scan-time updated_at (microsecond precision) — enriched_at
729
+ * is set to it, so activity during the run keeps the chat dirty while an
730
+ * unchanged chat becomes exactly clean (updated_at = enriched_at).
731
+ * `description`/`title` are omitted when the current value is user-authored.
732
+ */
733
+ applyEnrichment(input: {
734
+ conversationId: string;
735
+ /** Internal rolling search projection; never replaces the user-visible description. */
736
+ searchSummary: string;
737
+ description?: string;
738
+ keywords: string[];
739
+ title?: string;
740
+ dirtyAsOf: string;
741
+ }): Promise<void>;
742
+ /** Record a failed enrichment attempt — the candidate query backs the chat off exponentially. */
743
+ markEnrichmentFailed(input: { conversationId: string }): Promise<void>;
744
+ /** Append one run to the user-visible enrichment history (keeps the newest 20 per conversation). */
745
+ recordEnrichmentRun(input: {
746
+ conversationId: string;
747
+ status: AiEnrichmentRunStatus;
748
+ trigger: AiEnrichmentTrigger;
749
+ modelProfileId?: string;
750
+ mode?: string;
751
+ durationMs?: number;
752
+ titleUpdated?: boolean;
753
+ keywordsCount?: number;
754
+ error?: string;
755
+ }): Promise<void>;
756
+ listEnrichmentRuns(input: { conversationId: string; limit?: number }): Promise<AiEnrichmentRun[]>;
757
+ getEnrichmentStatus(input: { conversationId: string }): Promise<AiEnrichmentStatus | null>;
758
+ getEnrichmentOverview(): Promise<AiEnrichmentOverview>;
759
+ /** Chat history for humans: includes compacted messages, hides superseded summaries. */
760
+ listMessages(input: { conversationId: string }): Promise<AiStoredMessage[]>;
761
+ /**
762
+ * Newest window of the human view for infinite scroll. `beforeSeq` pages
763
+ * older history (exclusive). Whole seq groups are always returned together
764
+ * (compaction can put several rows on one seq), so the cursor
765
+ * `min(seq) of the page` never skips rows.
766
+ */
767
+ listMessagesPage(input: { conversationId: string; beforeSeq?: number; limit?: number }): Promise<{
768
+ messages: AiStoredMessage[];
769
+ hasMore: boolean;
770
+ }>;
771
+ searchConversationMessages(input: {
772
+ conversationId: string;
773
+ query: string;
774
+ beforeSeq?: number;
775
+ limit?: number;
776
+ }): Promise<{ messages: AiStoredMessage[]; nextCursor?: string }>;
777
+ /** Compact full-conversation index used by the long-chat turn navigator. */
778
+ listConversationTimeline(input: { conversationId: string }): Promise<AiConversationTimelineEntry[]>;
779
+ /** Model context: only active (non-compacted) messages — what the LLM sees. */
780
+ listContextMessages(input: { conversationId: string }): Promise<AiStoredMessage[]>;
781
+ copyMessages(input: { sourceConversationId: string; targetConversationId: string; throughSeq: number }): Promise<void>;
782
+ truncateMessagesFrom(input: { conversationId: string; fromSeq: number }): Promise<void>;
783
+ setLatestAssistantLoopAggregate(input: {
784
+ conversationId: string;
785
+ loopId?: string | null;
786
+ aggregate: LoopAggregate;
787
+ doneReason: DoneReason;
788
+ }): Promise<void>;
789
+ compactMessages(input: {
790
+ conversationId: string;
791
+ checkpointSeq: number;
792
+ summary: Message;
793
+ modelProfileId?: string | null;
794
+ }): Promise<void>;
795
+ listTurnMessages(input: { conversationId: string; loopId: string; includeCompacted?: boolean }): Promise<AiStoredMessage[]>;
796
+ setMessageFeedback(input: {
797
+ conversationId: string;
798
+ messageShortId: string;
799
+ feedback: Omit<AiMessageFeedback, "updatedAt">;
800
+ }): Promise<AiMessageFeedback | null>;
801
+ clearMessageFeedback(input: { conversationId: string; messageShortId: string }): Promise<boolean>;
802
+ /** Create a queued compaction turn. Chat turns must use submitChatTurn. */
803
+ createCompactionTurn(input: { conversationId: string; modelProfileId: string; runConfig: AiCompactionTurnRunConfig }): Promise<AiTurn>;
804
+ /** Persist the user message and create its turn in one transaction. */
805
+ submitChatTurn(input: {
806
+ conversationId: string;
807
+ modelProfileId: string;
808
+ runConfig: AiChatTurnRunConfig;
809
+ userMessage: Message;
810
+ /** Atomically consume this saved draft revision when present. */
811
+ expectedDraftRevision?: number;
812
+ /** Conversation Project observed while resolving this turn's immutable snapshot. */
813
+ expectedProjectId?: string | null;
814
+ /** Delete active messages with seq >= truncateFromSeq first (retry-in-place). */
815
+ truncateFromSeq?: number;
816
+ /** Resources introduced by this user message, indexed in the same transaction. */
817
+ resources?: AiConversationResourceObservation[];
818
+ /** Retry source whose immutable turn-file bytes are copied into the new turn. */
819
+ retrySourceTurnId?: string;
820
+ }): Promise<{ turn: AiTurn; message: AiStoredMessage }>;
821
+ getTurnRunConfig(input: { conversationId: string; turnId: string }): Promise<AiTurnRunConfig | null>;
822
+ getTurn(input: { conversationId: string; turnId: string }): Promise<AiTurn | null>;
823
+ getTurnByShortId(input: { conversationId: string; shortId: string }): Promise<AiTurn | null>;
824
+ getActiveTurn(input: { conversationId: string }): Promise<{ turn: AiTurn; liveBlocks: AiTurnBlock[]; liveSeq: number } | null>;
825
+ /**
826
+ * Claim a turn attempt. Increments attempt and takes the lease atomically.
827
+ * `from: "queue"` claims queued or lease-expired running turns; `from: "waiting"`
828
+ * claims a suspended turn only when its currently awaiting action was resolved.
829
+ * Normal action continuations do not consume the recovery-attempt budget.
830
+ */
831
+ claimTurn(input: {
832
+ conversationId: string;
833
+ turnId: string;
834
+ leaseOwner: string;
835
+ leaseMs: number;
836
+ from: "queue" | "waiting";
837
+ maxAttempts: number;
838
+ runBudgetMs: number;
839
+ }): Promise<AiTurnClaim | null>;
840
+ heartbeatTurn(input: { conversationId: string; turnId: string; leaseOwner: string; leaseMs: number }): Promise<boolean>;
841
+ /** Release the worker: persist live state, drop the lease, park the turn until its actions resolve. */
842
+ suspendTurn(input: {
843
+ conversationId: string;
844
+ turnId: string;
845
+ leaseOwner: string;
846
+ blocks: AiTurnBlock[];
847
+ seq: number;
848
+ waitingBudgetMs: number;
849
+ }): Promise<boolean>;
850
+ saveTurnLiveState(input: {
851
+ conversationId: string;
852
+ turnId: string;
853
+ leaseOwner: string;
854
+ blocks: AiTurnBlock[];
855
+ seq: number;
856
+ }): Promise<boolean>;
857
+ /** Record an abort wish. The caller finalizes ownerless turns itself. */
858
+ requestTurnAbort(input: { conversationId: string; turnId: string; reason?: string }): Promise<AiTurnAbortRequest>;
859
+ completeTurn(input: {
860
+ conversationId: string;
861
+ turnId: string;
862
+ status: "completed" | "failed" | "aborted";
863
+ error?: string | null;
864
+ /** When set, only the lease owner may finalize; otherwise only ownerless turns are finalized. */
865
+ leaseOwner?: string;
866
+ }): Promise<AiTurnCompletionResult>;
867
+ /** Periodic maintenance: requeue lost turns, fail exhausted/over-budget turns, abort stale waits. */
868
+ sweepTurns(input?: { limit?: number; maxAttempts?: number }): Promise<AiTurnSweepResult>;
869
+ savePendingTurnAction(input: AiPendingTurnActionRecord): Promise<void>;
870
+ listPendingTurnActions(input: { conversationId: string; turnId: string }): Promise<AiPendingTurnAction[]>;
871
+ getPendingTurnAction(input: { conversationId: string; turnId: string; callId: string }): Promise<AiPendingTurnActionRecord | null>;
872
+ listPendingActionRecords(input: { conversationId: string; turnId: string }): Promise<AiPendingTurnActionRecord[]>;
873
+ listResolvedPendingActions(input: { conversationId: string; turnId: string }): Promise<AiPendingTurnActionRecord[]>;
874
+ resolvePendingTurnAction(input: {
875
+ conversationId: string;
876
+ turnId: string;
877
+ callId: string;
878
+ event: InboundEvent;
879
+ }): Promise<AiPendingTurnActionRecord | null>;
880
+ clearPendingTurnActions(input: { conversationId: string; turnId: string }): Promise<void>;
881
+ enqueueTurnSteer(input: {
882
+ conversationId: string;
883
+ turnId: string;
884
+ clientRequestId: string;
885
+ text: string;
886
+ }): Promise<AiTurnSteerEnqueueResult>;
887
+ listTurnSteers(input: { conversationId: string; turnId: string }): Promise<AiTurnSteer[]>;
888
+ /** Atomically make pending steers visible to the model and return them in order. */
889
+ takePendingTurnSteers(input: { conversationId: string; turnId: string; leaseOwner: string }): Promise<AiTurnSteer[]>;
890
+ createSessionStore(input: {
891
+ conversationId: string;
892
+ modelProfileId?: string | null;
893
+ turnId?: string | null;
894
+ leaseOwner?: string | null;
895
+ /** Ephemeral provider input for this turn; user-message persistence remains reference-only. */
896
+ turnInput?: Input;
897
+ /** Mutable snapshot map read only when an assistant tool-call message is persisted. */
898
+ toolPresentations?: ReadonlyMap<string, AiToolPresentation>;
899
+ /** Mutable call-id set read only when a rejected tool result is persisted. */
900
+ rejectedToolCallIds?: ReadonlySet<string>;
901
+ }): SessionStore;
902
+ };
903
+
904
+ export type AiAccessResult<TAccess = unknown> = {
905
+ allowed: boolean;
906
+ data?: TAccess;
907
+ reason?: string;
908
+ };
909
+
910
+ export type AiToolApprovalPolicy = "never" | "once" | "always" | { kind: "user-configurable"; default: "once" | "always"; scope?: string };
911
+
912
+ export type AiFrontendToolMode = "client" | "client_view" | "client_interaction";
913
+
914
+ export type AiCapabilityToolPresentation = {
915
+ kind: "capability";
916
+ appId: string;
917
+ appName: string;
918
+ appIcon: string;
919
+ appAccent?: string;
920
+ title: string;
921
+ capabilityKind: "query" | "action";
922
+ };
923
+
924
+ export type AiToolPresentation = AiCapabilityToolPresentation;
925
+
926
+ export type AiToolDefinition<TInput extends z.ZodType = z.ZodType, TOutput extends z.ZodType = z.ZodType> = {
927
+ name: string;
928
+ /** Stable identity when the callable name is provider-encoded. */
929
+ canonicalName?: string;
930
+ description: string;
931
+ inputSchema: TInput;
932
+ outputSchema: TOutput;
933
+ approval: AiToolApprovalPolicy;
934
+ /** Per-tool execution timeout enforced by nessi. */
935
+ timeoutMs?: number;
936
+ /** One-line "when to use" hint listed in the system prompt's Tools section. Tools without a hint are not listed. */
937
+ promptHint?: string;
938
+ /** Optional compact representation sent to providers in later loops. The full result remains persisted and visible. */
939
+ toHistoricalResult?: (context: { input: z.infer<TInput>; output: z.infer<TOutput>; callId: string }) => unknown | Promise<unknown>;
940
+ };
941
+
942
+ export type AiToolRuntime<TInput extends z.ZodType = z.ZodType, TOutput extends z.ZodType = z.ZodType> =
943
+ | {
944
+ location: "server";
945
+ def: AiToolDefinition<TInput, TOutput>;
946
+ run(
947
+ input: z.infer<TInput>,
948
+ ctx: ToolContext & {
949
+ actor: RequestActor;
950
+ conversationId?: string;
951
+ turnId?: string;
952
+ attachedFilePaths?: ReadonlySet<string>;
953
+ allowedDataBoundaries?: AiDataBoundary[];
954
+ projectFiles?: AiProjectFileToolSource;
955
+ skillFiles?: AiSkillFileToolSource;
956
+ selectedModel?: AiResolvedModel;
957
+ locale?: string;
958
+ timeZone?: string;
959
+ },
960
+ ): Promise<z.infer<TOutput>>;
961
+ }
962
+ | {
963
+ location: AiFrontendToolMode;
964
+ def: AiToolDefinition<TInput, TOutput>;
965
+ };
966
+
967
+ export type AiRuntimeTool = Tool | AiToolRuntime;