create-windy 0.3.2 → 0.3.5

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 (343) hide show
  1. package/README.md +27 -9
  2. package/dist/cli.js +825 -117
  3. package/package.json +1 -1
  4. package/template/.agents/skills/windy-business-module/SKILL.md +16 -3
  5. package/template/.windy-template.json +2 -2
  6. package/template/AGENTS.md +4 -0
  7. package/template/README.md +18 -11
  8. package/template/_gitignore +1 -0
  9. package/template/apps/agent-server/README.md +2 -0
  10. package/template/apps/agent-server/pyproject.toml +8 -0
  11. package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +87 -10
  12. package/template/apps/agent-server/src/southwind_agent_server/adk_model.py +18 -3
  13. package/template/apps/agent-server/src/southwind_agent_server/adk_tools.py +78 -11
  14. package/template/apps/agent-server/src/southwind_agent_server/app.py +120 -115
  15. package/template/apps/agent-server/src/southwind_agent_server/artifact_input.py +153 -0
  16. package/template/apps/agent-server/src/southwind_agent_server/config.py +29 -0
  17. package/template/apps/agent-server/src/southwind_agent_server/contracts.py +81 -1
  18. package/template/apps/agent-server/src/southwind_agent_server/deterministic.py +8 -0
  19. package/template/apps/agent-server/src/southwind_agent_server/engine.py +28 -0
  20. package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +41 -0
  21. package/template/apps/agent-server/src/southwind_agent_server/http_helpers.py +62 -0
  22. package/template/apps/agent-server/src/southwind_agent_server/lease.py +15 -0
  23. package/template/apps/agent-server/src/southwind_agent_server/multimodal.py +76 -0
  24. package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +112 -20
  25. package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +14 -1
  26. package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +329 -0
  27. package/template/apps/agent-server/src/southwind_agent_server/postgres_store_backend.py +332 -0
  28. package/template/apps/agent-server/src/southwind_agent_server/provider_governance.py +64 -3
  29. package/template/apps/agent-server/src/southwind_agent_server/runtime_factory.py +68 -0
  30. package/template/apps/agent-server/src/southwind_agent_server/service.py +218 -56
  31. package/template/apps/agent-server/src/southwind_agent_server/signal_events.py +36 -0
  32. package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +107 -0
  33. package/template/apps/agent-server/src/southwind_agent_server/sqlite_schema.py +65 -0
  34. package/template/apps/agent-server/src/southwind_agent_server/sqlite_serialization.py +16 -0
  35. package/template/apps/agent-server/src/southwind_agent_server/sqlite_store.py +89 -57
  36. package/template/apps/agent-server/src/southwind_agent_server/store.py +105 -2
  37. package/template/apps/agent-server/src/southwind_agent_server/store_cipher.py +40 -0
  38. package/template/apps/agent-server/src/southwind_agent_server/telemetry.py +89 -0
  39. package/template/apps/agent-server/src/southwind_agent_server/tool_host.py +72 -0
  40. package/template/apps/agent-server/tests/test_adk_adapter.py +6 -2
  41. package/template/apps/agent-server/tests/test_api.py +24 -1
  42. package/template/apps/agent-server/tests/test_artifact_input.py +110 -0
  43. package/template/apps/agent-server/tests/test_config.py +4 -0
  44. package/template/apps/agent-server/tests/test_fingerprint.py +10 -0
  45. package/template/apps/agent-server/tests/test_multimodal.py +51 -0
  46. package/template/apps/agent-server/tests/test_openai_provider.py +6 -2
  47. package/template/apps/agent-server/tests/test_postgres_store.py +131 -0
  48. package/template/apps/agent-server/tests/test_provider_governance.py +61 -0
  49. package/template/apps/agent-server/tests/test_sqlite_store.py +95 -10
  50. package/template/apps/agent-server/tests/test_telemetry.py +25 -0
  51. package/template/apps/agent-server/tests/test_tool_approval.py +28 -0
  52. package/template/apps/agent-server/uv.lock +165 -0
  53. package/template/apps/document-server/Dockerfile +19 -0
  54. package/template/apps/document-server/pyproject.toml +43 -0
  55. package/template/apps/document-server/src/southwind_document_server/__init__.py +1 -0
  56. package/template/apps/document-server/src/southwind_document_server/adapter.py +337 -0
  57. package/template/apps/document-server/src/southwind_document_server/app.py +151 -0
  58. package/template/apps/document-server/src/southwind_document_server/config.py +94 -0
  59. package/template/apps/document-server/src/southwind_document_server/contracts.py +103 -0
  60. package/template/apps/document-server/src/southwind_document_server/service.py +149 -0
  61. package/template/apps/document-server/src/southwind_document_server/store.py +185 -0
  62. package/template/apps/document-server/tests/__init__.py +1 -0
  63. package/template/apps/document-server/tests/test_config.py +42 -0
  64. package/template/apps/document-server/tests/test_service.py +140 -0
  65. package/template/apps/document-server/uv.lock +430 -0
  66. package/template/apps/embedding-server/Dockerfile +17 -0
  67. package/template/apps/embedding-server/pyproject.toml +44 -0
  68. package/template/apps/embedding-server/src/southwind_embedding_server/__init__.py +1 -0
  69. package/template/apps/embedding-server/src/southwind_embedding_server/adapter.py +254 -0
  70. package/template/apps/embedding-server/src/southwind_embedding_server/app.py +119 -0
  71. package/template/apps/embedding-server/src/southwind_embedding_server/config.py +120 -0
  72. package/template/apps/embedding-server/src/southwind_embedding_server/contracts.py +106 -0
  73. package/template/apps/embedding-server/src/southwind_embedding_server/error.py +6 -0
  74. package/template/apps/embedding-server/src/southwind_embedding_server/image_input.py +87 -0
  75. package/template/apps/embedding-server/tests/__init__.py +1 -0
  76. package/template/apps/embedding-server/tests/test_adapter.py +92 -0
  77. package/template/apps/embedding-server/tests/test_config.py +38 -0
  78. package/template/apps/embedding-server/uv.lock +449 -0
  79. package/template/apps/server/src/agent/background-operation-port.ts +37 -0
  80. package/template/apps/server/src/agent/background-operation.test.ts +231 -0
  81. package/template/apps/server/src/agent/background-operation.ts +252 -0
  82. package/template/apps/server/src/agent/drizzle-run-binding-repository.ts +114 -0
  83. package/template/apps/server/src/agent/execution-grants.ts +7 -1
  84. package/template/apps/server/src/agent/fake-runtime.test-support.ts +43 -0
  85. package/template/apps/server/src/agent/idempotency-key.test.ts +28 -0
  86. package/template/apps/server/src/agent/idempotency-key.ts +11 -0
  87. package/template/apps/server/src/agent/remote-runtime.test.ts +115 -1
  88. package/template/apps/server/src/agent/remote-runtime.ts +173 -5
  89. package/template/apps/server/src/agent/run-authorization.test-support.ts +9 -0
  90. package/template/apps/server/src/agent/run-authorization.test.ts +126 -0
  91. package/template/apps/server/src/agent/run-authorization.ts +180 -0
  92. package/template/apps/server/src/agent/run-binding-repository.ts +93 -0
  93. package/template/apps/server/src/agent/run-contracts.ts +88 -1
  94. package/template/apps/server/src/agent/run-definition-support.ts +58 -0
  95. package/template/apps/server/src/agent/run-errors.ts +25 -0
  96. package/template/apps/server/src/agent/run-facade.test.ts +57 -46
  97. package/template/apps/server/src/agent/run-facade.ts +185 -65
  98. package/template/apps/server/src/agent/run-release.ts +78 -0
  99. package/template/apps/server/src/agent/run-route-input.ts +169 -0
  100. package/template/apps/server/src/agent/run-routes.ts +63 -76
  101. package/template/apps/server/src/agent/runtime-bootstrap.ts +169 -13
  102. package/template/apps/server/src/agent/sandbox-client.ts +200 -0
  103. package/template/apps/server/src/agent/sandbox-protocol.ts +76 -0
  104. package/template/apps/server/src/agent/sandbox-registry.ts +205 -0
  105. package/template/apps/server/src/agent/sandbox-runtime.test.ts +137 -0
  106. package/template/apps/server/src/agent/sandbox-worker-server.ts +195 -0
  107. package/template/apps/server/src/agent/sandbox-worker.ts +12 -0
  108. package/template/apps/server/src/agent/tool-approval.test.ts +75 -0
  109. package/template/apps/server/src/agent/tool-approval.ts +115 -0
  110. package/template/apps/server/src/agent/tool-audit.ts +62 -0
  111. package/template/apps/server/src/agent/tool-host.test.ts +39 -11
  112. package/template/apps/server/src/agent/tool-host.ts +184 -17
  113. package/template/apps/server/src/agent/tool-registry.ts +52 -47
  114. package/template/apps/server/src/agent/vision-facade.test.ts +256 -0
  115. package/template/apps/server/src/agent/vision-input.ts +120 -0
  116. package/template/apps/server/src/ai-artifact/codec.test.ts +44 -0
  117. package/template/apps/server/src/ai-artifact/codec.ts +137 -0
  118. package/template/apps/server/src/ai-artifact/routes.ts +37 -0
  119. package/template/apps/server/src/ai-artifact/runtime.ts +205 -0
  120. package/template/apps/server/src/application-services.ts +62 -2
  121. package/template/apps/server/src/auth/reauthentication.test.ts +40 -0
  122. package/template/apps/server/src/auth/reauthentication.ts +19 -0
  123. package/template/apps/server/src/auth/runtime.ts +9 -1
  124. package/template/apps/server/src/data-access/context.ts +6 -4
  125. package/template/apps/server/src/data-access/scope-snapshot.ts +27 -0
  126. package/template/apps/server/src/data-governance/export/approval-port.ts +6 -3
  127. package/template/apps/server/src/data-governance/export/authorization-port.test.ts +23 -4
  128. package/template/apps/server/src/data-governance/export/authorization-port.ts +89 -25
  129. package/template/apps/server/src/data-governance/export/drizzle-repository.integration.test.ts +2 -0
  130. package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -0
  131. package/template/apps/server/src/data-governance/export/job-runtime.test.ts +15 -4
  132. package/template/apps/server/src/data-governance/export/job-runtime.ts +68 -15
  133. package/template/apps/server/src/data-governance/export/ndjson-stream.ts +25 -6
  134. package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +4 -2
  135. package/template/apps/server/src/data-governance/export/renderer-job-runtime.test.ts +235 -0
  136. package/template/apps/server/src/data-governance/export/renderer-runtime.ts +293 -0
  137. package/template/apps/server/src/data-governance/export/renderer-selection.test.ts +67 -0
  138. package/template/apps/server/src/data-governance/export/repository.test.ts +2 -0
  139. package/template/apps/server/src/data-governance/export/request-fingerprint.test.ts +13 -0
  140. package/template/apps/server/src/data-governance/export/request-fingerprint.ts +2 -0
  141. package/template/apps/server/src/data-governance/export/routes.ts +11 -1
  142. package/template/apps/server/src/data-governance/export/scope-snapshot.ts +6 -18
  143. package/template/apps/server/src/data-governance/export/service-support.ts +188 -0
  144. package/template/apps/server/src/data-governance/export/service.ts +90 -113
  145. package/template/apps/server/src/data-governance/export/source.ts +101 -0
  146. package/template/apps/server/src/data-governance/export/types.ts +27 -0
  147. package/template/apps/server/src/document/contracts.ts +76 -0
  148. package/template/apps/server/src/document/facade.ts +339 -0
  149. package/template/apps/server/src/document/remote-runtime.test.ts +96 -0
  150. package/template/apps/server/src/document/remote-runtime.ts +223 -0
  151. package/template/apps/server/src/document/routes.ts +193 -0
  152. package/template/apps/server/src/embedding/contracts.ts +83 -0
  153. package/template/apps/server/src/embedding/error.ts +10 -0
  154. package/template/apps/server/src/embedding/facade.ts +217 -0
  155. package/template/apps/server/src/embedding/input.ts +172 -0
  156. package/template/apps/server/src/embedding/remote-runtime.test.ts +66 -0
  157. package/template/apps/server/src/embedding/remote-runtime.ts +218 -0
  158. package/template/apps/server/src/embedding/routes.ts +152 -0
  159. package/template/apps/server/src/index.ts +40 -43
  160. package/template/apps/server/src/jobs/artifact-service.test.ts +14 -2
  161. package/template/apps/server/src/jobs/artifact-service.ts +10 -0
  162. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +17 -18
  163. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +19 -1
  164. package/template/apps/server/src/jobs/drizzle-mappers.ts +4 -1
  165. package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +49 -2
  166. package/template/apps/server/src/jobs/drizzle-repository.ts +1 -0
  167. package/template/apps/server/src/jobs/execution-repository.ts +17 -0
  168. package/template/apps/server/src/jobs/execution.test.ts +34 -0
  169. package/template/apps/server/src/jobs/in-memory-control.ts +135 -0
  170. package/template/apps/server/src/jobs/in-memory-execution.ts +34 -65
  171. package/template/apps/server/src/jobs/legacy-service-runtime.ts +5 -2
  172. package/template/apps/server/src/jobs/repository.ts +3 -0
  173. package/template/apps/server/src/jobs/worker.ts +80 -41
  174. package/template/apps/server/src/module-host/ai-operation-port.ts +170 -0
  175. package/template/apps/server/src/module-host/durable-context.test.ts +312 -0
  176. package/template/apps/server/src/module-host/durable-context.ts +124 -0
  177. package/template/apps/server/src/module-host/durable-handler-registration.ts +72 -0
  178. package/template/apps/server/src/module-host/governed-export-route-support.ts +171 -0
  179. package/template/apps/server/src/module-host/governed-export-routes.test.ts +327 -0
  180. package/template/apps/server/src/module-host/governed-export-routes.ts +238 -0
  181. package/template/apps/server/src/module-host/governed-renderer-registration.test.ts +247 -0
  182. package/template/apps/server/src/module-host/governed-resource-routes.ts +331 -0
  183. package/template/apps/server/src/module-host/governed-resources.test.ts +344 -0
  184. package/template/apps/server/src/module-host/governed-resources.ts +203 -0
  185. package/template/apps/server/src/module-host/http-runtime.ts +95 -0
  186. package/template/apps/server/src/module-host/initialize-contracts.ts +14 -0
  187. package/template/apps/server/src/module-host/initialize.test.ts +49 -1
  188. package/template/apps/server/src/module-host/initialize.ts +39 -16
  189. package/template/apps/server/src/module-host/job-port.test.ts +262 -0
  190. package/template/apps/server/src/module-host/job-port.ts +334 -0
  191. package/template/apps/server/src/module-host/request-context.test.ts +88 -2
  192. package/template/apps/server/src/module-host/request-context.ts +56 -22
  193. package/template/apps/server/src/module-host/route-installer.test.ts +10 -0
  194. package/template/apps/server/src/module-host/route-installer.ts +36 -1
  195. package/template/apps/server/src/module-host/sandbox-tool-registration.ts +42 -0
  196. package/template/apps/server/src/module-host/tool-handlers.ts +67 -31
  197. package/template/apps/server/src/module-host.ts +1 -0
  198. package/template/apps/server/src/module-runtime-validation.ts +7 -3
  199. package/template/apps/server/src/speech/contracts.ts +76 -0
  200. package/template/apps/server/src/speech/facade.ts +316 -0
  201. package/template/apps/server/src/speech/remote-runtime.test.ts +88 -0
  202. package/template/apps/server/src/speech/remote-runtime.ts +227 -0
  203. package/template/apps/server/src/speech/routes.ts +180 -0
  204. package/template/apps/server/src/system/actor.ts +39 -0
  205. package/template/apps/server/src/system/route-helpers.ts +1 -0
  206. package/template/apps/server/src/workflow/service.ts +2 -1
  207. package/template/apps/speech-server/Dockerfile +22 -0
  208. package/template/apps/speech-server/pyproject.toml +43 -0
  209. package/template/apps/speech-server/src/southwind_speech_server/__init__.py +1 -0
  210. package/template/apps/speech-server/src/southwind_speech_server/adapter.py +249 -0
  211. package/template/apps/speech-server/src/southwind_speech_server/app.py +183 -0
  212. package/template/apps/speech-server/src/southwind_speech_server/config.py +100 -0
  213. package/template/apps/speech-server/src/southwind_speech_server/contracts.py +103 -0
  214. package/template/apps/speech-server/src/southwind_speech_server/errors.py +6 -0
  215. package/template/apps/speech-server/src/southwind_speech_server/normalizer.py +108 -0
  216. package/template/apps/speech-server/src/southwind_speech_server/output_validation.py +128 -0
  217. package/template/apps/speech-server/src/southwind_speech_server/service.py +162 -0
  218. package/template/apps/speech-server/src/southwind_speech_server/store.py +209 -0
  219. package/template/apps/speech-server/tests/__init__.py +1 -0
  220. package/template/apps/speech-server/tests/test_config.py +33 -0
  221. package/template/apps/speech-server/tests/test_service.py +154 -0
  222. package/template/apps/speech-server/uv.lock +430 -0
  223. package/template/apps/web/src/app/business-routes.ts +22 -0
  224. package/template/apps/web/src/components/common/AccessSnapshotBoundary.vue +112 -0
  225. package/template/apps/web/src/components/common/AccessSnapshotBoundary.webtest.ts +130 -0
  226. package/template/apps/web/src/components/common/AccessSnapshotNotice.vue +117 -0
  227. package/template/apps/web/src/components/common/FormDialog.vue +6 -0
  228. package/template/apps/web/src/components/common/ModalLayout.webtest.ts +13 -0
  229. package/template/apps/web/src/composables/access-snapshot-change.ts +131 -0
  230. package/template/apps/web/src/composables/access-snapshot-change.webtest.ts +103 -0
  231. package/template/apps/web/src/composables/useAccessSnapshot.ts +48 -2
  232. package/template/apps/web/src/composables/useAccessSnapshot.webtest.ts +54 -0
  233. package/template/apps/web/src/composables/useAccessSnapshotMonitor.ts +42 -0
  234. package/template/apps/web/src/layout/AppShell.vue +28 -25
  235. package/template/apps/web/src/layout/AppShell.webtest.ts +1 -0
  236. package/template/apps/web/src/router/business-routes.ts +68 -0
  237. package/template/apps/web/src/router/business-routes.webtest.ts +85 -0
  238. package/template/apps/web/src/router/index.ts +7 -0
  239. package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +12 -0
  240. package/template/apps/web/src/services/access-api.ts +5 -1
  241. package/template/apps/web/src/services/access-api.webtest.ts +35 -0
  242. package/template/docker-compose.yml +127 -0
  243. package/template/docs/architecture/ai-egress.md +12 -9
  244. package/template/docs/architecture/ai-runtime.md +23 -11
  245. package/template/docs/architecture/durable-jobs.md +25 -3
  246. package/template/docs/architecture/foundation-infrastructure.md +163 -0
  247. package/template/docs/architecture/module-host.md +115 -0
  248. package/template/docs/architecture/server-module-interface.md +39 -0
  249. package/template/docs/architecture/web-access-snapshot-resilience.md +60 -0
  250. package/template/docs/development/business-web-routes.md +66 -0
  251. package/template/docs/development/custom-login-page.md +3 -3
  252. package/template/docs/development/module-lifecycle.md +71 -0
  253. package/template/docs/operations/observability.md +5 -1
  254. package/template/docs/platform/agent-runtime.md +21 -11
  255. package/template/docs/platform/agent-tool-sandbox.md +58 -0
  256. package/template/docs/platform/agent-tools.md +5 -0
  257. package/template/docs/platform/document-ai-runtime.md +204 -0
  258. package/template/docs/platform/governed-export-renderers.md +132 -0
  259. package/template/docs/platform/navigation-registry.md +5 -0
  260. package/template/docs/platform/organization-membership.md +2 -1
  261. package/template/docs/platform/speech-ai-runtime.md +156 -0
  262. package/template/docs/platform/system-crud-api.md +7 -1
  263. package/template/docs/platform/vision-ai-runtime.md +97 -0
  264. package/template/docs/platform/web-system-crud.md +6 -0
  265. package/template/package.json +16 -2
  266. package/template/packages/ai-client/index.ts +4 -0
  267. package/template/packages/ai-client/package.json +5 -2
  268. package/template/packages/ai-client/src/agent/client/artifact.ts +26 -0
  269. package/template/packages/ai-client/src/agent/client/attach.test.ts +124 -0
  270. package/template/packages/ai-client/src/agent/client/client.ts +119 -7
  271. package/template/packages/ai-client/src/agent/client/run.ts +14 -0
  272. package/template/packages/ai-client/src/agent/client/types.ts +18 -0
  273. package/template/packages/ai-client/src/agent/client/vision.test.ts +53 -0
  274. package/template/packages/ai-client/src/agent/contracts/contracts.test.ts +1 -0
  275. package/template/packages/ai-client/src/agent/contracts/events.ts +33 -0
  276. package/template/packages/ai-client/src/agent/contracts/runs.ts +71 -0
  277. package/template/packages/ai-client/src/agent/index.ts +1 -0
  278. package/template/packages/ai-client/src/artifact-ref.ts +8 -0
  279. package/template/packages/ai-client/src/document/client.test.ts +114 -0
  280. package/template/packages/ai-client/src/document/client.ts +134 -0
  281. package/template/packages/ai-client/src/document/contracts.ts +152 -0
  282. package/template/packages/ai-client/src/document/error.ts +43 -0
  283. package/template/packages/ai-client/src/document/index.ts +3 -0
  284. package/template/packages/ai-client/src/document/run.ts +104 -0
  285. package/template/packages/ai-client/src/document/validation.ts +115 -0
  286. package/template/packages/ai-client/src/embedding/client.test.ts +77 -0
  287. package/template/packages/ai-client/src/embedding/client.ts +96 -0
  288. package/template/packages/ai-client/src/embedding/contracts.ts +46 -0
  289. package/template/packages/ai-client/src/embedding/error.ts +61 -0
  290. package/template/packages/ai-client/src/embedding/index.ts +3 -0
  291. package/template/packages/ai-client/src/embedding/validation.ts +117 -0
  292. package/template/packages/ai-client/src/speech/client.test.ts +135 -0
  293. package/template/packages/ai-client/src/speech/client.ts +104 -0
  294. package/template/packages/ai-client/src/speech/contracts.ts +129 -0
  295. package/template/packages/ai-client/src/speech/error.ts +43 -0
  296. package/template/packages/ai-client/src/speech/index.ts +3 -0
  297. package/template/packages/ai-client/src/speech/run.ts +133 -0
  298. package/template/packages/ai-client/src/speech/validation.ts +132 -0
  299. package/template/packages/config/package.json +2 -2
  300. package/template/packages/database/drizzle/0039_early_ezekiel_stane.sql +1 -0
  301. package/template/packages/database/drizzle/0040_colossal_baron_strucker.sql +63 -0
  302. package/template/packages/database/drizzle/0041_yummy_prowler.sql +21 -0
  303. package/template/packages/database/drizzle/0042_puzzling_rumiko_fujikawa.sql +27 -0
  304. package/template/packages/database/drizzle/meta/0039_snapshot.json +7755 -0
  305. package/template/packages/database/drizzle/meta/0040_snapshot.json +8150 -0
  306. package/template/packages/database/drizzle/meta/0041_snapshot.json +8323 -0
  307. package/template/packages/database/drizzle/meta/0042_snapshot.json +8541 -0
  308. package/template/packages/database/drizzle/meta/_journal.json +28 -0
  309. package/template/packages/database/package.json +2 -2
  310. package/template/packages/database/src/agent-runtime-schema.test.ts +54 -0
  311. package/template/packages/database/src/schema/agent-runtime.ts +149 -0
  312. package/template/packages/database/src/schema/common.ts +2 -14
  313. package/template/packages/database/src/schema/durable-jobs.ts +5 -0
  314. package/template/packages/database/src/schema/governed-exports.ts +17 -5
  315. package/template/packages/database/src/schema/index.ts +3 -0
  316. package/template/packages/database/src/schema-durable-recovery.test.ts +31 -0
  317. package/template/packages/database/src/schema-governed-exports.test.ts +21 -1
  318. package/template/packages/database/src/schema.test.ts +6 -23
  319. package/template/packages/jobs/package.json +3 -2
  320. package/template/packages/jobs/src/handlers.test.ts +13 -0
  321. package/template/packages/jobs/src/handlers.ts +7 -1
  322. package/template/packages/jobs/src/types.ts +4 -0
  323. package/template/packages/modules/package.json +2 -2
  324. package/template/packages/modules/src/ai-operation-composition.test-support.ts +165 -0
  325. package/template/packages/modules/src/ai-operation-composition.test.ts +91 -127
  326. package/template/packages/modules/src/ai-operation-composition.ts +59 -1
  327. package/template/packages/modules/src/manifest.ts +25 -1
  328. package/template/packages/modules/src/tool-composition.ts +18 -0
  329. package/template/packages/server-sdk/index.ts +50 -0
  330. package/template/packages/server-sdk/package.json +10 -4
  331. package/template/packages/server-sdk/src/ai-artifact-port.ts +34 -0
  332. package/template/packages/server-sdk/src/ai-operation-port.ts +65 -0
  333. package/template/packages/server-sdk/src/ai-operation-registration.ts +42 -1
  334. package/template/packages/server-sdk/src/background-ai-port.ts +43 -0
  335. package/template/packages/server-sdk/src/data-governance-registration.ts +116 -0
  336. package/template/packages/server-sdk/src/durable-handler.ts +29 -0
  337. package/template/packages/server-sdk/src/jobs-port.ts +69 -0
  338. package/template/packages/server-sdk/src/module-host.ts +16 -2
  339. package/template/packages/server-sdk/src/request-context.ts +6 -2
  340. package/template/packages/server-sdk/src/sandbox-tool.ts +21 -0
  341. package/template/packages/server-sdk/src/tool-registration.ts +2 -0
  342. package/template/packages/shared/package.json +1 -1
  343. package/template/packages/shared/src/rbac.ts +30 -0
@@ -0,0 +1,223 @@
1
+ import {
2
+ DocumentRuntimeError,
3
+ type DocumentRuntimeOperation,
4
+ type DocumentRuntimePort,
5
+ type DocumentRuntimeStartResponse,
6
+ } from "./contracts.js";
7
+
8
+ export class RemoteDocumentRuntime implements DocumentRuntimePort {
9
+ readonly #baseUrl: string;
10
+ readonly #timeoutMs: number;
11
+
12
+ constructor(
13
+ private readonly options: {
14
+ baseUrl: string;
15
+ internalToken: string;
16
+ timeoutMs?: number;
17
+ fetch?: (
18
+ input: string | URL | Request,
19
+ init?: RequestInit,
20
+ ) => Promise<Response>;
21
+ },
22
+ ) {
23
+ this.#baseUrl = normalizeUrl(options.baseUrl);
24
+ this.#timeoutMs = options.timeoutMs ?? 10_000;
25
+ if (!options.internalToken.trim()) {
26
+ throw new Error("Document Runtime 内部 Token 不能为空");
27
+ }
28
+ }
29
+
30
+ async start(
31
+ request: DocumentRuntimeOperation,
32
+ idempotencyKey: string,
33
+ signal?: AbortSignal,
34
+ ): Promise<DocumentRuntimeStartResponse> {
35
+ const response = await this.request("/api/document/runs", {
36
+ method: "POST",
37
+ headers: {
38
+ "content-type": "application/json",
39
+ "idempotency-key": idempotencyKey,
40
+ },
41
+ body: JSON.stringify(request),
42
+ signal,
43
+ });
44
+ if (!response.ok) throw await remoteError(response);
45
+ return parseStartResponse(await response.json());
46
+ }
47
+
48
+ events(runId: string, cursor: number, signal?: AbortSignal) {
49
+ return this.request(
50
+ `/api/document/runs/${encodeURIComponent(runId)}/events?after=${cursor}`,
51
+ { signal },
52
+ false,
53
+ );
54
+ }
55
+
56
+ result(runId: string, signal?: AbortSignal) {
57
+ return this.request(
58
+ `/api/document/runs/${encodeURIComponent(runId)}/result`,
59
+ { signal },
60
+ );
61
+ }
62
+
63
+ cancel(runId: string, reason?: string, signal?: AbortSignal) {
64
+ return this.request(
65
+ `/api/document/runs/${encodeURIComponent(runId)}/cancel`,
66
+ {
67
+ method: "POST",
68
+ headers: { "content-type": "application/json" },
69
+ body: JSON.stringify({ reason }),
70
+ signal,
71
+ },
72
+ );
73
+ }
74
+
75
+ health(signal?: AbortSignal) {
76
+ return this.request("/health/ready", { signal });
77
+ }
78
+
79
+ private request(
80
+ path: string,
81
+ init: RequestInit = {},
82
+ bounded = true,
83
+ ): Promise<Response> {
84
+ const timeout = AbortSignal.timeout(this.#timeoutMs);
85
+ const signal = init.signal
86
+ ? AbortSignal.any([init.signal, timeout])
87
+ : timeout;
88
+ const requestFetch = this.options.fetch ?? fetch;
89
+ return requestFetch(`${this.#baseUrl}${path}`, {
90
+ ...init,
91
+ signal,
92
+ headers: {
93
+ authorization: `Bearer ${this.options.internalToken}`,
94
+ ...init.headers,
95
+ },
96
+ }).then((response) => {
97
+ if (
98
+ bounded &&
99
+ Number(response.headers.get("content-length") || "0") >
100
+ 64 * 1_024 * 1_024
101
+ ) {
102
+ throw new DocumentRuntimeError(
103
+ "INVALID_RESPONSE",
104
+ "Document Runtime 响应超过上限",
105
+ false,
106
+ );
107
+ }
108
+ return response;
109
+ });
110
+ }
111
+ }
112
+
113
+ function parseStartResponse(value: unknown): DocumentRuntimeStartResponse {
114
+ if (!isRecord(value)) throw invalidResponse();
115
+ const { runId, status, eventsUrl } = value;
116
+ if (
117
+ typeof runId !== "string" ||
118
+ !runId.trim() ||
119
+ typeof status !== "string" ||
120
+ !["accepted", "running", "completed", "failed", "cancelled"].includes(
121
+ status,
122
+ ) ||
123
+ typeof eventsUrl !== "string" ||
124
+ !eventsUrl.startsWith("/")
125
+ ) {
126
+ throw invalidResponse();
127
+ }
128
+ return { runId, status, eventsUrl };
129
+ }
130
+
131
+ export const unavailableDocumentRuntime: DocumentRuntimePort = {
132
+ async start() {
133
+ throw new DocumentRuntimeError(
134
+ "CAPABILITY_UNAVAILABLE",
135
+ "Document Runtime 未安装或未配置",
136
+ true,
137
+ );
138
+ },
139
+ async events() {
140
+ throw unavailable();
141
+ },
142
+ async result() {
143
+ throw unavailable();
144
+ },
145
+ async cancel() {
146
+ throw unavailable();
147
+ },
148
+ async health() {
149
+ return Response.json(
150
+ { status: "unavailable", capabilities: [] },
151
+ { status: 503 },
152
+ );
153
+ },
154
+ };
155
+
156
+ function unavailable() {
157
+ return new DocumentRuntimeError(
158
+ "RUNTIME_UNAVAILABLE",
159
+ "Document Runtime 暂不可用",
160
+ true,
161
+ );
162
+ }
163
+
164
+ function invalidResponse() {
165
+ return new DocumentRuntimeError(
166
+ "INVALID_RESPONSE",
167
+ "Document Runtime 响应无效",
168
+ false,
169
+ );
170
+ }
171
+
172
+ function isRecord(value: unknown): value is Record<string, unknown> {
173
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
174
+ }
175
+
176
+ function normalizeUrl(raw: string) {
177
+ const url = new URL(raw);
178
+ if (
179
+ !["http:", "https:"].includes(url.protocol) ||
180
+ url.username ||
181
+ url.password ||
182
+ url.search ||
183
+ url.hash
184
+ ) {
185
+ throw new Error("Document Runtime URL 无效");
186
+ }
187
+ return url.toString().replace(/\/$/, "");
188
+ }
189
+
190
+ async function remoteError(response: Response) {
191
+ try {
192
+ const value = (await response.json()) as Record<string, unknown>;
193
+ if (
194
+ typeof value.code === "string" &&
195
+ typeof value.message === "string" &&
196
+ typeof value.retryable === "boolean" &&
197
+ value.message.length <= 200
198
+ ) {
199
+ return new DocumentRuntimeError(
200
+ knownRemoteCode(value.code),
201
+ value.message,
202
+ value.retryable,
203
+ );
204
+ }
205
+ } catch {
206
+ // 不透传远端正文。
207
+ }
208
+ return unavailable();
209
+ }
210
+
211
+ function knownRemoteCode(
212
+ code: string,
213
+ ): ConstructorParameters<typeof DocumentRuntimeError>[0] {
214
+ return [
215
+ "CAPABILITY_UNAVAILABLE",
216
+ "RUN_CONFLICT",
217
+ "FORBIDDEN",
218
+ "BUDGET_EXCEEDED",
219
+ "INVALID_INPUT",
220
+ ].includes(code)
221
+ ? (code as ConstructorParameters<typeof DocumentRuntimeError>[0])
222
+ : "RUNTIME_UNAVAILABLE";
223
+ }
@@ -0,0 +1,193 @@
1
+ import type {
2
+ ModuleAiArtifactRef,
3
+ ModuleAiJsonValue,
4
+ } from "@southwind-ai/server-sdk";
5
+ import type { RequestGuardContext } from "../guards.js";
6
+ import type { RouteApp } from "../system/route-types.js";
7
+ import type { DocumentRuntimePort } from "./contracts.js";
8
+ import { DocumentFacadeError, type DocumentRunFacade } from "./facade.js";
9
+
10
+ interface RouteContext {
11
+ readonly body?: unknown;
12
+ readonly params: Record<string, string | undefined>;
13
+ readonly query: Record<string, string | undefined>;
14
+ readonly request: Request;
15
+ readonly guardContext: RequestGuardContext;
16
+ }
17
+
18
+ export function registerDocumentRunRoutes(
19
+ app: RouteApp,
20
+ facade: DocumentRunFacade,
21
+ remote: DocumentRuntimePort,
22
+ ) {
23
+ app.post("/document/runs", async (raw) => {
24
+ const context = raw as RouteContext;
25
+ try {
26
+ const request = parseStart(context.body);
27
+ const idempotencyKey = context.request.headers.get("idempotency-key");
28
+ if (!idempotencyKey?.trim()) throw invalid("幂等键不能为空");
29
+ return Response.json(
30
+ await facade.start(
31
+ request.operationKey,
32
+ request.sources,
33
+ request.options,
34
+ idempotencyKey,
35
+ context.guardContext,
36
+ context.request.signal,
37
+ ),
38
+ { status: 202 },
39
+ );
40
+ } catch (error) {
41
+ return knownError(error);
42
+ }
43
+ });
44
+
45
+ app.get("/document/runs/:runId/events", async (raw) => {
46
+ const context = raw as RouteContext;
47
+ try {
48
+ const runId = required(context.params.runId);
49
+ facade.authorizeRun(runId, context.guardContext);
50
+ return await remote.events(
51
+ runId,
52
+ cursor(context.query.after),
53
+ context.request.signal,
54
+ );
55
+ } catch (error) {
56
+ return knownError(error);
57
+ }
58
+ });
59
+
60
+ app.get("/document/runs/:runId/result", async (raw) => {
61
+ const context = raw as RouteContext;
62
+ try {
63
+ const runId = required(context.params.runId);
64
+ facade.authorizeRun(runId, context.guardContext);
65
+ return await remote.result(runId, context.request.signal);
66
+ } catch (error) {
67
+ return knownError(error);
68
+ }
69
+ });
70
+
71
+ app.post("/document/runs/:runId/cancel", async (raw) => {
72
+ const context = raw as RouteContext;
73
+ try {
74
+ const runId = required(context.params.runId);
75
+ facade.authorizeRun(runId, context.guardContext);
76
+ const body = isRecord(context.body) ? context.body : {};
77
+ return await remote.cancel(
78
+ runId,
79
+ typeof body.reason === "string" ? body.reason.slice(0, 200) : undefined,
80
+ context.request.signal,
81
+ );
82
+ } catch (error) {
83
+ return knownError(error);
84
+ }
85
+ });
86
+ }
87
+
88
+ function parseStart(body: unknown): {
89
+ operationKey: string;
90
+ sources: readonly ModuleAiArtifactRef[];
91
+ options: ModuleAiJsonValue;
92
+ } {
93
+ if (
94
+ !isRecord(body) ||
95
+ Object.keys(body).some(
96
+ (key) => !["operationKey", "source", "sources", "options"].includes(key),
97
+ ) ||
98
+ typeof body.operationKey !== "string" ||
99
+ !body.operationKey.trim()
100
+ ) {
101
+ throw invalid("Document 请求格式无效");
102
+ }
103
+ if (body.source && body.sources) {
104
+ throw invalid("Document source 与 sources 不能同时提供");
105
+ }
106
+ const values = body.source
107
+ ? [body.source]
108
+ : Array.isArray(body.sources)
109
+ ? body.sources
110
+ : [];
111
+ if (!values.length || values.length > 100) {
112
+ throw invalid("Document 输入文件数量必须为 1 至 100");
113
+ }
114
+ const sources = values.map((value) => artifact(value));
115
+ assertJson(body.options ?? {});
116
+ return {
117
+ operationKey: body.operationKey,
118
+ sources,
119
+ options: (body.options ?? {}) as ModuleAiJsonValue,
120
+ };
121
+ }
122
+
123
+ function artifact(value: unknown): ModuleAiArtifactRef {
124
+ const source = isRecord(value) ? value : {};
125
+ if (
126
+ typeof source.value !== "string" ||
127
+ !source.value ||
128
+ typeof source.mediaType !== "string" ||
129
+ !Number.isSafeInteger(source.byteSize) ||
130
+ Number(source.byteSize) < 0 ||
131
+ typeof source.sha256 !== "string" ||
132
+ !/^[a-f0-9]{64}$/.test(source.sha256)
133
+ ) {
134
+ throw invalid("ArtifactRef 无效");
135
+ }
136
+ return {
137
+ value: source.value,
138
+ mediaType: source.mediaType,
139
+ byteSize: Number(source.byteSize),
140
+ sha256: source.sha256,
141
+ expiresAt: typeof source.expiresAt === "string" ? source.expiresAt : "",
142
+ };
143
+ }
144
+
145
+ function assertJson(value: unknown) {
146
+ try {
147
+ if (JSON.stringify(value) === undefined) throw new Error();
148
+ } catch {
149
+ throw invalid("Document options 必须是 JSON");
150
+ }
151
+ }
152
+
153
+ function cursor(value: string | undefined) {
154
+ if (value === undefined) return 0;
155
+ if (!/^\d+$/.test(value)) throw invalid("事件游标无效");
156
+ return Number(value);
157
+ }
158
+
159
+ function required(value: string | undefined) {
160
+ if (!value) throw invalid("Run ID 无效");
161
+ return value;
162
+ }
163
+
164
+ function invalid(message: string) {
165
+ return new DocumentFacadeError("INVALID_INPUT", message, 400);
166
+ }
167
+
168
+ function knownError(error: unknown) {
169
+ if (error instanceof DocumentFacadeError) {
170
+ return Response.json(
171
+ {
172
+ code: error.code,
173
+ message: error.message,
174
+ requestId: crypto.randomUUID(),
175
+ retryable: error.status >= 500,
176
+ },
177
+ { status: error.status },
178
+ );
179
+ }
180
+ return Response.json(
181
+ {
182
+ code: "RUNTIME_UNAVAILABLE",
183
+ message: "Document Runtime 暂不可用",
184
+ requestId: crypto.randomUUID(),
185
+ retryable: true,
186
+ },
187
+ { status: 503 },
188
+ );
189
+ }
190
+
191
+ function isRecord(value: unknown): value is Record<string, unknown> {
192
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
193
+ }
@@ -0,0 +1,83 @@
1
+ import type {
2
+ AiOperationDataClassification,
3
+ AiOperationInputModality,
4
+ AiProviderDataPolicy,
5
+ AiProviderEgressPolicy,
6
+ } from "@southwind-ai/modules";
7
+ import type { ModuleAiJsonValue } from "@southwind-ai/server-sdk";
8
+
9
+ export type EmbeddingRuntimeItem =
10
+ | { readonly id: string; readonly text: string }
11
+ | {
12
+ readonly id: string;
13
+ readonly source: {
14
+ readonly value: string;
15
+ readonly mediaType: string;
16
+ readonly byteSize: number;
17
+ readonly sha256: string;
18
+ };
19
+ };
20
+
21
+ export interface EmbeddingRuntimeOperation {
22
+ readonly kind: "embedding";
23
+ readonly operationKey: string;
24
+ readonly items: readonly EmbeddingRuntimeItem[];
25
+ readonly options: ModuleAiJsonValue;
26
+ readonly inputModalities: readonly AiOperationInputModality[];
27
+ readonly requiredCapabilities: readonly string[];
28
+ readonly dataClassification: AiOperationDataClassification;
29
+ readonly limits: {
30
+ readonly maxDurationSeconds: number;
31
+ readonly maxInputBytes: number;
32
+ readonly maxOutputBytes: number;
33
+ readonly maxUnits: number;
34
+ readonly maxArtifacts?: number;
35
+ readonly maxPixelsPerArtifact?: number;
36
+ };
37
+ readonly providerEgress: AiProviderEgressPolicy;
38
+ readonly providerDataPolicy?: AiProviderDataPolicy;
39
+ }
40
+
41
+ export interface EmbeddingBatchResponse {
42
+ readonly batchId: string;
43
+ readonly items: readonly {
44
+ readonly id: string;
45
+ readonly vector: readonly number[];
46
+ readonly inputSha256: string;
47
+ }[];
48
+ readonly metadata: {
49
+ readonly deploymentAlias: string;
50
+ readonly model: string;
51
+ readonly version: string;
52
+ readonly dimensions: number;
53
+ readonly normalized: boolean;
54
+ };
55
+ }
56
+
57
+ export interface EmbeddingRuntimePort {
58
+ embed(
59
+ request: EmbeddingRuntimeOperation,
60
+ idempotencyKey: string,
61
+ signal?: AbortSignal,
62
+ ): Promise<EmbeddingBatchResponse>;
63
+ health(signal?: AbortSignal): Promise<Response>;
64
+ }
65
+
66
+ export class EmbeddingRuntimeError extends Error {
67
+ constructor(
68
+ readonly code:
69
+ | "CAPABILITY_UNAVAILABLE"
70
+ | "RUNTIME_UNAVAILABLE"
71
+ | "RUN_CONFLICT"
72
+ | "FORBIDDEN"
73
+ | "BUDGET_EXCEEDED"
74
+ | "INVALID_INPUT"
75
+ | "OUTPUT_VALIDATION_FAILED"
76
+ | "INVALID_RESPONSE",
77
+ message: string,
78
+ readonly retryable: boolean,
79
+ ) {
80
+ super(message);
81
+ this.name = "EmbeddingRuntimeError";
82
+ }
83
+ }
@@ -0,0 +1,10 @@
1
+ export class EmbeddingFacadeError extends Error {
2
+ constructor(
3
+ readonly code: string,
4
+ message: string,
5
+ readonly status: number,
6
+ ) {
7
+ super(message);
8
+ this.name = "EmbeddingFacadeError";
9
+ }
10
+ }