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.
- package/README.md +27 -9
- package/dist/cli.js +825 -117
- package/package.json +1 -1
- package/template/.agents/skills/windy-business-module/SKILL.md +16 -3
- package/template/.windy-template.json +2 -2
- package/template/AGENTS.md +4 -0
- package/template/README.md +18 -11
- package/template/_gitignore +1 -0
- package/template/apps/agent-server/README.md +2 -0
- package/template/apps/agent-server/pyproject.toml +8 -0
- package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +87 -10
- package/template/apps/agent-server/src/southwind_agent_server/adk_model.py +18 -3
- package/template/apps/agent-server/src/southwind_agent_server/adk_tools.py +78 -11
- package/template/apps/agent-server/src/southwind_agent_server/app.py +120 -115
- package/template/apps/agent-server/src/southwind_agent_server/artifact_input.py +153 -0
- package/template/apps/agent-server/src/southwind_agent_server/config.py +29 -0
- package/template/apps/agent-server/src/southwind_agent_server/contracts.py +81 -1
- package/template/apps/agent-server/src/southwind_agent_server/deterministic.py +8 -0
- package/template/apps/agent-server/src/southwind_agent_server/engine.py +28 -0
- package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +41 -0
- package/template/apps/agent-server/src/southwind_agent_server/http_helpers.py +62 -0
- package/template/apps/agent-server/src/southwind_agent_server/lease.py +15 -0
- package/template/apps/agent-server/src/southwind_agent_server/multimodal.py +76 -0
- package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +112 -20
- package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +14 -1
- package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +329 -0
- package/template/apps/agent-server/src/southwind_agent_server/postgres_store_backend.py +332 -0
- package/template/apps/agent-server/src/southwind_agent_server/provider_governance.py +64 -3
- package/template/apps/agent-server/src/southwind_agent_server/runtime_factory.py +68 -0
- package/template/apps/agent-server/src/southwind_agent_server/service.py +218 -56
- package/template/apps/agent-server/src/southwind_agent_server/signal_events.py +36 -0
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +107 -0
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_schema.py +65 -0
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_serialization.py +16 -0
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_store.py +89 -57
- package/template/apps/agent-server/src/southwind_agent_server/store.py +105 -2
- package/template/apps/agent-server/src/southwind_agent_server/store_cipher.py +40 -0
- package/template/apps/agent-server/src/southwind_agent_server/telemetry.py +89 -0
- package/template/apps/agent-server/src/southwind_agent_server/tool_host.py +72 -0
- package/template/apps/agent-server/tests/test_adk_adapter.py +6 -2
- package/template/apps/agent-server/tests/test_api.py +24 -1
- package/template/apps/agent-server/tests/test_artifact_input.py +110 -0
- package/template/apps/agent-server/tests/test_config.py +4 -0
- package/template/apps/agent-server/tests/test_fingerprint.py +10 -0
- package/template/apps/agent-server/tests/test_multimodal.py +51 -0
- package/template/apps/agent-server/tests/test_openai_provider.py +6 -2
- package/template/apps/agent-server/tests/test_postgres_store.py +131 -0
- package/template/apps/agent-server/tests/test_provider_governance.py +61 -0
- package/template/apps/agent-server/tests/test_sqlite_store.py +95 -10
- package/template/apps/agent-server/tests/test_telemetry.py +25 -0
- package/template/apps/agent-server/tests/test_tool_approval.py +28 -0
- package/template/apps/agent-server/uv.lock +165 -0
- package/template/apps/document-server/Dockerfile +19 -0
- package/template/apps/document-server/pyproject.toml +43 -0
- package/template/apps/document-server/src/southwind_document_server/__init__.py +1 -0
- package/template/apps/document-server/src/southwind_document_server/adapter.py +337 -0
- package/template/apps/document-server/src/southwind_document_server/app.py +151 -0
- package/template/apps/document-server/src/southwind_document_server/config.py +94 -0
- package/template/apps/document-server/src/southwind_document_server/contracts.py +103 -0
- package/template/apps/document-server/src/southwind_document_server/service.py +149 -0
- package/template/apps/document-server/src/southwind_document_server/store.py +185 -0
- package/template/apps/document-server/tests/__init__.py +1 -0
- package/template/apps/document-server/tests/test_config.py +42 -0
- package/template/apps/document-server/tests/test_service.py +140 -0
- package/template/apps/document-server/uv.lock +430 -0
- package/template/apps/embedding-server/Dockerfile +17 -0
- package/template/apps/embedding-server/pyproject.toml +44 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/__init__.py +1 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/adapter.py +254 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/app.py +119 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/config.py +120 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/contracts.py +106 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/error.py +6 -0
- package/template/apps/embedding-server/src/southwind_embedding_server/image_input.py +87 -0
- package/template/apps/embedding-server/tests/__init__.py +1 -0
- package/template/apps/embedding-server/tests/test_adapter.py +92 -0
- package/template/apps/embedding-server/tests/test_config.py +38 -0
- package/template/apps/embedding-server/uv.lock +449 -0
- package/template/apps/server/src/agent/background-operation-port.ts +37 -0
- package/template/apps/server/src/agent/background-operation.test.ts +231 -0
- package/template/apps/server/src/agent/background-operation.ts +252 -0
- package/template/apps/server/src/agent/drizzle-run-binding-repository.ts +114 -0
- package/template/apps/server/src/agent/execution-grants.ts +7 -1
- package/template/apps/server/src/agent/fake-runtime.test-support.ts +43 -0
- package/template/apps/server/src/agent/idempotency-key.test.ts +28 -0
- package/template/apps/server/src/agent/idempotency-key.ts +11 -0
- package/template/apps/server/src/agent/remote-runtime.test.ts +115 -1
- package/template/apps/server/src/agent/remote-runtime.ts +173 -5
- package/template/apps/server/src/agent/run-authorization.test-support.ts +9 -0
- package/template/apps/server/src/agent/run-authorization.test.ts +126 -0
- package/template/apps/server/src/agent/run-authorization.ts +180 -0
- package/template/apps/server/src/agent/run-binding-repository.ts +93 -0
- package/template/apps/server/src/agent/run-contracts.ts +88 -1
- package/template/apps/server/src/agent/run-definition-support.ts +58 -0
- package/template/apps/server/src/agent/run-errors.ts +25 -0
- package/template/apps/server/src/agent/run-facade.test.ts +57 -46
- package/template/apps/server/src/agent/run-facade.ts +185 -65
- package/template/apps/server/src/agent/run-release.ts +78 -0
- package/template/apps/server/src/agent/run-route-input.ts +169 -0
- package/template/apps/server/src/agent/run-routes.ts +63 -76
- package/template/apps/server/src/agent/runtime-bootstrap.ts +169 -13
- package/template/apps/server/src/agent/sandbox-client.ts +200 -0
- package/template/apps/server/src/agent/sandbox-protocol.ts +76 -0
- package/template/apps/server/src/agent/sandbox-registry.ts +205 -0
- package/template/apps/server/src/agent/sandbox-runtime.test.ts +137 -0
- package/template/apps/server/src/agent/sandbox-worker-server.ts +195 -0
- package/template/apps/server/src/agent/sandbox-worker.ts +12 -0
- package/template/apps/server/src/agent/tool-approval.test.ts +75 -0
- package/template/apps/server/src/agent/tool-approval.ts +115 -0
- package/template/apps/server/src/agent/tool-audit.ts +62 -0
- package/template/apps/server/src/agent/tool-host.test.ts +39 -11
- package/template/apps/server/src/agent/tool-host.ts +184 -17
- package/template/apps/server/src/agent/tool-registry.ts +52 -47
- package/template/apps/server/src/agent/vision-facade.test.ts +256 -0
- package/template/apps/server/src/agent/vision-input.ts +120 -0
- package/template/apps/server/src/ai-artifact/codec.test.ts +44 -0
- package/template/apps/server/src/ai-artifact/codec.ts +137 -0
- package/template/apps/server/src/ai-artifact/routes.ts +37 -0
- package/template/apps/server/src/ai-artifact/runtime.ts +205 -0
- package/template/apps/server/src/application-services.ts +62 -2
- package/template/apps/server/src/auth/reauthentication.test.ts +40 -0
- package/template/apps/server/src/auth/reauthentication.ts +19 -0
- package/template/apps/server/src/auth/runtime.ts +9 -1
- package/template/apps/server/src/data-access/context.ts +6 -4
- package/template/apps/server/src/data-access/scope-snapshot.ts +27 -0
- package/template/apps/server/src/data-governance/export/approval-port.ts +6 -3
- package/template/apps/server/src/data-governance/export/authorization-port.test.ts +23 -4
- package/template/apps/server/src/data-governance/export/authorization-port.ts +89 -25
- package/template/apps/server/src/data-governance/export/drizzle-repository.integration.test.ts +2 -0
- package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -0
- package/template/apps/server/src/data-governance/export/job-runtime.test.ts +15 -4
- package/template/apps/server/src/data-governance/export/job-runtime.ts +68 -15
- package/template/apps/server/src/data-governance/export/ndjson-stream.ts +25 -6
- package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +4 -2
- package/template/apps/server/src/data-governance/export/renderer-job-runtime.test.ts +235 -0
- package/template/apps/server/src/data-governance/export/renderer-runtime.ts +293 -0
- package/template/apps/server/src/data-governance/export/renderer-selection.test.ts +67 -0
- package/template/apps/server/src/data-governance/export/repository.test.ts +2 -0
- package/template/apps/server/src/data-governance/export/request-fingerprint.test.ts +13 -0
- package/template/apps/server/src/data-governance/export/request-fingerprint.ts +2 -0
- package/template/apps/server/src/data-governance/export/routes.ts +11 -1
- package/template/apps/server/src/data-governance/export/scope-snapshot.ts +6 -18
- package/template/apps/server/src/data-governance/export/service-support.ts +188 -0
- package/template/apps/server/src/data-governance/export/service.ts +90 -113
- package/template/apps/server/src/data-governance/export/source.ts +101 -0
- package/template/apps/server/src/data-governance/export/types.ts +27 -0
- package/template/apps/server/src/document/contracts.ts +76 -0
- package/template/apps/server/src/document/facade.ts +339 -0
- package/template/apps/server/src/document/remote-runtime.test.ts +96 -0
- package/template/apps/server/src/document/remote-runtime.ts +223 -0
- package/template/apps/server/src/document/routes.ts +193 -0
- package/template/apps/server/src/embedding/contracts.ts +83 -0
- package/template/apps/server/src/embedding/error.ts +10 -0
- package/template/apps/server/src/embedding/facade.ts +217 -0
- package/template/apps/server/src/embedding/input.ts +172 -0
- package/template/apps/server/src/embedding/remote-runtime.test.ts +66 -0
- package/template/apps/server/src/embedding/remote-runtime.ts +218 -0
- package/template/apps/server/src/embedding/routes.ts +152 -0
- package/template/apps/server/src/index.ts +40 -43
- package/template/apps/server/src/jobs/artifact-service.test.ts +14 -2
- package/template/apps/server/src/jobs/artifact-service.ts +10 -0
- package/template/apps/server/src/jobs/drizzle-execution-repository.ts +17 -18
- package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +19 -1
- package/template/apps/server/src/jobs/drizzle-mappers.ts +4 -1
- package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +49 -2
- package/template/apps/server/src/jobs/drizzle-repository.ts +1 -0
- package/template/apps/server/src/jobs/execution-repository.ts +17 -0
- package/template/apps/server/src/jobs/execution.test.ts +34 -0
- package/template/apps/server/src/jobs/in-memory-control.ts +135 -0
- package/template/apps/server/src/jobs/in-memory-execution.ts +34 -65
- package/template/apps/server/src/jobs/legacy-service-runtime.ts +5 -2
- package/template/apps/server/src/jobs/repository.ts +3 -0
- package/template/apps/server/src/jobs/worker.ts +80 -41
- package/template/apps/server/src/module-host/ai-operation-port.ts +170 -0
- package/template/apps/server/src/module-host/durable-context.test.ts +312 -0
- package/template/apps/server/src/module-host/durable-context.ts +124 -0
- package/template/apps/server/src/module-host/durable-handler-registration.ts +72 -0
- package/template/apps/server/src/module-host/governed-export-route-support.ts +171 -0
- package/template/apps/server/src/module-host/governed-export-routes.test.ts +327 -0
- package/template/apps/server/src/module-host/governed-export-routes.ts +238 -0
- package/template/apps/server/src/module-host/governed-renderer-registration.test.ts +247 -0
- package/template/apps/server/src/module-host/governed-resource-routes.ts +331 -0
- package/template/apps/server/src/module-host/governed-resources.test.ts +344 -0
- package/template/apps/server/src/module-host/governed-resources.ts +203 -0
- package/template/apps/server/src/module-host/http-runtime.ts +95 -0
- package/template/apps/server/src/module-host/initialize-contracts.ts +14 -0
- package/template/apps/server/src/module-host/initialize.test.ts +49 -1
- package/template/apps/server/src/module-host/initialize.ts +39 -16
- package/template/apps/server/src/module-host/job-port.test.ts +262 -0
- package/template/apps/server/src/module-host/job-port.ts +334 -0
- package/template/apps/server/src/module-host/request-context.test.ts +88 -2
- package/template/apps/server/src/module-host/request-context.ts +56 -22
- package/template/apps/server/src/module-host/route-installer.test.ts +10 -0
- package/template/apps/server/src/module-host/route-installer.ts +36 -1
- package/template/apps/server/src/module-host/sandbox-tool-registration.ts +42 -0
- package/template/apps/server/src/module-host/tool-handlers.ts +67 -31
- package/template/apps/server/src/module-host.ts +1 -0
- package/template/apps/server/src/module-runtime-validation.ts +7 -3
- package/template/apps/server/src/speech/contracts.ts +76 -0
- package/template/apps/server/src/speech/facade.ts +316 -0
- package/template/apps/server/src/speech/remote-runtime.test.ts +88 -0
- package/template/apps/server/src/speech/remote-runtime.ts +227 -0
- package/template/apps/server/src/speech/routes.ts +180 -0
- package/template/apps/server/src/system/actor.ts +39 -0
- package/template/apps/server/src/system/route-helpers.ts +1 -0
- package/template/apps/server/src/workflow/service.ts +2 -1
- package/template/apps/speech-server/Dockerfile +22 -0
- package/template/apps/speech-server/pyproject.toml +43 -0
- package/template/apps/speech-server/src/southwind_speech_server/__init__.py +1 -0
- package/template/apps/speech-server/src/southwind_speech_server/adapter.py +249 -0
- package/template/apps/speech-server/src/southwind_speech_server/app.py +183 -0
- package/template/apps/speech-server/src/southwind_speech_server/config.py +100 -0
- package/template/apps/speech-server/src/southwind_speech_server/contracts.py +103 -0
- package/template/apps/speech-server/src/southwind_speech_server/errors.py +6 -0
- package/template/apps/speech-server/src/southwind_speech_server/normalizer.py +108 -0
- package/template/apps/speech-server/src/southwind_speech_server/output_validation.py +128 -0
- package/template/apps/speech-server/src/southwind_speech_server/service.py +162 -0
- package/template/apps/speech-server/src/southwind_speech_server/store.py +209 -0
- package/template/apps/speech-server/tests/__init__.py +1 -0
- package/template/apps/speech-server/tests/test_config.py +33 -0
- package/template/apps/speech-server/tests/test_service.py +154 -0
- package/template/apps/speech-server/uv.lock +430 -0
- package/template/apps/web/src/app/business-routes.ts +22 -0
- package/template/apps/web/src/components/common/AccessSnapshotBoundary.vue +112 -0
- package/template/apps/web/src/components/common/AccessSnapshotBoundary.webtest.ts +130 -0
- package/template/apps/web/src/components/common/AccessSnapshotNotice.vue +117 -0
- package/template/apps/web/src/components/common/FormDialog.vue +6 -0
- package/template/apps/web/src/components/common/ModalLayout.webtest.ts +13 -0
- package/template/apps/web/src/composables/access-snapshot-change.ts +131 -0
- package/template/apps/web/src/composables/access-snapshot-change.webtest.ts +103 -0
- package/template/apps/web/src/composables/useAccessSnapshot.ts +48 -2
- package/template/apps/web/src/composables/useAccessSnapshot.webtest.ts +54 -0
- package/template/apps/web/src/composables/useAccessSnapshotMonitor.ts +42 -0
- package/template/apps/web/src/layout/AppShell.vue +28 -25
- package/template/apps/web/src/layout/AppShell.webtest.ts +1 -0
- package/template/apps/web/src/router/business-routes.ts +68 -0
- package/template/apps/web/src/router/business-routes.webtest.ts +85 -0
- package/template/apps/web/src/router/index.ts +7 -0
- package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +12 -0
- package/template/apps/web/src/services/access-api.ts +5 -1
- package/template/apps/web/src/services/access-api.webtest.ts +35 -0
- package/template/docker-compose.yml +127 -0
- package/template/docs/architecture/ai-egress.md +12 -9
- package/template/docs/architecture/ai-runtime.md +23 -11
- package/template/docs/architecture/durable-jobs.md +25 -3
- package/template/docs/architecture/foundation-infrastructure.md +163 -0
- package/template/docs/architecture/module-host.md +115 -0
- package/template/docs/architecture/server-module-interface.md +39 -0
- package/template/docs/architecture/web-access-snapshot-resilience.md +60 -0
- package/template/docs/development/business-web-routes.md +66 -0
- package/template/docs/development/custom-login-page.md +3 -3
- package/template/docs/development/module-lifecycle.md +71 -0
- package/template/docs/operations/observability.md +5 -1
- package/template/docs/platform/agent-runtime.md +21 -11
- package/template/docs/platform/agent-tool-sandbox.md +58 -0
- package/template/docs/platform/agent-tools.md +5 -0
- package/template/docs/platform/document-ai-runtime.md +204 -0
- package/template/docs/platform/governed-export-renderers.md +132 -0
- package/template/docs/platform/navigation-registry.md +5 -0
- package/template/docs/platform/organization-membership.md +2 -1
- package/template/docs/platform/speech-ai-runtime.md +156 -0
- package/template/docs/platform/system-crud-api.md +7 -1
- package/template/docs/platform/vision-ai-runtime.md +97 -0
- package/template/docs/platform/web-system-crud.md +6 -0
- package/template/package.json +16 -2
- package/template/packages/ai-client/index.ts +4 -0
- package/template/packages/ai-client/package.json +5 -2
- package/template/packages/ai-client/src/agent/client/artifact.ts +26 -0
- package/template/packages/ai-client/src/agent/client/attach.test.ts +124 -0
- package/template/packages/ai-client/src/agent/client/client.ts +119 -7
- package/template/packages/ai-client/src/agent/client/run.ts +14 -0
- package/template/packages/ai-client/src/agent/client/types.ts +18 -0
- package/template/packages/ai-client/src/agent/client/vision.test.ts +53 -0
- package/template/packages/ai-client/src/agent/contracts/contracts.test.ts +1 -0
- package/template/packages/ai-client/src/agent/contracts/events.ts +33 -0
- package/template/packages/ai-client/src/agent/contracts/runs.ts +71 -0
- package/template/packages/ai-client/src/agent/index.ts +1 -0
- package/template/packages/ai-client/src/artifact-ref.ts +8 -0
- package/template/packages/ai-client/src/document/client.test.ts +114 -0
- package/template/packages/ai-client/src/document/client.ts +134 -0
- package/template/packages/ai-client/src/document/contracts.ts +152 -0
- package/template/packages/ai-client/src/document/error.ts +43 -0
- package/template/packages/ai-client/src/document/index.ts +3 -0
- package/template/packages/ai-client/src/document/run.ts +104 -0
- package/template/packages/ai-client/src/document/validation.ts +115 -0
- package/template/packages/ai-client/src/embedding/client.test.ts +77 -0
- package/template/packages/ai-client/src/embedding/client.ts +96 -0
- package/template/packages/ai-client/src/embedding/contracts.ts +46 -0
- package/template/packages/ai-client/src/embedding/error.ts +61 -0
- package/template/packages/ai-client/src/embedding/index.ts +3 -0
- package/template/packages/ai-client/src/embedding/validation.ts +117 -0
- package/template/packages/ai-client/src/speech/client.test.ts +135 -0
- package/template/packages/ai-client/src/speech/client.ts +104 -0
- package/template/packages/ai-client/src/speech/contracts.ts +129 -0
- package/template/packages/ai-client/src/speech/error.ts +43 -0
- package/template/packages/ai-client/src/speech/index.ts +3 -0
- package/template/packages/ai-client/src/speech/run.ts +133 -0
- package/template/packages/ai-client/src/speech/validation.ts +132 -0
- package/template/packages/config/package.json +2 -2
- package/template/packages/database/drizzle/0039_early_ezekiel_stane.sql +1 -0
- package/template/packages/database/drizzle/0040_colossal_baron_strucker.sql +63 -0
- package/template/packages/database/drizzle/0041_yummy_prowler.sql +21 -0
- package/template/packages/database/drizzle/0042_puzzling_rumiko_fujikawa.sql +27 -0
- package/template/packages/database/drizzle/meta/0039_snapshot.json +7755 -0
- package/template/packages/database/drizzle/meta/0040_snapshot.json +8150 -0
- package/template/packages/database/drizzle/meta/0041_snapshot.json +8323 -0
- package/template/packages/database/drizzle/meta/0042_snapshot.json +8541 -0
- package/template/packages/database/drizzle/meta/_journal.json +28 -0
- package/template/packages/database/package.json +2 -2
- package/template/packages/database/src/agent-runtime-schema.test.ts +54 -0
- package/template/packages/database/src/schema/agent-runtime.ts +149 -0
- package/template/packages/database/src/schema/common.ts +2 -14
- package/template/packages/database/src/schema/durable-jobs.ts +5 -0
- package/template/packages/database/src/schema/governed-exports.ts +17 -5
- package/template/packages/database/src/schema/index.ts +3 -0
- package/template/packages/database/src/schema-durable-recovery.test.ts +31 -0
- package/template/packages/database/src/schema-governed-exports.test.ts +21 -1
- package/template/packages/database/src/schema.test.ts +6 -23
- package/template/packages/jobs/package.json +3 -2
- package/template/packages/jobs/src/handlers.test.ts +13 -0
- package/template/packages/jobs/src/handlers.ts +7 -1
- package/template/packages/jobs/src/types.ts +4 -0
- package/template/packages/modules/package.json +2 -2
- package/template/packages/modules/src/ai-operation-composition.test-support.ts +165 -0
- package/template/packages/modules/src/ai-operation-composition.test.ts +91 -127
- package/template/packages/modules/src/ai-operation-composition.ts +59 -1
- package/template/packages/modules/src/manifest.ts +25 -1
- package/template/packages/modules/src/tool-composition.ts +18 -0
- package/template/packages/server-sdk/index.ts +50 -0
- package/template/packages/server-sdk/package.json +10 -4
- package/template/packages/server-sdk/src/ai-artifact-port.ts +34 -0
- package/template/packages/server-sdk/src/ai-operation-port.ts +65 -0
- package/template/packages/server-sdk/src/ai-operation-registration.ts +42 -1
- package/template/packages/server-sdk/src/background-ai-port.ts +43 -0
- package/template/packages/server-sdk/src/data-governance-registration.ts +116 -0
- package/template/packages/server-sdk/src/durable-handler.ts +29 -0
- package/template/packages/server-sdk/src/jobs-port.ts +69 -0
- package/template/packages/server-sdk/src/module-host.ts +16 -2
- package/template/packages/server-sdk/src/request-context.ts +6 -2
- package/template/packages/server-sdk/src/sandbox-tool.ts +21 -0
- package/template/packages/server-sdk/src/tool-registration.ts +2 -0
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/rbac.ts +30 -0
|
@@ -1,33 +1,38 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import cast
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
7
8
|
|
|
9
|
+
from southwind_agent_server.contracts import JsonValue
|
|
8
10
|
from southwind_agent_server.sqlite_store import (
|
|
9
11
|
RunStoreCapacityError,
|
|
10
12
|
SqliteRunStore,
|
|
11
13
|
)
|
|
12
|
-
from southwind_agent_server.store import RunRecord
|
|
14
|
+
from southwind_agent_server.store import IdempotencyConflictError, RunRecord
|
|
15
|
+
from southwind_agent_server.store_cipher import RunStoreCipher
|
|
16
|
+
|
|
17
|
+
TEST_CIPHER = RunStoreCipher("test-secret-" * 4)
|
|
13
18
|
|
|
14
19
|
|
|
15
20
|
async def test_terminal_run_and_cursor_survive_store_rebuild(
|
|
16
21
|
tmp_path: Path,
|
|
17
22
|
) -> None:
|
|
18
23
|
path = str(tmp_path / "runs.sqlite3")
|
|
19
|
-
first = SqliteRunStore(path)
|
|
24
|
+
first = SqliteRunStore(path, TEST_CIPHER)
|
|
20
25
|
record = fixture("run_1", "key_1")
|
|
21
26
|
await first.create_or_get(record)
|
|
22
27
|
await first.append("run_1", "run.started")
|
|
23
28
|
await first.append("run_1", "output.delta", {"text": "你好"})
|
|
24
29
|
await first.complete("run_1", {"text": "你好"})
|
|
25
|
-
first.close()
|
|
30
|
+
await first.close()
|
|
26
31
|
|
|
27
|
-
restored = SqliteRunStore(path)
|
|
32
|
+
restored = SqliteRunStore(path, TEST_CIPHER)
|
|
28
33
|
current = await restored.get("run_1")
|
|
29
34
|
events, terminal = await restored.events_after("run_1", 1, 0.01)
|
|
30
|
-
restored.close()
|
|
35
|
+
await restored.close()
|
|
31
36
|
|
|
32
37
|
assert current is not None
|
|
33
38
|
assert current.status == "completed"
|
|
@@ -40,14 +45,14 @@ async def test_incomplete_run_recovers_as_one_safe_terminal(
|
|
|
40
45
|
tmp_path: Path,
|
|
41
46
|
) -> None:
|
|
42
47
|
path = str(tmp_path / "runs.sqlite3")
|
|
43
|
-
first = SqliteRunStore(path)
|
|
48
|
+
first = SqliteRunStore(path, TEST_CIPHER)
|
|
44
49
|
await first.create_or_get(fixture("run_2", "key_2"))
|
|
45
50
|
await first.append("run_2", "run.started")
|
|
46
|
-
first.close()
|
|
51
|
+
await first.close()
|
|
47
52
|
|
|
48
|
-
restored = SqliteRunStore(path)
|
|
53
|
+
restored = SqliteRunStore(path, TEST_CIPHER)
|
|
49
54
|
current = await restored.get("run_2")
|
|
50
|
-
restored.close()
|
|
55
|
+
await restored.close()
|
|
51
56
|
|
|
52
57
|
assert current is not None
|
|
53
58
|
assert current.status == "failed"
|
|
@@ -61,9 +66,38 @@ async def test_incomplete_run_recovers_as_one_safe_terminal(
|
|
|
61
66
|
assert "secret" not in str(current.events)
|
|
62
67
|
|
|
63
68
|
|
|
69
|
+
async def test_encrypted_waiting_run_is_recoverable(tmp_path: Path) -> None:
|
|
70
|
+
path = str(tmp_path / "recoverable.sqlite3")
|
|
71
|
+
first = SqliteRunStore(path, TEST_CIPHER)
|
|
72
|
+
await first.create_or_get(
|
|
73
|
+
fixture("run_wait", "key_wait"),
|
|
74
|
+
{
|
|
75
|
+
"kind": "agent",
|
|
76
|
+
"operationKey": "test.echo",
|
|
77
|
+
"input": {"text": "secret"},
|
|
78
|
+
},
|
|
79
|
+
)
|
|
80
|
+
await first.append("run_wait", "approval.required")
|
|
81
|
+
await first.close()
|
|
82
|
+
|
|
83
|
+
database_bytes = await asyncio.to_thread(Path(path).read_bytes)
|
|
84
|
+
assert "secret" not in database_bytes.decode(errors="ignore")
|
|
85
|
+
restored = SqliteRunStore(path, TEST_CIPHER)
|
|
86
|
+
recovered = await restored.recoverable()
|
|
87
|
+
await restored.close()
|
|
88
|
+
|
|
89
|
+
assert recovered[0][0].status == "awaiting-approval"
|
|
90
|
+
assert recovered[0][1] == {
|
|
91
|
+
"kind": "agent",
|
|
92
|
+
"operationKey": "test.echo",
|
|
93
|
+
"input": {"text": "secret"},
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
64
97
|
async def test_event_and_run_capacity_are_bounded(tmp_path: Path) -> None:
|
|
65
98
|
store = SqliteRunStore(
|
|
66
99
|
str(tmp_path / "bounded.sqlite3"),
|
|
100
|
+
TEST_CIPHER,
|
|
67
101
|
max_runs=1,
|
|
68
102
|
max_events_per_run=3,
|
|
69
103
|
)
|
|
@@ -80,7 +114,48 @@ async def test_event_and_run_capacity_are_bounded(tmp_path: Path) -> None:
|
|
|
80
114
|
|
|
81
115
|
with pytest.raises(RunStoreCapacityError):
|
|
82
116
|
await store.create_or_get(fixture("run_4", "key_4"))
|
|
83
|
-
store.close()
|
|
117
|
+
await store.close()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async def test_release_evaluation_and_trace_are_immutable(tmp_path: Path) -> None:
|
|
121
|
+
store = SqliteRunStore(str(tmp_path / "release.sqlite3"), TEST_CIPHER)
|
|
122
|
+
original = fixture("run_release", "key_release")
|
|
123
|
+
await store.create_or_get(original)
|
|
124
|
+
first = await store.record_evaluation(
|
|
125
|
+
"release_test",
|
|
126
|
+
"quality",
|
|
127
|
+
"1",
|
|
128
|
+
{"accuracy": 0.9},
|
|
129
|
+
)
|
|
130
|
+
repeated = await store.record_evaluation(
|
|
131
|
+
"release_test",
|
|
132
|
+
"quality",
|
|
133
|
+
"1",
|
|
134
|
+
{"accuracy": 0.9},
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
conflicting = fixture("run_conflict", "key_conflict")
|
|
138
|
+
conflicting.release = {
|
|
139
|
+
**cast(dict[str, JsonValue], conflicting.release),
|
|
140
|
+
"promptVersion": "changed",
|
|
141
|
+
}
|
|
142
|
+
with pytest.raises(IdempotencyConflictError):
|
|
143
|
+
await store.create_or_get(conflicting)
|
|
144
|
+
with pytest.raises(IdempotencyConflictError):
|
|
145
|
+
await store.record_evaluation(
|
|
146
|
+
"release_test",
|
|
147
|
+
"quality",
|
|
148
|
+
"1",
|
|
149
|
+
{"accuracy": 0.8},
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
restored = await store.get("run_release")
|
|
153
|
+
assert first == repeated
|
|
154
|
+
assert restored is not None
|
|
155
|
+
assert restored.release == original.release
|
|
156
|
+
assert restored.trace_id == original.trace_id
|
|
157
|
+
assert await store.get("run_conflict") is None
|
|
158
|
+
await store.close()
|
|
84
159
|
|
|
85
160
|
|
|
86
161
|
def fixture(run_id: str, idempotency_key: str) -> RunRecord:
|
|
@@ -90,4 +165,14 @@ def fixture(run_id: str, idempotency_key: str) -> RunRecord:
|
|
|
90
165
|
input={"text": "hello"},
|
|
91
166
|
idempotency_key=idempotency_key,
|
|
92
167
|
fingerprint=f"fingerprint-{run_id}",
|
|
168
|
+
release={
|
|
169
|
+
"releaseId": "release_test",
|
|
170
|
+
"operationVersion": "1.0.0",
|
|
171
|
+
"workflowVersion": "workflow-1",
|
|
172
|
+
"promptVersion": "prompt-1",
|
|
173
|
+
"routeVersion": "route-1",
|
|
174
|
+
"toolSchemaVersion": "schema-1",
|
|
175
|
+
"manifestDigest": "0" * 64,
|
|
176
|
+
},
|
|
177
|
+
trace_id="1" * 32,
|
|
93
178
|
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from opentelemetry import trace
|
|
4
|
+
|
|
5
|
+
from southwind_agent_server.store import RunRecord
|
|
6
|
+
from southwind_agent_server.telemetry import AgentRunTrace
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_agent_run_trace_uses_redacted_parent_and_metadata_only() -> None:
|
|
10
|
+
record = RunRecord(
|
|
11
|
+
run_id="run_trace",
|
|
12
|
+
operation_key="business.answer",
|
|
13
|
+
input={"secret": "never-export"},
|
|
14
|
+
idempotency_key="key_trace",
|
|
15
|
+
fingerprint="0" * 64,
|
|
16
|
+
release={"releaseId": "release_trace"},
|
|
17
|
+
trace_id="1" * 32,
|
|
18
|
+
)
|
|
19
|
+
run_trace = AgentRunTrace(record)
|
|
20
|
+
run_trace.start()
|
|
21
|
+
current = trace.get_current_span().get_span_context()
|
|
22
|
+
run_trace.finish("completed")
|
|
23
|
+
|
|
24
|
+
assert f"{current.trace_id:032x}" == record.trace_id
|
|
25
|
+
assert current.is_valid
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from southwind_agent_server.tool_host import (
|
|
2
|
+
ToolApprovalPending,
|
|
3
|
+
approval_pending,
|
|
4
|
+
canonical_tool_call_id,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_tool_call_id_is_stable_across_provider_attempts() -> None:
|
|
9
|
+
first = canonical_tool_call_id(
|
|
10
|
+
"run-1",
|
|
11
|
+
"case.finding.merge",
|
|
12
|
+
{"expectedVersion": 3, "ids": ["a", "b"]},
|
|
13
|
+
)
|
|
14
|
+
second = canonical_tool_call_id(
|
|
15
|
+
"run-1",
|
|
16
|
+
"case.finding.merge",
|
|
17
|
+
{"ids": ["a", "b"], "expectedVersion": 3},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
assert first == second
|
|
21
|
+
assert first.startswith("tool_")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_parses_only_typed_approval_pending_response() -> None:
|
|
25
|
+
error = approval_pending(b'{"code":"APPROVAL_REQUIRED","workItemId":"work-1"}')
|
|
26
|
+
|
|
27
|
+
assert isinstance(error, ToolApprovalPending)
|
|
28
|
+
assert error.work_item_id == "work-1"
|
|
@@ -303,6 +303,18 @@ wheels = [
|
|
|
303
303
|
{ url = "https://files.pythonhosted.org/packages/ba/86/5ac5fb53e44cca4a6607fb917eb331fa237c65a103b9ec2e8e8acc8a42db/google_genai-2.14.0-py3-none-any.whl", hash = "sha256:ae7172cdd35695189b516b33a878e4132e5daa2dbc03a5b44cddfa8a82fad664", size = 1030738, upload-time = "2026-07-22T21:35:42.785Z" },
|
|
304
304
|
]
|
|
305
305
|
|
|
306
|
+
[[package]]
|
|
307
|
+
name = "googleapis-common-protos"
|
|
308
|
+
version = "1.75.0"
|
|
309
|
+
source = { registry = "https://pypi.org/simple" }
|
|
310
|
+
dependencies = [
|
|
311
|
+
{ name = "protobuf" },
|
|
312
|
+
]
|
|
313
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b5/c8/f439cffde755cffa462bfbb156278fa6f9d09119719af9814b858fd4f81f/googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd", size = 151035, upload-time = "2026-05-07T08:04:49.423Z" }
|
|
314
|
+
wheels = [
|
|
315
|
+
{ url = "https://files.pythonhosted.org/packages/e7/c8/e2645aa8ed02fd4c7a2f59d68783b65b1f3cbdfe39a6308e156509d1fee8/googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed", size = 300631, upload-time = "2026-05-07T08:03:30.345Z" },
|
|
316
|
+
]
|
|
317
|
+
|
|
306
318
|
[[package]]
|
|
307
319
|
name = "graphviz"
|
|
308
320
|
version = "0.21"
|
|
@@ -471,6 +483,48 @@ wheels = [
|
|
|
471
483
|
{ url = "https://files.pythonhosted.org/packages/a3/ca/9520cc1f3dfbbd03ac5903bbf55833e257bc64b1cf30fa8b0d6df374d821/opentelemetry_api-1.42.1-py3-none-any.whl", hash = "sha256:51a69edacadbc03a8950ace1c4c21099cacc538820ac2c9e36277e78cebba714", size = 61311, upload-time = "2026-05-21T16:32:28.822Z" },
|
|
472
484
|
]
|
|
473
485
|
|
|
486
|
+
[[package]]
|
|
487
|
+
name = "opentelemetry-exporter-otlp-proto-common"
|
|
488
|
+
version = "1.42.1"
|
|
489
|
+
source = { registry = "https://pypi.org/simple" }
|
|
490
|
+
dependencies = [
|
|
491
|
+
{ name = "opentelemetry-proto" },
|
|
492
|
+
]
|
|
493
|
+
sdist = { url = "https://files.pythonhosted.org/packages/0e/9c/216acfeaedadf2e1937f4373929b20f73197c5c4a2546d4f584b7fa63813/opentelemetry_exporter_otlp_proto_common-1.42.1.tar.gz", hash = "sha256:04f1f01fb597c4249dfcd7f8b861c902c2102369d376d9d346ff38de4469a2ee", size = 21433, upload-time = "2026-05-21T16:32:55.526Z" }
|
|
494
|
+
wheels = [
|
|
495
|
+
{ url = "https://files.pythonhosted.org/packages/d6/43/2375e7612e1121a4518c17603b6e0b03ad94f565aafad53f464dc5be2bf6/opentelemetry_exporter_otlp_proto_common-1.42.1-py3-none-any.whl", hash = "sha256:f48d395ab815b444da118868977e9798ea354c25737d5cf39578ae894011c140", size = 17327, upload-time = "2026-05-21T16:32:33.387Z" },
|
|
496
|
+
]
|
|
497
|
+
|
|
498
|
+
[[package]]
|
|
499
|
+
name = "opentelemetry-exporter-otlp-proto-http"
|
|
500
|
+
version = "1.42.1"
|
|
501
|
+
source = { registry = "https://pypi.org/simple" }
|
|
502
|
+
dependencies = [
|
|
503
|
+
{ name = "googleapis-common-protos" },
|
|
504
|
+
{ name = "opentelemetry-api" },
|
|
505
|
+
{ name = "opentelemetry-exporter-otlp-proto-common" },
|
|
506
|
+
{ name = "opentelemetry-proto" },
|
|
507
|
+
{ name = "opentelemetry-sdk" },
|
|
508
|
+
{ name = "requests" },
|
|
509
|
+
{ name = "typing-extensions" },
|
|
510
|
+
]
|
|
511
|
+
sdist = { url = "https://files.pythonhosted.org/packages/77/32/826bfa1d80ecea24f47808de03cd4a0d13c17ecc07712f45123f0f61e4ac/opentelemetry_exporter_otlp_proto_http-1.42.1.tar.gz", hash = "sha256:bf142a21035d7571ac3a09cb2e5639f49886f243972883cfe777ed3bf02b734d", size = 25406, upload-time = "2026-05-21T16:32:56.807Z" }
|
|
512
|
+
wheels = [
|
|
513
|
+
{ url = "https://files.pythonhosted.org/packages/d3/96/82cb223a1502f0787d4bbff12907f5f8d870a50731febcd5818d93ef9555/opentelemetry_exporter_otlp_proto_http-1.42.1-py3-none-any.whl", hash = "sha256:00a16da1b312a1d6c7233d600d557c91df71125af73020f3b9a7765bd699d59d", size = 21793, upload-time = "2026-05-21T16:32:35.277Z" },
|
|
514
|
+
]
|
|
515
|
+
|
|
516
|
+
[[package]]
|
|
517
|
+
name = "opentelemetry-proto"
|
|
518
|
+
version = "1.42.1"
|
|
519
|
+
source = { registry = "https://pypi.org/simple" }
|
|
520
|
+
dependencies = [
|
|
521
|
+
{ name = "protobuf" },
|
|
522
|
+
]
|
|
523
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b4/55/63eac3e1089b768ba014091fdd2ae8a9a440c821ef5e2b786909c94c8836/opentelemetry_proto-1.42.1.tar.gz", hash = "sha256:c6a51e6b4f05ae63565f3a113217f3d2bfaec68f78c02d7a6c85f9010d1cfca6", size = 45839, upload-time = "2026-05-21T16:33:03.937Z" }
|
|
524
|
+
wheels = [
|
|
525
|
+
{ url = "https://files.pythonhosted.org/packages/41/9d/171c02c84a76940b7e601805b3bb536985aded9168fbcc9ba52f0a730fa2/opentelemetry_proto-1.42.1-py3-none-any.whl", hash = "sha256:dedb74cba2886c59c7789b227a7a670613025a07489040050aedff6e5c0fb43c", size = 71782, upload-time = "2026-05-21T16:32:44.867Z" },
|
|
526
|
+
]
|
|
527
|
+
|
|
474
528
|
[[package]]
|
|
475
529
|
name = "opentelemetry-sdk"
|
|
476
530
|
version = "1.42.1"
|
|
@@ -516,6 +570,23 @@ wheels = [
|
|
|
516
570
|
{ url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" },
|
|
517
571
|
]
|
|
518
572
|
|
|
573
|
+
[[package]]
|
|
574
|
+
name = "pillow"
|
|
575
|
+
version = "12.3.0"
|
|
576
|
+
source = { registry = "https://pypi.org/simple" }
|
|
577
|
+
sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" }
|
|
578
|
+
wheels = [
|
|
579
|
+
{ url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" },
|
|
580
|
+
{ url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" },
|
|
581
|
+
{ url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" },
|
|
582
|
+
{ url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" },
|
|
583
|
+
{ url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" },
|
|
584
|
+
{ url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" },
|
|
585
|
+
{ url = "https://files.pythonhosted.org/packages/20/20/25e0f4dc178a6bc0696793720055519a0de89e7661dae886992decbd2f81/pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f", size = 6472684, upload-time = "2026-07-01T11:54:19.839Z" },
|
|
586
|
+
{ url = "https://files.pythonhosted.org/packages/45/89/da2f7971a317f83d807fdd4065c0af40208e59e692cc43d315a71a0e96d1/pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09", size = 7227137, upload-time = "2026-07-01T11:54:22.025Z" },
|
|
587
|
+
{ url = "https://files.pythonhosted.org/packages/de/47/4845a0a6c0dbf1db8456bd9fc791f13c5ced7ced20606d08a0aacfd25b49/pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510", size = 2568267, upload-time = "2026-07-01T11:54:24.051Z" },
|
|
588
|
+
]
|
|
589
|
+
|
|
519
590
|
[[package]]
|
|
520
591
|
name = "pluggy"
|
|
521
592
|
version = "1.6.0"
|
|
@@ -525,6 +596,72 @@ wheels = [
|
|
|
525
596
|
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
526
597
|
]
|
|
527
598
|
|
|
599
|
+
[[package]]
|
|
600
|
+
name = "protobuf"
|
|
601
|
+
version = "6.33.6"
|
|
602
|
+
source = { registry = "https://pypi.org/simple" }
|
|
603
|
+
sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" }
|
|
604
|
+
wheels = [
|
|
605
|
+
{ url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" },
|
|
606
|
+
{ url = "https://files.pythonhosted.org/packages/76/5d/683efcd4798e0030c1bab27374fd13a89f7c2515fb1f3123efdfaa5eab57/protobuf-6.33.6-cp310-abi3-win_amd64.whl", hash = "sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326", size = 437089, upload-time = "2026-03-18T19:04:50.381Z" },
|
|
607
|
+
{ url = "https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a", size = 427737, upload-time = "2026-03-18T19:04:51.866Z" },
|
|
608
|
+
{ url = "https://files.pythonhosted.org/packages/ee/90/b3c01fdec7d2f627b3a6884243ba328c1217ed2d978def5c12dc50d328a3/protobuf-6.33.6-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2", size = 324610, upload-time = "2026-03-18T19:04:53.096Z" },
|
|
609
|
+
{ url = "https://files.pythonhosted.org/packages/9b/ca/25afc144934014700c52e05103c2421997482d561f3101ff352e1292fb81/protobuf-6.33.6-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3", size = 339381, upload-time = "2026-03-18T19:04:54.616Z" },
|
|
610
|
+
{ url = "https://files.pythonhosted.org/packages/16/92/d1e32e3e0d894fe00b15ce28ad4944ab692713f2e7f0a99787405e43533a/protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593", size = 323436, upload-time = "2026-03-18T19:04:55.768Z" },
|
|
611
|
+
{ url = "https://files.pythonhosted.org/packages/c4/72/02445137af02769918a93807b2b7890047c32bfb9f90371cbc12688819eb/protobuf-6.33.6-py3-none-any.whl", hash = "sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901", size = 170656, upload-time = "2026-03-18T19:04:59.826Z" },
|
|
612
|
+
]
|
|
613
|
+
|
|
614
|
+
[[package]]
|
|
615
|
+
name = "psycopg"
|
|
616
|
+
version = "3.3.4"
|
|
617
|
+
source = { registry = "https://pypi.org/simple" }
|
|
618
|
+
dependencies = [
|
|
619
|
+
{ name = "typing-extensions" },
|
|
620
|
+
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
|
621
|
+
]
|
|
622
|
+
sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" }
|
|
623
|
+
wheels = [
|
|
624
|
+
{ url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" },
|
|
625
|
+
]
|
|
626
|
+
|
|
627
|
+
[package.optional-dependencies]
|
|
628
|
+
binary = [
|
|
629
|
+
{ name = "psycopg-binary", marker = "implementation_name != 'pypy'" },
|
|
630
|
+
]
|
|
631
|
+
pool = [
|
|
632
|
+
{ name = "psycopg-pool" },
|
|
633
|
+
]
|
|
634
|
+
|
|
635
|
+
[[package]]
|
|
636
|
+
name = "psycopg-binary"
|
|
637
|
+
version = "3.3.4"
|
|
638
|
+
source = { registry = "https://pypi.org/simple" }
|
|
639
|
+
wheels = [
|
|
640
|
+
{ url = "https://files.pythonhosted.org/packages/95/7d/03818e13ba7f36de93573c93ee3482006d3dfa8b0f8d28df511bad0a1a92/psycopg_binary-3.3.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089", size = 4591122, upload-time = "2026-05-01T23:27:56.162Z" },
|
|
641
|
+
{ url = "https://files.pythonhosted.org/packages/a5/b9/11b341edf8d54e2694726b273fe9652b254d989f4f63e3ac6816ad6b55f4/psycopg_binary-3.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578", size = 4669943, upload-time = "2026-05-01T23:28:04.522Z" },
|
|
642
|
+
{ url = "https://files.pythonhosted.org/packages/8b/18/4665bacd65e7865b4372fcd8abb8b9186ada4b0025f8c2ca691b364a556c/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9", size = 5469697, upload-time = "2026-05-01T23:28:11.337Z" },
|
|
643
|
+
{ url = "https://files.pythonhosted.org/packages/7c/b1/b83136c6e510593d9b0c759ba5384337bc4ad82d19fda675adc4b2703c84/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d", size = 5152995, upload-time = "2026-05-01T23:28:20.529Z" },
|
|
644
|
+
{ url = "https://files.pythonhosted.org/packages/67/8d/a9821e2a648afe6091989929982a3b0f00b2631a859cb81379728f08fb75/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b", size = 6738180, upload-time = "2026-05-01T23:28:30.654Z" },
|
|
645
|
+
{ url = "https://files.pythonhosted.org/packages/7e/58/2e349e8d23905dc2317b80ac65f48fb6f821a4777a4e994a60da91c4850f/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070", size = 4978828, upload-time = "2026-05-01T23:28:37.277Z" },
|
|
646
|
+
{ url = "https://files.pythonhosted.org/packages/45/48/57b00d03b4721878326122a1f1e6b0a90b85bcaec56b5b2f8ea6cfa45235/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68", size = 4509757, upload-time = "2026-05-01T23:28:43.078Z" },
|
|
647
|
+
{ url = "https://files.pythonhosted.org/packages/25/37/33b47d8c007df69aec500df5889767c4d313748e8e9e27a2fef8a6dabcee/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16", size = 4190546, upload-time = "2026-05-01T23:28:50.016Z" },
|
|
648
|
+
{ url = "https://files.pythonhosted.org/packages/ca/c6/32b0835dbc2122617902b649d76a91c1e75406e76bf3d595b0c3bb5ffad6/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652", size = 3926197, upload-time = "2026-05-01T23:28:55.55Z" },
|
|
649
|
+
{ url = "https://files.pythonhosted.org/packages/cd/68/d190ef0c0c5b16ded07831dabc8ddd412f4cdab07ec6e30ed38d9bda0e1f/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e", size = 4236627, upload-time = "2026-05-01T23:29:05.336Z" },
|
|
650
|
+
{ url = "https://files.pythonhosted.org/packages/25/8f/81dcbc2e8454b74d14881275ea45f00791052dac531a9fa8be1730d1685b/psycopg_binary-3.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4", size = 3560782, upload-time = "2026-05-01T23:29:11.967Z" },
|
|
651
|
+
]
|
|
652
|
+
|
|
653
|
+
[[package]]
|
|
654
|
+
name = "psycopg-pool"
|
|
655
|
+
version = "3.3.1"
|
|
656
|
+
source = { registry = "https://pypi.org/simple" }
|
|
657
|
+
dependencies = [
|
|
658
|
+
{ name = "typing-extensions" },
|
|
659
|
+
]
|
|
660
|
+
sdist = { url = "https://files.pythonhosted.org/packages/90/82/7a23d26039827ecd4ebe93905651029ddd307c5182ad59296dfb6f67b528/psycopg_pool-3.3.1.tar.gz", hash = "sha256:b10b10b7a175d5cc1592147dc5b7eec8a9e0834eb3ed2c4a92c858e2f51eb63c", size = 31661, upload-time = "2026-05-01T23:31:59.809Z" }
|
|
661
|
+
wheels = [
|
|
662
|
+
{ url = "https://files.pythonhosted.org/packages/37/ed/89c2c620af0e1660354cd8aabf9f5b21f911597ce22acb37c805d6c86bc8/psycopg_pool-3.3.1-py3-none-any.whl", hash = "sha256:2af5b432941c4c9ad5c87b3fa410aec910ec8f7c122855897983a06c45f2e4b5", size = 40023, upload-time = "2026-05-01T23:31:53.136Z" },
|
|
663
|
+
]
|
|
664
|
+
|
|
528
665
|
[[package]]
|
|
529
666
|
name = "pyasn1"
|
|
530
667
|
version = "0.6.4"
|
|
@@ -765,9 +902,16 @@ name = "southwind-agent-server"
|
|
|
765
902
|
version = "0.1.0"
|
|
766
903
|
source = { editable = "." }
|
|
767
904
|
dependencies = [
|
|
905
|
+
{ name = "cryptography" },
|
|
768
906
|
{ name = "fastapi" },
|
|
769
907
|
{ name = "google-adk" },
|
|
770
908
|
{ name = "httpx" },
|
|
909
|
+
{ name = "jsonschema" },
|
|
910
|
+
{ name = "opentelemetry-api" },
|
|
911
|
+
{ name = "opentelemetry-exporter-otlp-proto-http" },
|
|
912
|
+
{ name = "opentelemetry-sdk" },
|
|
913
|
+
{ name = "pillow" },
|
|
914
|
+
{ name = "psycopg", extra = ["binary", "pool"] },
|
|
771
915
|
{ name = "pydantic" },
|
|
772
916
|
{ name = "uvicorn" },
|
|
773
917
|
]
|
|
@@ -778,13 +922,21 @@ dev = [
|
|
|
778
922
|
{ name = "pytest" },
|
|
779
923
|
{ name = "pytest-asyncio" },
|
|
780
924
|
{ name = "ruff" },
|
|
925
|
+
{ name = "types-jsonschema" },
|
|
781
926
|
]
|
|
782
927
|
|
|
783
928
|
[package.metadata]
|
|
784
929
|
requires-dist = [
|
|
930
|
+
{ name = "cryptography", specifier = "==49.0.0" },
|
|
785
931
|
{ name = "fastapi", specifier = "==0.139.2" },
|
|
786
932
|
{ name = "google-adk", specifier = "==2.5.0" },
|
|
787
933
|
{ name = "httpx", specifier = "==0.28.1" },
|
|
934
|
+
{ name = "jsonschema", specifier = "==4.26.0" },
|
|
935
|
+
{ name = "opentelemetry-api", specifier = "==1.42.1" },
|
|
936
|
+
{ name = "opentelemetry-exporter-otlp-proto-http", specifier = "==1.42.1" },
|
|
937
|
+
{ name = "opentelemetry-sdk", specifier = "==1.42.1" },
|
|
938
|
+
{ name = "pillow", specifier = "==12.3.0" },
|
|
939
|
+
{ name = "psycopg", extras = ["binary", "pool"], specifier = "==3.3.4" },
|
|
788
940
|
{ name = "pydantic", specifier = "==2.13.4" },
|
|
789
941
|
{ name = "uvicorn", specifier = "==0.51.0" },
|
|
790
942
|
]
|
|
@@ -795,6 +947,7 @@ dev = [
|
|
|
795
947
|
{ name = "pytest", specifier = "==9.1.1" },
|
|
796
948
|
{ name = "pytest-asyncio", specifier = "==1.4.0" },
|
|
797
949
|
{ name = "ruff", specifier = "==0.15.22" },
|
|
950
|
+
{ name = "types-jsonschema", specifier = "==4.26.0.20260518" },
|
|
798
951
|
]
|
|
799
952
|
|
|
800
953
|
[[package]]
|
|
@@ -819,6 +972,18 @@ wheels = [
|
|
|
819
972
|
{ url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" },
|
|
820
973
|
]
|
|
821
974
|
|
|
975
|
+
[[package]]
|
|
976
|
+
name = "types-jsonschema"
|
|
977
|
+
version = "4.26.0.20260518"
|
|
978
|
+
source = { registry = "https://pypi.org/simple" }
|
|
979
|
+
dependencies = [
|
|
980
|
+
{ name = "referencing" },
|
|
981
|
+
]
|
|
982
|
+
sdist = { url = "https://files.pythonhosted.org/packages/dd/46/73b6a5d61a61015c4248030a8cb07e5bdddb4041430fae9e585a68692578/types_jsonschema-4.26.0.20260518.tar.gz", hash = "sha256:e1dd53dc97a64f5eccdd6fa9839666e09bb500a8ebba2db6fdaf1789faea81a6", size = 16638, upload-time = "2026-05-18T06:06:44.106Z" }
|
|
983
|
+
wheels = [
|
|
984
|
+
{ url = "https://files.pythonhosted.org/packages/07/d5/134f8a147dcecda10db7f60cfc6af0578a25a5c53c87b3907a64385e0184/types_jsonschema-4.26.0.20260518-py3-none-any.whl", hash = "sha256:30b30a518c7fe335df85c919fcbcc631b69c03d4a4b5b632fa916bea03065307", size = 16072, upload-time = "2026-05-18T06:06:43.264Z" },
|
|
985
|
+
]
|
|
986
|
+
|
|
822
987
|
[[package]]
|
|
823
988
|
name = "typing-extensions"
|
|
824
989
|
version = "4.16.0"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
FROM python:3.12-slim AS runtime
|
|
3
|
+
|
|
4
|
+
WORKDIR /app/apps/document-server
|
|
5
|
+
RUN pip install --no-cache-dir uv==0.9.27 \
|
|
6
|
+
&& useradd --create-home --uid 10001 windy
|
|
7
|
+
COPY apps/document-server/pyproject.toml apps/document-server/uv.lock ./
|
|
8
|
+
RUN uv sync --frozen --no-dev --no-install-project
|
|
9
|
+
COPY apps/document-server/src ./src
|
|
10
|
+
RUN uv sync --frozen --no-dev
|
|
11
|
+
|
|
12
|
+
ENV PATH="/app/apps/document-server/.venv/bin:${PATH}"
|
|
13
|
+
ENV PYTHONUNBUFFERED=1
|
|
14
|
+
EXPOSE 8090
|
|
15
|
+
RUN mkdir -p /app/data/document && chown -R windy:windy /app/data
|
|
16
|
+
USER windy
|
|
17
|
+
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=4 \
|
|
18
|
+
CMD ["python", "-c", "import os,urllib.request; r=urllib.request.Request('http://127.0.0.1:8090/health/ready',headers={'Authorization':'Bearer '+os.environ['DOCUMENT_SERVER_INTERNAL_TOKEN']}); urllib.request.urlopen(r,timeout=3)"]
|
|
19
|
+
CMD ["uvicorn", "southwind_document_server.app:app", "--host", "0.0.0.0", "--port", "8090"]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "southwind-document-server"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Southwind AI governed Document Runtime server"
|
|
5
|
+
requires-python = ">=3.12,<3.13"
|
|
6
|
+
dependencies = [
|
|
7
|
+
"fastapi==0.139.2",
|
|
8
|
+
"httpx==0.28.1",
|
|
9
|
+
"pydantic==2.13.4",
|
|
10
|
+
"uvicorn==0.51.0",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[dependency-groups]
|
|
14
|
+
dev = [
|
|
15
|
+
"mypy==2.3.0",
|
|
16
|
+
"pytest==9.1.1",
|
|
17
|
+
"pytest-asyncio==1.4.0",
|
|
18
|
+
"ruff==0.15.22",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[tool.pytest.ini_options]
|
|
22
|
+
asyncio_mode = "auto"
|
|
23
|
+
pythonpath = [".", "src"]
|
|
24
|
+
testpaths = ["tests"]
|
|
25
|
+
|
|
26
|
+
[tool.ruff]
|
|
27
|
+
line-length = 88
|
|
28
|
+
target-version = "py312"
|
|
29
|
+
|
|
30
|
+
[tool.ruff.lint]
|
|
31
|
+
select = ["E", "F", "I", "UP", "B", "ASYNC"]
|
|
32
|
+
|
|
33
|
+
[tool.mypy]
|
|
34
|
+
python_version = "3.12"
|
|
35
|
+
strict = true
|
|
36
|
+
files = ["src", "tests"]
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["hatchling"]
|
|
40
|
+
build-backend = "hatchling.build"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.build.targets.wheel]
|
|
43
|
+
packages = ["src/southwind_document_server"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Southwind Document Runtime."""
|