@flowdular/sdk 0.1.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 (883) hide show
  1. package/.ai/agents/README.md +27 -0
  2. package/.ai/agents/module-executor.md +36 -0
  3. package/.ai/agents/reviewer.md +23 -0
  4. package/.ai/agents/sandbox/agentic-engineer.md +31 -0
  5. package/.ai/agents/sandbox/backend-engineer.md +36 -0
  6. package/.ai/agents/sandbox/business-manager.md +23 -0
  7. package/.ai/agents/sandbox/frontend-engineer.md +27 -0
  8. package/.ai/agents/sandbox/ux-designer.md +23 -0
  9. package/.ai/agents/spec-author.md +29 -0
  10. package/.ai/blueprints/add-migration/README.md +5 -0
  11. package/.ai/blueprints/add-migration/allowed-paths.yaml +23 -0
  12. package/.ai/blueprints/add-migration/blueprint.json +14 -0
  13. package/.ai/blueprints/add-migration/examples/invalid/input-destructive.json +6 -0
  14. package/.ai/blueprints/add-migration/examples/invalid/plan-unnumbered-file.json +9 -0
  15. package/.ai/blueprints/add-migration/examples/valid/input.json +6 -0
  16. package/.ai/blueprints/add-migration/examples/valid/plan.json +9 -0
  17. package/.ai/blueprints/add-migration/gates.yaml +30 -0
  18. package/.ai/blueprints/add-migration/input.schema.json +23 -0
  19. package/.ai/blueprints/add-migration/plan.schema.json +54 -0
  20. package/.ai/blueprints/add-migration/required-files.yaml +18 -0
  21. package/.ai/blueprints/add-migration/spec-requirements.yaml +13 -0
  22. package/.ai/blueprints/add-migration/steps.yaml +62 -0
  23. package/.ai/blueprints/author-spec/README.md +5 -0
  24. package/.ai/blueprints/author-spec/allowed-paths.yaml +7 -0
  25. package/.ai/blueprints/author-spec/blueprint.json +14 -0
  26. package/.ai/blueprints/author-spec/examples/invalid/input-missing-outcome.json +5 -0
  27. package/.ai/blueprints/author-spec/examples/valid/input.json +6 -0
  28. package/.ai/blueprints/author-spec/gates.yaml +13 -0
  29. package/.ai/blueprints/author-spec/input.schema.json +20 -0
  30. package/.ai/blueprints/author-spec/plan.schema.json +14 -0
  31. package/.ai/blueprints/author-spec/required-files.yaml +6 -0
  32. package/.ai/blueprints/author-spec/spec-requirements.yaml +35 -0
  33. package/.ai/blueprints/author-spec/steps.yaml +28 -0
  34. package/.ai/blueprints/author-spec/templates/module.yaml +45 -0
  35. package/.ai/blueprints/bug-fix/README.md +5 -0
  36. package/.ai/blueprints/bug-fix/allowed-paths.yaml +29 -0
  37. package/.ai/blueprints/bug-fix/blueprint.json +14 -0
  38. package/.ai/blueprints/bug-fix/examples/invalid/input-no-symptom.json +4 -0
  39. package/.ai/blueprints/bug-fix/examples/invalid/plan-no-test.json +8 -0
  40. package/.ai/blueprints/bug-fix/examples/valid/input.json +6 -0
  41. package/.ai/blueprints/bug-fix/examples/valid/plan.json +8 -0
  42. package/.ai/blueprints/bug-fix/gates.yaml +30 -0
  43. package/.ai/blueprints/bug-fix/input.schema.json +25 -0
  44. package/.ai/blueprints/bug-fix/plan.schema.json +53 -0
  45. package/.ai/blueprints/bug-fix/required-files.yaml +7 -0
  46. package/.ai/blueprints/bug-fix/spec-requirements.yaml +7 -0
  47. package/.ai/blueprints/bug-fix/steps.yaml +51 -0
  48. package/.ai/blueprints/core-extend/README.md +5 -0
  49. package/.ai/blueprints/core-extend/allowed-paths.yaml +49 -0
  50. package/.ai/blueprints/core-extend/blueprint.json +14 -0
  51. package/.ai/blueprints/core-extend/examples/invalid/input-unknown-package.json +5 -0
  52. package/.ai/blueprints/core-extend/examples/invalid/plan-missing-gates.json +7 -0
  53. package/.ai/blueprints/core-extend/examples/valid/input.json +6 -0
  54. package/.ai/blueprints/core-extend/examples/valid/plan.json +10 -0
  55. package/.ai/blueprints/core-extend/gates.yaml +16 -0
  56. package/.ai/blueprints/core-extend/input.schema.json +54 -0
  57. package/.ai/blueprints/core-extend/plan.schema.json +39 -0
  58. package/.ai/blueprints/core-extend/required-files.yaml +36 -0
  59. package/.ai/blueprints/core-extend/spec-requirements.yaml +17 -0
  60. package/.ai/blueprints/core-extend/steps.yaml +54 -0
  61. package/.ai/blueprints/edit-module/README.md +9 -0
  62. package/.ai/blueprints/edit-module/allowed-paths.yaml +27 -0
  63. package/.ai/blueprints/edit-module/blueprint.json +20 -0
  64. package/.ai/blueprints/edit-module/examples/invalid/input-unknown-change.json +5 -0
  65. package/.ai/blueprints/edit-module/examples/invalid/plan-touches-platform.json +15 -0
  66. package/.ai/blueprints/edit-module/examples/valid/input.json +5 -0
  67. package/.ai/blueprints/edit-module/examples/valid/plan.json +25 -0
  68. package/.ai/blueprints/edit-module/gates.yaml +30 -0
  69. package/.ai/blueprints/edit-module/input.schema.json +31 -0
  70. package/.ai/blueprints/edit-module/plan.schema.json +65 -0
  71. package/.ai/blueprints/edit-module/required-files.yaml +80 -0
  72. package/.ai/blueprints/edit-module/spec-requirements.yaml +15 -0
  73. package/.ai/blueprints/edit-module/steps.yaml +115 -0
  74. package/.ai/blueprints/new-module/README.md +7 -0
  75. package/.ai/blueprints/new-module/allowed-paths.yaml +27 -0
  76. package/.ai/blueprints/new-module/blueprint.json +20 -0
  77. package/.ai/blueprints/new-module/examples/invalid/input-spec-outside-modules.json +4 -0
  78. package/.ai/blueprints/new-module/examples/invalid/plan-unknown-gate.json +8 -0
  79. package/.ai/blueprints/new-module/examples/valid/input.json +5 -0
  80. package/.ai/blueprints/new-module/examples/valid/plan.json +22 -0
  81. package/.ai/blueprints/new-module/gates.yaml +30 -0
  82. package/.ai/blueprints/new-module/input.schema.json +21 -0
  83. package/.ai/blueprints/new-module/plan.schema.json +58 -0
  84. package/.ai/blueprints/new-module/required-files.yaml +73 -0
  85. package/.ai/blueprints/new-module/spec-requirements.yaml +30 -0
  86. package/.ai/blueprints/new-module/steps.yaml +138 -0
  87. package/.ai/blueprints/release/README.md +5 -0
  88. package/.ai/blueprints/release/allowed-paths.yaml +19 -0
  89. package/.ai/blueprints/release/blueprint.json +14 -0
  90. package/.ai/blueprints/release/examples/invalid/input-bad-version.json +4 -0
  91. package/.ai/blueprints/release/examples/invalid/plan-bad-branch.json +7 -0
  92. package/.ai/blueprints/release/examples/valid/input.json +5 -0
  93. package/.ai/blueprints/release/examples/valid/plan.json +20 -0
  94. package/.ai/blueprints/release/gates.yaml +20 -0
  95. package/.ai/blueprints/release/input.schema.json +24 -0
  96. package/.ai/blueprints/release/plan.schema.json +46 -0
  97. package/.ai/blueprints/release/required-files.yaml +19 -0
  98. package/.ai/blueprints/release/spec-requirements.yaml +8 -0
  99. package/.ai/blueprints/release/steps.yaml +47 -0
  100. package/.ai/blueprints/security-review/README.md +5 -0
  101. package/.ai/blueprints/security-review/allowed-paths.yaml +6 -0
  102. package/.ai/blueprints/security-review/blueprint.json +14 -0
  103. package/.ai/blueprints/security-review/examples/invalid/input-unknown-kind.json +4 -0
  104. package/.ai/blueprints/security-review/examples/invalid/plan-finding-without-scenario.json +14 -0
  105. package/.ai/blueprints/security-review/examples/valid/input.json +4 -0
  106. package/.ai/blueprints/security-review/examples/valid/plan.json +19 -0
  107. package/.ai/blueprints/security-review/gates.yaml +22 -0
  108. package/.ai/blueprints/security-review/input.schema.json +20 -0
  109. package/.ai/blueprints/security-review/plan.schema.json +65 -0
  110. package/.ai/blueprints/security-review/required-files.yaml +6 -0
  111. package/.ai/blueprints/security-review/spec-requirements.yaml +9 -0
  112. package/.ai/blueprints/security-review/steps.yaml +38 -0
  113. package/.ai/policies/capabilities.yaml +164 -0
  114. package/.ai/policies/model-routing.yaml +72 -0
  115. package/.ai/policies/path-ownership.yaml +65 -0
  116. package/.ai/policies/task-budgets.yaml +37 -0
  117. package/.ai/references/catalog/LICENSE +21 -0
  118. package/.ai/references/catalog/migrations/0001_catalog_core.down.sql +2 -0
  119. package/.ai/references/catalog/migrations/0001_catalog_core.up.sql +21 -0
  120. package/.ai/references/catalog/migrations/0002_catalog_history.down.sql +3 -0
  121. package/.ai/references/catalog/migrations/0002_catalog_history.up.sql +20 -0
  122. package/.ai/references/catalog/migrations/0003_catalog_history_service_actors.down.sql +3 -0
  123. package/.ai/references/catalog/migrations/0003_catalog_history_service_actors.up.sql +36 -0
  124. package/.ai/references/catalog/migrations/0004_catalog_idempotency_ledger.down.sql +3 -0
  125. package/.ai/references/catalog/migrations/0004_catalog_idempotency_ledger.up.sql +19 -0
  126. package/.ai/references/catalog/migrations/README.md +3 -0
  127. package/.ai/references/catalog/module.json +27 -0
  128. package/.ai/references/catalog/package.json +49 -0
  129. package/.ai/references/catalog/spec/module.yaml +86 -0
  130. package/.ai/references/catalog/src/acl/permissions.ts +6 -0
  131. package/.ai/references/catalog/src/agent/tools.ts +164 -0
  132. package/.ai/references/catalog/src/api/endpoints.ts +243 -0
  133. package/.ai/references/catalog/src/client/CatalogHistoryDrawer.tsrx +123 -0
  134. package/.ai/references/catalog/src/client/CatalogItemForm.tsrx +190 -0
  135. package/.ai/references/catalog/src/client/CatalogView.tsrx +473 -0
  136. package/.ai/references/catalog/src/client/api.ts +111 -0
  137. package/.ai/references/catalog/src/client/contribution.tsrx +61 -0
  138. package/.ai/references/catalog/src/client/index.ts +18 -0
  139. package/.ai/references/catalog/src/client/navigation-copy.ts +9 -0
  140. package/.ai/references/catalog/src/client/state.ts +24 -0
  141. package/.ai/references/catalog/src/domain/types.ts +32 -0
  142. package/.ai/references/catalog/src/domain/variables.ts +111 -0
  143. package/.ai/references/catalog/src/index.ts +31 -0
  144. package/.ai/references/catalog/src/platform.ts +35 -0
  145. package/.ai/references/catalog/src/server/index.ts +4 -0
  146. package/.ai/references/catalog/src/server/runtime.ts +86 -0
  147. package/.ai/references/catalog/src/services/catalog-service.ts +306 -0
  148. package/.ai/references/catalog/src/services/database-repository.ts +440 -0
  149. package/.ai/references/catalog/src/services/index.ts +4 -0
  150. package/.ai/references/catalog/src/services/migration.ts +171 -0
  151. package/.ai/references/catalog/src/services/repository.ts +36 -0
  152. package/.ai/references/catalog/src/services/target-idempotency.ts +59 -0
  153. package/.ai/references/catalog/tests/agent-tools.test.ts +277 -0
  154. package/.ai/references/catalog/tests/endpoints.test.ts +320 -0
  155. package/.ai/references/catalog/tests/idempotency.test.ts +297 -0
  156. package/.ai/references/catalog/tests/migrations.test.ts +149 -0
  157. package/.ai/references/catalog/tests/module.test.ts +271 -0
  158. package/.ai/references/catalog/tests/support/database.ts +76 -0
  159. package/.ai/references/catalog/translations/en.json +101 -0
  160. package/.ai/references/catalog/translations/pl.json +101 -0
  161. package/.ai/references/catalog/tsconfig.json +15 -0
  162. package/.ai/references/catalog/vitest.config.ts +16 -0
  163. package/.ai/references/catalog.provenance.json +55 -0
  164. package/.ai/skills/README.md +36 -0
  165. package/.ai/skills/agent-tool-design/SKILL.md +209 -0
  166. package/.ai/skills/auth-security-review/SKILL.md +96 -0
  167. package/.ai/skills/auto-review/SKILL.md +112 -0
  168. package/.ai/skills/bug-hunt/SKILL.md +110 -0
  169. package/.ai/skills/business-agent-design/SKILL.md +188 -0
  170. package/.ai/skills/cli-extension/SKILL.md +114 -0
  171. package/.ai/skills/core-extend/SKILL.md +104 -0
  172. package/.ai/skills/database-adapter/SKILL.md +204 -0
  173. package/.ai/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  174. package/.ai/skills/migration-authoring/SKILL.md +167 -0
  175. package/.ai/skills/module-new/SKILL.md +180 -0
  176. package/.ai/skills/module-update/SKILL.md +100 -0
  177. package/.ai/skills/perf-audit/SKILL.md +105 -0
  178. package/.ai/skills/release-eject-pr/SKILL.md +113 -0
  179. package/.ai/skills/spec-approval/SKILL.md +112 -0
  180. package/.ai/skills/test-hardening/SKILL.md +86 -0
  181. package/.ai/skills/translations-i18n/SKILL.md +85 -0
  182. package/.ai/skills/ux-design/SKILL.md +97 -0
  183. package/.ai/skills/variables/SKILL.md +164 -0
  184. package/.ai/skills/workflow-development/SKILL.md +199 -0
  185. package/AGENTS.md +59 -0
  186. package/LICENSE +21 -0
  187. package/README.md +24 -0
  188. package/docs/agent-contract.md +45 -0
  189. package/docs/design-system.md +217 -0
  190. package/modules/agents/migrations/0001_agents_core.down.sql +4 -0
  191. package/modules/agents/migrations/0001_agents_core.up.sql +106 -0
  192. package/modules/agents/migrations/0002_provider_connections.down.sql +1 -0
  193. package/modules/agents/migrations/0002_provider_connections.up.sql +34 -0
  194. package/modules/agents/migrations/0003_resource_audit.down.sql +1 -0
  195. package/modules/agents/migrations/0003_resource_audit.up.sql +25 -0
  196. package/modules/agents/migrations/0004_run_grants.down.sql +1 -0
  197. package/modules/agents/migrations/0004_run_grants.up.sql +19 -0
  198. package/modules/agents/migrations/0005_long_running_limits.down.sql +2 -0
  199. package/modules/agents/migrations/0005_long_running_limits.up.sql +14 -0
  200. package/modules/agents/migrations/0006_agent_skills.down.sql +3 -0
  201. package/modules/agents/migrations/0006_agent_skills.up.sql +44 -0
  202. package/modules/agents/migrations/0007_model_readiness.down.sql +1 -0
  203. package/modules/agents/migrations/0007_model_readiness.up.sql +18 -0
  204. package/modules/agents/migrations/0008_output_limits.down.sql +2 -0
  205. package/modules/agents/migrations/0008_output_limits.up.sql +8 -0
  206. package/modules/agents/migrations/0009_agent_audit_v3.down.sql +1 -0
  207. package/modules/agents/migrations/0009_agent_audit_v3.up.sql +25 -0
  208. package/modules/agents/migrations/0012_agent_run_costs.down.sql +3 -0
  209. package/modules/agents/migrations/0012_agent_run_costs.up.sql +32 -0
  210. package/modules/agents/migrations/0013_workflow_prerequisites.down.sql +3 -0
  211. package/modules/agents/migrations/0013_workflow_prerequisites.up.sql +97 -0
  212. package/modules/agents/migrations/0014_agent_action_audit.down.sql +1 -0
  213. package/modules/agents/migrations/0014_agent_action_audit.up.sql +25 -0
  214. package/modules/agents/migrations/0015_agent_run_actors.down.sql +1 -0
  215. package/modules/agents/migrations/0015_agent_run_actors.up.sql +17 -0
  216. package/modules/agents/migrations/0016_module_owned_agents.down.sql +6 -0
  217. package/modules/agents/migrations/0016_module_owned_agents.up.sql +68 -0
  218. package/modules/agents/migrations/0017_agent_authorization_subjects.down.sql +2 -0
  219. package/modules/agents/migrations/0017_agent_authorization_subjects.up.sql +18 -0
  220. package/modules/agents/migrations/0018_agent_child_tenant_isolation.down.sql +12 -0
  221. package/modules/agents/migrations/0018_agent_child_tenant_isolation.up.sql +88 -0
  222. package/modules/agents/migrations/0019_background_recovery_grants.down.sql +6 -0
  223. package/modules/agents/migrations/0019_background_recovery_grants.up.sql +17 -0
  224. package/modules/agents/migrations/0020_provider_summary_role.down.sql +2 -0
  225. package/modules/agents/migrations/0020_provider_summary_role.up.sql +17 -0
  226. package/modules/agents/migrations/0021_agents_agent_reconciliation_role.down.sql +4 -0
  227. package/modules/agents/migrations/0021_agents_agent_reconciliation_role.up.sql +7 -0
  228. package/modules/agents/migrations/README.md +39 -0
  229. package/modules/agents/module.json +38 -0
  230. package/modules/agents/package.json +56 -0
  231. package/modules/agents/spec/module.yaml +271 -0
  232. package/modules/agents/spec/procedures-compatibility.md +63 -0
  233. package/modules/agents/src/acl/permissions.ts +13 -0
  234. package/modules/agents/src/api/endpoints.ts +1122 -0
  235. package/modules/agents/src/cli/commands.json +29 -0
  236. package/modules/agents/src/cli/index.ts +162 -0
  237. package/modules/agents/src/client/AgentDashboardWidget.tsrx +32 -0
  238. package/modules/agents/src/client/AgentDefinitionForm.tsrx +362 -0
  239. package/modules/agents/src/client/AgentDefinitionList.tsrx +127 -0
  240. package/modules/agents/src/client/AgentPlaygroundView.tsrx +246 -0
  241. package/modules/agents/src/client/AgentProcedureForm.tsrx +182 -0
  242. package/modules/agents/src/client/AgentProcedureList.tsrx +118 -0
  243. package/modules/agents/src/client/AgentProceduresView.tsrx +253 -0
  244. package/modules/agents/src/client/AgentProvidersView.tsrx +248 -0
  245. package/modules/agents/src/client/AgentRunsView.tsrx +304 -0
  246. package/modules/agents/src/client/AgentUsageView.tsrx +233 -0
  247. package/modules/agents/src/client/AgentsView.tsrx +339 -0
  248. package/modules/agents/src/client/ModuleAgentBindingForm.tsrx +239 -0
  249. package/modules/agents/src/client/ModuleAgentList.tsrx +122 -0
  250. package/modules/agents/src/client/ProviderConnectionForm.tsrx +273 -0
  251. package/modules/agents/src/client/ProviderConnectionList.tsrx +229 -0
  252. package/modules/agents/src/client/ProviderModelEditor.tsrx +313 -0
  253. package/modules/agents/src/client/RunTimeline.tsrx +212 -0
  254. package/modules/agents/src/client/agents.css +349 -0
  255. package/modules/agents/src/client/api.ts +373 -0
  256. package/modules/agents/src/client/contribution.tsrx +181 -0
  257. package/modules/agents/src/client/index.ts +21 -0
  258. package/modules/agents/src/client/presentation.ts +162 -0
  259. package/modules/agents/src/client/state.ts +100 -0
  260. package/modules/agents/src/domain/context-variables.ts +58 -0
  261. package/modules/agents/src/domain/run-timeline.ts +145 -0
  262. package/modules/agents/src/domain/types.ts +481 -0
  263. package/modules/agents/src/index.ts +88 -0
  264. package/modules/agents/src/platform.ts +82 -0
  265. package/modules/agents/src/server/action-execution.ts +811 -0
  266. package/modules/agents/src/server/define-agent.ts +170 -0
  267. package/modules/agents/src/server/index.ts +67 -0
  268. package/modules/agents/src/server/run-execution.ts +231 -0
  269. package/modules/agents/src/server/run-queue.ts +96 -0
  270. package/modules/agents/src/server/runtime.ts +448 -0
  271. package/modules/agents/src/server/tools.ts +18 -0
  272. package/modules/agents/src/services/agent-service.ts +2167 -0
  273. package/modules/agents/src/services/credential-vault.ts +133 -0
  274. package/modules/agents/src/services/database-repository.ts +2786 -0
  275. package/modules/agents/src/services/index.ts +33 -0
  276. package/modules/agents/src/services/migration.ts +1152 -0
  277. package/modules/agents/src/services/module-agent-preflight.ts +76 -0
  278. package/modules/agents/src/services/outbound-policy.ts +136 -0
  279. package/modules/agents/src/services/provider-broker.ts +80 -0
  280. package/modules/agents/src/services/provider-repository.ts +589 -0
  281. package/modules/agents/src/services/provider-service.ts +968 -0
  282. package/modules/agents/src/services/repository.ts +294 -0
  283. package/modules/agents/src/services/run-grant.ts +305 -0
  284. package/modules/agents/src/services/usage-service.ts +119 -0
  285. package/modules/agents/src/services/worker.ts +442 -0
  286. package/modules/agents/src/settings.ts +244 -0
  287. package/modules/agents/translations/en.json +403 -0
  288. package/modules/agents/translations/pl.json +403 -0
  289. package/modules/auth/README.md +215 -0
  290. package/modules/auth/migrations/0001_auth_core.up.sql +108 -0
  291. package/modules/auth/migrations/0002_bundled_module_scopes.up.sql +26 -0
  292. package/modules/auth/migrations/0003_agent_core_scopes.up.sql +12 -0
  293. package/modules/auth/migrations/0004_owner_only_development_scopes.up.sql +8 -0
  294. package/modules/auth/migrations/0005_agent_provider_scopes.up.sql +13 -0
  295. package/modules/auth/migrations/0006_tenant_slug.up.sql +6 -0
  296. package/modules/auth/migrations/0007_sandbox_scopes.up.sql +13 -0
  297. package/modules/auth/migrations/0008_api_tokens.up.sql +43 -0
  298. package/modules/auth/migrations/0009_module_settings.up.sql +24 -0
  299. package/modules/auth/migrations/0010_sign_in_lockout.up.sql +11 -0
  300. package/modules/auth/migrations/0011_session_ids_and_password_reset.up.sql +7 -0
  301. package/modules/auth/migrations/0012_roles.up.sql +31 -0
  302. package/modules/auth/migrations/0013_audit.up.sql +27 -0
  303. package/modules/auth/migrations/0014_audit_actor.up.sql +4 -0
  304. package/modules/auth/migrations/0015_account_security.up.sql +81 -0
  305. package/modules/auth/module.json +26 -0
  306. package/modules/auth/package.json +61 -0
  307. package/modules/auth/spec/module.yaml +190 -0
  308. package/modules/auth/src/acl/scopes.ts +86 -0
  309. package/modules/auth/src/api/attempt-limiter.ts +42 -0
  310. package/modules/auth/src/api/client-address.ts +14 -0
  311. package/modules/auth/src/api/cookies.ts +52 -0
  312. package/modules/auth/src/api/origin.ts +40 -0
  313. package/modules/auth/src/cli/commands.json +74 -0
  314. package/modules/auth/src/cli/database.ts +51 -0
  315. package/modules/auth/src/cli/greenfield.ts +173 -0
  316. package/modules/auth/src/cli/index.ts +184 -0
  317. package/modules/auth/src/cli/provisioning.ts +211 -0
  318. package/modules/auth/src/client/AuthBackdrop.tsrx +137 -0
  319. package/modules/auth/src/client/AuthenticationCore.tsrx +630 -0
  320. package/modules/auth/src/client/PasswordChangeRequired.tsrx +145 -0
  321. package/modules/auth/src/client/PublicAuthFlows.tsrx +379 -0
  322. package/modules/auth/src/client/api.ts +464 -0
  323. package/modules/auth/src/client/audit/AuditView.tsrx +357 -0
  324. package/modules/auth/src/client/audit/api.ts +164 -0
  325. package/modules/auth/src/client/audit/audit-columns.tsrx +47 -0
  326. package/modules/auth/src/client/audit/audit-row.ts +38 -0
  327. package/modules/auth/src/client/auth.css +483 -0
  328. package/modules/auth/src/client/contribution.tsrx +100 -0
  329. package/modules/auth/src/client/index.ts +32 -0
  330. package/modules/auth/src/client/security/SecurityView.tsrx +253 -0
  331. package/modules/auth/src/client/settings/PreferencesCard.tsrx +65 -0
  332. package/modules/auth/src/client/settings/SettingsView.tsrx +212 -0
  333. package/modules/auth/src/client/settings/WorkspaceCard.tsrx +59 -0
  334. package/modules/auth/src/client/settings/api.ts +115 -0
  335. package/modules/auth/src/client/slug.ts +26 -0
  336. package/modules/auth/src/client/state.ts +115 -0
  337. package/modules/auth/src/client/tokens/ApiTokenForm.tsrx +153 -0
  338. package/modules/auth/src/client/tokens/ApiTokenSecret.tsrx +35 -0
  339. package/modules/auth/src/client/tokens/ApiTokensView.tsrx +216 -0
  340. package/modules/auth/src/client/tokens/api.ts +59 -0
  341. package/modules/auth/src/client/tokens/state.ts +26 -0
  342. package/modules/auth/src/client/tokens/token-columns.tsrx +64 -0
  343. package/modules/auth/src/client/translations.ts +23 -0
  344. package/modules/auth/src/domain/types.ts +152 -0
  345. package/modules/auth/src/index.ts +42 -0
  346. package/modules/auth/src/middleware/authentication.ts +97 -0
  347. package/modules/auth/src/platform.ts +0 -0
  348. package/modules/auth/src/server/actor.ts +12 -0
  349. package/modules/auth/src/server/audit-endpoints.ts +51 -0
  350. package/modules/auth/src/server/composition.ts +9 -0
  351. package/modules/auth/src/server/endpoints.ts +893 -0
  352. package/modules/auth/src/server/http.ts +153 -0
  353. package/modules/auth/src/server/index.ts +37 -0
  354. package/modules/auth/src/server/roles-endpoints.ts +120 -0
  355. package/modules/auth/src/server/runtime.ts +705 -0
  356. package/modules/auth/src/server/session-endpoints.ts +86 -0
  357. package/modules/auth/src/server/session-security.ts +62 -0
  358. package/modules/auth/src/server/token-endpoints.ts +106 -0
  359. package/modules/auth/src/services/auth-service-error.ts +11 -0
  360. package/modules/auth/src/services/auth-service.ts +2309 -0
  361. package/modules/auth/src/services/database-repository.ts +1825 -0
  362. package/modules/auth/src/services/mail-delivery.ts +27 -0
  363. package/modules/auth/src/services/migration.ts +591 -0
  364. package/modules/auth/src/services/password.ts +115 -0
  365. package/modules/auth/src/services/repository.ts +395 -0
  366. package/modules/auth/src/services/settings-store.ts +92 -0
  367. package/modules/auth/src/services/totp.ts +135 -0
  368. package/modules/auth/src/services/validation.ts +186 -0
  369. package/modules/auth/src/settings.ts +150 -0
  370. package/modules/auth/translations/en.json +263 -0
  371. package/modules/auth/translations/pl.json +263 -0
  372. package/modules/automations/migrations/0001_automations_core.down.sql +10 -0
  373. package/modules/automations/migrations/0001_automations_core.up.sql +76 -0
  374. package/modules/automations/migrations/0002_automations_targets.down.sql +9 -0
  375. package/modules/automations/migrations/0002_automations_targets.up.sql +37 -0
  376. package/modules/automations/migrations/0003_automations_scheduler_role.down.sql +3 -0
  377. package/modules/automations/migrations/0003_automations_scheduler_role.up.sql +19 -0
  378. package/modules/automations/migrations/0004_automations_trigger_routing_role.down.sql +3 -0
  379. package/modules/automations/migrations/0004_automations_trigger_routing_role.up.sql +18 -0
  380. package/modules/automations/migrations/README.md +3 -0
  381. package/modules/automations/module.json +31 -0
  382. package/modules/automations/package.json +55 -0
  383. package/modules/automations/spec/module.yaml +93 -0
  384. package/modules/automations/src/acl/permissions.ts +10 -0
  385. package/modules/automations/src/api/endpoints.ts +480 -0
  386. package/modules/automations/src/client/AutomationScheduleForm.tsrx +218 -0
  387. package/modules/automations/src/client/AutomationSchedulesView.tsrx +339 -0
  388. package/modules/automations/src/client/AutomationTriggerForm.tsrx +190 -0
  389. package/modules/automations/src/client/AutomationTriggersView.tsrx +329 -0
  390. package/modules/automations/src/client/api.ts +148 -0
  391. package/modules/automations/src/client/contribution.tsrx +70 -0
  392. package/modules/automations/src/client/index.ts +20 -0
  393. package/modules/automations/src/client/presentation.ts +38 -0
  394. package/modules/automations/src/client/state.ts +40 -0
  395. package/modules/automations/src/client/target-selection.ts +44 -0
  396. package/modules/automations/src/domain/cadence.ts +44 -0
  397. package/modules/automations/src/domain/types.ts +110 -0
  398. package/modules/automations/src/domain/variables.ts +178 -0
  399. package/modules/automations/src/index.ts +39 -0
  400. package/modules/automations/src/platform.ts +73 -0
  401. package/modules/automations/src/server/execution.ts +77 -0
  402. package/modules/automations/src/server/index.ts +39 -0
  403. package/modules/automations/src/server/runtime.ts +218 -0
  404. package/modules/automations/src/server/targets.ts +116 -0
  405. package/modules/automations/src/services/automations-service.ts +10 -0
  406. package/modules/automations/src/services/database-repository.ts +763 -0
  407. package/modules/automations/src/services/index.ts +5 -0
  408. package/modules/automations/src/services/migration.ts +223 -0
  409. package/modules/automations/src/services/repository.ts +119 -0
  410. package/modules/automations/src/services/schedule-service.ts +837 -0
  411. package/modules/automations/src/services/secret-vault.ts +124 -0
  412. package/modules/automations/src/services/trigger-service.ts +648 -0
  413. package/modules/automations/src/settings.ts +69 -0
  414. package/modules/automations/translations/en.json +126 -0
  415. package/modules/automations/translations/pl.json +126 -0
  416. package/modules/automations-workflows-integration/module.json +27 -0
  417. package/modules/automations-workflows-integration/package.json +48 -0
  418. package/modules/automations-workflows-integration/spec/module.yaml +93 -0
  419. package/modules/automations-workflows-integration/src/index.ts +14 -0
  420. package/modules/automations-workflows-integration/src/platform.ts +24 -0
  421. package/modules/automations-workflows-integration/src/server/adapter.ts +272 -0
  422. package/modules/automations-workflows-integration/src/server/index.ts +11 -0
  423. package/modules/automations-workflows-integration/src/server/tools.ts +0 -0
  424. package/modules/automations-workflows-integration/translations/en.json +21 -0
  425. package/modules/automations-workflows-integration/translations/pl.json +21 -0
  426. package/modules/profile/migrations/0001_profile_core.down.sql +1 -0
  427. package/modules/profile/migrations/0001_profile_core.up.sql +13 -0
  428. package/modules/profile/migrations/0002_profile_language.down.sql +1 -0
  429. package/modules/profile/migrations/0002_profile_language.up.sql +12 -0
  430. package/modules/profile/migrations/README.md +3 -0
  431. package/modules/profile/module.json +23 -0
  432. package/modules/profile/package.json +55 -0
  433. package/modules/profile/spec/module.yaml +136 -0
  434. package/modules/profile/src/acl/permissions.ts +5 -0
  435. package/modules/profile/src/api/endpoints.ts +184 -0
  436. package/modules/profile/src/client/DisplayNameCard.tsrx +59 -0
  437. package/modules/profile/src/client/LanguageCard.tsrx +89 -0
  438. package/modules/profile/src/client/PasswordCard.tsrx +79 -0
  439. package/modules/profile/src/client/ProfileView.tsrx +192 -0
  440. package/modules/profile/src/client/SessionsCard.tsrx +158 -0
  441. package/modules/profile/src/client/api.ts +134 -0
  442. package/modules/profile/src/client/contribution.tsrx +61 -0
  443. package/modules/profile/src/client/index.ts +15 -0
  444. package/modules/profile/src/client/password.ts +41 -0
  445. package/modules/profile/src/client/sessions-api.ts +52 -0
  446. package/modules/profile/src/client/state.ts +23 -0
  447. package/modules/profile/src/domain/types.ts +21 -0
  448. package/modules/profile/src/index.ts +21 -0
  449. package/modules/profile/src/platform.ts +23 -0
  450. package/modules/profile/src/server/index.ts +7 -0
  451. package/modules/profile/src/server/runtime.ts +84 -0
  452. package/modules/profile/src/services/database-repository.ts +154 -0
  453. package/modules/profile/src/services/index.ts +6 -0
  454. package/modules/profile/src/services/migration.ts +58 -0
  455. package/modules/profile/src/services/profile-service.ts +114 -0
  456. package/modules/profile/src/services/repository.ts +13 -0
  457. package/modules/profile/translations/en.json +58 -0
  458. package/modules/profile/translations/pl.json +58 -0
  459. package/modules/sandbox/migrations/0001_sandbox_core.down.sql +6 -0
  460. package/modules/sandbox/migrations/0001_sandbox_core.up.sql +70 -0
  461. package/modules/sandbox/migrations/0002_sandbox_session_lifecycle.down.sql +36 -0
  462. package/modules/sandbox/migrations/0002_sandbox_session_lifecycle.up.sql +37 -0
  463. package/modules/sandbox/migrations/README.md +7 -0
  464. package/modules/sandbox/module.json +31 -0
  465. package/modules/sandbox/package.json +56 -0
  466. package/modules/sandbox/spec/module.yaml +111 -0
  467. package/modules/sandbox/src/acl/permissions.ts +18 -0
  468. package/modules/sandbox/src/api/endpoints.ts +439 -0
  469. package/modules/sandbox/src/cli/commands.json +84 -0
  470. package/modules/sandbox/src/cli/index.ts +450 -0
  471. package/modules/sandbox/src/client/SandboxAccessView.tsrx +191 -0
  472. package/modules/sandbox/src/client/SandboxGrantForm.tsrx +134 -0
  473. package/modules/sandbox/src/client/SandboxGrantList.tsrx +83 -0
  474. package/modules/sandbox/src/client/SandboxSessionList.tsrx +56 -0
  475. package/modules/sandbox/src/client/api.ts +87 -0
  476. package/modules/sandbox/src/client/contribution.tsrx +47 -0
  477. package/modules/sandbox/src/client/index.ts +18 -0
  478. package/modules/sandbox/src/client/presentation.ts +47 -0
  479. package/modules/sandbox/src/client/state.ts +20 -0
  480. package/modules/sandbox/src/domain/types.ts +125 -0
  481. package/modules/sandbox/src/index.ts +33 -0
  482. package/modules/sandbox/src/platform.ts +28 -0
  483. package/modules/sandbox/src/server/index.ts +20 -0
  484. package/modules/sandbox/src/server/runtime.ts +119 -0
  485. package/modules/sandbox/src/services/database-repository.ts +567 -0
  486. package/modules/sandbox/src/services/directory.ts +33 -0
  487. package/modules/sandbox/src/services/index.ts +19 -0
  488. package/modules/sandbox/src/services/migration.ts +145 -0
  489. package/modules/sandbox/src/services/repository.ts +55 -0
  490. package/modules/sandbox/src/services/sandbox-service-error.ts +10 -0
  491. package/modules/sandbox/src/services/sandbox-service.ts +533 -0
  492. package/modules/sandbox/translations/en.json +77 -0
  493. package/modules/sandbox/translations/pl.json +77 -0
  494. package/modules/system/module.json +18 -0
  495. package/modules/system/package.json +56 -0
  496. package/modules/system/spec/module.yaml +104 -0
  497. package/modules/system/src/acl/permissions.ts +10 -0
  498. package/modules/system/src/client/ModuleSettingRow.tsrx +191 -0
  499. package/modules/system/src/client/ModuleSettingsSection.tsrx +155 -0
  500. package/modules/system/src/client/ModulesView.tsrx +241 -0
  501. package/modules/system/src/client/api.ts +36 -0
  502. package/modules/system/src/client/contribution.tsrx +48 -0
  503. package/modules/system/src/client/index.ts +26 -0
  504. package/modules/system/src/client/module-columns.tsrx +66 -0
  505. package/modules/system/src/client/overview-api.ts +30 -0
  506. package/modules/system/src/client/setting-copy.ts +30 -0
  507. package/modules/system/src/client/settings-api.ts +57 -0
  508. package/modules/system/src/client/state.ts +16 -0
  509. package/modules/system/src/index.ts +11 -0
  510. package/modules/system/src/platform.ts +11 -0
  511. package/modules/system/src/server/endpoints.ts +372 -0
  512. package/modules/system/src/server/index.ts +11 -0
  513. package/modules/system/src/server/module-catalog.ts +117 -0
  514. package/modules/system/translations/en.json +64 -0
  515. package/modules/system/translations/pl.json +64 -0
  516. package/modules/users/migrations/README.md +3 -0
  517. package/modules/users/module.json +27 -0
  518. package/modules/users/package.json +54 -0
  519. package/modules/users/spec/module.yaml +79 -0
  520. package/modules/users/src/acl/permissions.ts +6 -0
  521. package/modules/users/src/api/endpoints.ts +222 -0
  522. package/modules/users/src/client/InviteMemberForm.tsrx +62 -0
  523. package/modules/users/src/client/MemberDrawer.tsrx +298 -0
  524. package/modules/users/src/client/RoleForm.tsrx +140 -0
  525. package/modules/users/src/client/RolesView.tsrx +288 -0
  526. package/modules/users/src/client/UserAccountForm.tsrx +86 -0
  527. package/modules/users/src/client/UsersView.tsrx +486 -0
  528. package/modules/users/src/client/api.ts +172 -0
  529. package/modules/users/src/client/contribution.tsrx +92 -0
  530. package/modules/users/src/client/index.ts +19 -0
  531. package/modules/users/src/client/member-columns.tsrx +52 -0
  532. package/modules/users/src/client/roles-api.ts +90 -0
  533. package/modules/users/src/client/state.ts +42 -0
  534. package/modules/users/src/index.ts +27 -0
  535. package/modules/users/src/platform.ts +11 -0
  536. package/modules/users/src/services/index.ts +2 -0
  537. package/modules/users/src/services/users-service.ts +142 -0
  538. package/modules/users/translations/en.json +133 -0
  539. package/modules/users/translations/pl.json +133 -0
  540. package/modules/workflows/migrations/0001_workflows_core.down.sql +19 -0
  541. package/modules/workflows/migrations/0001_workflows_core.up.sql +228 -0
  542. package/modules/workflows/migrations/0002_workflows_authorization_subject.down.sql +1 -0
  543. package/modules/workflows/migrations/0002_workflows_authorization_subject.up.sql +9 -0
  544. package/modules/workflows/migrations/0003_workflows_worker_role.up.sql +34 -0
  545. package/modules/workflows/migrations/README.md +7 -0
  546. package/modules/workflows/module.json +31 -0
  547. package/modules/workflows/package.json +55 -0
  548. package/modules/workflows/spec/module.yaml +227 -0
  549. package/modules/workflows/src/acl/permissions.ts +10 -0
  550. package/modules/workflows/src/api/endpoints.ts +852 -0
  551. package/modules/workflows/src/client/WorkflowCanvas.tsrx +819 -0
  552. package/modules/workflows/src/client/WorkflowCreateForm.tsrx +111 -0
  553. package/modules/workflows/src/client/WorkflowEditor.tsrx +443 -0
  554. package/modules/workflows/src/client/WorkflowExecutionHistory.tsrx +169 -0
  555. package/modules/workflows/src/client/WorkflowFixtureDrawer.tsrx +206 -0
  556. package/modules/workflows/src/client/WorkflowInputForm.tsrx +125 -0
  557. package/modules/workflows/src/client/WorkflowInputSchemaEditor.tsrx +185 -0
  558. package/modules/workflows/src/client/WorkflowInspector.tsrx +471 -0
  559. package/modules/workflows/src/client/WorkflowLiveConfirmation.tsrx +67 -0
  560. package/modules/workflows/src/client/WorkflowMappingEditor.tsrx +283 -0
  561. package/modules/workflows/src/client/WorkflowNodePalette.tsrx +50 -0
  562. package/modules/workflows/src/client/WorkflowPointerField.tsrx +178 -0
  563. package/modules/workflows/src/client/WorkflowRevisionReview.tsrx +49 -0
  564. package/modules/workflows/src/client/WorkflowRunInspector.tsrx +143 -0
  565. package/modules/workflows/src/client/WorkflowTestPanel.tsrx +109 -0
  566. package/modules/workflows/src/client/WorkflowValidationPanel.tsrx +139 -0
  567. package/modules/workflows/src/client/WorkflowsView.tsrx +1060 -0
  568. package/modules/workflows/src/client/api.ts +312 -0
  569. package/modules/workflows/src/client/canvas-model.ts +472 -0
  570. package/modules/workflows/src/client/connected-node.ts +71 -0
  571. package/modules/workflows/src/client/contribution.tsrx +57 -0
  572. package/modules/workflows/src/client/create-model.ts +15 -0
  573. package/modules/workflows/src/client/draft-repair.ts +86 -0
  574. package/modules/workflows/src/client/index.ts +19 -0
  575. package/modules/workflows/src/client/input-model.ts +124 -0
  576. package/modules/workflows/src/client/mapping-model.ts +110 -0
  577. package/modules/workflows/src/client/pointer-model.ts +123 -0
  578. package/modules/workflows/src/client/presentation.ts +62 -0
  579. package/modules/workflows/src/client/run-actions.ts +19 -0
  580. package/modules/workflows/src/client/state.ts +57 -0
  581. package/modules/workflows/src/client/viewport.ts +107 -0
  582. package/modules/workflows/src/client/workflows.css +899 -0
  583. package/modules/workflows/src/domain/events.ts +399 -0
  584. package/modules/workflows/src/domain/graph.ts +1136 -0
  585. package/modules/workflows/src/domain/types.ts +563 -0
  586. package/modules/workflows/src/index.ts +27 -0
  587. package/modules/workflows/src/platform.ts +49 -0
  588. package/modules/workflows/src/server/index.ts +13 -0
  589. package/modules/workflows/src/server/runtime.ts +266 -0
  590. package/modules/workflows/src/services/cursor-codec.ts +62 -0
  591. package/modules/workflows/src/services/database-repository.ts +2407 -0
  592. package/modules/workflows/src/services/index.ts +6 -0
  593. package/modules/workflows/src/services/migration.ts +375 -0
  594. package/modules/workflows/src/services/payload-codec.ts +264 -0
  595. package/modules/workflows/src/services/repository.ts +285 -0
  596. package/modules/workflows/src/services/simulation.ts +359 -0
  597. package/modules/workflows/src/services/worker.ts +1196 -0
  598. package/modules/workflows/src/services/workflows-service.ts +1395 -0
  599. package/modules/workflows/translations/en.json +348 -0
  600. package/modules/workflows/translations/pl.json +348 -0
  601. package/modules.json +41 -0
  602. package/package.json +125 -0
  603. package/packages/ai-provider/package.json +46 -0
  604. package/packages/ai-provider/src/catalog.ts +102 -0
  605. package/packages/ai-provider/src/errors.ts +110 -0
  606. package/packages/ai-provider/src/index.ts +33 -0
  607. package/packages/ai-provider/src/model.ts +198 -0
  608. package/packages/ai-provider/src/pricing.ts +73 -0
  609. package/packages/cli-protocol/package.json +40 -0
  610. package/packages/cli-protocol/src/index.ts +113 -0
  611. package/packages/client/package.json +46 -0
  612. package/packages/client/src/ApplicationShell.tsrx +374 -0
  613. package/packages/client/src/contributions.ts +172 -0
  614. package/packages/client/src/i18n/index.ts +30 -0
  615. package/packages/client/src/i18n/locale.ts +25 -0
  616. package/packages/client/src/i18n/locales/en.json +66 -0
  617. package/packages/client/src/i18n/locales/pl.json +66 -0
  618. package/packages/client/src/i18n/runtime.ts +201 -0
  619. package/packages/client/src/i18n/translations.ts +88 -0
  620. package/packages/client/src/index.ts +55 -0
  621. package/packages/client/src/routing.ts +9 -0
  622. package/packages/client/src/shell/BrandMark.tsrx +10 -0
  623. package/packages/client/src/shell/CommandPalette.tsrx +79 -0
  624. package/packages/client/src/shell/ContributionOutlets.tsrx +31 -0
  625. package/packages/client/src/shell/DashboardView.tsrx +60 -0
  626. package/packages/client/src/shell/MobileHeader.tsrx +24 -0
  627. package/packages/client/src/shell/OrganizationSwitcher.tsrx +100 -0
  628. package/packages/client/src/shell/OverviewCharts.tsrx +167 -0
  629. package/packages/client/src/shell/PrimaryNavigation.tsrx +75 -0
  630. package/packages/client/src/shell/Sidebar.tsrx +76 -0
  631. package/packages/client/src/shell/Topbar.tsrx +44 -0
  632. package/packages/client/src/shell/UserMenu.tsrx +103 -0
  633. package/packages/client/src/shell/WorkspaceContent.tsrx +30 -0
  634. package/packages/client/src/shell/identity.ts +12 -0
  635. package/packages/client/src/shell/navigation.ts +68 -0
  636. package/packages/client/src/shell/shell.css +734 -0
  637. package/packages/client/src/shell/types.ts +29 -0
  638. package/packages/client/src/state.ts +63 -0
  639. package/packages/client/src/web.ts +39 -0
  640. package/packages/coding-agent/package.json +44 -0
  641. package/packages/coding-agent/src/drivers/byok.ts +322 -0
  642. package/packages/coding-agent/src/drivers/claude-code.ts +290 -0
  643. package/packages/coding-agent/src/drivers/codex.ts +281 -0
  644. package/packages/coding-agent/src/index.ts +56 -0
  645. package/packages/coding-agent/src/registry.ts +119 -0
  646. package/packages/coding-agent/src/roles/contract.ts +60 -0
  647. package/packages/coding-agent/src/roles/defaults.ts +134 -0
  648. package/packages/coding-agent/src/roles/handoff.ts +41 -0
  649. package/packages/coding-agent/src/roles/registry.ts +156 -0
  650. package/packages/coding-agent/src/roles/skills.ts +72 -0
  651. package/packages/coding-agent/src/roles/sync.ts +88 -0
  652. package/packages/coding-agent/src/types.ts +102 -0
  653. package/packages/coding-agent/src/workspace.ts +275 -0
  654. package/packages/contracts/package.json +38 -0
  655. package/packages/contracts/schemas/blueprint.schema.json +48 -0
  656. package/packages/contracts/schemas/cli-extension.schema.json +90 -0
  657. package/packages/contracts/schemas/module-artifact.schema.json +82 -0
  658. package/packages/contracts/schemas/module-catalog.schema.json +48 -0
  659. package/packages/contracts/schemas/module-spec.schema.json +111 -0
  660. package/packages/contracts/schemas/module.schema.json +156 -0
  661. package/packages/contracts/schemas/platform-spec.schema.json +17 -0
  662. package/packages/contracts/schemas/project.schema.json +270 -0
  663. package/packages/contracts/src/index.ts +191 -0
  664. package/packages/contracts/src/module-distribution.ts +47 -0
  665. package/packages/contracts/src/schemas.ts +18 -0
  666. package/packages/contracts/src/variables.ts +156 -0
  667. package/packages/contracts/src/web.ts +60 -0
  668. package/packages/database/package.json +43 -0
  669. package/packages/database/src/contracts.ts +399 -0
  670. package/packages/database/src/index.ts +112 -0
  671. package/packages/database/src/migrations.ts +444 -0
  672. package/packages/database/src/postgresql.ts +517 -0
  673. package/packages/database/src/provider.ts +639 -0
  674. package/packages/database/src/record-history.ts +201 -0
  675. package/packages/database/src/registry.ts +265 -0
  676. package/packages/database/src/reset.ts +87 -0
  677. package/packages/database-pglite/package.json +42 -0
  678. package/packages/database-pglite/src/driver.ts +168 -0
  679. package/packages/database-pglite/src/index.ts +2 -0
  680. package/packages/database-testing/package.json +44 -0
  681. package/packages/database-testing/src/index.ts +8 -0
  682. package/packages/database-testing/src/pglite.ts +124 -0
  683. package/packages/database-testing/src/postgres.ts +184 -0
  684. package/packages/database-testing/src/provider.ts +43 -0
  685. package/packages/database-testing/src/vitest-preset.ts +23 -0
  686. package/packages/dev-console/README.md +6 -0
  687. package/packages/dev-console/package.json +38 -0
  688. package/packages/dev-console/src/index.mjs +220 -0
  689. package/packages/harness/package.json +47 -0
  690. package/packages/harness/schemas/task-packet.schema.json +48 -0
  691. package/packages/harness/src/catalog.ts +24 -0
  692. package/packages/harness/src/errors.ts +9 -0
  693. package/packages/harness/src/index.ts +53 -0
  694. package/packages/harness/src/preamble.ts +31 -0
  695. package/packages/harness/src/runtime.ts +833 -0
  696. package/packages/harness/src/task-packet.ts +86 -0
  697. package/packages/harness/src/tool-adapters.ts +106 -0
  698. package/packages/harness/src/tool-contract.ts +242 -0
  699. package/packages/harness/src/vercel-ai-provider.ts +198 -0
  700. package/packages/kernel/package.json +44 -0
  701. package/packages/kernel/src/acl.ts +20 -0
  702. package/packages/kernel/src/actor.ts +139 -0
  703. package/packages/kernel/src/agent-registry.ts +81 -0
  704. package/packages/kernel/src/capability-registry.ts +28 -0
  705. package/packages/kernel/src/errors.ts +9 -0
  706. package/packages/kernel/src/index.ts +90 -0
  707. package/packages/kernel/src/legacy-local-state.ts +103 -0
  708. package/packages/kernel/src/module-compatibility.ts +70 -0
  709. package/packages/kernel/src/module-registry.ts +124 -0
  710. package/packages/kernel/src/module-settings.ts +403 -0
  711. package/packages/kernel/src/record-history.ts +146 -0
  712. package/packages/kernel/src/runtime-config.ts +51 -0
  713. package/packages/kernel/src/tool-registry.ts +25 -0
  714. package/packages/kernel/src/variable-registry.ts +339 -0
  715. package/packages/sandbox/README.md +691 -0
  716. package/packages/sandbox/bin/flowdular-sandbox.mjs +393 -0
  717. package/packages/sandbox/dist/client/assets/App-ClMOrpyg.js +11 -0
  718. package/packages/sandbox/dist/client/assets/PreviewHost-BHiHrfbQ.js +1 -0
  719. package/packages/sandbox/dist/client/assets/auto-buGEq6de.js +3 -0
  720. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  721. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  722. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
  723. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
  724. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  725. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  726. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
  727. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
  728. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  729. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  730. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  731. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  732. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  733. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  734. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
  735. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
  736. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  737. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  738. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
  739. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
  740. package/packages/sandbox/dist/client/assets/ibm-plex-sans-cyrillic-ext-wght-normal-d45eAU9y.woff2 +0 -0
  741. package/packages/sandbox/dist/client/assets/ibm-plex-sans-cyrillic-wght-normal-BAAhND-U.woff2 +0 -0
  742. package/packages/sandbox/dist/client/assets/ibm-plex-sans-greek-wght-normal-CmyJS8uq.woff2 +0 -0
  743. package/packages/sandbox/dist/client/assets/ibm-plex-sans-latin-ext-wght-normal-CIII54If.woff2 +0 -0
  744. package/packages/sandbox/dist/client/assets/ibm-plex-sans-latin-wght-normal-IvpUvPa2.woff2 +0 -0
  745. package/packages/sandbox/dist/client/assets/ibm-plex-sans-vietnamese-wght-normal-Dg1JeJN0.woff2 +0 -0
  746. package/packages/sandbox/dist/client/assets/index-CvwhlQ87.js +4 -0
  747. package/packages/sandbox/dist/client/assets/styles-BPWaGf55.js +3 -0
  748. package/packages/sandbox/dist/client/assets/styles-Dx1_KOag.css +1 -0
  749. package/packages/sandbox/dist/client/favicon.svg +1 -0
  750. package/packages/sandbox/dist/server/assets/auto-CVGNYyb3.js +12785 -0
  751. package/packages/sandbox/dist/server/assets/chunk-DDJLRBDX-3OUNo51g.js +4125 -0
  752. package/packages/sandbox/dist/server/assets/nodefs-DVSI7kG0.js +24 -0
  753. package/packages/sandbox/dist/server/assets/opfs-ahp-D56iokt1.js +388 -0
  754. package/packages/sandbox/dist/server/assets/token-Bvaq7Anz.js +55 -0
  755. package/packages/sandbox/dist/server/assets/token-util-BqSvdIPQ.js +3 -0
  756. package/packages/sandbox/dist/server/assets/token-util-CktFFT4z.js +494 -0
  757. package/packages/sandbox/dist/server/entry.js +91671 -0
  758. package/packages/sandbox/dist/server/favicon.svg +1 -0
  759. package/packages/sandbox/dist/server/index.html +161 -0
  760. package/packages/sandbox/index.html +159 -0
  761. package/packages/sandbox/octane.config.ts +36 -0
  762. package/packages/sandbox/package.json +83 -0
  763. package/packages/sandbox/public/favicon.svg +1 -0
  764. package/packages/sandbox/public/og.png +0 -0
  765. package/packages/sandbox/src/App.tsrx +924 -0
  766. package/packages/sandbox/src/client/ApprovalHandoff.tsrx +39 -0
  767. package/packages/sandbox/src/client/ChatPane.tsrx +694 -0
  768. package/packages/sandbox/src/client/ConnectView.tsrx +86 -0
  769. package/packages/sandbox/src/client/DiffPane.tsrx +150 -0
  770. package/packages/sandbox/src/client/EjectModal.tsrx +571 -0
  771. package/packages/sandbox/src/client/GateResults.tsrx +60 -0
  772. package/packages/sandbox/src/client/GitHubSettingsModal.tsrx +219 -0
  773. package/packages/sandbox/src/client/NewSessionForm.tsrx +214 -0
  774. package/packages/sandbox/src/client/SessionBar.tsrx +151 -0
  775. package/packages/sandbox/src/client/SessionPicker.tsrx +472 -0
  776. package/packages/sandbox/src/client/SpecEditor.tsrx +109 -0
  777. package/packages/sandbox/src/client/SpecReviewCard.tsrx +321 -0
  778. package/packages/sandbox/src/client/WorkCard.tsrx +128 -0
  779. package/packages/sandbox/src/client/WorkbenchModal.tsrx +161 -0
  780. package/packages/sandbox/src/client/WorkspaceMenu.tsrx +100 -0
  781. package/packages/sandbox/src/client/api.ts +797 -0
  782. package/packages/sandbox/src/client/attachments.ts +73 -0
  783. package/packages/sandbox/src/client/dashboard.ts +46 -0
  784. package/packages/sandbox/src/client/github-settings.ts +48 -0
  785. package/packages/sandbox/src/client/highlight.ts +105 -0
  786. package/packages/sandbox/src/client/i18n.ts +32 -0
  787. package/packages/sandbox/src/client/locales/en.json +466 -0
  788. package/packages/sandbox/src/client/locales/pl.json +466 -0
  789. package/packages/sandbox/src/client/session-labels.ts +77 -0
  790. package/packages/sandbox/src/client/state.ts +108 -0
  791. package/packages/sandbox/src/index.ts +10 -0
  792. package/packages/sandbox/src/preview/PreviewHost.tsrx +373 -0
  793. package/packages/sandbox/src/preview/load-module.ts +16 -0
  794. package/packages/sandbox/src/server/attachments.ts +308 -0
  795. package/packages/sandbox/src/server/auto-review.ts +181 -0
  796. package/packages/sandbox/src/server/checkpoints.ts +90 -0
  797. package/packages/sandbox/src/server/config.ts +460 -0
  798. package/packages/sandbox/src/server/dashboard.ts +245 -0
  799. package/packages/sandbox/src/server/delivery/configuration.ts +193 -0
  800. package/packages/sandbox/src/server/delivery/git-pr.ts +1473 -0
  801. package/packages/sandbox/src/server/delivery/index.ts +83 -0
  802. package/packages/sandbox/src/server/delivery/local.ts +151 -0
  803. package/packages/sandbox/src/server/delivery/official-modules.ts +516 -0
  804. package/packages/sandbox/src/server/delivery/plan.ts +218 -0
  805. package/packages/sandbox/src/server/delivery/policies.ts +239 -0
  806. package/packages/sandbox/src/server/delivery/record.ts +41 -0
  807. package/packages/sandbox/src/server/delivery/steps.ts +464 -0
  808. package/packages/sandbox/src/server/delivery/types.ts +158 -0
  809. package/packages/sandbox/src/server/dependencies.ts +88 -0
  810. package/packages/sandbox/src/server/diff.ts +230 -0
  811. package/packages/sandbox/src/server/gates.ts +388 -0
  812. package/packages/sandbox/src/server/index.ts +139 -0
  813. package/packages/sandbox/src/server/path-guard.ts +282 -0
  814. package/packages/sandbox/src/server/planning.ts +749 -0
  815. package/packages/sandbox/src/server/platform-client.ts +189 -0
  816. package/packages/sandbox/src/server/preview-database-host.ts +340 -0
  817. package/packages/sandbox/src/server/preview-database-protocol.ts +163 -0
  818. package/packages/sandbox/src/server/preview-database-proxy.ts +356 -0
  819. package/packages/sandbox/src/server/preview-database.ts +109 -0
  820. package/packages/sandbox/src/server/preview-ipc.ts +15 -0
  821. package/packages/sandbox/src/server/preview-modules.ts +83 -0
  822. package/packages/sandbox/src/server/preview-revision.ts +44 -0
  823. package/packages/sandbox/src/server/preview-runtime.ts +467 -0
  824. package/packages/sandbox/src/server/preview-worker-manager.ts +436 -0
  825. package/packages/sandbox/src/server/preview-worker.ts +168 -0
  826. package/packages/sandbox/src/server/reference.ts +251 -0
  827. package/packages/sandbox/src/server/routes.ts +2258 -0
  828. package/packages/sandbox/src/server/runtime.ts +188 -0
  829. package/packages/sandbox/src/server/session-owner.ts +23 -0
  830. package/packages/sandbox/src/server/sessions.ts +849 -0
  831. package/packages/sandbox/src/server/spec.ts +471 -0
  832. package/packages/sandbox/src/server/turn-lifecycle.ts +56 -0
  833. package/packages/sandbox/src/server/turns.ts +993 -0
  834. package/packages/sandbox/src/server/workspace-install.ts +266 -0
  835. package/packages/sandbox/src/server/workspace-root.ts +73 -0
  836. package/packages/sandbox/src/styles.css +1573 -0
  837. package/packages/sandbox/vite.config.ts +133 -0
  838. package/packages/server/package.json +43 -0
  839. package/packages/server/src/application-routes.ts +21 -0
  840. package/packages/server/src/composition.ts +48 -0
  841. package/packages/server/src/endpoint.ts +142 -0
  842. package/packages/server/src/http.ts +128 -0
  843. package/packages/server/src/index.ts +46 -0
  844. package/packages/server/src/response-lifetime.ts +56 -0
  845. package/packages/server/src/security-headers.ts +130 -0
  846. package/packages/server/src/web-html.ts +55 -0
  847. package/packages/server/src/web.ts +361 -0
  848. package/packages/ui/package.json +46 -0
  849. package/packages/ui/src/brand/BrandMark.tsrx +66 -0
  850. package/packages/ui/src/brand/mark.ts +44 -0
  851. package/packages/ui/src/components/Alert.tsrx +17 -0
  852. package/packages/ui/src/components/Avatar.tsrx +18 -0
  853. package/packages/ui/src/components/Button.tsrx +29 -0
  854. package/packages/ui/src/components/Chart.tsrx +274 -0
  855. package/packages/ui/src/components/CheckGrid.tsrx +93 -0
  856. package/packages/ui/src/components/ConfirmDialog.tsrx +63 -0
  857. package/packages/ui/src/components/Drawer.tsrx +71 -0
  858. package/packages/ui/src/components/EmptyState.tsrx +26 -0
  859. package/packages/ui/src/components/Filters.tsrx +39 -0
  860. package/packages/ui/src/components/FormField.tsrx +27 -0
  861. package/packages/ui/src/components/Kpi.tsrx +36 -0
  862. package/packages/ui/src/components/PageHeader.tsrx +26 -0
  863. package/packages/ui/src/components/ScopeSummary.tsrx +76 -0
  864. package/packages/ui/src/components/SearchField.tsrx +24 -0
  865. package/packages/ui/src/components/SettingRow.tsrx +50 -0
  866. package/packages/ui/src/components/Switch.tsrx +21 -0
  867. package/packages/ui/src/components/Table.tsrx +267 -0
  868. package/packages/ui/src/components/TableCard.tsrx +52 -0
  869. package/packages/ui/src/components/Tag.tsrx +28 -0
  870. package/packages/ui/src/components/VariableField.tsrx +284 -0
  871. package/packages/ui/src/components/VariableInput.tsrx +7 -0
  872. package/packages/ui/src/components/VariableSelect.tsrx +72 -0
  873. package/packages/ui/src/components/VariableTextarea.tsrx +9 -0
  874. package/packages/ui/src/components/variable-field.ts +61 -0
  875. package/packages/ui/src/components/variable-select.ts +69 -0
  876. package/packages/ui/src/icons/Icon.tsrx +56 -0
  877. package/packages/ui/src/index.ts +81 -0
  878. package/packages/ui/src/initials.ts +10 -0
  879. package/packages/ui/src/styles/base.css +71 -0
  880. package/packages/ui/src/styles/components.css +1859 -0
  881. package/packages/ui/src/styles/index.css +3 -0
  882. package/packages/ui/src/styles/tokens.css +124 -0
  883. package/tsconfig.base.json +18 -0
@@ -0,0 +1,968 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import {
3
+ createVercelAiSdkProvider,
4
+ probeVercelAiSdkProvider,
5
+ type AgentProvider,
6
+ type VercelAiProviderConfiguration,
7
+ } from '@flowdular/sdk/harness';
8
+ import { modelSupportsTemperature } from '@flowdular/sdk/harness/catalog';
9
+ import type {
10
+ AgentModelReadiness,
11
+ AgentProviderConnection,
12
+ AgentProviderKind,
13
+ AgentProviderModel,
14
+ AgentProviderModelConfiguration,
15
+ CreateAgentProviderInput,
16
+ UpdateAgentProviderInput,
17
+ } from '../domain/types.ts';
18
+ import type { CredentialVault } from './credential-vault.ts';
19
+ import {
20
+ assertPublicHost,
21
+ createProviderFetch,
22
+ type ProviderEgressError,
23
+ validateCompatibleBaseUrl,
24
+ } from './outbound-policy.ts';
25
+ import {
26
+ DuplicateProviderKeyError,
27
+ type ProviderRepository,
28
+ type StoredProviderConnection,
29
+ } from './provider-repository.ts';
30
+ import type { AgentRepository } from './repository.ts';
31
+
32
+ const LOCAL_PROVIDER_ID = 'local-simulation';
33
+ const LOCAL_MODEL_ID = 'deterministic-v1';
34
+
35
+ export class AgentProviderServiceError extends Error {
36
+ constructor(
37
+ readonly code: string,
38
+ message: string,
39
+ readonly status = 400,
40
+ ) {
41
+ super(message);
42
+ this.name = 'AgentProviderServiceError';
43
+ }
44
+ }
45
+
46
+ export interface AgentProviderServiceOptions {
47
+ /* Functions are read per call so an admin change applies live. */
48
+ readonly hostAllowlist: ReadonlySet<string> | (() => ReadonlySet<string>);
49
+ readonly readinessTtlMs: number | (() => number);
50
+ readonly readinessTimeoutMs: number;
51
+ readonly readinessCooldownMs?: number;
52
+ readonly now?: () => number;
53
+ readonly probe?: typeof probeVercelAiSdkProvider;
54
+ }
55
+
56
+ const MIN_READINESS_TTL_MS = 10_000;
57
+ const MAX_READINESS_TTL_MS = 86_400_000;
58
+
59
+ function validReadinessTtl(value: number): boolean {
60
+ return (
61
+ Number.isSafeInteger(value) &&
62
+ value >= MIN_READINESS_TTL_MS &&
63
+ value <= MAX_READINESS_TTL_MS
64
+ );
65
+ }
66
+
67
+ function bounded(
68
+ value: string,
69
+ field: string,
70
+ minimum: number,
71
+ maximum: number,
72
+ ): string {
73
+ const normalized = value.trim();
74
+ if (
75
+ normalized.length < minimum ||
76
+ normalized.length > maximum ||
77
+ normalized.includes('\u0000')
78
+ ) {
79
+ throw new AgentProviderServiceError(
80
+ 'INVALID_INPUT',
81
+ `${field} must contain between ${minimum} and ${maximum} characters.`,
82
+ );
83
+ }
84
+ return normalized;
85
+ }
86
+
87
+ function providerKey(value: string): string {
88
+ const normalized = value.trim().toLowerCase();
89
+ if (!/^[a-z][a-z0-9-]{1,62}[a-z0-9]$/.test(normalized)) {
90
+ throw new AgentProviderServiceError(
91
+ 'INVALID_PROVIDER_KEY',
92
+ 'key must contain 3 to 64 lowercase letters, numbers, or hyphens.',
93
+ );
94
+ }
95
+ return normalized;
96
+ }
97
+
98
+ function providerKind(
99
+ value: string,
100
+ ): Exclude<AgentProviderKind, 'local-simulation'> {
101
+ if (
102
+ !['vercel', 'azure', 'openai', 'openai-compatible', 'anthropic'].includes(
103
+ value,
104
+ )
105
+ ) {
106
+ throw new AgentProviderServiceError(
107
+ 'INVALID_PROVIDER_KIND',
108
+ 'Provider kind is not supported.',
109
+ );
110
+ }
111
+ return value as Exclude<AgentProviderKind, 'local-simulation'>;
112
+ }
113
+
114
+ function optionalBounded(
115
+ value: string | undefined,
116
+ field: string,
117
+ maximum: number,
118
+ ): string | null {
119
+ if (value === undefined || value.trim() === '') return null;
120
+ return bounded(value, field, 1, maximum);
121
+ }
122
+
123
+ const UNPROVEN: AgentModelReadiness = {
124
+ status: 'unknown',
125
+ latencyMs: null,
126
+ errorCode: null,
127
+ checkedAt: null,
128
+ };
129
+
130
+ function providerModels(
131
+ kind: AgentProviderKind,
132
+ value: readonly AgentProviderModelConfiguration[],
133
+ ): readonly AgentProviderModelConfiguration[] {
134
+ if (value.length < 1 || value.length > 50) {
135
+ throw new AgentProviderServiceError(
136
+ 'INVALID_PROVIDER_MODELS',
137
+ 'A provider must define between 1 and 50 models.',
138
+ );
139
+ }
140
+ const seen = new Set<string>();
141
+ return value.map((item) => {
142
+ const id = bounded(item.id, 'model id', 1, 160);
143
+ if (!/^[A-Za-z0-9][A-Za-z0-9._:/-]*$/.test(id)) {
144
+ throw new AgentProviderServiceError(
145
+ 'INVALID_MODEL_ID',
146
+ 'Model IDs may contain letters, numbers, dots, underscores, colons, slashes, and hyphens.',
147
+ );
148
+ }
149
+ if (seen.has(id)) {
150
+ throw new AgentProviderServiceError(
151
+ 'DUPLICATE_MODEL_ID',
152
+ `Model ${id} is configured more than once.`,
153
+ );
154
+ }
155
+ seen.add(id);
156
+ return {
157
+ id,
158
+ label: bounded(item.label, 'model label', 1, 120),
159
+ enabled: Boolean(item.enabled),
160
+ supportsTools: Boolean(item.supportsTools),
161
+ supportsStreaming: Boolean(item.supportsStreaming),
162
+ supportsWebSearch: Boolean(item.supportsWebSearch),
163
+ supportsTemperature:
164
+ item.supportsTemperature ??
165
+ (kind === 'local-simulation' || modelSupportsTemperature(kind, id)),
166
+ };
167
+ });
168
+ }
169
+
170
+ /* A probe proves that one model answers with this credential. Configuration
171
+ edits keep that evidence; a rotated credential and a removed model do not. */
172
+ function withReadiness(
173
+ models: readonly AgentProviderModelConfiguration[],
174
+ previous: readonly AgentProviderModel[],
175
+ keepEvidence: boolean,
176
+ ): readonly AgentProviderModel[] {
177
+ return models.map((model) => ({
178
+ ...model,
179
+ supportsTemperature: model.supportsTemperature !== false,
180
+ readiness:
181
+ (keepEvidence
182
+ ? previous.find((item) => item.id === model.id)?.readiness
183
+ : undefined) ?? UNPROVEN,
184
+ }));
185
+ }
186
+
187
+ function resourceName(
188
+ kind: AgentProviderKind,
189
+ value: string | null,
190
+ ): string | null {
191
+ if (kind !== 'azure') return null;
192
+ if (!value || !/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/.test(value)) {
193
+ throw new AgentProviderServiceError(
194
+ 'INVALID_AZURE_RESOURCE_NAME',
195
+ 'Azure resource name must contain 3 to 64 lowercase letters, numbers, or hyphens.',
196
+ );
197
+ }
198
+ return value;
199
+ }
200
+
201
+ function credentialContext(connection: {
202
+ readonly tenantId: string;
203
+ readonly id: string;
204
+ readonly kind: AgentProviderKind;
205
+ }): string {
206
+ return `${connection.tenantId}:${connection.id}:${connection.kind}`;
207
+ }
208
+
209
+ function localConnection(tenantId: string): AgentProviderConnection {
210
+ return {
211
+ id: LOCAL_PROVIDER_ID,
212
+ tenantId,
213
+ key: LOCAL_PROVIDER_ID,
214
+ name: 'Local simulation',
215
+ kind: 'local-simulation',
216
+ enabled: true,
217
+ resourceName: null,
218
+ baseURL: null,
219
+ models: [
220
+ {
221
+ id: LOCAL_MODEL_ID,
222
+ label: 'Deterministic local simulation',
223
+ enabled: true,
224
+ supportsTools: true,
225
+ supportsStreaming: true,
226
+ supportsWebSearch: false,
227
+ supportsTemperature: true,
228
+ readiness: {
229
+ status: 'healthy',
230
+ latencyMs: 0,
231
+ errorCode: null,
232
+ checkedAt: 0,
233
+ },
234
+ },
235
+ ],
236
+ credentialConfigured: false,
237
+ credentialRevision: 0,
238
+ revision: 1,
239
+ createdBy: 'system',
240
+ createdAt: 0,
241
+ updatedBy: 'system',
242
+ updatedAt: 0,
243
+ };
244
+ }
245
+
246
+ function removedModels(
247
+ current: readonly AgentProviderModel[],
248
+ next: readonly AgentProviderModelConfiguration[],
249
+ ): readonly string[] {
250
+ const kept = new Set(next.map((model) => model.id));
251
+ return current
252
+ .filter((model) => !kept.has(model.id))
253
+ .map((model) => model.id);
254
+ }
255
+
256
+ function mapEgressError(error: unknown): never {
257
+ const candidate = error as Partial<ProviderEgressError>;
258
+ if (typeof candidate.code === 'string' && error instanceof Error) {
259
+ throw new AgentProviderServiceError(candidate.code, error.message, 400);
260
+ }
261
+ throw error;
262
+ }
263
+
264
+ export class AgentProviderService {
265
+ readonly #now: () => number;
266
+ readonly #readinessCooldownMs: number;
267
+ readonly #probe: typeof probeVercelAiSdkProvider;
268
+ readonly #lastProbe = new Map<string, number>();
269
+ readonly #probesInFlight = new Map<
270
+ string,
271
+ Promise<AgentProviderConnection>
272
+ >();
273
+
274
+ constructor(
275
+ private readonly repository: ProviderRepository,
276
+ private readonly credentials: CredentialVault,
277
+ private readonly audit: AgentRepository,
278
+ private readonly options: AgentProviderServiceOptions,
279
+ ) {
280
+ this.#now = options.now ?? Date.now;
281
+ this.#readinessCooldownMs = options.readinessCooldownMs ?? 10_000;
282
+ this.#probe = options.probe ?? probeVercelAiSdkProvider;
283
+ if (
284
+ typeof options.readinessTtlMs === 'number' &&
285
+ !validReadinessTtl(options.readinessTtlMs)
286
+ ) {
287
+ throw new Error(
288
+ 'Provider readiness TTL must be between 10000 and 86400000 ms.',
289
+ );
290
+ }
291
+ }
292
+
293
+ /* How long a probe result stays valid. Clients show staleness with it. */
294
+ get readinessTtlMs(): number {
295
+ const value =
296
+ typeof this.options.readinessTtlMs === 'function'
297
+ ? this.options.readinessTtlMs()
298
+ : this.options.readinessTtlMs;
299
+ return validReadinessTtl(value) ? value : MAX_READINESS_TTL_MS;
300
+ }
301
+
302
+ #hostAllowlist(): ReadonlySet<string> {
303
+ return typeof this.options.hostAllowlist === 'function'
304
+ ? this.options.hostAllowlist()
305
+ : this.options.hostAllowlist;
306
+ }
307
+
308
+ async list(tenantId: string): Promise<readonly AgentProviderConnection[]> {
309
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
310
+ return [
311
+ localConnection(trustedTenantId),
312
+ ...(await this.repository.list(trustedTenantId)),
313
+ ];
314
+ }
315
+
316
+ async get(
317
+ tenantId: string,
318
+ id: string,
319
+ ): Promise<AgentProviderConnection | null> {
320
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
321
+ if (id === LOCAL_PROVIDER_ID) return localConnection(trustedTenantId);
322
+ return (
323
+ (
324
+ await this.repository.get(
325
+ trustedTenantId,
326
+ bounded(id, 'provider id', 1, 128),
327
+ )
328
+ )?.connection ?? null
329
+ );
330
+ }
331
+
332
+ async create(
333
+ tenantId: string,
334
+ actorId: string,
335
+ input: CreateAgentProviderInput,
336
+ ): Promise<AgentProviderConnection> {
337
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
338
+ const actor = bounded(actorId, 'actorId', 1, 128);
339
+ const kind = providerKind(input.kind);
340
+ const compatibleBaseUrl = optionalBounded(input.baseURL, 'baseURL', 2_048);
341
+ let baseURL: string | null = null;
342
+ if (kind === 'openai-compatible') {
343
+ if (!compatibleBaseUrl) {
344
+ throw new AgentProviderServiceError(
345
+ 'PROVIDER_BASE_URL_REQUIRED',
346
+ 'OpenAI-compatible providers require a base URL.',
347
+ );
348
+ }
349
+ try {
350
+ baseURL = validateCompatibleBaseUrl(
351
+ compatibleBaseUrl,
352
+ this.#hostAllowlist(),
353
+ ).href.replace(/\/$/, '');
354
+ } catch (error) {
355
+ mapEgressError(error);
356
+ }
357
+ }
358
+ const now = this.#now();
359
+ const id = `provider.${randomUUID().replaceAll('-', '')}`;
360
+ const connection: AgentProviderConnection = {
361
+ id,
362
+ tenantId: trustedTenantId,
363
+ key: providerKey(input.key),
364
+ name: bounded(input.name, 'name', 2, 120),
365
+ kind,
366
+ enabled: false,
367
+ resourceName: resourceName(
368
+ kind,
369
+ optionalBounded(input.resourceName, 'resourceName', 120),
370
+ ),
371
+ baseURL,
372
+ models: withReadiness(providerModels(kind, input.models), [], false),
373
+ credentialConfigured: true,
374
+ credentialRevision: 1,
375
+ revision: 1,
376
+ createdBy: actor,
377
+ createdAt: now,
378
+ updatedBy: actor,
379
+ updatedAt: now,
380
+ };
381
+ try {
382
+ const created = await this.repository.create({
383
+ connection,
384
+ credential: this.credentials.encrypt(
385
+ bounded(input.credential, 'credential', 8, 16_384),
386
+ credentialContext(connection),
387
+ ),
388
+ });
389
+ await this.audit.appendAuditEvent({
390
+ tenantId: trustedTenantId,
391
+ actorId: actor,
392
+ action: 'agent-provider.created',
393
+ subjectType: 'agent-provider',
394
+ subjectId: created.id,
395
+ metadata: { kind: created.kind, key: created.key, revision: 1 },
396
+ occurredAt: now,
397
+ });
398
+ return created;
399
+ } catch (error) {
400
+ if (error instanceof DuplicateProviderKeyError) {
401
+ throw new AgentProviderServiceError(
402
+ 'DUPLICATE_PROVIDER_KEY',
403
+ error.message,
404
+ 409,
405
+ );
406
+ }
407
+ throw error;
408
+ }
409
+ }
410
+
411
+ async update(
412
+ tenantId: string,
413
+ actorId: string,
414
+ input: UpdateAgentProviderInput,
415
+ ): Promise<AgentProviderConnection> {
416
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
417
+ const actor = bounded(actorId, 'actorId', 1, 128);
418
+ const stored = await this.repository.get(
419
+ trustedTenantId,
420
+ bounded(input.id, 'provider id', 1, 128),
421
+ );
422
+ if (!stored) {
423
+ throw new AgentProviderServiceError(
424
+ 'PROVIDER_NOT_FOUND',
425
+ 'Provider connection not found.',
426
+ 404,
427
+ );
428
+ }
429
+ if (stored.connection.revision !== input.expectedRevision) {
430
+ throw new AgentProviderServiceError(
431
+ 'PROVIDER_REVISION_CONFLICT',
432
+ 'The provider was changed by another request. Reload before saving.',
433
+ 409,
434
+ );
435
+ }
436
+ let baseURL: string | null = null;
437
+ if (stored.connection.kind === 'openai-compatible') {
438
+ const value = optionalBounded(input.baseURL, 'baseURL', 2_048);
439
+ if (!value) {
440
+ throw new AgentProviderServiceError(
441
+ 'PROVIDER_BASE_URL_REQUIRED',
442
+ 'OpenAI-compatible providers require a base URL.',
443
+ );
444
+ }
445
+ try {
446
+ baseURL = validateCompatibleBaseUrl(
447
+ value,
448
+ this.#hostAllowlist(),
449
+ ).href.replace(/\/$/, '');
450
+ } catch (error) {
451
+ mapEgressError(error);
452
+ }
453
+ }
454
+ const nextConfiguration = {
455
+ resourceName: resourceName(
456
+ stored.connection.kind,
457
+ optionalBounded(input.resourceName, 'resourceName', 120),
458
+ ),
459
+ baseURL,
460
+ models: providerModels(stored.connection.kind, input.models),
461
+ };
462
+ const credentialChanged = input.credential !== undefined;
463
+ const models = withReadiness(
464
+ nextConfiguration.models,
465
+ stored.connection.models,
466
+ !credentialChanged,
467
+ );
468
+ /* Enabling asks whether at least one model was proven, not whether the
469
+ connection is already usable: the stored one is disabled by
470
+ definition here. */
471
+ if (input.enabled) this.assertProvenModel(models);
472
+ const now = this.#now();
473
+ const connection: AgentProviderConnection = {
474
+ ...stored.connection,
475
+ name: bounded(input.name, 'name', 2, 120),
476
+ enabled: Boolean(input.enabled),
477
+ ...nextConfiguration,
478
+ models,
479
+ credentialRevision:
480
+ stored.connection.credentialRevision + (credentialChanged ? 1 : 0),
481
+ revision: stored.connection.revision + 1,
482
+ updatedBy: actor,
483
+ updatedAt: now,
484
+ };
485
+ const credential = credentialChanged
486
+ ? this.credentials.encrypt(
487
+ bounded(input.credential!, 'credential', 8, 16_384),
488
+ credentialContext(connection),
489
+ )
490
+ : stored.credential;
491
+ const updated = await this.repository.update({ connection, credential });
492
+ /* Evidence that no longer describes anything reachable. */
493
+ if (credentialChanged) {
494
+ await this.repository.clearReadiness(
495
+ trustedTenantId,
496
+ connection.id,
497
+ null,
498
+ );
499
+ } else {
500
+ const dropped = removedModels(
501
+ stored.connection.models,
502
+ nextConfiguration.models,
503
+ );
504
+ if (dropped.length > 0) {
505
+ await this.repository.clearReadiness(
506
+ trustedTenantId,
507
+ connection.id,
508
+ dropped,
509
+ );
510
+ }
511
+ }
512
+ await this.audit.appendAuditEvent({
513
+ tenantId: trustedTenantId,
514
+ actorId: actor,
515
+ action: credentialChanged
516
+ ? 'agent-provider.credential-rotated'
517
+ : 'agent-provider.updated',
518
+ subjectType: 'agent-provider',
519
+ subjectId: updated.id,
520
+ metadata: {
521
+ enabled: updated.enabled,
522
+ revision: updated.revision,
523
+ credentialRevision: updated.credentialRevision,
524
+ },
525
+ occurredAt: now,
526
+ });
527
+ return updated;
528
+ }
529
+
530
+ async delete(
531
+ tenantId: string,
532
+ actorId: string,
533
+ providerId: string,
534
+ expectedRevision: number,
535
+ ): Promise<void> {
536
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
537
+ const actor = bounded(actorId, 'actorId', 1, 128);
538
+ const id = bounded(providerId, 'provider id', 1, 128);
539
+ if (id === LOCAL_PROVIDER_ID) {
540
+ throw new AgentProviderServiceError(
541
+ 'PROVIDER_BUILT_IN',
542
+ 'The local simulation provider is built in and cannot be deleted.',
543
+ 409,
544
+ );
545
+ }
546
+ const stored = await this.repository.get(trustedTenantId, id);
547
+ if (!stored) {
548
+ throw new AgentProviderServiceError(
549
+ 'PROVIDER_NOT_FOUND',
550
+ 'Provider connection not found.',
551
+ 404,
552
+ );
553
+ }
554
+ if (stored.connection.revision !== expectedRevision) {
555
+ throw new AgentProviderServiceError(
556
+ 'PROVIDER_REVISION_CONFLICT',
557
+ 'The provider was changed by another request. Reload before deleting.',
558
+ 409,
559
+ );
560
+ }
561
+ const usage = await this.audit.providerUsage(trustedTenantId, id);
562
+ if (usage.definitions > 0 || usage.pendingRuns > 0) {
563
+ throw new AgentProviderServiceError(
564
+ 'PROVIDER_IN_USE',
565
+ 'Archive or move every agent using this provider and wait for its queued runs before deleting the connection.',
566
+ 409,
567
+ );
568
+ }
569
+ if (!(await this.repository.delete(trustedTenantId, id))) {
570
+ throw new AgentProviderServiceError(
571
+ 'PROVIDER_NOT_FOUND',
572
+ 'Provider connection not found.',
573
+ 404,
574
+ );
575
+ }
576
+ await this.audit.appendAuditEvent({
577
+ tenantId: trustedTenantId,
578
+ actorId: actor,
579
+ action: 'agent-provider.deleted',
580
+ subjectType: 'agent-provider',
581
+ subjectId: id,
582
+ metadata: {
583
+ key: stored.connection.key,
584
+ kind: stored.connection.kind,
585
+ credentialRevision: stored.connection.credentialRevision,
586
+ },
587
+ occurredAt: this.#now(),
588
+ });
589
+ }
590
+
591
+ async test(
592
+ tenantId: string,
593
+ providerId: string,
594
+ modelId: string,
595
+ actorId: string,
596
+ ): Promise<AgentProviderConnection> {
597
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
598
+ const id = bounded(providerId, 'provider id', 1, 128);
599
+ const actor = bounded(actorId, 'actorId', 1, 128);
600
+ if (id === LOCAL_PROVIDER_ID) return localConnection(trustedTenantId);
601
+ const stored = await this.repository.get(trustedTenantId, id);
602
+ if (!stored) {
603
+ throw new AgentProviderServiceError(
604
+ 'PROVIDER_NOT_FOUND',
605
+ 'Provider connection not found.',
606
+ 404,
607
+ );
608
+ }
609
+ const model = this.model(stored.connection, modelId, true);
610
+ if (this.#withinCooldown(this.#probeKey(trustedTenantId, id, model.id))) {
611
+ throw new AgentProviderServiceError(
612
+ 'PROVIDER_READINESS_RATE_LIMITED',
613
+ 'Wait before testing this model again.',
614
+ 429,
615
+ );
616
+ }
617
+ return await this.#probeModel(trustedTenantId, stored, model, actor);
618
+ }
619
+
620
+ #probeKey(tenantId: string, providerId: string, modelId: string): string {
621
+ return `${tenantId}:${providerId}:${modelId}`;
622
+ }
623
+
624
+ #withinCooldown(probeKey: string): boolean {
625
+ const previousProbe = this.#lastProbe.get(probeKey);
626
+ return (
627
+ previousProbe !== undefined &&
628
+ this.#now() - previousProbe < this.#readinessCooldownMs
629
+ );
630
+ }
631
+
632
+ async #probeModel(
633
+ trustedTenantId: string,
634
+ stored: StoredProviderConnection,
635
+ model: AgentProviderModel,
636
+ actor: string,
637
+ ): Promise<AgentProviderConnection> {
638
+ const id = stored.connection.id;
639
+ this.#lastProbe.set(
640
+ this.#probeKey(trustedTenantId, id, model.id),
641
+ this.#now(),
642
+ );
643
+ const configuration = await this.configuration(stored, model.id);
644
+ const result = await this.#probe(
645
+ configuration,
646
+ this.options.readinessTimeoutMs,
647
+ );
648
+ /* The stored code is stable and coarse. The provider's own reason is
649
+ redacted of credentials and stays in the server log, which is the only
650
+ place a failed probe can be diagnosed. */
651
+ if (!result.healthy) {
652
+ console.error(
653
+ `[agents.core] readiness failed for provider ${id} on ${model.id}: ${result.errorCode}`,
654
+ result.detail ?? '',
655
+ );
656
+ }
657
+ const checkedAt = this.#now();
658
+ const updated = await this.repository.recordReadiness(
659
+ trustedTenantId,
660
+ id,
661
+ model.id,
662
+ {
663
+ status: result.healthy ? 'healthy' : 'unhealthy',
664
+ latencyMs: result.latencyMs,
665
+ errorCode: result.errorCode,
666
+ checkedAt,
667
+ },
668
+ actor,
669
+ checkedAt,
670
+ );
671
+ await this.audit.appendAuditEvent({
672
+ tenantId: trustedTenantId,
673
+ actorId: actor,
674
+ action: 'agent-provider.readiness-tested',
675
+ subjectType: 'agent-provider',
676
+ subjectId: id,
677
+ metadata: {
678
+ status: result.healthy ? 'healthy' : 'unhealthy',
679
+ model: model.id,
680
+ latencyMs: result.latencyMs,
681
+ ...(result.errorCode ? { errorCode: result.errorCode } : {}),
682
+ },
683
+ occurredAt: checkedAt,
684
+ });
685
+ return updated;
686
+ }
687
+
688
+ async assertUsable(
689
+ tenantId: string,
690
+ providerId: string,
691
+ modelId: string,
692
+ ): Promise<void> {
693
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
694
+ if (providerId === LOCAL_PROVIDER_ID) {
695
+ if (modelId !== LOCAL_MODEL_ID) {
696
+ throw new AgentProviderServiceError(
697
+ 'MODEL_NOT_CONFIGURED',
698
+ 'Model is not configured for the selected provider.',
699
+ 409,
700
+ );
701
+ }
702
+ return;
703
+ }
704
+ const stored = await this.repository.get(
705
+ trustedTenantId,
706
+ bounded(providerId, 'provider id', 1, 128),
707
+ );
708
+ if (!stored) {
709
+ throw new AgentProviderServiceError(
710
+ 'PROVIDER_NOT_FOUND',
711
+ 'Provider connection not found.',
712
+ 404,
713
+ );
714
+ }
715
+ this.model(stored.connection, modelId, true);
716
+ this.assertUsableConnection(stored.connection, modelId);
717
+ }
718
+
719
+ async supportsStructuredOutput(
720
+ tenantId: string,
721
+ providerId: string,
722
+ modelId: string,
723
+ ): Promise<boolean> {
724
+ if (providerId === LOCAL_PROVIDER_ID) return false;
725
+ const stored = await this.repository.get(
726
+ bounded(tenantId, 'tenantId', 1, 128),
727
+ bounded(providerId, 'provider id', 1, 128),
728
+ );
729
+ if (!stored) return false;
730
+ return Boolean(
731
+ stored.connection.models.find(
732
+ (model) => model.id === modelId && model.enabled,
733
+ ),
734
+ );
735
+ }
736
+
737
+ /* Like assertUsable, except expired evidence triggers one automatic
738
+ re-test on behalf of the actor. Concurrent callers share that probe. */
739
+ async ensureUsable(
740
+ tenantId: string,
741
+ providerId: string,
742
+ modelId: string,
743
+ actorId: string,
744
+ ): Promise<void> {
745
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
746
+ if (providerId === LOCAL_PROVIDER_ID) {
747
+ await this.assertUsable(trustedTenantId, providerId, modelId);
748
+ return;
749
+ }
750
+ const stored = await this.repository.get(
751
+ trustedTenantId,
752
+ bounded(providerId, 'provider id', 1, 128),
753
+ );
754
+ if (!stored) {
755
+ throw new AgentProviderServiceError(
756
+ 'PROVIDER_NOT_FOUND',
757
+ 'Provider connection not found.',
758
+ 404,
759
+ );
760
+ }
761
+ const model = this.model(stored.connection, modelId, true);
762
+ if (!stored.connection.enabled) {
763
+ throw new AgentProviderServiceError(
764
+ 'PROVIDER_DISABLED',
765
+ 'Provider connection is disabled.',
766
+ 409,
767
+ );
768
+ }
769
+ if (this.proven(model)) return;
770
+ if (model.readiness.status !== 'healthy') {
771
+ this.assertUsableConnection(stored.connection, model.id);
772
+ return;
773
+ }
774
+ const refreshed = await this.#reprobe(
775
+ trustedTenantId,
776
+ stored,
777
+ model,
778
+ bounded(actorId, 'actorId', 1, 128),
779
+ );
780
+ if (!this.proven(this.model(refreshed, model.id, true))) {
781
+ throw new AgentProviderServiceError(
782
+ 'PROVIDER_READINESS_REQUIRED',
783
+ 'Readiness for this model expired and the automatic re-test failed. Test it again.',
784
+ 409,
785
+ );
786
+ }
787
+ }
788
+
789
+ async #reprobe(
790
+ trustedTenantId: string,
791
+ stored: StoredProviderConnection,
792
+ model: AgentProviderModel,
793
+ actor: string,
794
+ ): Promise<AgentProviderConnection> {
795
+ const key = this.#probeKey(trustedTenantId, stored.connection.id, model.id);
796
+ const inFlight = this.#probesInFlight.get(key);
797
+ if (inFlight) return inFlight;
798
+ if (this.#withinCooldown(key)) {
799
+ throw new AgentProviderServiceError(
800
+ 'PROVIDER_READINESS_REQUIRED',
801
+ 'Readiness for this model expired and a re-test just failed. Test it again.',
802
+ 409,
803
+ );
804
+ }
805
+ const pending = this.#probeModel(
806
+ trustedTenantId,
807
+ stored,
808
+ model,
809
+ actor,
810
+ ).finally(() => this.#probesInFlight.delete(key));
811
+ this.#probesInFlight.set(key, pending);
812
+ return pending;
813
+ }
814
+
815
+ /* A completed run proves the model as well as a probe does, and it did so
816
+ more recently. Local simulation needs no evidence. */
817
+ async recordRunSuccess(
818
+ tenantId: string,
819
+ providerId: string,
820
+ modelId: string,
821
+ completedAt: number,
822
+ durationMs: number,
823
+ ): Promise<void> {
824
+ if (providerId === LOCAL_PROVIDER_ID) return;
825
+ await this.repository.refreshReadiness(
826
+ bounded(tenantId, 'tenantId', 1, 128),
827
+ bounded(providerId, 'provider id', 1, 128),
828
+ bounded(modelId, 'model', 1, 160),
829
+ {
830
+ status: 'healthy',
831
+ latencyMs: Math.max(0, Math.trunc(durationMs)),
832
+ errorCode: null,
833
+ checkedAt: completedAt,
834
+ },
835
+ );
836
+ }
837
+
838
+ async resolve(
839
+ tenantId: string,
840
+ providerId: string,
841
+ modelId: string,
842
+ ): Promise<AgentProvider | null> {
843
+ if (providerId === LOCAL_PROVIDER_ID) return null;
844
+ const trustedTenantId = bounded(tenantId, 'tenantId', 1, 128);
845
+ const stored = await this.repository.get(
846
+ trustedTenantId,
847
+ bounded(providerId, 'provider id', 1, 128),
848
+ );
849
+ if (!stored) {
850
+ throw new AgentProviderServiceError(
851
+ 'PROVIDER_NOT_FOUND',
852
+ 'Provider connection not found.',
853
+ 404,
854
+ );
855
+ }
856
+ this.model(stored.connection, modelId, true);
857
+ this.assertUsableConnection(stored.connection, modelId);
858
+ return createVercelAiSdkProvider(await this.configuration(stored, modelId));
859
+ }
860
+
861
+ private model(
862
+ connection: AgentProviderConnection,
863
+ modelId: string,
864
+ requireEnabled: boolean,
865
+ ): AgentProviderModel {
866
+ const id = bounded(modelId, 'model', 1, 160);
867
+ const model = connection.models.find((item) => item.id === id);
868
+ if (!model || (requireEnabled && !model.enabled)) {
869
+ throw new AgentProviderServiceError(
870
+ 'MODEL_NOT_CONFIGURED',
871
+ 'Model is not enabled for the selected provider.',
872
+ 409,
873
+ );
874
+ }
875
+ return model;
876
+ }
877
+
878
+ private assertUsableConnection(
879
+ connection: AgentProviderConnection,
880
+ modelId: string,
881
+ ): void {
882
+ if (!connection.enabled) {
883
+ throw new AgentProviderServiceError(
884
+ 'PROVIDER_DISABLED',
885
+ 'Provider connection is disabled.',
886
+ 409,
887
+ );
888
+ }
889
+ const model = connection.models.find((item) => item.id === modelId);
890
+ if (!model || this.proven(model)) return;
891
+ throw new AgentProviderServiceError(
892
+ 'PROVIDER_READINESS_REQUIRED',
893
+ model.readiness.status === 'healthy'
894
+ ? 'Readiness for this model expired. Test it again.'
895
+ : 'This model was never proven. Test it first.',
896
+ 409,
897
+ );
898
+ }
899
+
900
+ /* A connection may be enabled once any model an agent could pick answers. */
901
+ private assertProvenModel(models: readonly AgentProviderModel[]): void {
902
+ if (!models.some((model) => model.enabled && this.proven(model))) {
903
+ throw new AgentProviderServiceError(
904
+ 'PROVIDER_READINESS_REQUIRED',
905
+ 'Test at least one enabled model before enabling the connection.',
906
+ 409,
907
+ );
908
+ }
909
+ }
910
+
911
+ private proven(model: AgentProviderModel): boolean {
912
+ const { readiness } = model;
913
+ return (
914
+ readiness.status === 'healthy' &&
915
+ readiness.checkedAt !== null &&
916
+ this.#now() - readiness.checkedAt <= this.readinessTtlMs
917
+ );
918
+ }
919
+
920
+ private async configuration(
921
+ stored: StoredProviderConnection,
922
+ model: string,
923
+ ): Promise<VercelAiProviderConfiguration> {
924
+ const connection = stored.connection;
925
+ if (connection.kind === 'local-simulation') {
926
+ throw new AgentProviderServiceError(
927
+ 'INVALID_PROVIDER_CONFIGURATION',
928
+ 'Local simulation does not use a stored provider connection.',
929
+ );
930
+ }
931
+ const credential = this.credentials.decrypt(
932
+ stored.credential,
933
+ credentialContext(connection),
934
+ );
935
+ const base = {
936
+ id: connection.id,
937
+ kind: connection.kind,
938
+ model,
939
+ credential,
940
+ supportsTemperature:
941
+ connection.models.find((item) => item.id === model)
942
+ ?.supportsTemperature !== false,
943
+ };
944
+ if (connection.kind === 'azure') {
945
+ return {
946
+ ...base,
947
+ resourceName: connection.resourceName ?? '',
948
+ };
949
+ }
950
+ if (connection.kind === 'openai-compatible') {
951
+ try {
952
+ const baseURL = validateCompatibleBaseUrl(
953
+ connection.baseURL ?? '',
954
+ this.#hostAllowlist(),
955
+ );
956
+ await assertPublicHost(baseURL.hostname);
957
+ return {
958
+ ...base,
959
+ baseURL: baseURL.href.replace(/\/$/, ''),
960
+ fetch: createProviderFetch(baseURL),
961
+ };
962
+ } catch (error) {
963
+ mapEgressError(error);
964
+ }
965
+ }
966
+ return base;
967
+ }
968
+ }