create-windy 0.5.1 → 0.6.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.
- package/dist/cli.js +486 -156
- package/package.json +2 -1
- package/template/.windy-template.json +2 -2
- package/template/apps/agent-server/README.md +25 -6
- package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +15 -2
- package/template/apps/agent-server/src/southwind_agent_server/app.py +13 -34
- package/template/apps/agent-server/src/southwind_agent_server/config.py +49 -0
- package/template/apps/agent-server/src/southwind_agent_server/contracts.py +13 -0
- package/template/apps/agent-server/src/southwind_agent_server/engine_capacity.py +31 -0
- package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +5 -0
- package/template/apps/agent-server/src/southwind_agent_server/health_routes.py +50 -0
- package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +11 -2
- package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +3 -9
- package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +5 -0
- package/template/apps/agent-server/src/southwind_agent_server/readiness_pin.py +37 -0
- package/template/apps/agent-server/src/southwind_agent_server/run_admission.py +64 -0
- package/template/apps/agent-server/src/southwind_agent_server/run_capacity.py +59 -0
- package/template/apps/agent-server/src/southwind_agent_server/service.py +42 -43
- package/template/apps/agent-server/src/southwind_agent_server/service_errors.py +4 -0
- package/template/apps/agent-server/src/southwind_agent_server/service_execution.py +31 -0
- package/template/apps/agent-server/src/southwind_agent_server/service_tasks.py +34 -0
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +11 -0
- package/template/apps/agent-server/src/southwind_agent_server/store.py +6 -0
- package/template/apps/agent-server/src/southwind_agent_server/vision_probe.py +87 -0
- package/template/apps/agent-server/src/southwind_agent_server/vision_requirement.py +28 -0
- package/template/apps/agent-server/src/southwind_agent_server/vlm_readiness.py +247 -0
- package/template/apps/agent-server/tests/test_api.py +16 -3
- package/template/apps/agent-server/tests/test_openai_provider.py +21 -4
- package/template/apps/agent-server/tests/test_postgres_store.py +3 -0
- package/template/apps/agent-server/tests/test_run_capacity.py +110 -0
- package/template/apps/agent-server/tests/test_runtime_factory_readiness.py +37 -0
- package/template/apps/agent-server/tests/test_sqlite_store.py +3 -0
- package/template/apps/agent-server/tests/test_vision_readiness_enforcement.py +72 -0
- package/template/apps/agent-server/tests/test_vlm_readiness.py +106 -0
- package/template/apps/document-server/src/southwind_document_server/adapter.py +117 -205
- package/template/apps/document-server/src/southwind_document_server/adapter_errors.py +13 -0
- package/template/apps/document-server/src/southwind_document_server/app.py +62 -14
- package/template/apps/document-server/src/southwind_document_server/artifacts.py +27 -0
- package/template/apps/document-server/src/southwind_document_server/config.py +96 -2
- package/template/apps/document-server/src/southwind_document_server/contracts.py +168 -13
- package/template/apps/document-server/src/southwind_document_server/fingerprint.py +128 -0
- package/template/apps/document-server/src/southwind_document_server/grants.py +81 -0
- package/template/apps/document-server/src/southwind_document_server/multipart_output.py +265 -0
- package/template/apps/document-server/src/southwind_document_server/output_validation.py +202 -0
- package/template/apps/document-server/src/southwind_document_server/progress.py +27 -0
- package/template/apps/document-server/src/southwind_document_server/readiness.py +280 -0
- package/template/apps/document-server/src/southwind_document_server/readiness_contracts.py +280 -0
- package/template/apps/document-server/src/southwind_document_server/readiness_http.py +87 -0
- package/template/apps/document-server/src/southwind_document_server/readiness_support.py +120 -0
- package/template/apps/document-server/src/southwind_document_server/request_validation.py +48 -0
- package/template/apps/document-server/src/southwind_document_server/service.py +297 -96
- package/template/apps/document-server/src/southwind_document_server/service_recovery.py +183 -0
- package/template/apps/document-server/src/southwind_document_server/sink.py +316 -0
- package/template/apps/document-server/src/southwind_document_server/store.py +301 -141
- package/template/apps/document-server/src/southwind_document_server/store_events.py +40 -0
- package/template/apps/document-server/src/southwind_document_server/store_models.py +62 -0
- package/template/apps/document-server/src/southwind_document_server/store_recovery.py +247 -0
- package/template/apps/document-server/src/southwind_document_server/store_schema.py +50 -0
- package/template/apps/document-server/tests/recovery_support.py +230 -0
- package/template/apps/document-server/tests/support.py +210 -0
- package/template/apps/document-server/tests/test_adapter.py +251 -0
- package/template/apps/document-server/tests/test_config.py +43 -0
- package/template/apps/document-server/tests/test_contracts.py +80 -0
- package/template/apps/document-server/tests/test_fingerprint.py +125 -0
- package/template/apps/document-server/tests/test_grants.py +46 -0
- package/template/apps/document-server/tests/test_handshake.py +154 -0
- package/template/apps/document-server/tests/test_integration.py +192 -0
- package/template/apps/document-server/tests/test_multipart_security.py +259 -0
- package/template/apps/document-server/tests/test_readiness.py +311 -0
- package/template/apps/document-server/tests/test_readiness_contracts.py +131 -0
- package/template/apps/document-server/tests/test_recovery.py +222 -0
- package/template/apps/document-server/tests/test_recovery_faults.py +101 -0
- package/template/apps/document-server/tests/test_recovery_races.py +283 -0
- package/template/apps/document-server/tests/test_service.py +16 -13
- package/template/apps/document-server/tests/test_service_artifacts.py +296 -0
- package/template/apps/document-server/tests/test_sink.py +253 -0
- package/template/apps/document-server/tests/test_store.py +199 -0
- package/template/apps/embedding-server/pyproject.toml +5 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/adapter.py +38 -2
- package/template/apps/embedding-server/src/southwind_embedding_server/app.py +111 -3
- package/template/apps/embedding-server/src/southwind_embedding_server/config.py +27 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/image_input.py +16 -5
- package/template/apps/embedding-server/src/southwind_embedding_server/run_cipher.py +31 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/run_service.py +130 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/run_store.py +250 -0
- package/template/apps/embedding-server/tests/test_adapter.py +25 -0
- package/template/apps/embedding-server/tests/test_run_http.py +185 -0
- package/template/apps/embedding-server/tests/test_run_service.py +200 -0
- package/template/apps/embedding-server/uv.lock +71 -0
- package/template/apps/server/Dockerfile +13 -0
- package/template/apps/server/package.json +1 -0
- package/template/apps/server/src/agent/drizzle-screenshot-intake-repository.integration.test.ts +283 -0
- package/template/apps/server/src/agent/drizzle-screenshot-intake-repository.ts +175 -0
- package/template/apps/server/src/agent/persistent-screenshot-intake-producer.ts +320 -0
- package/template/apps/server/src/agent/remote-runtime.ts +8 -1
- package/template/apps/server/src/agent/required-environment.ts +5 -0
- package/template/apps/server/src/agent/run-attach.ts +41 -0
- package/template/apps/server/src/agent/run-audit.ts +49 -0
- package/template/apps/server/src/agent/run-contracts.ts +6 -1
- package/template/apps/server/src/agent/run-facade.ts +66 -68
- package/template/apps/server/src/agent/run-route-input.ts +26 -1
- package/template/apps/server/src/agent/run-routes.ts +1 -0
- package/template/apps/server/src/agent/runtime-bootstrap-report.test.ts +1 -1
- package/template/apps/server/src/agent/runtime-bootstrap.ts +110 -60
- package/template/apps/server/src/agent/runtime-readiness-sources.test.ts +27 -0
- package/template/apps/server/src/agent/runtime-readiness-sources.ts +31 -0
- package/template/apps/server/src/agent/runtime-reporting-bootstrap.ts +40 -0
- package/template/apps/server/src/agent/screenshot-intake-authorization.ts +29 -0
- package/template/apps/server/src/agent/screenshot-intake-bootstrap.ts +61 -0
- package/template/apps/server/src/agent/screenshot-intake-durable.ts +53 -0
- package/template/apps/server/src/agent/screenshot-intake-errors.ts +9 -0
- package/template/apps/server/src/agent/screenshot-intake-producer.ts +41 -0
- package/template/apps/server/src/agent/screenshot-intake-record.ts +44 -0
- package/template/apps/server/src/agent/screenshot-intake-recovery.ts +106 -0
- package/template/apps/server/src/agent/screenshot-intake-repository.ts +64 -0
- package/template/apps/server/src/agent/screenshot-intake-reservation.ts +24 -0
- package/template/apps/server/src/agent/screenshot-intake-routes.ts +171 -0
- package/template/apps/server/src/agent/screenshot-intake-runtime-types.ts +6 -0
- package/template/apps/server/src/agent/screenshot-intake-sweep.ts +26 -0
- package/template/apps/server/src/agent/screenshot-intake-test-support.ts +87 -0
- package/template/apps/server/src/agent/screenshot-intake-v2-validation.ts +152 -0
- package/template/apps/server/src/agent/screenshot-intake-v2.test.ts +338 -0
- package/template/apps/server/src/agent/screenshot-intake-v2.ts +350 -0
- package/template/apps/server/src/agent/screenshot-png.ts +15 -0
- package/template/apps/server/src/agent/screenshot-run-binding.ts +34 -0
- package/template/apps/server/src/agent/unavailable-routes.ts +9 -0
- package/template/apps/server/src/agent/vision-facade.test.ts +98 -8
- package/template/apps/server/src/agent/vision-input.ts +5 -2
- package/template/apps/server/src/agent/vision-readiness-pin.ts +74 -0
- package/template/apps/server/src/agent/vision-readiness.ts +58 -0
- package/template/apps/server/src/ai-artifact/runtime-reference.test.ts +135 -0
- package/template/apps/server/src/ai-artifact/runtime.ts +134 -5
- package/template/apps/server/src/ai-output-artifact/cleanup.ts +214 -0
- package/template/apps/server/src/ai-output-artifact/contracts.ts +152 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-cleanup.ts +37 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-complete.ts +71 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-grant-cleanup.ts +45 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-grants.ts +109 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-mapping.ts +77 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-readiness.ts +46 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-repository.ts +350 -0
- package/template/apps/server/src/ai-output-artifact/drizzle-seal.ts +64 -0
- package/template/apps/server/src/ai-output-artifact/grant.ts +30 -0
- package/template/apps/server/src/ai-output-artifact/host-registry.ts +53 -0
- package/template/apps/server/src/ai-output-artifact/memory-cleanup.ts +47 -0
- package/template/apps/server/src/ai-output-artifact/memory-grants.ts +98 -0
- package/template/apps/server/src/ai-output-artifact/memory-readiness.ts +26 -0
- package/template/apps/server/src/ai-output-artifact/memory-repository.ts +348 -0
- package/template/apps/server/src/ai-output-artifact/policy.test.ts +67 -0
- package/template/apps/server/src/ai-output-artifact/policy.ts +125 -0
- package/template/apps/server/src/ai-output-artifact/postgres-test-support.ts +147 -0
- package/template/apps/server/src/ai-output-artifact/postgres.integration.test.ts +349 -0
- package/template/apps/server/src/ai-output-artifact/reference-codec.ts +128 -0
- package/template/apps/server/src/ai-output-artifact/repository-grant-invariants.test-support.ts +165 -0
- package/template/apps/server/src/ai-output-artifact/repository-invariants.test-support.ts +239 -0
- package/template/apps/server/src/ai-output-artifact/repository-invariants.test.ts +18 -0
- package/template/apps/server/src/ai-output-artifact/repository.ts +107 -0
- package/template/apps/server/src/ai-output-artifact/route-input.ts +173 -0
- package/template/apps/server/src/ai-output-artifact/routes-delete.test.ts +287 -0
- package/template/apps/server/src/ai-output-artifact/routes-grant.test.ts +116 -0
- package/template/apps/server/src/ai-output-artifact/routes-nonblocking-body.test.ts +136 -0
- package/template/apps/server/src/ai-output-artifact/routes-security.test.ts +176 -0
- package/template/apps/server/src/ai-output-artifact/routes-storage-error.test.ts +105 -0
- package/template/apps/server/src/ai-output-artifact/routes.test-support.ts +84 -0
- package/template/apps/server/src/ai-output-artifact/routes.test.ts +198 -0
- package/template/apps/server/src/ai-output-artifact/routes.ts +280 -0
- package/template/apps/server/src/ai-output-artifact/service-completion.ts +60 -0
- package/template/apps/server/src/ai-output-artifact/service-grants.test.ts +169 -0
- package/template/apps/server/src/ai-output-artifact/service-grants.ts +217 -0
- package/template/apps/server/src/ai-output-artifact/service-input.ts +175 -0
- package/template/apps/server/src/ai-output-artifact/service-read.ts +89 -0
- package/template/apps/server/src/ai-output-artifact/service-recovery.test.ts +238 -0
- package/template/apps/server/src/ai-output-artifact/service-support.ts +240 -0
- package/template/apps/server/src/ai-output-artifact/service.test.ts +283 -0
- package/template/apps/server/src/ai-output-artifact/service.ts +334 -0
- package/template/apps/server/src/ai-output-artifact/storage-recovery.ts +33 -0
- package/template/apps/server/src/ai-output-artifact/storage-writer.ts +103 -0
- package/template/apps/server/src/ai-output-artifact/test-support.ts +161 -0
- package/template/apps/server/src/ai-runtime-readiness/health-response.ts +92 -0
- package/template/apps/server/src/ai-runtime-readiness/operation-port-trust.test.ts +66 -0
- package/template/apps/server/src/ai-runtime-readiness/operation-port.test-support.ts +143 -0
- package/template/apps/server/src/ai-runtime-readiness/operation-port.test.ts +193 -0
- package/template/apps/server/src/ai-runtime-readiness/operation-port.ts +172 -0
- package/template/apps/server/src/ai-runtime-readiness/trust-store.ts +61 -0
- package/template/apps/server/src/app/ai-screenshot-intake-binding.ts +22 -0
- package/template/apps/server/src/app/document-output-artifact-bindings.ts +5 -0
- package/template/apps/server/src/app/speech-output-artifact-bindings.ts +5 -0
- package/template/apps/server/src/application-services.ts +9 -3
- package/template/apps/server/src/audit/redaction.ts +1 -0
- package/template/apps/server/src/audit/reliable-writer.test.ts +8 -0
- package/template/apps/server/src/auth/password-change-license-restriction.test.ts +156 -0
- package/template/apps/server/src/document/cancel-response.ts +33 -0
- package/template/apps/server/src/document/contracts.ts +6 -0
- package/template/apps/server/src/document/errors.ts +11 -0
- package/template/apps/server/src/document/facade-cancel.test.ts +226 -0
- package/template/apps/server/src/document/facade-cancel.ts +110 -0
- package/template/apps/server/src/document/facade-grant-handoff.test.ts +113 -0
- package/template/apps/server/src/document/facade-idempotency.test.ts +195 -0
- package/template/apps/server/src/document/facade-invocation.ts +46 -0
- package/template/apps/server/src/document/facade-output-artifact.test.ts +310 -0
- package/template/apps/server/src/document/facade-read-response.ts +116 -0
- package/template/apps/server/src/document/facade-readiness.test.ts +95 -0
- package/template/apps/server/src/document/facade-support.ts +297 -0
- package/template/apps/server/src/document/facade.ts +164 -173
- package/template/apps/server/src/document/output-artifact-composition.test.ts +64 -0
- package/template/apps/server/src/document/output-artifact-composition.ts +78 -0
- package/template/apps/server/src/document/output-artifact-fingerprint.contract.test.ts +110 -0
- package/template/apps/server/src/document/output-artifact-fingerprint.ts +150 -0
- package/template/apps/server/src/document/output-artifact-host-registry.ts +44 -0
- package/template/apps/server/src/document/output-artifact-host.test.ts +332 -0
- package/template/apps/server/src/document/output-artifact-host.ts +331 -0
- package/template/apps/server/src/document/output-artifact-manifest.test-support.ts +71 -0
- package/template/apps/server/src/document/output-artifact-publish.test-support.ts +48 -0
- package/template/apps/server/src/document/output-artifact-readiness-probe.ts +347 -0
- package/template/apps/server/src/document/output-artifact-readiness-timeout.ts +30 -0
- package/template/apps/server/src/document/output-artifact-readiness.test.ts +264 -0
- package/template/apps/server/src/document/output-artifact-readiness.ts +87 -0
- package/template/apps/server/src/document/output-artifact-route-composition.test.ts +27 -0
- package/template/apps/server/src/document/output-artifact-route-composition.ts +14 -0
- package/template/apps/server/src/document/output-artifact-runtime.test-support.ts +8 -0
- package/template/apps/server/src/document/output-artifact-runtime.test.ts +124 -0
- package/template/apps/server/src/document/output-artifact-runtime.ts +275 -0
- package/template/apps/server/src/document/output-artifact.test-support.ts +350 -0
- package/template/apps/server/src/document/remote-response.ts +162 -0
- package/template/apps/server/src/document/remote-runtime.test.ts +100 -4
- package/template/apps/server/src/document/remote-runtime.ts +37 -85
- package/template/apps/server/src/document/routes-read-response.test.ts +267 -0
- package/template/apps/server/src/document/routes.test.ts +109 -0
- package/template/apps/server/src/document/routes.ts +23 -14
- package/template/apps/server/src/embedding/audit.ts +46 -0
- package/template/apps/server/src/embedding/contracts.ts +13 -0
- package/template/apps/server/src/embedding/drizzle-run-binding-repository.integration.test.ts +100 -0
- package/template/apps/server/src/embedding/drizzle-run-binding-repository.ts +102 -0
- package/template/apps/server/src/embedding/facade-types.ts +18 -0
- package/template/apps/server/src/embedding/facade.ts +242 -111
- package/template/apps/server/src/embedding/operation-authorization.ts +23 -0
- package/template/apps/server/src/embedding/remote-runtime.test.ts +18 -0
- package/template/apps/server/src/embedding/remote-runtime.ts +77 -0
- package/template/apps/server/src/embedding/routes.test.ts +118 -0
- package/template/apps/server/src/embedding/routes.ts +98 -0
- package/template/apps/server/src/embedding/run-artifact.ts +18 -0
- package/template/apps/server/src/embedding/run-authorization.test.ts +133 -0
- package/template/apps/server/src/embedding/run-authorization.ts +91 -0
- package/template/apps/server/src/embedding/run-binding-repository.ts +75 -0
- package/template/apps/server/src/embedding/run-fingerprint.test.ts +52 -0
- package/template/apps/server/src/embedding/run-fingerprint.ts +39 -0
- package/template/apps/server/src/embedding/terminal-observer.test.ts +26 -0
- package/template/apps/server/src/embedding/terminal-observer.ts +44 -0
- package/template/apps/server/src/index.ts +38 -31
- package/template/apps/server/src/module-host/ai-operation-port.ts +3 -3
- package/template/apps/server/src/module-host/durable-context.ts +194 -16
- package/template/apps/server/src/module-host/durable-handler-registration.ts +1 -0
- package/template/apps/server/src/module-host/durable-storage-filesystem-restart.test.ts +265 -0
- package/template/apps/server/src/module-host/durable-storage-write.test.ts +345 -0
- package/template/apps/server/src/module-host/http-runtime.ts +25 -0
- package/template/apps/server/src/module-host/initialize-contracts.ts +18 -1
- package/template/apps/server/src/module-host/initialize.test.ts +18 -0
- package/template/apps/server/src/module-host/initialize.ts +42 -2
- package/template/apps/server/src/module-host/module-secret-audit-version.test.ts +73 -0
- package/template/apps/server/src/module-host/module-secret-binding-resolution.ts +60 -0
- package/template/apps/server/src/module-host/module-secret-durable.test.ts +206 -0
- package/template/apps/server/src/module-host/module-secret-port.test-support.ts +125 -0
- package/template/apps/server/src/module-host/module-secret-port.test.ts +161 -0
- package/template/apps/server/src/module-host/module-secret-port.ts +249 -0
- package/template/apps/server/src/module-host/module-secret-result.test.ts +324 -0
- package/template/apps/server/src/module-host/module-secret-result.ts +274 -0
- package/template/apps/server/src/module-host/module-secret-tool-boundary.test.ts +143 -0
- package/template/apps/server/src/module-host/project-composition.ts +1 -0
- package/template/apps/server/src/module-host/report-staging-port.ts +55 -0
- package/template/apps/server/src/module-host/report-staging-registration.test.ts +104 -0
- package/template/apps/server/src/module-host/request-context.ts +58 -1
- package/template/apps/server/src/module-host/route-declaration.ts +11 -4
- package/template/apps/server/src/module-host/route-installer.test-fixture.ts +246 -0
- package/template/apps/server/src/module-host/route-installer.test.ts +47 -211
- package/template/apps/server/src/module-host/route-installer.ts +192 -21
- package/template/apps/server/src/module-host/route-registration.test.ts +44 -4
- package/template/apps/server/src/module-host/runtime-composition.ts +2 -0
- package/template/apps/server/src/module-host/scoped-host.ts +84 -0
- package/template/apps/server/src/module-host/screenshot-artifact-ref.ts +91 -0
- package/template/apps/server/src/module-host/screenshot-intake-composition.test.ts +292 -0
- package/template/apps/server/src/module-host/screenshot-intake-deadline.ts +38 -0
- package/template/apps/server/src/module-host/screenshot-intake-plan.ts +75 -0
- package/template/apps/server/src/module-host/screenshot-intake-port.ts +297 -0
- package/template/apps/server/src/module-host/screenshot-intake-security.test.ts +311 -0
- package/template/apps/server/src/module-host/screenshot-intake-store.ts +76 -0
- package/template/apps/server/src/module-host/screenshot-intake-test-support.ts +68 -0
- package/template/apps/server/src/module-host/secret-bindings.test.ts +167 -0
- package/template/apps/server/src/module-host/secret-bindings.ts +184 -0
- package/template/apps/server/src/module-host/storage-authorization-binding.test.ts +242 -0
- package/template/apps/server/src/module-host/storage-port.test.ts +8 -1
- package/template/apps/server/src/module-host/storage-port.ts +84 -8
- package/template/apps/server/src/module-host/storage-restart-fixture.test-support.ts +242 -0
- package/template/apps/server/src/module-host/storage-restart-postgres.integration.test.ts +280 -0
- package/template/apps/server/src/module-host/storage-scope-drift-http.test.ts +68 -0
- package/template/apps/server/src/module-host/storage-scope.ts +52 -1
- package/template/apps/server/src/module-host/storage-stream-route.test.ts +282 -0
- package/template/apps/server/src/module-host/storage-write-error.test.ts +174 -0
- package/template/apps/server/src/module-host/storage-write-error.ts +62 -0
- package/template/apps/server/src/module-host/storage-write-port.test.ts +323 -0
- package/template/apps/server/src/module-host/storage-write-port.ts +320 -0
- package/template/apps/server/src/module-host/storage-write-unavailable.ts +21 -0
- package/template/apps/server/src/module-host/storage-writer-retention.test.ts +109 -0
- package/template/apps/server/src/module-host/user-directory-composition.test.ts +1 -0
- package/template/apps/server/src/module-preflight-secret.test.ts +79 -0
- package/template/apps/server/src/module-preflight.ts +5 -0
- package/template/apps/server/src/platform-http-runtime.ts +16 -4
- package/template/apps/server/src/report-staging/archive-frame-stream.test.ts +209 -0
- package/template/apps/server/src/report-staging/archive-frame-stream.ts +341 -0
- package/template/apps/server/src/report-staging/archive-process.test.ts +302 -0
- package/template/apps/server/src/report-staging/archive-process.ts +257 -0
- package/template/apps/server/src/report-staging/archive-volumes.ts +30 -0
- package/template/apps/server/src/report-staging/cancellation.ts +13 -0
- package/template/apps/server/src/report-staging/contracts.ts +94 -0
- package/template/apps/server/src/report-staging/drizzle-lifecycle.ts +278 -0
- package/template/apps/server/src/report-staging/drizzle-mapping.ts +140 -0
- package/template/apps/server/src/report-staging/drizzle-repository.integration.test.ts +346 -0
- package/template/apps/server/src/report-staging/drizzle-repository.ts +255 -0
- package/template/apps/server/src/report-staging/drizzle-seal.integration.test.ts +267 -0
- package/template/apps/server/src/report-staging/drizzle-seal.ts +177 -0
- package/template/apps/server/src/report-staging/filesystem-cleanup.test.ts +68 -0
- package/template/apps/server/src/report-staging/filesystem-cleanup.ts +102 -0
- package/template/apps/server/src/report-staging/filesystem-errors.ts +15 -0
- package/template/apps/server/src/report-staging/filesystem-identifiers.ts +19 -0
- package/template/apps/server/src/report-staging/filesystem-io.test.ts +85 -0
- package/template/apps/server/src/report-staging/filesystem-io.ts +206 -0
- package/template/apps/server/src/report-staging/filesystem-scan.ts +85 -0
- package/template/apps/server/src/report-staging/filesystem-store.ts +346 -0
- package/template/apps/server/src/report-staging/heartbeat.test.ts +47 -0
- package/template/apps/server/src/report-staging/heartbeat.ts +53 -0
- package/template/apps/server/src/report-staging/manifest-stream.ts +46 -0
- package/template/apps/server/src/report-staging/memory-repository.ts +256 -0
- package/template/apps/server/src/report-staging/metadata-catalog.ts +89 -0
- package/template/apps/server/src/report-staging/metadata-spool-paths.ts +195 -0
- package/template/apps/server/src/report-staging/metadata-spool-schema.ts +54 -0
- package/template/apps/server/src/report-staging/metadata-spool.test.ts +214 -0
- package/template/apps/server/src/report-staging/metadata-spool.ts +305 -0
- package/template/apps/server/src/report-staging/native/archive-frame-helper.c +309 -0
- package/template/apps/server/src/report-staging/path-policy.test.ts +127 -0
- package/template/apps/server/src/report-staging/path-policy.ts +263 -0
- package/template/apps/server/src/report-staging/repository-fence.test.ts +114 -0
- package/template/apps/server/src/report-staging/repository.ts +75 -0
- package/template/apps/server/src/report-staging/runtime.ts +31 -0
- package/template/apps/server/src/report-staging/sealed-file.test.ts +34 -0
- package/template/apps/server/src/report-staging/sealed-file.ts +137 -0
- package/template/apps/server/src/report-staging/service-input-limits.test.ts +62 -0
- package/template/apps/server/src/report-staging/service-input.ts +204 -0
- package/template/apps/server/src/report-staging/service-lifecycle.test.ts +132 -0
- package/template/apps/server/src/report-staging/service-read-fence.test.ts +37 -0
- package/template/apps/server/src/report-staging/service-read.ts +172 -0
- package/template/apps/server/src/report-staging/service-support.ts +149 -0
- package/template/apps/server/src/report-staging/service.test-fixture.ts +226 -0
- package/template/apps/server/src/report-staging/service.test.ts +314 -0
- package/template/apps/server/src/report-staging/service.ts +255 -0
- package/template/apps/server/src/report-staging/supervised-process.ts +194 -0
- package/template/apps/server/src/speech/contracts.ts +8 -0
- package/template/apps/server/src/speech/errors.ts +10 -0
- package/template/apps/server/src/speech/facade-contract.ts +49 -0
- package/template/apps/server/src/speech/facade-output.test.ts +299 -0
- package/template/apps/server/src/speech/facade-output.ts +298 -0
- package/template/apps/server/src/speech/facade-validation.ts +127 -0
- package/template/apps/server/src/speech/facade.ts +185 -151
- package/template/apps/server/src/speech/fingerprint.test.ts +42 -0
- package/template/apps/server/src/speech/fingerprint.ts +28 -0
- package/template/apps/server/src/speech/output-artifact-binding.test.ts +11 -0
- package/template/apps/server/src/speech/output-artifact-binding.ts +30 -0
- package/template/apps/server/src/speech/output-artifact-error.ts +9 -0
- package/template/apps/server/src/speech/output-artifact-host.test-support.ts +73 -0
- package/template/apps/server/src/speech/output-artifact-host.test.ts +302 -0
- package/template/apps/server/src/speech/output-artifact-host.ts +279 -0
- package/template/apps/server/src/speech/output-artifact-policy.ts +114 -0
- package/template/apps/server/src/speech/output-artifact-replay.ts +91 -0
- package/template/apps/server/src/speech/remote-response.ts +158 -0
- package/template/apps/server/src/speech/remote-runtime.test.ts +90 -0
- package/template/apps/server/src/speech/remote-runtime.ts +36 -78
- package/template/apps/server/src/speech/routes.ts +60 -16
- package/template/apps/server/src/startup-finalization.ts +52 -0
- package/template/apps/server/src/startup-preflight.ts +2 -0
- package/template/apps/server/src/startup-shutdown.test.ts +69 -0
- package/template/apps/server/src/startup-shutdown.ts +61 -0
- package/template/apps/server/src/storage/drizzle-upload-purge.ts +61 -0
- package/template/apps/server/src/storage/drizzle-upload-references.ts +23 -0
- package/template/apps/server/src/storage/drizzle-upload-repository.integration.test.ts +103 -0
- package/template/apps/server/src/storage/drizzle-upload-repository.ts +109 -14
- package/template/apps/server/src/storage/host-runtime.ts +15 -0
- package/template/apps/server/src/storage/routes-stream-cancellation.test.ts +154 -0
- package/template/apps/server/src/storage/routes.test.ts +13 -2
- package/template/apps/server/src/storage/routes.ts +57 -18
- package/template/apps/server/src/storage/runtime.ts +17 -4
- package/template/apps/server/src/system/route-types.ts +5 -1
- package/template/apps/server/src/system/system-resource-monitoring.test.ts +47 -0
- package/template/apps/server/src/system/system-resource-monitoring.ts +60 -10
- package/template/apps/server/src/work-order/routes.test.ts +1 -0
- package/template/apps/speech-server/src/southwind_speech_server/adapter.py +58 -17
- package/template/apps/speech-server/src/southwind_speech_server/app.py +24 -17
- package/template/apps/speech-server/src/southwind_speech_server/bounded_json.py +60 -0
- package/template/apps/speech-server/src/southwind_speech_server/config.py +122 -2
- package/template/apps/speech-server/src/southwind_speech_server/contracts.py +58 -0
- package/template/apps/speech-server/src/southwind_speech_server/errors.py +8 -0
- package/template/apps/speech-server/src/southwind_speech_server/normalizer.py +14 -0
- package/template/apps/speech-server/src/southwind_speech_server/output_artifact.py +190 -0
- package/template/apps/speech-server/src/southwind_speech_server/output_validation.py +54 -0
- package/template/apps/speech-server/src/southwind_speech_server/pin_cli.py +83 -0
- package/template/apps/speech-server/src/southwind_speech_server/readiness.py +266 -0
- package/template/apps/speech-server/src/southwind_speech_server/readiness_contracts.py +268 -0
- package/template/apps/speech-server/src/southwind_speech_server/readiness_http.py +91 -0
- package/template/apps/speech-server/src/southwind_speech_server/readiness_local.py +161 -0
- package/template/apps/speech-server/src/southwind_speech_server/readiness_support.py +106 -0
- package/template/apps/speech-server/src/southwind_speech_server/service.py +118 -13
- package/template/apps/speech-server/src/southwind_speech_server/store.py +7 -0
- package/template/apps/speech-server/tests/test_bounded_json.py +55 -0
- package/template/apps/speech-server/tests/test_config.py +22 -0
- package/template/apps/speech-server/tests/test_output_artifact.py +60 -0
- package/template/apps/speech-server/tests/test_output_validation.py +44 -0
- package/template/apps/speech-server/tests/test_readiness.py +315 -0
- package/template/apps/speech-server/tests/test_readiness_http.py +48 -0
- package/template/apps/speech-server/tests/test_readiness_local.py +43 -0
- package/template/apps/speech-server/tests/test_service.py +211 -36
- package/template/apps/web/src/pages/system/components/OperationGpuMonitor.vue +23 -3
- package/template/apps/web/src/pages/system/components/OperationGpuMonitor.webtest.ts +29 -0
- package/template/apps/web/src/pages/system/components/OperationServiceMonitor.vue +2 -1
- package/template/apps/web/src/pages/system/components/OperationServiceMonitor.webtest.ts +4 -1
- package/template/docker-compose.yml +38 -1
- package/template/docs/architecture/ai-runtime-readiness.md +498 -0
- package/template/docs/architecture/ai-runtime.md +20 -4
- package/template/docs/architecture/durable-jobs.md +54 -5
- package/template/docs/architecture/module-host.md +72 -9
- package/template/docs/architecture/module-manifest-composition.md +5 -2
- package/template/docs/architecture/module-secret-resolution.md +250 -0
- package/template/docs/architecture/object-storage.md +144 -3
- package/template/docs/architecture/report-staging.md +158 -0
- package/template/docs/architecture/server-module-interface.md +29 -0
- package/template/docs/architecture/speech-variants.md +45 -0
- package/template/docs/platform/agent-tools.md +16 -0
- package/template/docs/platform/document-ai-runtime.md +199 -17
- package/template/docs/platform/module-configuration.md +5 -0
- package/template/docs/platform/speech-ai-runtime.md +34 -5
- package/template/docs/platform/vision-ai-runtime.md +24 -0
- package/template/package.json +4 -1
- package/template/packages/ai-client/package.json +1 -1
- package/template/packages/ai-client/src/agent/client/client.ts +3 -0
- package/template/packages/ai-client/src/agent/client/index.ts +1 -0
- package/template/packages/ai-client/src/agent/client/screenshot.test.ts +40 -0
- package/template/packages/ai-client/src/agent/client/screenshot.ts +146 -0
- package/template/packages/ai-client/src/agent/client/types.ts +2 -0
- package/template/packages/ai-client/src/agent/contracts/runs.ts +1 -0
- package/template/packages/ai-client/src/embedding/client.test.ts +52 -0
- package/template/packages/ai-client/src/embedding/client.ts +69 -0
- package/template/packages/ai-client/src/embedding/contracts.ts +47 -0
- package/template/packages/ai-client/src/embedding/index.ts +1 -0
- package/template/packages/ai-client/src/embedding/run.ts +130 -0
- package/template/packages/ai-client/src/speech/client.test.ts +26 -0
- package/template/packages/ai-client/src/speech/client.ts +25 -1
- package/template/packages/ai-client/src/speech/contracts.ts +19 -0
- package/template/packages/config/package.json +1 -1
- package/template/packages/database/drizzle/0048_illegal_magneto.sql +11 -0
- package/template/packages/database/drizzle/0049_right_lenny_balinger.sql +79 -0
- package/template/packages/database/drizzle/0050_greedy_sister_grimm.sql +92 -0
- package/template/packages/database/drizzle/0051_lame_shockwave.sql +19 -0
- package/template/packages/database/drizzle/0052_tiresome_komodo.sql +1 -0
- package/template/packages/database/drizzle/0053_calm_victor_mancha.sql +1 -0
- package/template/packages/database/drizzle/0054_tough_thanos.sql +29 -0
- package/template/packages/database/drizzle/meta/0048_snapshot.json +8852 -0
- package/template/packages/database/drizzle/meta/0049_snapshot.json +9410 -0
- package/template/packages/database/drizzle/meta/0050_snapshot.json +10115 -0
- package/template/packages/database/drizzle/meta/0051_snapshot.json +10257 -0
- package/template/packages/database/drizzle/meta/0052_snapshot.json +10263 -0
- package/template/packages/database/drizzle/meta/0053_snapshot.json +10270 -0
- package/template/packages/database/drizzle/meta/0054_snapshot.json +10468 -0
- package/template/packages/database/drizzle/meta/_journal.json +49 -0
- package/template/packages/database/package.json +1 -1
- package/template/packages/database/src/agent-runtime-schema.test.ts +15 -0
- package/template/packages/database/src/ai-output-artifacts.test.ts +57 -0
- package/template/packages/database/src/schema/agent-runtime.ts +43 -0
- package/template/packages/database/src/schema/ai-output-artifacts.ts +182 -0
- package/template/packages/database/src/schema/embedding-runtime.ts +62 -0
- package/template/packages/database/src/schema/file-storage.ts +18 -0
- package/template/packages/database/src/schema/index.ts +3 -0
- package/template/packages/database/src/schema/report-staging.ts +212 -0
- package/template/packages/database/src/schema.test.ts +19 -0
- package/template/packages/jobs/package.json +1 -1
- package/template/packages/modules/index.ts +1 -0
- package/template/packages/modules/package.json +1 -1
- package/template/packages/modules/src/ai-operation-composition.test.ts +37 -0
- package/template/packages/modules/src/ai-operation-composition.ts +2 -0
- package/template/packages/modules/src/ai-operation-readiness-contract.test.ts +38 -0
- package/template/packages/modules/src/ai-operation-readiness-contract.ts +34 -0
- package/template/packages/modules/src/capability-audit-validation.ts +20 -0
- package/template/packages/modules/src/capability-guard-validation.ts +41 -0
- package/template/packages/modules/src/composition.ts +11 -0
- package/template/packages/modules/src/manifest.ts +40 -0
- package/template/packages/modules/src/secret-composition.test.ts +308 -0
- package/template/packages/modules/src/secret-composition.ts +176 -0
- package/template/packages/modules/src/system-api-control-plane.ts +17 -1
- package/template/packages/modules/src/system-module-catalog.test.ts +52 -0
- package/template/packages/modules/src/system-module-catalog.ts +1 -1
- package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/document-python-parity.json +12 -0
- package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/document.json +70 -0
- package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/embedding.json +68 -0
- package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/speech.json +80 -0
- package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/vlm.json +70 -0
- package/template/packages/server-sdk/contracts/document-runtime/v1/fingerprint-fixture.json +101 -0
- package/template/packages/server-sdk/index.ts +109 -0
- package/template/packages/server-sdk/package.json +22 -3
- package/template/packages/server-sdk/src/ai-runtime-readiness-capture.ts +168 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-digest.ts +49 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-identity.ts +16 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-keys.ts +23 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-limits.ts +141 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-projection.ts +326 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-requirement.ts +31 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-time.ts +16 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-trust.ts +84 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-validation-values.ts +147 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-validation.ts +299 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness-values.ts +42 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.adversarial-input.contract.test.ts +146 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.contract-support.ts +139 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.contract.test.ts +314 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.digest-safety.contract.test.ts +131 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.fail-closed.contract.test.ts +215 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.identity.contract.test.ts +138 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.input-safety.contract.test.ts +314 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.public-api.test.ts +18 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.python-parity.contract.test.ts +160 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.trust.contract.test.ts +135 -0
- package/template/packages/server-sdk/src/ai-runtime-readiness.ts +198 -0
- package/template/packages/server-sdk/src/ai-screenshot-intake-port.ts +58 -0
- package/template/packages/server-sdk/src/data-governance-registration.ts +1 -3
- package/template/packages/server-sdk/src/durable-handler.ts +12 -0
- package/template/packages/server-sdk/src/module-adapter.test.ts +10 -0
- package/template/packages/server-sdk/src/module-adapter.ts +3 -0
- package/template/packages/server-sdk/src/module-host.ts +8 -0
- package/template/packages/server-sdk/src/report-staging-context-compatibility.test.ts +25 -0
- package/template/packages/server-sdk/src/report-staging-port.ts +190 -0
- package/template/packages/server-sdk/src/request-context.ts +27 -1
- package/template/packages/server-sdk/src/route-definition.ts +6 -0
- package/template/packages/server-sdk/src/secret-binding.test.ts +66 -0
- package/template/packages/server-sdk/src/secret-binding.ts +54 -0
- package/template/packages/server-sdk/src/secret-context-compatibility.test.ts +77 -0
- package/template/packages/server-sdk/src/secret-port.ts +80 -0
- package/template/packages/server-sdk/src/storage-port.ts +129 -9
- package/template/packages/server-sdk/src/storage-v052-source-compatibility.test.ts +61 -0
- package/template/packages/shared/index.ts +2 -0
- package/template/packages/shared/package.json +4 -1
- package/template/packages/shared/src/ai-operation-readiness.test.ts +75 -0
- package/template/packages/shared/src/ai-operation-readiness.ts +170 -0
- package/template/packages/shared/src/license-catalog.ts +14 -9
- package/template/packages/shared/src/stable-key.ts +26 -0
- package/template/packages/shared/tsconfig.json +16 -0
- package/template/packages/storage/index.ts +2 -0
- package/template/packages/storage/package.json +1 -1
- package/template/packages/storage/src/in-memory-upload-repository.ts +105 -2
- package/template/packages/storage/src/local-file-blob-store.test.ts +58 -0
- package/template/packages/storage/src/local-file-blob-store.ts +5 -71
- package/template/packages/storage/src/local-file-blob-writer.ts +96 -0
- package/template/packages/storage/src/upload-abort-recovery.test.ts +234 -0
- package/template/packages/storage/src/upload-abort.ts +130 -0
- package/template/packages/storage/src/upload-cleanup-race.test.ts +207 -0
- package/template/packages/storage/src/upload-cleanup.ts +85 -0
- package/template/packages/storage/src/upload-completion.ts +52 -0
- package/template/packages/storage/src/upload-purge.test.ts +163 -0
- package/template/packages/storage/src/upload-purge.ts +261 -0
- package/template/packages/storage/src/upload-repository-v052-compatibility.test.ts +31 -0
- package/template/packages/storage/src/upload-repository.ts +61 -0
- package/template/packages/storage/src/upload-service-recovery.test.ts +296 -0
- package/template/packages/storage/src/upload-service.ts +138 -150
- package/template/packages/storage/src/upload-streams.ts +126 -30
- package/template/packages/storage/src/upload-types.ts +13 -0
- package/template/packages/storage/src/upload-validation.ts +127 -0
- package/template/scripts/provision-speech-readiness.ts +147 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-windy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "bun build src/cli.ts --target=bun --format=esm --outdir=dist",
|
|
17
|
+
"regression:update-candidate": "bun run src/candidate-update-regression.ts",
|
|
17
18
|
"template:sync": "bun run src/sync-template.ts",
|
|
18
19
|
"prepack": "bun run template:sync && bun run build",
|
|
19
20
|
"postpack": "bun run src/clean-template.ts",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Southwind AI Agent Server
|
|
2
2
|
|
|
3
|
-
Python 3.12 Agent
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Python 3.12 Agent 运行时。HTTP 层只公开 Southwind AI 的 canonical Agent 契约;真实业务
|
|
4
|
+
Run 在内部通过 Google ADK 2.5 的 Runner、Session、LlmAgent 和 Event 执行,ADK 类型不会
|
|
5
|
+
越过 `AgentEngineAdapter`。模型调用继续复用受治理的 OpenAI-compatible
|
|
6
|
+
`/chat/completions` Provider。
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
9
|
uv sync --frozen
|
|
@@ -13,7 +13,7 @@ uv run ruff format --check .
|
|
|
13
13
|
uv run mypy
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
HTTP
|
|
16
|
+
HTTP 接口:
|
|
17
17
|
|
|
18
18
|
- `POST /api/agent/runs`
|
|
19
19
|
- `GET /api/agent/runs/:runId/events`
|
|
@@ -40,8 +40,27 @@ export AI_PROVIDER_AUDIT_RETENTION_DAYS='90'
|
|
|
40
40
|
uv run uvicorn southwind_agent_server.app:app
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
VLM Operation readiness 比 Endpoint 可达性更严格。必须固定 Deployment 事实并声明
|
|
44
|
+
图片 offer;否则 `/health/vlm-ready` 返回 V1 `unavailable` snapshot,视觉 Operation 保持
|
|
45
|
+
关闭:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
export AI_PROVIDER_CAPABILITIES='text-generation,vision'
|
|
49
|
+
export AI_PROVIDER_INPUT_MODALITIES='text,image'
|
|
50
|
+
export AI_PROVIDER_DEPLOYMENT_IDENTITY='windy-deployment-v1_<uuid-v4>'
|
|
51
|
+
export AI_PROVIDER_RELEASE_DIGEST='sha256:<64-lowercase-hex>'
|
|
52
|
+
export AI_PROVIDER_READINESS_TTL_SECONDS='60'
|
|
53
|
+
export AI_PROVIDER_MAX_CONCURRENT_RUNS='1'
|
|
54
|
+
export AI_PROVIDER_MAX_QUEUE_DEPTH='0'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Readiness 请求用固定的一像素合成图片调用已配置的 `/chat/completions`,并要求有界
|
|
58
|
+
结构化结果。它不会调用 `/models`,不会读取客户截图,也不会把用户 Artifact、URL、Run
|
|
59
|
+
ID、Prompt 或 Provider 输出放进 health payload。`offersDigest` 始终按公开 V1 算法由
|
|
60
|
+
实际 offer 计算,不能由环境变量伪造。
|
|
61
|
+
|
|
43
62
|
公网 URL 必须使用 HTTPS 且 Host 精确命中 allowlist;本机、容器服务名和内网地址允许
|
|
44
|
-
HTTP。Provider 请求包含连接和总超时、响应大小限制、错误脱敏与
|
|
63
|
+
HTTP。Provider 请求包含连接和总超时、响应大小限制、错误脱敏与 VLM 合成图片
|
|
45
64
|
readiness。缺少 URL/Model 时回退
|
|
46
65
|
未配置的 `AdkEngineAdapter` 并返回 unavailable,不调用模型。测试另使用
|
|
47
66
|
`DeterministicEngineAdapter`。每个 ADK Tool 只声明 Operation 已允许的 Key;其执行
|
|
@@ -32,6 +32,7 @@ from .provider_governance import ProviderRequestGovernance
|
|
|
32
32
|
from .report_store import AgentRuntimeReportStore
|
|
33
33
|
from .report_types import CacheStatus, UsageFacts, UsageSource
|
|
34
34
|
from .tool_host import ToolHostClient, canonical_tool_call_id
|
|
35
|
+
from .vlm_readiness import VlmReadinessProbe, unavailable_vlm_snapshot
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
class AdkEngineAdapter(AgentEngineAdapter):
|
|
@@ -58,6 +59,14 @@ class AdkEngineAdapter(AgentEngineAdapter):
|
|
|
58
59
|
def input_modalities(self) -> tuple[str, ...]:
|
|
59
60
|
return self._provider.config.input_modalities if self._provider else ()
|
|
60
61
|
|
|
62
|
+
@property
|
|
63
|
+
def max_concurrent_runs(self) -> int:
|
|
64
|
+
return self._provider.config.max_concurrent_runs if self._provider else 1
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def max_queue_depth(self) -> int:
|
|
68
|
+
return self._provider.config.max_queue_depth if self._provider else 0
|
|
69
|
+
|
|
61
70
|
def supports(self, operation_key: str) -> bool:
|
|
62
71
|
return bool(operation_key.strip())
|
|
63
72
|
|
|
@@ -183,8 +192,12 @@ class AdkEngineAdapter(AgentEngineAdapter):
|
|
|
183
192
|
cancellation.set()
|
|
184
193
|
|
|
185
194
|
async def health(self) -> None:
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
self._configured()
|
|
196
|
+
|
|
197
|
+
async def readiness(self) -> dict[str, object]:
|
|
198
|
+
if not self._provider:
|
|
199
|
+
return unavailable_vlm_snapshot(configured=False)
|
|
200
|
+
return await VlmReadinessProbe(self._provider.config, self._provider).inspect()
|
|
188
201
|
|
|
189
202
|
def governance_health(self) -> dict[str, int | float | str | None]:
|
|
190
203
|
_, _, governance = self._configured()
|
|
@@ -23,6 +23,8 @@ from .contracts import (
|
|
|
23
23
|
StartRunResponse,
|
|
24
24
|
)
|
|
25
25
|
from .engine import AgentEngineAdapter, SafeEngineError
|
|
26
|
+
from .engine_capacity import engine_capacity
|
|
27
|
+
from .health_routes import install_health_routes
|
|
26
28
|
from .http_helpers import (
|
|
27
29
|
authorized,
|
|
28
30
|
parse_cursor,
|
|
@@ -36,15 +38,13 @@ from .runtime_factory import (
|
|
|
36
38
|
default_report_store,
|
|
37
39
|
default_store,
|
|
38
40
|
)
|
|
39
|
-
from .service import
|
|
40
|
-
|
|
41
|
-
OperationNotFoundError,
|
|
42
|
-
RunNotFoundError,
|
|
43
|
-
)
|
|
41
|
+
from .service import AgentRunService
|
|
42
|
+
from .service_errors import OperationNotFoundError, RunNotFoundError
|
|
44
43
|
from .sqlite_store import RunStoreCapacityError
|
|
45
44
|
from .sse import event_stream
|
|
46
45
|
from .store import IdempotencyConflictError, ReleaseNotFoundError, RunStore
|
|
47
46
|
from .telemetry import configure_telemetry
|
|
47
|
+
from .vision_requirement import require_vision_readiness
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def create_app(
|
|
@@ -58,6 +58,7 @@ def create_app(
|
|
|
58
58
|
configure_telemetry()
|
|
59
59
|
runtime_report_store = report_store or default_report_store()
|
|
60
60
|
runtime_engine = engine or default_engine(runtime_report_store)
|
|
61
|
+
capacity = engine_capacity(runtime_engine)
|
|
61
62
|
runtime = AgentRunService(
|
|
62
63
|
runtime_engine,
|
|
63
64
|
store or default_store(),
|
|
@@ -73,6 +74,8 @@ def create_app(
|
|
|
73
74
|
if internal_token
|
|
74
75
|
else None
|
|
75
76
|
),
|
|
77
|
+
max_concurrent_runs=capacity.max_concurrent_runs,
|
|
78
|
+
max_queue_depth=capacity.max_queue_depth,
|
|
76
79
|
)
|
|
77
80
|
|
|
78
81
|
@asynccontextmanager
|
|
@@ -92,35 +95,7 @@ def create_app(
|
|
|
92
95
|
create_report_router(runtime_report_store, internal_token)
|
|
93
96
|
)
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
async def live() -> dict[str, str]:
|
|
97
|
-
return {"status": "live"}
|
|
98
|
-
|
|
99
|
-
@application.get("/health/ready", response_model=None)
|
|
100
|
-
async def ready() -> dict[str, object] | JSONResponse:
|
|
101
|
-
health = getattr(runtime_engine, "health", None)
|
|
102
|
-
if not health:
|
|
103
|
-
return safe_error(
|
|
104
|
-
503,
|
|
105
|
-
"RUNTIME_UNAVAILABLE",
|
|
106
|
-
"Agent Runtime 尚未配置",
|
|
107
|
-
True,
|
|
108
|
-
)
|
|
109
|
-
try:
|
|
110
|
-
await runtime.probe()
|
|
111
|
-
await health()
|
|
112
|
-
return {
|
|
113
|
-
"status": "ready",
|
|
114
|
-
"capabilities": list(runtime_engine.capabilities),
|
|
115
|
-
"inputModalities": list(runtime_engine.input_modalities),
|
|
116
|
-
}
|
|
117
|
-
except Exception:
|
|
118
|
-
return safe_error(
|
|
119
|
-
503,
|
|
120
|
-
"PROVIDER_UNAVAILABLE",
|
|
121
|
-
"模型服务暂不可用",
|
|
122
|
-
True,
|
|
123
|
-
)
|
|
98
|
+
install_health_routes(application, runtime, runtime_engine)
|
|
124
99
|
|
|
125
100
|
@application.get("/health/provider-governance", response_model=None)
|
|
126
101
|
async def provider_governance_health(
|
|
@@ -219,6 +194,10 @@ def create_app(
|
|
|
219
194
|
return safe_error(403, "FORBIDDEN", "内部调用认证失败", False)
|
|
220
195
|
if not idempotency_key.strip():
|
|
221
196
|
return safe_error(400, "INVALID_INPUT", "幂等键不能为空", False)
|
|
197
|
+
try:
|
|
198
|
+
await require_vision_readiness(runtime_engine, request)
|
|
199
|
+
except SafeEngineError as error:
|
|
200
|
+
return safe_error(503, error.code, error.safe_message, error.retryable)
|
|
222
201
|
record = await runtime.start(
|
|
223
202
|
request,
|
|
224
203
|
idempotency_key,
|
|
@@ -35,11 +35,20 @@ class OpenAiCompatibleConfig:
|
|
|
35
35
|
connect_timeout_seconds: float = 5.0
|
|
36
36
|
request_timeout_seconds: float = 60.0
|
|
37
37
|
max_response_bytes: int = 2 * 1024 * 1024
|
|
38
|
+
max_duration_seconds: int = 300
|
|
39
|
+
max_input_bytes: int = 67_108_864
|
|
40
|
+
max_artifacts: int = 16
|
|
41
|
+
max_pixels_per_artifact: int = 100_000_000
|
|
38
42
|
max_tool_rounds: int = 8
|
|
39
43
|
https_host_allowlist: tuple[str, ...] = ()
|
|
40
44
|
deployment_key: str = "ai.openai-compatible"
|
|
41
45
|
capabilities: tuple[str, ...] = ("text-generation",)
|
|
42
46
|
input_modalities: tuple[str, ...] = ("text",)
|
|
47
|
+
readiness_deployment_identity: str | None = None
|
|
48
|
+
readiness_release_digest: str | None = None
|
|
49
|
+
readiness_ttl_seconds: int = 60
|
|
50
|
+
max_concurrent_runs: int = 1
|
|
51
|
+
max_queue_depth: int = 0
|
|
43
52
|
|
|
44
53
|
def __post_init__(self) -> None:
|
|
45
54
|
normalized = normalize_base_url(self.base_url)
|
|
@@ -91,6 +100,26 @@ class OpenAiCompatibleConfig:
|
|
|
91
100
|
1_024,
|
|
92
101
|
16 * 1024 * 1024,
|
|
93
102
|
),
|
|
103
|
+
max_duration_seconds=read_integer(
|
|
104
|
+
environment, "AI_PROVIDER_MAX_DURATION_SECONDS", 300, 1, 300
|
|
105
|
+
),
|
|
106
|
+
max_input_bytes=read_integer(
|
|
107
|
+
environment,
|
|
108
|
+
"AI_PROVIDER_MAX_INPUT_BYTES",
|
|
109
|
+
67_108_864,
|
|
110
|
+
1_024,
|
|
111
|
+
67_108_864,
|
|
112
|
+
),
|
|
113
|
+
max_artifacts=read_integer(
|
|
114
|
+
environment, "AI_PROVIDER_MAX_ARTIFACTS", 16, 1, 16
|
|
115
|
+
),
|
|
116
|
+
max_pixels_per_artifact=read_integer(
|
|
117
|
+
environment,
|
|
118
|
+
"AI_PROVIDER_MAX_PIXELS_PER_ARTIFACT",
|
|
119
|
+
100_000_000,
|
|
120
|
+
1,
|
|
121
|
+
100_000_000,
|
|
122
|
+
),
|
|
94
123
|
capabilities=read_csv(
|
|
95
124
|
environment,
|
|
96
125
|
"AI_PROVIDER_CAPABILITIES",
|
|
@@ -101,6 +130,21 @@ class OpenAiCompatibleConfig:
|
|
|
101
130
|
"AI_PROVIDER_INPUT_MODALITIES",
|
|
102
131
|
("text",),
|
|
103
132
|
),
|
|
133
|
+
readiness_deployment_identity=optional_value(
|
|
134
|
+
environment, "AI_PROVIDER_DEPLOYMENT_IDENTITY"
|
|
135
|
+
),
|
|
136
|
+
readiness_release_digest=optional_value(
|
|
137
|
+
environment, "AI_PROVIDER_RELEASE_DIGEST"
|
|
138
|
+
),
|
|
139
|
+
readiness_ttl_seconds=read_integer(
|
|
140
|
+
environment, "AI_PROVIDER_READINESS_TTL_SECONDS", 60, 1, 300
|
|
141
|
+
),
|
|
142
|
+
max_concurrent_runs=read_integer(
|
|
143
|
+
environment, "AI_PROVIDER_MAX_CONCURRENT_RUNS", 1, 1, 1_000
|
|
144
|
+
),
|
|
145
|
+
max_queue_depth=read_integer(
|
|
146
|
+
environment, "AI_PROVIDER_MAX_QUEUE_DEPTH", 0, 0, 10_000
|
|
147
|
+
),
|
|
104
148
|
)
|
|
105
149
|
|
|
106
150
|
|
|
@@ -216,3 +260,8 @@ def read_csv(
|
|
|
216
260
|
if not values or len(values) > 32:
|
|
217
261
|
raise ValueError(f"{key} 无效")
|
|
218
262
|
return values
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def optional_value(environment: Mapping[str, str], key: str) -> str | None:
|
|
266
|
+
value = environment.get(key, "").strip()
|
|
267
|
+
return value or None
|
|
@@ -139,6 +139,18 @@ class RuntimeRelease(CanonicalModel):
|
|
|
139
139
|
manifest_digest: str = Field(pattern=r"^[a-f0-9]{64}$")
|
|
140
140
|
|
|
141
141
|
|
|
142
|
+
class VlmReadinessPin(CanonicalModel):
|
|
143
|
+
key: str = Field(min_length=1, max_length=160)
|
|
144
|
+
identity: str = Field(
|
|
145
|
+
pattern=(
|
|
146
|
+
r"^windy-deployment-v1_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-"
|
|
147
|
+
r"[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
release_digest: str = Field(pattern=r"^sha256:[a-f0-9]{64}$")
|
|
151
|
+
offers_digest: str = Field(pattern=r"^sha256:[a-f0-9]{64}$")
|
|
152
|
+
|
|
153
|
+
|
|
142
154
|
class RunReportingContext(CanonicalModel):
|
|
143
155
|
"""Trusted platform metadata for reporting, never an authorization fact."""
|
|
144
156
|
|
|
@@ -180,6 +192,7 @@ class StartRunRequest(CanonicalModel):
|
|
|
180
192
|
tool_network_policy: ToolNetworkPolicy = Field(default_factory=ToolNetworkPolicy)
|
|
181
193
|
execution_grant: str = ""
|
|
182
194
|
tool_host_url: str = ""
|
|
195
|
+
readiness_pin: VlmReadinessPin | None = None
|
|
183
196
|
release: RuntimeRelease = Field(default_factory=legacy_release)
|
|
184
197
|
trace_id: str = Field(default="", max_length=160)
|
|
185
198
|
reporting: RunReportingContext | None = None
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Protocol, runtime_checkable
|
|
5
|
+
|
|
6
|
+
from .engine import AgentEngineAdapter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class EngineCapacity:
|
|
11
|
+
max_concurrent_runs: int
|
|
12
|
+
max_queue_depth: int
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@runtime_checkable
|
|
16
|
+
class ResourceLimitedEngine(Protocol):
|
|
17
|
+
@property
|
|
18
|
+
def max_concurrent_runs(self) -> int: ...
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def max_queue_depth(self) -> int: ...
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def engine_capacity(engine: AgentEngineAdapter) -> EngineCapacity:
|
|
25
|
+
if not isinstance(engine, ResourceLimitedEngine):
|
|
26
|
+
return EngineCapacity(1, 0)
|
|
27
|
+
concurrent = engine.max_concurrent_runs
|
|
28
|
+
queued = engine.max_queue_depth
|
|
29
|
+
if concurrent < 1 or queued < 0:
|
|
30
|
+
raise ValueError("Agent Engine 容量声明无效")
|
|
31
|
+
return EngineCapacity(concurrent, queued)
|
|
@@ -33,6 +33,11 @@ def request_fingerprint(request: StartRunRequest) -> str:
|
|
|
33
33
|
"outputSchemaKey": request.output_schema_key,
|
|
34
34
|
"outputSchema": request.output_schema,
|
|
35
35
|
"release": resolved_release(request),
|
|
36
|
+
"readinessPin": (
|
|
37
|
+
request.readiness_pin.model_dump(by_alias=True)
|
|
38
|
+
if request.readiness_pin
|
|
39
|
+
else None
|
|
40
|
+
),
|
|
36
41
|
},
|
|
37
42
|
ensure_ascii=False,
|
|
38
43
|
separators=(",", ":"),
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from fastapi import FastAPI
|
|
4
|
+
from fastapi.responses import JSONResponse
|
|
5
|
+
|
|
6
|
+
from .http_helpers import safe_error
|
|
7
|
+
from .service import AgentRunService
|
|
8
|
+
from .vlm_readiness import unavailable_vlm_snapshot
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def install_health_routes(
|
|
12
|
+
application: FastAPI, runtime: AgentRunService, engine: object
|
|
13
|
+
) -> None:
|
|
14
|
+
@application.get("/health/live")
|
|
15
|
+
async def live() -> dict[str, str]:
|
|
16
|
+
return {"status": "live"}
|
|
17
|
+
|
|
18
|
+
@application.get("/health/ready", response_model=None)
|
|
19
|
+
async def ready() -> dict[str, object] | JSONResponse:
|
|
20
|
+
try:
|
|
21
|
+
await runtime.probe()
|
|
22
|
+
return {"status": "ready"}
|
|
23
|
+
except Exception:
|
|
24
|
+
return safe_error(
|
|
25
|
+
503,
|
|
26
|
+
"RUNTIME_UNAVAILABLE",
|
|
27
|
+
"Agent Run 存储暂不可用",
|
|
28
|
+
True,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
@application.get("/health/vlm-ready", response_model=None)
|
|
32
|
+
async def vlm_ready() -> dict[str, object] | JSONResponse:
|
|
33
|
+
readiness = getattr(engine, "readiness", None)
|
|
34
|
+
if not readiness:
|
|
35
|
+
return JSONResponse(
|
|
36
|
+
unavailable_vlm_snapshot(configured=False), status_code=503
|
|
37
|
+
)
|
|
38
|
+
try:
|
|
39
|
+
await runtime.probe()
|
|
40
|
+
snapshot = await readiness()
|
|
41
|
+
status = 200 if snapshot.get("status") == "ready" else 503
|
|
42
|
+
return JSONResponse(snapshot, status_code=status)
|
|
43
|
+
except Exception:
|
|
44
|
+
return JSONResponse(
|
|
45
|
+
unavailable_vlm_snapshot(
|
|
46
|
+
configured=True,
|
|
47
|
+
failure_code="CONNECTION_FAILED",
|
|
48
|
+
),
|
|
49
|
+
status_code=503,
|
|
50
|
+
)
|
|
@@ -49,6 +49,7 @@ from .tool_host import (
|
|
|
49
49
|
ToolInvocation,
|
|
50
50
|
canonical_tool_call_id,
|
|
51
51
|
)
|
|
52
|
+
from .vlm_readiness import VlmReadinessProbe
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
class OpenAiCompatibleEngineAdapter(AgentEngineAdapter):
|
|
@@ -73,6 +74,14 @@ class OpenAiCompatibleEngineAdapter(AgentEngineAdapter):
|
|
|
73
74
|
def input_modalities(self) -> tuple[str, ...]:
|
|
74
75
|
return self._provider.config.input_modalities
|
|
75
76
|
|
|
77
|
+
@property
|
|
78
|
+
def max_concurrent_runs(self) -> int:
|
|
79
|
+
return self._provider.config.max_concurrent_runs
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def max_queue_depth(self) -> int:
|
|
83
|
+
return self._provider.config.max_queue_depth
|
|
84
|
+
|
|
76
85
|
def supports(self, operation_key: str) -> bool:
|
|
77
86
|
return bool(operation_key.strip())
|
|
78
87
|
|
|
@@ -293,8 +302,8 @@ class OpenAiCompatibleEngineAdapter(AgentEngineAdapter):
|
|
|
293
302
|
if event is not None:
|
|
294
303
|
event.set()
|
|
295
304
|
|
|
296
|
-
async def
|
|
297
|
-
await self._provider.
|
|
305
|
+
async def readiness(self) -> dict[str, object]:
|
|
306
|
+
return await VlmReadinessProbe(self._provider.config, self._provider).inspect()
|
|
298
307
|
|
|
299
308
|
def governance_health(self) -> dict[str, int | float | str | None]:
|
|
300
309
|
return self._governance.health()
|
|
@@ -15,6 +15,7 @@ from .contracts import AgentErrorCode, JsonValue, RuntimeToolDefinition
|
|
|
15
15
|
from .engine import SafeEngineError
|
|
16
16
|
from .multimodal import response_format
|
|
17
17
|
from .report_types import UsageFacts
|
|
18
|
+
from .vision_probe import probe_vision
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
@dataclass
|
|
@@ -48,15 +49,8 @@ class OpenAiCompatibleProvider:
|
|
|
48
49
|
self._resolver = resolver
|
|
49
50
|
self._transport = transport
|
|
50
51
|
|
|
51
|
-
async def
|
|
52
|
-
|
|
53
|
-
try:
|
|
54
|
-
response = await client.get("/models")
|
|
55
|
-
await self._bounded_body(response)
|
|
56
|
-
except httpx.HTTPError as error:
|
|
57
|
-
raise provider_failure(error) from None
|
|
58
|
-
if not response.is_success:
|
|
59
|
-
raise provider_status_failure(response.status_code)
|
|
52
|
+
async def probe_vision(self) -> None:
|
|
53
|
+
await probe_vision(self)
|
|
60
54
|
|
|
61
55
|
async def complete_turn(
|
|
62
56
|
self,
|
|
@@ -124,6 +124,11 @@ class PostgresRunStore:
|
|
|
124
124
|
async with self._pool.connection() as connection:
|
|
125
125
|
return await self._backend.read(connection, run_id)
|
|
126
126
|
|
|
127
|
+
async def get_by_idempotency(self, idempotency_key: str) -> RunRecord | None:
|
|
128
|
+
await self._backend.ready()
|
|
129
|
+
async with self._pool.connection() as connection:
|
|
130
|
+
return await self._backend.by_idempotency(connection, idempotency_key)
|
|
131
|
+
|
|
127
132
|
async def append(
|
|
128
133
|
self,
|
|
129
134
|
run_id: str,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Protocol
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ReadinessEngine(Protocol):
|
|
7
|
+
async def readiness(self) -> dict[str, object]: ...
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def readiness_pin_matches(engine: object, expected: dict[str, object]) -> bool:
|
|
11
|
+
readiness = getattr(engine, "readiness", None)
|
|
12
|
+
if not readiness:
|
|
13
|
+
return False
|
|
14
|
+
try:
|
|
15
|
+
snapshot = await readiness()
|
|
16
|
+
except Exception:
|
|
17
|
+
return False
|
|
18
|
+
deployment = snapshot.get("deployment") if isinstance(snapshot, dict) else None
|
|
19
|
+
probe = snapshot.get("downstreamProbe") if isinstance(snapshot, dict) else None
|
|
20
|
+
probe_names = {
|
|
21
|
+
"identity": "deploymentIdentity",
|
|
22
|
+
"releaseDigest": "releaseDigest",
|
|
23
|
+
"offersDigest": "offersDigest",
|
|
24
|
+
}
|
|
25
|
+
return bool(
|
|
26
|
+
isinstance(snapshot, dict)
|
|
27
|
+
and snapshot.get("status") == "ready"
|
|
28
|
+
and isinstance(deployment, dict)
|
|
29
|
+
and isinstance(probe, dict)
|
|
30
|
+
and probe.get("status") == "passed"
|
|
31
|
+
and all(deployment.get(key) == value for key, value in expected.items())
|
|
32
|
+
and all(
|
|
33
|
+
probe.get(probe_names[key]) == value
|
|
34
|
+
for key, value in expected.items()
|
|
35
|
+
if key in probe_names
|
|
36
|
+
)
|
|
37
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
from .contracts import JsonValue
|
|
7
|
+
from .engine import SafeEngineError
|
|
8
|
+
from .run_capacity import (
|
|
9
|
+
RunCapacity,
|
|
10
|
+
RunCapacityReservation,
|
|
11
|
+
RunCapacityUnavailable,
|
|
12
|
+
)
|
|
13
|
+
from .store import IdempotencyConflictError, RunRecord, RunStore
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class RunAdmissionResult:
|
|
18
|
+
record: RunRecord
|
|
19
|
+
reservation: RunCapacityReservation | None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RunAdmission:
|
|
23
|
+
def __init__(self, store: RunStore, capacity: RunCapacity) -> None:
|
|
24
|
+
self._store = store
|
|
25
|
+
self._capacity = capacity
|
|
26
|
+
self._lock = asyncio.Lock()
|
|
27
|
+
|
|
28
|
+
async def admit(
|
|
29
|
+
self,
|
|
30
|
+
candidate: RunRecord,
|
|
31
|
+
invocation: JsonValue,
|
|
32
|
+
) -> RunAdmissionResult:
|
|
33
|
+
async with self._lock:
|
|
34
|
+
current = await self._store.get_by_idempotency(candidate.idempotency_key)
|
|
35
|
+
if current:
|
|
36
|
+
if current.fingerprint != candidate.fingerprint:
|
|
37
|
+
raise IdempotencyConflictError
|
|
38
|
+
return RunAdmissionResult(current, None)
|
|
39
|
+
try:
|
|
40
|
+
reservation = await self._capacity.reserve()
|
|
41
|
+
except RunCapacityUnavailable:
|
|
42
|
+
raise SafeEngineError(
|
|
43
|
+
"RUNTIME_UNAVAILABLE",
|
|
44
|
+
"VLM Runtime 容量已满",
|
|
45
|
+
retryable=True,
|
|
46
|
+
) from None
|
|
47
|
+
try:
|
|
48
|
+
record, created = await self._store.create_or_get(
|
|
49
|
+
candidate,
|
|
50
|
+
invocation,
|
|
51
|
+
)
|
|
52
|
+
except Exception:
|
|
53
|
+
await reservation.release()
|
|
54
|
+
raise
|
|
55
|
+
if not created:
|
|
56
|
+
await reservation.release()
|
|
57
|
+
return RunAdmissionResult(record, None)
|
|
58
|
+
return RunAdmissionResult(record, reservation)
|
|
59
|
+
|
|
60
|
+
async def reserve_recovery(self) -> RunCapacityReservation | None:
|
|
61
|
+
try:
|
|
62
|
+
return await self._capacity.reserve()
|
|
63
|
+
except RunCapacityUnavailable:
|
|
64
|
+
return None
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RunCapacityUnavailable(Exception):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RunCapacity:
|
|
11
|
+
def __init__(self, max_concurrent_runs: int, max_queue_depth: int) -> None:
|
|
12
|
+
if max_concurrent_runs < 1 or max_queue_depth < 0:
|
|
13
|
+
raise ValueError("Agent Run 容量配置无效")
|
|
14
|
+
self._maximum = max_concurrent_runs
|
|
15
|
+
self._queue_maximum = max_queue_depth
|
|
16
|
+
self._active = 0
|
|
17
|
+
self._queued = 0
|
|
18
|
+
self._condition = asyncio.Condition()
|
|
19
|
+
|
|
20
|
+
async def reserve(self) -> RunCapacityReservation:
|
|
21
|
+
async with self._condition:
|
|
22
|
+
if self._active + self._queued >= self._maximum + self._queue_maximum:
|
|
23
|
+
raise RunCapacityUnavailable
|
|
24
|
+
self._queued += 1
|
|
25
|
+
return RunCapacityReservation(self)
|
|
26
|
+
|
|
27
|
+
async def enter(self, reservation: RunCapacityReservation) -> None:
|
|
28
|
+
async with self._condition:
|
|
29
|
+
while self._active >= self._maximum:
|
|
30
|
+
await self._condition.wait()
|
|
31
|
+
if reservation.released or reservation.entered:
|
|
32
|
+
raise RuntimeError("Agent Run 容量票据状态无效")
|
|
33
|
+
self._queued -= 1
|
|
34
|
+
self._active += 1
|
|
35
|
+
reservation.entered = True
|
|
36
|
+
|
|
37
|
+
async def release(self, reservation: RunCapacityReservation) -> None:
|
|
38
|
+
async with self._condition:
|
|
39
|
+
if reservation.released:
|
|
40
|
+
return
|
|
41
|
+
if reservation.entered:
|
|
42
|
+
self._active -= 1
|
|
43
|
+
else:
|
|
44
|
+
self._queued -= 1
|
|
45
|
+
reservation.released = True
|
|
46
|
+
self._condition.notify_all()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class RunCapacityReservation:
|
|
50
|
+
def __init__(self, capacity: RunCapacity) -> None:
|
|
51
|
+
self._capacity = capacity
|
|
52
|
+
self.entered = False
|
|
53
|
+
self.released = False
|
|
54
|
+
|
|
55
|
+
async def enter(self) -> None:
|
|
56
|
+
await self._capacity.enter(self)
|
|
57
|
+
|
|
58
|
+
async def release(self) -> None:
|
|
59
|
+
await self._capacity.release(self)
|