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
package/dist/cli.js
CHANGED
|
@@ -229,7 +229,9 @@ var optionalModuleManifests = [
|
|
|
229
229
|
{
|
|
230
230
|
...module("system.agent", "Agent Tool", "\u53D7\u63A7 Agent \u5DE5\u5177\u5BBF\u4E3B\u3002", [
|
|
231
231
|
"system",
|
|
232
|
-
"system.audit"
|
|
232
|
+
"system.audit",
|
|
233
|
+
"system.storage",
|
|
234
|
+
"system.scheduler"
|
|
233
235
|
]),
|
|
234
236
|
registryDependencies: [
|
|
235
237
|
{
|
|
@@ -245,17 +247,41 @@ var optionalModuleManifests = [
|
|
|
245
247
|
],
|
|
246
248
|
fileRoots: [
|
|
247
249
|
"apps/agent-server",
|
|
250
|
+
"apps/document-server",
|
|
251
|
+
"apps/speech-server",
|
|
252
|
+
"apps/embedding-server",
|
|
248
253
|
"apps/server/src/agent",
|
|
254
|
+
"apps/server/src/ai-artifact",
|
|
255
|
+
"apps/server/src/document",
|
|
256
|
+
"apps/server/src/speech",
|
|
257
|
+
"apps/server/src/embedding",
|
|
249
258
|
"apps/server/src/mcp",
|
|
250
259
|
"apps/server/src/module-host/tool-handlers.ts",
|
|
251
260
|
"apps/server/src/module-host/tool-handlers.test.ts",
|
|
252
|
-
"packages/modules/src/system-agent-tools.ts"
|
|
261
|
+
"packages/modules/src/system-agent-tools.ts",
|
|
262
|
+
"packages/database/src/agent-runtime-schema.test.ts"
|
|
253
263
|
],
|
|
254
264
|
documentation: [
|
|
255
265
|
"docs/architecture/ai-runtime.md",
|
|
256
266
|
"docs/architecture/mcp-business-capabilities.md",
|
|
257
267
|
"docs/platform/agent-runtime.md",
|
|
258
|
-
"docs/platform/agent-tools.md"
|
|
268
|
+
"docs/platform/agent-tools.md",
|
|
269
|
+
"docs/platform/agent-tool-approval.md",
|
|
270
|
+
"docs/platform/agent-tool-sandbox.md",
|
|
271
|
+
"docs/platform/agent-production-store.md",
|
|
272
|
+
"docs/platform/agent-run-reattachment.md",
|
|
273
|
+
"docs/platform/background-ai-operations.md",
|
|
274
|
+
"docs/platform/document-ai-runtime.md",
|
|
275
|
+
"docs/platform/speech-ai-runtime.md",
|
|
276
|
+
"docs/platform/embedding-ai-runtime.md"
|
|
277
|
+
],
|
|
278
|
+
schemaFiles: ["packages/database/src/schema/agent-runtime.ts"],
|
|
279
|
+
databaseTables: [
|
|
280
|
+
"agent_operation_releases",
|
|
281
|
+
"agent_runtime_runs",
|
|
282
|
+
"agent_runtime_events",
|
|
283
|
+
"agent_evaluation_results",
|
|
284
|
+
"agent_run_bindings"
|
|
259
285
|
]
|
|
260
286
|
},
|
|
261
287
|
{
|
|
@@ -267,7 +293,11 @@ var optionalModuleManifests = [
|
|
|
267
293
|
"apps/server/src/scheduler",
|
|
268
294
|
"apps/server/src/jobs",
|
|
269
295
|
"apps/server/src/application-services.ts",
|
|
296
|
+
"apps/server/src/module-host/durable-context.ts",
|
|
297
|
+
"apps/server/src/module-host/durable-context.test.ts",
|
|
298
|
+
"apps/server/src/module-host/job-port.test.ts",
|
|
270
299
|
"apps/server/src/module-host/task-definitions.ts",
|
|
300
|
+
"packages/database/src/schema-durable-recovery.test.ts",
|
|
271
301
|
"apps/web/src/pages/system/components/SchedulerOperationsPanel.vue",
|
|
272
302
|
"apps/web/src/pages/system/components/SchedulerOperationsPanel.webtest.ts",
|
|
273
303
|
"apps/web/src/pages/system/components/SchedulerRunTable.vue",
|
|
@@ -401,6 +431,11 @@ var optionalModuleManifests = [
|
|
|
401
431
|
]),
|
|
402
432
|
fileRoots: [
|
|
403
433
|
"apps/server/src/data-governance",
|
|
434
|
+
"apps/server/src/module-host/governed-resource-routes.ts",
|
|
435
|
+
"apps/server/src/module-host/governed-export-routes.ts",
|
|
436
|
+
"apps/server/src/module-host/governed-export-route-support.ts",
|
|
437
|
+
"apps/server/src/module-host/governed-export-routes.test.ts",
|
|
438
|
+
"apps/server/src/module-host/governed-resources.test.ts",
|
|
404
439
|
"packages/modules/src/system-api-data-governance.ts",
|
|
405
440
|
"packages/modules/src/system-data-governance.ts",
|
|
406
441
|
"packages/modules/src/system-governed-export-bindings.ts",
|
|
@@ -426,6 +461,7 @@ var optionalModuleManifests = [
|
|
|
426
461
|
],
|
|
427
462
|
documentation: ["docs/development/example-work-order.md"],
|
|
428
463
|
schemaFiles: ["packages/example-work-order/src/drizzle-schema.ts"],
|
|
464
|
+
migrationRoots: ["packages/example-work-order/drizzle"],
|
|
429
465
|
databaseTables: ["work_orders"],
|
|
430
466
|
databaseLineageOwner: "module"
|
|
431
467
|
}
|
|
@@ -435,6 +471,7 @@ function module(name, label, description, dependencies) {
|
|
|
435
471
|
return {
|
|
436
472
|
name,
|
|
437
473
|
version: "0.1.0",
|
|
474
|
+
windyRange: "^0.3.0",
|
|
438
475
|
label,
|
|
439
476
|
description,
|
|
440
477
|
selection,
|
|
@@ -445,11 +482,15 @@ function module(name, label, description, dependencies) {
|
|
|
445
482
|
fileRoots: [],
|
|
446
483
|
documentation: [],
|
|
447
484
|
schemaFiles: [],
|
|
485
|
+
migrationRoots: [],
|
|
448
486
|
databaseTables: [],
|
|
449
487
|
databaseLineageOwner: "platform",
|
|
450
488
|
transientDatabaseTables: [],
|
|
451
489
|
databaseStatementTokens: [],
|
|
452
|
-
uninstallPolicy: "retain-data"
|
|
490
|
+
uninstallPolicy: "retain-data",
|
|
491
|
+
installRecipe: `module-${name}-install`,
|
|
492
|
+
updateRecipes: [`module-${name}-update-0.1.0`],
|
|
493
|
+
uninstallRecipe: `module-${name}-uninstall`
|
|
453
494
|
};
|
|
454
495
|
}
|
|
455
496
|
|
|
@@ -507,7 +548,7 @@ var platformModules = [
|
|
|
507
548
|
{
|
|
508
549
|
sourceName: "@southwind-ai/license",
|
|
509
550
|
name: "@southwind-ai/license",
|
|
510
|
-
version: "^0.1.
|
|
551
|
+
version: "^0.1.4"
|
|
511
552
|
}
|
|
512
553
|
],
|
|
513
554
|
fileRoots: [
|
|
@@ -654,6 +695,7 @@ function module2(name, label, description, selection, dependencies = []) {
|
|
|
654
695
|
return {
|
|
655
696
|
name,
|
|
656
697
|
version: "0.1.0",
|
|
698
|
+
windyRange: "^0.3.0",
|
|
657
699
|
label,
|
|
658
700
|
description,
|
|
659
701
|
selection,
|
|
@@ -664,11 +706,15 @@ function module2(name, label, description, selection, dependencies = []) {
|
|
|
664
706
|
fileRoots: [],
|
|
665
707
|
documentation: [],
|
|
666
708
|
schemaFiles: [],
|
|
709
|
+
migrationRoots: [],
|
|
667
710
|
databaseTables: [],
|
|
668
711
|
databaseLineageOwner: "platform",
|
|
669
712
|
transientDatabaseTables: [],
|
|
670
713
|
databaseStatementTokens: [],
|
|
671
|
-
uninstallPolicy: "retain-data"
|
|
714
|
+
uninstallPolicy: "retain-data",
|
|
715
|
+
installRecipe: `module-${name}-install`,
|
|
716
|
+
updateRecipes: [`module-${name}-update-0.1.0`],
|
|
717
|
+
uninstallRecipe: `module-${name}-uninstall`
|
|
672
718
|
};
|
|
673
719
|
}
|
|
674
720
|
function validateCatalog(manifests) {
|
|
@@ -689,6 +735,12 @@ function validateCatalog(manifests) {
|
|
|
689
735
|
if (!names.has(conflict))
|
|
690
736
|
throw new Error(`${manifest.name} \u51B2\u7A81\u6A21\u5757\u672A\u77E5\uFF1A${conflict}`);
|
|
691
737
|
}
|
|
738
|
+
if (!manifest.installRecipe) {
|
|
739
|
+
throw new Error(`${manifest.name} \u7F3A\u5C11\u5B89\u88C5 recipe`);
|
|
740
|
+
}
|
|
741
|
+
if (!manifest.uninstallRecipe) {
|
|
742
|
+
throw new Error(`${manifest.name} \u7F3A\u5C11\u5378\u8F7D recipe`);
|
|
743
|
+
}
|
|
692
744
|
}
|
|
693
745
|
return manifests;
|
|
694
746
|
}
|
|
@@ -773,6 +825,11 @@ var helpText = `create-windy <\u9879\u76EE\u540D> [\u9009\u9879]
|
|
|
773
825
|
create-windy update --check [--cwd <\u76EE\u5F55>]
|
|
774
826
|
create-windy update --dry-run [--to <\u7248\u672C>] [--cwd <\u76EE\u5F55>]
|
|
775
827
|
create-windy update [--to <\u7248\u672C>] [--cwd <\u76EE\u5F55>]
|
|
828
|
+
create-windy module list [--cwd <\u76EE\u5F55>]
|
|
829
|
+
create-windy module add <key...> [--dry-run] [--cwd <\u76EE\u5F55>]
|
|
830
|
+
create-windy module update [key...] [--dry-run] [--cwd <\u76EE\u5F55>]
|
|
831
|
+
create-windy module remove <key...> [--dry-run] [--data-disposition <\u7B56\u7565>]
|
|
832
|
+
[--data-plan <\u6587\u4EF6>] [--confirm-data-disposition] [--cwd <\u76EE\u5F55>]
|
|
776
833
|
create-windy reconcile --to <\u7CBE\u786E\u7248\u672C> [--cwd <\u76EE\u5F55>] [--apply]
|
|
777
834
|
create-windy schema handoff [--config <JSON>] [--cwd <\u76EE\u5F55>]
|
|
778
835
|
|
|
@@ -962,6 +1019,9 @@ async function initializeLocalEnvironment(projectRoot, generateSecret = defaultS
|
|
|
962
1019
|
if (/^AGENT_SERVER_INTERNAL_TOKEN=[ \t\r]*$/m.test(content)) {
|
|
963
1020
|
content = setEmptyVariable(content, "AGENT_SERVER_INTERNAL_TOKEN", generateSecret());
|
|
964
1021
|
}
|
|
1022
|
+
if (/^AI_ARTIFACT_ENCRYPTION_SECRET=[ \t\r]*$/m.test(content)) {
|
|
1023
|
+
content = setEmptyVariable(content, "AI_ARTIFACT_ENCRYPTION_SECRET", generateSecret());
|
|
1024
|
+
}
|
|
965
1025
|
let handle;
|
|
966
1026
|
try {
|
|
967
1027
|
handle = await open(target, "wx", 384);
|
|
@@ -979,7 +1039,11 @@ async function initializeLocalEnvironment(projectRoot, generateSecret = defaultS
|
|
|
979
1039
|
return "created";
|
|
980
1040
|
}
|
|
981
1041
|
function setEmptyVariable(source, key, value) {
|
|
982
|
-
|
|
1042
|
+
const minimumLength = [
|
|
1043
|
+
"AGENT_SERVER_INTERNAL_TOKEN",
|
|
1044
|
+
"AI_ARTIFACT_ENCRYPTION_SECRET"
|
|
1045
|
+
].includes(key) ? 32 : 12;
|
|
1046
|
+
if (value.length < minimumLength || /\s|=/.test(value)) {
|
|
983
1047
|
throw new Error(`${key} \u7684\u968F\u673A\u503C\u4E0D\u6EE1\u8DB3\u672C\u5730\u5BC6\u7801\u5B89\u5168\u8981\u6C42`);
|
|
984
1048
|
}
|
|
985
1049
|
const pattern = new RegExp(`^${key}=[ \\t\\r]*$`, "m");
|
|
@@ -3212,9 +3276,9 @@ MCP \u6BCF\u6B21\u8C03\u7528\u90FD\u4F1A\u91CD\u65B0\u6267\u884C Feature\u3001RB
|
|
|
3212
3276
|
\u548C \`dev:agent\` \u662F\u53E6\u4E00\u6761\u53EF\u9009\u94FE\u8DEF\u3002\u5B8C\u6574\u8FB9\u754C\u89C1
|
|
3213
3277
|
[MCP \u4E1A\u52A1\u80FD\u529B](./docs/architecture/mcp-business-capabilities.md) \u4E0E
|
|
3214
3278
|
[Agent Tool](./docs/platform/agent-tools.md)\u3002` : `\u5F53\u524D\u7EC4\u5408\u672A\u5305\u542B \`system.agent\`\uFF0CMCP Server\u3001Agent Tool Host \u548C\u76F8\u5173\u6587\u6863\u5DF2\u88AB
|
|
3215
|
-
\u7269\u7406\u88C1\u526A\u3002\
|
|
3216
|
-
|
|
3217
|
-
\
|
|
3279
|
+
\u7269\u7406\u88C1\u526A\u3002\u521B\u5EFA\u65F6\u53EF\u589E\u52A0 \`--module system.agent\` \u6216\u4F7F\u7528 \`--all-modules\`\uFF1B\u5DF2\u90E8\u7F72
|
|
3280
|
+
\u9879\u76EE\u4F7F\u7528 \`bun run windy module add system.agent\`\uFF0C\u4E0D\u8981\u624B\u5DE5\u590D\u5236 MCP Adapter \u6216
|
|
3281
|
+
\u53E6\u5EFA\u6388\u6743\u94FE\u3002\u4ED3\u5E93 Skill \u4ECD\u53EF\u7528\u4E8E\u666E\u901A\u4E1A\u52A1\u6A21\u5757\u5F00\u53D1\u3002`}
|
|
3218
3282
|
`;
|
|
3219
3283
|
}
|
|
3220
3284
|
|
|
@@ -3266,7 +3330,13 @@ var starterComposeBase = `services:
|
|
|
3266
3330
|
PLATFORM_ENABLE_AI: \${PLATFORM_ENABLE_AI:-false}
|
|
3267
3331
|
AGENT_SERVER_URL: http://agent-server:8080
|
|
3268
3332
|
AGENT_TOOL_HOST_URL: http://server:9747
|
|
3333
|
+
__TOOL_SANDBOX_SERVER_ENV__
|
|
3269
3334
|
AGENT_SERVER_INTERNAL_TOKEN: \${AGENT_SERVER_INTERNAL_TOKEN:-}
|
|
3335
|
+
AI_ARTIFACT_URL: http://server:9747/api/internal/ai/artifacts
|
|
3336
|
+
AI_ARTIFACT_ENCRYPTION_SECRET: \${AI_ARTIFACT_ENCRYPTION_SECRET:-}
|
|
3337
|
+
DOCUMENT_SERVER_URL: \${DOCUMENT_SERVER_URL:-}
|
|
3338
|
+
SPEECH_SERVER_URL: \${SPEECH_SERVER_URL:-}
|
|
3339
|
+
EMBEDDING_SERVER_URL: \${EMBEDDING_SERVER_URL:-}
|
|
3270
3340
|
__OPENSEARCH_SERVER_ENV__
|
|
3271
3341
|
ports:
|
|
3272
3342
|
- "9747:9747"
|
|
@@ -3274,6 +3344,7 @@ __OPENSEARCH_SERVER_ENV__
|
|
|
3274
3344
|
- ./apps/server:/app/apps/server
|
|
3275
3345
|
- ./packages:/app/packages
|
|
3276
3346
|
- server-audit-data:/app/data/audit
|
|
3347
|
+
__TOOL_SANDBOX_SERVER_VOLUME__
|
|
3277
3348
|
depends_on:
|
|
3278
3349
|
migrate:
|
|
3279
3350
|
condition: service_completed_successfully
|
|
@@ -3337,7 +3408,53 @@ var openSearchComposeService = ` opensearch:
|
|
|
3337
3408
|
retries: 12
|
|
3338
3409
|
|
|
3339
3410
|
`;
|
|
3340
|
-
var agentComposeService = `
|
|
3411
|
+
var agentComposeService = ` tool-sandbox-init:
|
|
3412
|
+
profiles: ["agent"]
|
|
3413
|
+
build:
|
|
3414
|
+
context: .
|
|
3415
|
+
dockerfile: apps/server/Dockerfile
|
|
3416
|
+
user: "0:0"
|
|
3417
|
+
command:
|
|
3418
|
+
[
|
|
3419
|
+
"sh",
|
|
3420
|
+
"-c",
|
|
3421
|
+
"chmod 0700 /run/windy-tool-sandbox && chown 1000:1000 /run/windy-tool-sandbox",
|
|
3422
|
+
]
|
|
3423
|
+
network_mode: none
|
|
3424
|
+
read_only: true
|
|
3425
|
+
cap_drop: ["ALL"]
|
|
3426
|
+
cap_add: ["CHOWN"]
|
|
3427
|
+
security_opt:
|
|
3428
|
+
- no-new-privileges:true
|
|
3429
|
+
volumes:
|
|
3430
|
+
- tool-sandbox-ipc:/run/windy-tool-sandbox
|
|
3431
|
+
healthcheck:
|
|
3432
|
+
disable: true
|
|
3433
|
+
|
|
3434
|
+
tool-sandbox:
|
|
3435
|
+
profiles: ["agent"]
|
|
3436
|
+
build:
|
|
3437
|
+
context: .
|
|
3438
|
+
dockerfile: apps/server/Dockerfile
|
|
3439
|
+
command: ["bun", "run", "apps/server/src/agent/sandbox-worker.ts"]
|
|
3440
|
+
environment:
|
|
3441
|
+
TOOL_SANDBOX_SOCKET: /run/windy-tool-sandbox/worker.sock
|
|
3442
|
+
network_mode: none
|
|
3443
|
+
read_only: true
|
|
3444
|
+
tmpfs:
|
|
3445
|
+
- /tmp:rw,noexec,nosuid,nodev,size=16m
|
|
3446
|
+
cap_drop: ["ALL"]
|
|
3447
|
+
security_opt:
|
|
3448
|
+
- no-new-privileges:true
|
|
3449
|
+
volumes:
|
|
3450
|
+
- tool-sandbox-ipc:/run/windy-tool-sandbox
|
|
3451
|
+
depends_on:
|
|
3452
|
+
tool-sandbox-init:
|
|
3453
|
+
condition: service_completed_successfully
|
|
3454
|
+
healthcheck:
|
|
3455
|
+
disable: true
|
|
3456
|
+
|
|
3457
|
+
agent-server:
|
|
3341
3458
|
profiles: ["agent"]
|
|
3342
3459
|
build:
|
|
3343
3460
|
context: .
|
|
@@ -3345,6 +3462,10 @@ var agentComposeService = ` agent-server:
|
|
|
3345
3462
|
environment:
|
|
3346
3463
|
AGENT_SERVER_INTERNAL_TOKEN: \${AGENT_SERVER_INTERNAL_TOKEN:-}
|
|
3347
3464
|
AGENT_RUN_STORE_PATH: /app/data/agent/runs.sqlite3
|
|
3465
|
+
AGENT_DATABASE_URL: postgresql://windy:\${POSTGRES_PASSWORD}@postgres:5432/windy
|
|
3466
|
+
AGENT_RUN_ENCRYPTION_SECRET: \${AGENT_RUN_ENCRYPTION_SECRET:-}
|
|
3467
|
+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: \${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT:-}
|
|
3468
|
+
OTEL_EXPORTER_OTLP_HEADERS: \${OTEL_EXPORTER_OTLP_HEADERS:-}
|
|
3348
3469
|
AI_PROVIDER_AUDIT_STORE_PATH: /app/data/agent/provider-audit.sqlite3
|
|
3349
3470
|
AI_PROVIDER_AUDIT_RETENTION_DAYS: \${AI_PROVIDER_AUDIT_RETENTION_DAYS:-90}
|
|
3350
3471
|
QWEN_API_URL: \${QWEN_API_URL:-}
|
|
@@ -3354,8 +3475,75 @@ var agentComposeService = ` agent-server:
|
|
|
3354
3475
|
AI_PROVIDER_CONNECT_TIMEOUT_MS: \${AI_PROVIDER_CONNECT_TIMEOUT_MS:-5000}
|
|
3355
3476
|
AI_PROVIDER_REQUEST_TIMEOUT_MS: \${AI_PROVIDER_REQUEST_TIMEOUT_MS:-60000}
|
|
3356
3477
|
AI_PROVIDER_MAX_RESPONSE_BYTES: \${AI_PROVIDER_MAX_RESPONSE_BYTES:-2097152}
|
|
3478
|
+
AI_PROVIDER_CAPABILITIES: \${AI_PROVIDER_CAPABILITIES:-text-generation}
|
|
3479
|
+
AI_PROVIDER_INPUT_MODALITIES: \${AI_PROVIDER_INPUT_MODALITIES:-text}
|
|
3357
3480
|
volumes:
|
|
3358
3481
|
- agent-run-data:/app/data/agent
|
|
3482
|
+
depends_on:
|
|
3483
|
+
migrate:
|
|
3484
|
+
condition: service_completed_successfully
|
|
3485
|
+
server:
|
|
3486
|
+
condition: service_started
|
|
3487
|
+
|
|
3488
|
+
document-server:
|
|
3489
|
+
profiles: ["document"]
|
|
3490
|
+
build:
|
|
3491
|
+
context: .
|
|
3492
|
+
dockerfile: apps/document-server/Dockerfile
|
|
3493
|
+
environment:
|
|
3494
|
+
DOCUMENT_SERVER_INTERNAL_TOKEN: \${AGENT_SERVER_INTERNAL_TOKEN:-}
|
|
3495
|
+
DOCUMENT_RUN_STORE_PATH: /app/data/document/runs.sqlite3
|
|
3496
|
+
DOCUMENT_ARTIFACT_URL: \${DOCUMENT_ARTIFACT_URL:-http://server:9747/api/internal/ai/artifacts}
|
|
3497
|
+
DOCUMENT_ADAPTER_URL: \${DOCUMENT_ADAPTER_URL:-}
|
|
3498
|
+
DOCUMENT_ADAPTER_TOKEN: \${DOCUMENT_ADAPTER_TOKEN:-}
|
|
3499
|
+
DOCUMENT_DEPLOYMENT_KEY: \${DOCUMENT_DEPLOYMENT_KEY:-}
|
|
3500
|
+
DOCUMENT_ADAPTER_CAPABILITIES: \${DOCUMENT_ADAPTER_CAPABILITIES:-document.ocr,document.layout,document.table}
|
|
3501
|
+
DOCUMENT_MAX_UNITS: \${DOCUMENT_MAX_UNITS:-500}
|
|
3502
|
+
volumes:
|
|
3503
|
+
- document-run-data:/app/data/document
|
|
3504
|
+
depends_on:
|
|
3505
|
+
server:
|
|
3506
|
+
condition: service_started
|
|
3507
|
+
|
|
3508
|
+
speech-server:
|
|
3509
|
+
profiles: ["speech"]
|
|
3510
|
+
build:
|
|
3511
|
+
context: .
|
|
3512
|
+
dockerfile: apps/speech-server/Dockerfile
|
|
3513
|
+
environment:
|
|
3514
|
+
SPEECH_SERVER_INTERNAL_TOKEN: \${AGENT_SERVER_INTERNAL_TOKEN:-}
|
|
3515
|
+
SPEECH_RUN_STORE_PATH: /app/data/speech/runs.sqlite3
|
|
3516
|
+
SPEECH_ARTIFACT_URL: \${SPEECH_ARTIFACT_URL:-http://server:9747/api/internal/ai/artifacts}
|
|
3517
|
+
SPEECH_ADAPTER_URL: \${SPEECH_ADAPTER_URL:-}
|
|
3518
|
+
SPEECH_ADAPTER_TOKEN: \${SPEECH_ADAPTER_TOKEN:-}
|
|
3519
|
+
SPEECH_DEPLOYMENT_KEY: \${SPEECH_DEPLOYMENT_KEY:-}
|
|
3520
|
+
SPEECH_ADAPTER_CAPABILITIES: \${SPEECH_ADAPTER_CAPABILITIES:-speech.transcribe.batch,speech.normalize,speech.vad,speech.timestamps}
|
|
3521
|
+
SPEECH_MAX_UNITS: \${SPEECH_MAX_UNITS:-100000}
|
|
3522
|
+
SPEECH_MAX_MEDIA_DURATION_SECONDS: \${SPEECH_MAX_MEDIA_DURATION_SECONDS:-86400}
|
|
3523
|
+
volumes:
|
|
3524
|
+
- speech-run-data:/app/data/speech
|
|
3525
|
+
depends_on:
|
|
3526
|
+
server:
|
|
3527
|
+
condition: service_started
|
|
3528
|
+
|
|
3529
|
+
embedding-server:
|
|
3530
|
+
profiles: ["embedding"]
|
|
3531
|
+
build:
|
|
3532
|
+
context: .
|
|
3533
|
+
dockerfile: apps/embedding-server/Dockerfile
|
|
3534
|
+
environment:
|
|
3535
|
+
EMBEDDING_SERVER_INTERNAL_TOKEN: \${AGENT_SERVER_INTERNAL_TOKEN:-}
|
|
3536
|
+
EMBEDDING_ARTIFACT_URL: \${EMBEDDING_ARTIFACT_URL:-http://server:9747/api/internal/ai/artifacts}
|
|
3537
|
+
EMBEDDING_ADAPTER_URL: \${EMBEDDING_ADAPTER_URL:-}
|
|
3538
|
+
EMBEDDING_ADAPTER_TOKEN: \${EMBEDDING_ADAPTER_TOKEN:-}
|
|
3539
|
+
EMBEDDING_DEPLOYMENT_KEY: \${EMBEDDING_DEPLOYMENT_KEY:-}
|
|
3540
|
+
EMBEDDING_DEPLOYMENT_ALIAS: \${EMBEDDING_DEPLOYMENT_ALIAS:-}
|
|
3541
|
+
EMBEDDING_MODEL: \${EMBEDDING_MODEL:-}
|
|
3542
|
+
EMBEDDING_MODEL_VERSION: \${EMBEDDING_MODEL_VERSION:-}
|
|
3543
|
+
EMBEDDING_DIMENSIONS: \${EMBEDDING_DIMENSIONS:-}
|
|
3544
|
+
EMBEDDING_NORMALIZED: \${EMBEDDING_NORMALIZED:-true}
|
|
3545
|
+
EMBEDDING_CAPABILITIES: \${EMBEDDING_CAPABILITIES:-embedding.text}
|
|
3546
|
+
EMBEDDING_MAX_UNITS: \${EMBEDDING_MAX_UNITS:-256}
|
|
3359
3547
|
depends_on:
|
|
3360
3548
|
server:
|
|
3361
3549
|
condition: service_started
|
|
@@ -3402,16 +3590,20 @@ var agentComposeService = ` agent-server:
|
|
|
3402
3590
|
function starterComposeFor(includeAgent, includeSearch = true) {
|
|
3403
3591
|
return starterComposeBase.replace(` web:
|
|
3404
3592
|
`, `${includeAgent ? agentComposeService : ""} web:
|
|
3405
|
-
`).replace("__OPENSEARCH_SERVER_ENV__", includeSearch ? ` OPENSEARCH_URL: \${OPENSEARCH_URL:-}
|
|
3593
|
+
`).replace("__TOOL_SANDBOX_SERVER_ENV__", includeAgent ? " TOOL_SANDBOX_SOCKET: /run/windy-tool-sandbox/worker.sock" : "").replace("__TOOL_SANDBOX_SERVER_VOLUME__", includeAgent ? " - tool-sandbox-ipc:/run/windy-tool-sandbox" : "").replace("__OPENSEARCH_SERVER_ENV__", includeSearch ? ` OPENSEARCH_URL: \${OPENSEARCH_URL:-}
|
|
3406
3594
|
OPENSEARCH_USERNAME: \${OPENSEARCH_USERNAME:-}
|
|
3407
3595
|
OPENSEARCH_PASSWORD: \${OPENSEARCH_PASSWORD:-}
|
|
3408
3596
|
OPENSEARCH_WORK_ORDER_INDEX: \${OPENSEARCH_WORK_ORDER_INDEX:-windy-work-orders-v1}` : "").replace("__OPENSEARCH_SERVICE__", includeSearch ? openSearchComposeService : "").replace("__OPTIONAL_VOLUMES__", [
|
|
3409
3597
|
includeAgent ? " agent-run-data:" : "",
|
|
3598
|
+
includeAgent ? " tool-sandbox-ipc:" : "",
|
|
3599
|
+
includeAgent ? " document-run-data:" : "",
|
|
3600
|
+
includeAgent ? " speech-run-data:" : "",
|
|
3410
3601
|
includeSearch ? " opensearch-data:" : ""
|
|
3411
3602
|
].filter(Boolean).join(`
|
|
3412
3603
|
`));
|
|
3413
3604
|
}
|
|
3414
3605
|
var starterCompose = starterComposeFor(true);
|
|
3606
|
+
// src/runtime-environment-example.ts
|
|
3415
3607
|
function environmentExample(includeExample, includeAgent = true, includeSearch = true) {
|
|
3416
3608
|
return `# \u590D\u5236\u4E3A .env \u540E\u586B\u5199\u3002\u4E0D\u8981\u63D0\u4EA4\u771F\u5B9E\u5BC6\u7801\u3002
|
|
3417
3609
|
POSTGRES_PASSWORD=
|
|
@@ -3421,10 +3613,47 @@ ${includeAgent ? `
|
|
|
3421
3613
|
# ADK Web \u8C03\u8BD5 profile \u4E0D\u8BFB\u53D6\u4EE5\u4E0B\u53D8\u91CF\uFF0C\u4E5F\u4E0D\u80FD\u8C03\u7528\u771F\u5B9E\u4E1A\u52A1 Operation \u6216 Tool\u3002
|
|
3422
3614
|
PLATFORM_ENABLE_AI=false
|
|
3423
3615
|
AGENT_SERVER_INTERNAL_TOKEN=
|
|
3616
|
+
AGENT_RUN_ENCRYPTION_SECRET=
|
|
3617
|
+
# \u591A\u526F\u672C\u751F\u4EA7\u9ED8\u8BA4\u4F7F\u7528 Compose \u6CE8\u5165\u7684 PostgreSQL\uFF1B\u7559\u7A7A\u624D\u56DE\u9000\u5355\u526F\u672C SQLite\u3002
|
|
3618
|
+
AGENT_DATABASE_URL=
|
|
3619
|
+
# \u53EF\u9009\uFF1A\u53EA\u53D1\u9001\u65E0 Prompt/\u8F93\u5165/\u8F93\u51FA\u7684 Agent Run \u5143\u6570\u636E Span\u3002
|
|
3620
|
+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=
|
|
3621
|
+
OTEL_EXPORTER_OTLP_HEADERS=
|
|
3622
|
+
AI_ARTIFACT_ENCRYPTION_SECRET=
|
|
3623
|
+
DOCUMENT_SERVER_URL=
|
|
3624
|
+
DOCUMENT_ARTIFACT_URL=
|
|
3625
|
+
DOCUMENT_ADAPTER_URL=
|
|
3626
|
+
DOCUMENT_ADAPTER_TOKEN=
|
|
3627
|
+
DOCUMENT_DEPLOYMENT_KEY=
|
|
3628
|
+
# DOCUMENT_ADAPTER_CAPABILITIES=document.ocr,document.layout,document.table
|
|
3629
|
+
# DOCUMENT_MAX_UNITS=500
|
|
3630
|
+
SPEECH_SERVER_URL=
|
|
3631
|
+
SPEECH_ARTIFACT_URL=
|
|
3632
|
+
SPEECH_ADAPTER_URL=
|
|
3633
|
+
SPEECH_ADAPTER_TOKEN=
|
|
3634
|
+
SPEECH_DEPLOYMENT_KEY=
|
|
3635
|
+
# SPEECH_ADAPTER_CAPABILITIES=speech.transcribe.batch,speech.normalize,speech.vad,speech.timestamps
|
|
3636
|
+
# SPEECH_MAX_UNITS=100000
|
|
3637
|
+
# SPEECH_MAX_MEDIA_DURATION_SECONDS=86400
|
|
3638
|
+
EMBEDDING_SERVER_URL=
|
|
3639
|
+
EMBEDDING_ARTIFACT_URL=
|
|
3640
|
+
EMBEDDING_ADAPTER_URL=
|
|
3641
|
+
EMBEDDING_ADAPTER_TOKEN=
|
|
3642
|
+
EMBEDDING_DEPLOYMENT_KEY=
|
|
3643
|
+
EMBEDDING_DEPLOYMENT_ALIAS=
|
|
3644
|
+
EMBEDDING_MODEL=
|
|
3645
|
+
EMBEDDING_MODEL_VERSION=
|
|
3646
|
+
EMBEDDING_DIMENSIONS=
|
|
3647
|
+
# EMBEDDING_NORMALIZED=true
|
|
3648
|
+
# EMBEDDING_CAPABILITIES=embedding.text,embedding.image
|
|
3649
|
+
# EMBEDDING_MAX_UNITS=256
|
|
3424
3650
|
QWEN_API_URL=
|
|
3425
3651
|
QWEN_API_KEY=
|
|
3426
3652
|
QWEN_MODEL=
|
|
3427
3653
|
AI_PROVIDER_HTTPS_HOST_ALLOWLIST=
|
|
3654
|
+
# VLM Deployment \u793A\u4F8B\uFF1Atext-generation,vision\uFF1B\u8F93\u5165\u6A21\u6001\uFF1Atext,image
|
|
3655
|
+
# AI_PROVIDER_CAPABILITIES=text-generation
|
|
3656
|
+
# AI_PROVIDER_INPUT_MODALITIES=text
|
|
3428
3657
|
# AI_PROVIDER_AUDIT_RETENTION_DAYS=90
|
|
3429
3658
|
# AI_PROVIDER_CONNECT_TIMEOUT_MS=5000
|
|
3430
3659
|
# AI_PROVIDER_REQUEST_TIMEOUT_MS=60000
|
|
@@ -3448,7 +3677,7 @@ OPENSEARCH_PASSWORD=
|
|
|
3448
3677
|
`;
|
|
3449
3678
|
}
|
|
3450
3679
|
// src/project-files.ts
|
|
3451
|
-
function starterDocsReadme(includeOfflineLicense = true, includeAgent = true) {
|
|
3680
|
+
function starterDocsReadme(includeOfflineLicense = true, includeAgent = true, includeOperations = true) {
|
|
3452
3681
|
return `# Windy Starter \u6587\u6863
|
|
3453
3682
|
|
|
3454
3683
|
\u672C\u76EE\u5F55\u53EA\u5305\u542B\u5BA2\u6237\u8FD0\u884C\u9879\u76EE\u9700\u8981\u7684\u5E73\u53F0\u67B6\u6784\u3001\u5F00\u53D1\u63A5\u5165\u548C\u8FD0\u7EF4\u53EF\u89C2\u6D4B\u6027\u6587\u6863\u3002
|
|
@@ -3458,10 +3687,12 @@ License \u7B7E\u53D1\u4E2D\u5FC3\u3001\u72EC\u7ACB\u7B7E\u540D\u670D\u52A1\u3001
|
|
|
3458
3687
|
- \u67B6\u6784\uFF1A\u4ECE [Module Manifest \u7EC4\u5408](./architecture/module-manifest-composition.md) \u5F00\u59CB\u3002
|
|
3459
3688
|
- \u6570\u636E\u5E93\uFF1A\u4E1A\u52A1\u8868\u4F7F\u7528 [Migration Bundle \u4E0E\u72EC\u7ACB Drizzle lineage](./architecture/migration-bundle.md)\u3002
|
|
3460
3689
|
- \u5E73\u53F0\u5F00\u53D1\uFF1A\u4ECE [\u7CFB\u7EDF CRUD API](./platform/system-crud-api.md) \u548C [CRUD \u751F\u6210\u5668](./development/crud-generator.md) \u5F00\u59CB\u3002
|
|
3690
|
+
- Web \u4E1A\u52A1\u9875\u9762\uFF1A[project-owned \u4E1A\u52A1 Web \u8DEF\u7531](./development/business-web-routes.md)\u3002
|
|
3691
|
+
- \u90E8\u7F72\u671F\u6A21\u5757\u7BA1\u7406\uFF1A[\u6A21\u5757\u751F\u547D\u5468\u671F](./development/module-lifecycle.md)\u3002
|
|
3461
3692
|
- \u4E1A\u52A1\u6A21\u5757\u5F00\u53D1\uFF1A[windy-business-module Skill](../.agents/skills/windy-business-module/SKILL.md)\u3002
|
|
3462
3693
|
${includeOfflineLicense ? "- License \u6D88\u8D39\u7AEF\uFF1A[\u79BB\u7EBF\u6FC0\u6D3B\u4E0E\u5B89\u88C5\u534F\u8BAE](./license/license-offline-activation-code.md)\uFF1B\u8FD0\u884C\u65F6\u80FD\u529B\u7531 npm \u4F9D\u8D56 `@southwind-ai/license` \u63D0\u4F9B\u3002" : ""}
|
|
3463
|
-
- \u8FD0\u7EF4\uFF1A[\u53EF\u89C2\u6D4B\u6027](./operations/observability.md) \u4E0E [\u8FD0\u7EF4\u603B\u89C8](./platform/operations-overview.md)\u3002
|
|
3464
|
-
${includeAgent ? "- Agent \u4E0E MCP\uFF1A[Agent Runtime \u63A5\u5165](./platform/agent-runtime.md)\u3001[\u53D7\u63A7\u5DE5\u5177](./platform/agent-tools.md)\u4E0E[MCP \u4E1A\u52A1\u80FD\u529B](./architecture/mcp-business-capabilities.md)\u3002" : ""}
|
|
3694
|
+
- \u8FD0\u7EF4\uFF1A[\u53EF\u89C2\u6D4B\u6027](./operations/observability.md)${includeOperations ? " \u4E0E [\u8FD0\u7EF4\u603B\u89C8](./platform/operations-overview.md)" : ""}\u3002
|
|
3695
|
+
${includeAgent ? "- Agent\u3001\u591A\u6A21\u6001 Runtime \u4E0E MCP\uFF1A[Agent Runtime \u63A5\u5165](./platform/agent-runtime.md)\u3001[Document AI Runtime](./platform/document-ai-runtime.md)\u3001[Speech AI Runtime](./platform/speech-ai-runtime.md)\u3001[\u53D7\u63A7\u5DE5\u5177](./platform/agent-tools.md)\u4E0E[MCP \u4E1A\u52A1\u80FD\u529B](./architecture/mcp-business-capabilities.md)\u3002" : ""}
|
|
3465
3696
|
- \u517C\u5BB9\uFF1A[RuoYi-Vue Adapter](./adapters/ruoyi-vue-compatibility.md)\u3002
|
|
3466
3697
|
`;
|
|
3467
3698
|
}
|
|
@@ -3469,7 +3700,7 @@ function starterReadme(projectName, includeExample = true, includeOxc = true, pr
|
|
|
3469
3700
|
const selected = new Set(selectedModules);
|
|
3470
3701
|
const includeAgent = selected.has("system.agent");
|
|
3471
3702
|
const includeSearch = selected.has("system.search");
|
|
3472
|
-
const moduleRows = moduleDistributionCatalog.map(({ name, description, selection }) => `| \`${name}\` | ${selected.has(name) ? "\u5DF2\u5305\u542B" : "\u672A\u5305\u542B"} | ${selection === "required" ? "H0" : "H2"} | ${description} |`).join(`
|
|
3703
|
+
const moduleRows = moduleDistributionCatalog.map(({ name, description, selection }) => `| \`${name}\` | ${selected.has(name) ? "\u5DF2\u5305\u542B" : "\u672A\u5305\u542B"} | ${selection === "required" ? "H0" : name === "work-order" ? "H3" : "H2"} | ${description} |`).join(`
|
|
3473
3704
|
`);
|
|
3474
3705
|
return `# ${projectName}
|
|
3475
3706
|
|
|
@@ -3543,6 +3774,30 @@ bun run dev:agent
|
|
|
3543
3774
|
\`AI_PROVIDER_HTTPS_HOST_ALLOWLIST\`\u3002\u8FD0\u884C\u4E0E\u6A21\u5757
|
|
3544
3775
|
\u63A5\u5165\u7EC6\u8282\u89C1 [Agent Runtime \u63A5\u5165](./docs/platform/agent-runtime.md)\u3002
|
|
3545
3776
|
|
|
3777
|
+
Document Runtime \u540C\u6837\u9ED8\u8BA4\u5173\u95ED\u3002\u914D\u7F6E\u81F3\u5C11 32 \u5B57\u7B26\u7684
|
|
3778
|
+
\`AI_ARTIFACT_ENCRYPTION_SECRET\`\u3001\u672C\u5730\u6216\u5185\u7F51 \`DOCUMENT_ADAPTER_URL\` \u53CA\u5176
|
|
3779
|
+
capability \u540E\u8FD0\u884C\uFF1A
|
|
3780
|
+
|
|
3781
|
+
\`\`\`bash
|
|
3782
|
+
bun run dev:document
|
|
3783
|
+
\`\`\`
|
|
3784
|
+
|
|
3785
|
+
\u8BE5 profile \u53EA\u63A5\u53D7\u5E73\u53F0\u7B7E\u53D1\u7684\u77ED\u65F6 opaque ArtifactRef\uFF1B\u4E1A\u52A1\u4E0D\u5F97\u4F20 Base64\u3001\u5BBF\u4E3B\u8DEF\u5F84\u6216
|
|
3786
|
+
\u4EFB\u610F\u516C\u7F51 URL\u3002\u672A\u914D\u7F6E Document Adapter \u65F6\u4EC5\u5BF9\u5E94 Operation \u8FD4\u56DE\u7A33\u5B9A unavailable\uFF0C
|
|
3787
|
+
\u666E\u901A\u4E1A\u52A1\u4E0E\u6587\u672C Agent \u4E0D\u53D7\u5F71\u54CD\u3002\u8BE6\u89C1
|
|
3788
|
+
[Document AI Runtime](./docs/platform/document-ai-runtime.md)\u3002
|
|
3789
|
+
|
|
3790
|
+
\u6279\u91CF\u8BED\u97F3\u8F6C\u5199\u4F7F\u7528\u72EC\u7ACB Speech profile\u3002\u914D\u7F6E\u672C\u5730/\u5185\u7F51
|
|
3791
|
+
\`SPEECH_ADAPTER_URL\` \u4E0E capability \u540E\u8FD0\u884C\uFF1A
|
|
3792
|
+
|
|
3793
|
+
\`\`\`bash
|
|
3794
|
+
bun run dev:speech
|
|
3795
|
+
\`\`\`
|
|
3796
|
+
|
|
3797
|
+
Speech Runtime \u53EA\u63A5\u6536\u6388\u6743 Artifact\uFF0C\u8D1F\u8D23\u683C\u5F0F\u5F52\u4E00\u5316\u3001VAD/\u65F6\u95F4\u6233\u5951\u7EA6\u3001\u7A33\u5B9A\u5206\u6BB5\u4E0E\u7ED3\u679C
|
|
3798
|
+
Artifact\uFF1B\u5B9E\u65F6 ASR\u3001TTS \u548C Dictation \u5C1A\u672A\u5F00\u653E\u3002\u8BE6\u89C1
|
|
3799
|
+
[Speech AI Runtime](./docs/platform/speech-ai-runtime.md)\u3002
|
|
3800
|
+
|
|
3546
3801
|
ADK Web \u4EC5\u7528\u4E8E\u672C\u673A\u5F00\u53D1\u8C03\u8BD5\uFF1A
|
|
3547
3802
|
|
|
3548
3803
|
\`\`\`bash
|
|
@@ -3602,19 +3857,22 @@ create-windy \u5728\u672C\u673A \`.env\` \u4E2D\u968F\u673A\u751F\u6210\u7684 \`
|
|
|
3602
3857
|
| \u6CD5\u5F8B\u8BB8\u53EF | \`${projectLicense}\` |
|
|
3603
3858
|
|
|
3604
3859
|
\u5E73\u53F0\u5F53\u524D\u6CE8\u518C\u7684\u5168\u90E8\u6A21\u5757\u5982\u4E0B\u3002H0 \u8868\u793A profile \u9501\u5B9A\u6838\u5FC3\uFF1BH2 \u8868\u793A\u521B\u5EFA\u65F6\u53EF\u4EE5\u7269\u7406\u5305\u542B\u6216
|
|
3605
|
-
\u6392\u9664\
|
|
3606
|
-
\
|
|
3860
|
+
\u6392\u9664\uFF1BH3 \u8FD8\u5177\u5907\u90E8\u7F72\u671F\u5B89\u88C5\u3001\u66F4\u65B0\u3001\u6570\u636E\u4FDD\u7559\u5378\u8F7D\u548C\u91CD\u88C5\u8BC1\u636E\u3002\u901A\u7528\u751F\u547D\u5468\u671F\u547D\u4EE4\u4F1A\u4FDD\u5B88
|
|
3861
|
+
\u5904\u7406\u6240\u6709\u76EE\u5F55\u6A21\u5757\uFF0C\u4F46\u53EA\u6709\u901A\u8FC7\u5B8C\u6574 H3 \u56DE\u5F52\u7684\u6A21\u5757\u624D\u6807\u8BB0\u4E3A H3\u3002
|
|
3607
3862
|
|
|
3608
3863
|
| Module Key | \u5F53\u524D\u9879\u76EE | \u70ED\u63D2\u62D4\u53EF\u9760\u5EA6 | \u8BF4\u660E |
|
|
3609
3864
|
| ---------- | -------- | ------------ | ---- |
|
|
3610
3865
|
${moduleRows}
|
|
3611
3866
|
|
|
3612
3867
|
\u9879\u76EE\u81EA\u6709\u4E1A\u52A1\u6A21\u5757\u4EE5 \`apps/server/src/installed-business-modules.ts\` \u88C5\u914D\u7684 Module Manifest
|
|
3613
|
-
\u4E3A\u51C6\
|
|
3868
|
+
\u4E3A\u51C6\uFF1B\u5BF9\u5E94 Vue \u9875\u9762\u5728 project-owned \u7684
|
|
3869
|
+
\`apps/web/src/app/business-routes.ts\` \u6CE8\u518C\uFF0C\u4FA7\u680F\u7EE7\u7EED\u4ECE\u670D\u52A1\u7AEF Manifest \u5FEB\u7167\u751F\u6210\u3002
|
|
3870
|
+
\u4E0D\u8981\u4E3A\u589E\u52A0\u4E1A\u52A1\u9875\u9762\u4FEE\u6539 shared-scaffold Router \u6216 AppSidebar\u3002shared-scaffold README
|
|
3871
|
+
\u4E0D\u590D\u5236\u9879\u76EE\u4E1A\u52A1 Key\uFF0C\u907F\u514D\u5E73\u53F0\u5347\u7EA7\u56FA\u5316\u4EA7\u54C1\u547D\u540D\u3002
|
|
3614
3872
|
|
|
3615
3873
|
\u7CBE\u786E\u751F\u6210\u6765\u6E90\u548C\u9009\u62E9\u8BB0\u5F55\u5728 \`.windy/generation.json\`\u3002\u5F53\u524D\u7248\u672C\u5DF2\u63D0\u4F9B\u53EF\u56DE\u6EDA\u7684
|
|
3616
|
-
\`windy update
|
|
3617
|
-
\u6A21\u5757\
|
|
3874
|
+
\`windy update\` \u4E0E \`windy module list/add/update/remove\`\u3002Feature Flag \u5173\u95ED\u4ECD\u4E0D
|
|
3875
|
+
\u7B49\u4E8E\u6A21\u5757\u5378\u8F7D\u3002
|
|
3618
3876
|
|
|
3619
3877
|
## \u5E38\u7528\u547D\u4EE4
|
|
3620
3878
|
|
|
@@ -3630,6 +3888,9 @@ bun run build
|
|
|
3630
3888
|
bun run windy doctor
|
|
3631
3889
|
bun run windy update --check
|
|
3632
3890
|
bun run windy update --dry-run
|
|
3891
|
+
bun run windy module list
|
|
3892
|
+
bun run windy module add work-order --dry-run
|
|
3893
|
+
bun run windy module remove work-order --dry-run
|
|
3633
3894
|
bun run windy reconcile --to <\u7CBE\u786E\u76EE\u6807\u7248\u672C>
|
|
3634
3895
|
${includeOxc ? `bun run lint
|
|
3635
3896
|
bun run format` : "# \u672C\u9879\u76EE\u672A\u9884\u88C5 lint/format \u5DE5\u5177\uFF0C\u53EF\u6309\u56E2\u961F\u9700\u8981\u81EA\u884C\u9009\u62E9\u3002"}
|
|
@@ -3666,8 +3927,9 @@ create-windy \u9ED8\u8BA4\u5EFA\u7ACB \`main\` \u5206\u652F\u5E76\u521B\u5EFA \`
|
|
|
3666
3927
|
\u6CA1\u6709\u914D\u7F6E Git \u7528\u6237\u8EAB\u4EFD\uFF0C\u6587\u4EF6\u4F1A\u4FDD\u7559\u5728\u6682\u5B58\u533A\uFF1B\u914D\u7F6E\u8EAB\u4EFD\u540E\u624B\u52A8\u63D0\u4EA4\u5373\u53EF\u3002
|
|
3667
3928
|
|
|
3668
3929
|
\u5F53\u524D\u5DF2\u4EA4\u4ED8\u7684 Windy \u66F4\u65B0\u5668\u4F1A\u6839\u636E Project Lock \u548C\u6587\u4EF6\u6240\u6709\u6743\uFF0C\u4ECE npm \u5386\u53F2 artifact
|
|
3669
|
-
\u91CD\u5EFA Base \u5E76\u6267\u884C\u4E09\u65B9\u5408\u5E76\uFF1B\u5B83\u4E0D\u8FDE\u63A5\u79C1\u6709\u6E90\u4ED3\u5E93\uFF0C\u4E5F\u4E0D\u4F1A\u9759\u9ED8\u8986\u76D6\u9879\u76EE\u4EE3\u7801\u3002\
|
|
3670
|
-
|
|
3930
|
+
\u91CD\u5EFA Base \u5E76\u6267\u884C\u4E09\u65B9\u5408\u5E76\uFF1B\u5B83\u4E0D\u8FDE\u63A5\u79C1\u6709\u6E90\u4ED3\u5E93\uFF0C\u4E5F\u4E0D\u4F1A\u9759\u9ED8\u8986\u76D6\u9879\u76EE\u4EE3\u7801\u3002\u6A21\u5757
|
|
3931
|
+
\u751F\u547D\u5468\u671F\u547D\u4EE4\u590D\u7528\u540C\u4E00\u8BA1\u5212\u3001\u4E8B\u52A1\u3001\u9A8C\u8BC1\u4E0E\u6062\u590D\u8FB9\u754C\uFF1B\u5378\u8F7D\u9ED8\u8BA4\u4FDD\u7559\u6570\u636E\u5E93\u6570\u636E\uFF0C\u5E76\u8981\u6C42
|
|
3932
|
+
\u663E\u5F0F\u786E\u8BA4\u6570\u636E\u5904\u7F6E\u8BA1\u5212\u3002
|
|
3671
3933
|
|
|
3672
3934
|
## License
|
|
3673
3935
|
|
|
@@ -3764,6 +4026,9 @@ var templateDirectories = [
|
|
|
3764
4026
|
".agents/skills/windy-business-module",
|
|
3765
4027
|
"apps/server",
|
|
3766
4028
|
"apps/agent-server",
|
|
4029
|
+
"apps/document-server",
|
|
4030
|
+
"apps/speech-server",
|
|
4031
|
+
"apps/embedding-server",
|
|
3767
4032
|
"apps/web",
|
|
3768
4033
|
"examples",
|
|
3769
4034
|
"packages/ai-client",
|
|
@@ -3784,23 +4049,32 @@ var templateDocumentationFiles = [
|
|
|
3784
4049
|
"docs/architecture/ai-runtime.md",
|
|
3785
4050
|
"docs/architecture/data-scope-query-enforcement.md",
|
|
3786
4051
|
"docs/architecture/durable-jobs.md",
|
|
4052
|
+
"docs/architecture/foundation-infrastructure.md",
|
|
3787
4053
|
"docs/architecture/minimal-approval-workflow.md",
|
|
3788
4054
|
"docs/architecture/mcp-business-capabilities.md",
|
|
3789
4055
|
"docs/architecture/migration-bundle.md",
|
|
4056
|
+
"docs/architecture/module-host.md",
|
|
3790
4057
|
"docs/architecture/module-manifest-composition.md",
|
|
3791
4058
|
"docs/architecture/object-storage.md",
|
|
3792
4059
|
"docs/architecture/search-provider-protocol.md",
|
|
4060
|
+
"docs/architecture/server-module-interface.md",
|
|
4061
|
+
"docs/architecture/web-access-snapshot-resilience.md",
|
|
4062
|
+
"docs/development/business-web-routes.md",
|
|
3793
4063
|
"docs/development/crud-generator.md",
|
|
3794
4064
|
"docs/development/custom-error-pages.md",
|
|
3795
4065
|
"docs/development/custom-login-page.md",
|
|
4066
|
+
"docs/development/module-lifecycle.md",
|
|
3796
4067
|
"docs/license/license-offline-activation-code.md",
|
|
3797
4068
|
"docs/operations/observability.md",
|
|
3798
4069
|
"docs/platform/agent-tools.md",
|
|
3799
4070
|
"docs/platform/agent-runtime.md",
|
|
4071
|
+
"docs/platform/agent-tool-sandbox.md",
|
|
3800
4072
|
"docs/platform/audit-reliability.md",
|
|
3801
4073
|
"docs/platform/bulk-data-jobs.md",
|
|
3802
4074
|
"docs/platform/business-user-directory.md",
|
|
3803
4075
|
"docs/platform/data-access-control.md",
|
|
4076
|
+
"docs/platform/document-ai-runtime.md",
|
|
4077
|
+
"docs/platform/governed-export-renderers.md",
|
|
3804
4078
|
"docs/platform/module-configuration.md",
|
|
3805
4079
|
"docs/platform/navigation-registry.md",
|
|
3806
4080
|
"docs/platform/notifications.md",
|
|
@@ -3809,7 +4083,9 @@ var templateDocumentationFiles = [
|
|
|
3809
4083
|
"docs/platform/platform-authentication.md",
|
|
3810
4084
|
"docs/platform/platform-shell-settings.md",
|
|
3811
4085
|
"docs/platform/scheduled-task-executor.md",
|
|
4086
|
+
"docs/platform/speech-ai-runtime.md",
|
|
3812
4087
|
"docs/platform/system-crud-api.md",
|
|
4088
|
+
"docs/platform/vision-ai-runtime.md",
|
|
3813
4089
|
"docs/platform/web-system-crud.md",
|
|
3814
4090
|
"docs/product/built-in-roles.md"
|
|
3815
4091
|
];
|
|
@@ -4030,7 +4306,7 @@ async function generateProject(input) {
|
|
|
4030
4306
|
await writeFile8(join12(input.targetDirectory, "docker-compose.yml"), starterComposeFor(selectedModules.includes("system.agent"), selectedModules.includes("system.search")));
|
|
4031
4307
|
await writeFile8(join12(input.targetDirectory, ".env.example"), environmentExample(includeExample, selectedModules.includes("system.agent"), selectedModules.includes("system.search")));
|
|
4032
4308
|
await writeFile8(join12(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
|
|
4033
|
-
await writeFile8(join12(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license"), selectedModules.includes("system.agent")));
|
|
4309
|
+
await writeFile8(join12(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license"), selectedModules.includes("system.agent"), selectedModules.includes("system.operations")));
|
|
4034
4310
|
await reflectCodeQualityChoice(input.targetDirectory, includeOxc);
|
|
4035
4311
|
await applyWindyBaseLicense(input.targetDirectory);
|
|
4036
4312
|
await applyProjectLicense(input.targetDirectory, projectLicense, input.licenseHolder);
|
|
@@ -5957,8 +6233,8 @@ function sentenceWithoutStop(value) {
|
|
|
5957
6233
|
}
|
|
5958
6234
|
|
|
5959
6235
|
// src/update/cli.ts
|
|
5960
|
-
import { rm as
|
|
5961
|
-
import { resolve as
|
|
6236
|
+
import { rm as rm11 } from "fs/promises";
|
|
6237
|
+
import { resolve as resolve8 } from "path";
|
|
5962
6238
|
|
|
5963
6239
|
// src/reconcile/managed-reconciler.ts
|
|
5964
6240
|
import { rm as rm6 } from "fs/promises";
|
|
@@ -8366,8 +8642,51 @@ function isObject(value) {
|
|
|
8366
8642
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8367
8643
|
}
|
|
8368
8644
|
|
|
8645
|
+
// src/update/planner-project-owned.ts
|
|
8646
|
+
function planGeneratedProjectOwned(path2, source, target, ours, theirs, expected) {
|
|
8647
|
+
if (!source && target) {
|
|
8648
|
+
return !ours && theirs ? ready(path2, "create", "\u6A21\u5757\u5B89\u88C5\u65B0\u589E\u9879\u76EE\u6269\u5C55\u70B9", expected, theirs) : conflict(path2, "\u6A21\u5757\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
|
|
8649
|
+
}
|
|
8650
|
+
if (source && !target) {
|
|
8651
|
+
if (!ours) {
|
|
8652
|
+
return ready(path2, "preserve", "\u6A21\u5757\u8DEF\u5F84\u5DF2\u79FB\u9664", expected);
|
|
8653
|
+
}
|
|
8654
|
+
return hashContent(ours) === source.hash ? ready(path2, "delete", "\u6A21\u5757\u5378\u8F7D\u79FB\u9664\u672A\u4FEE\u6539\u6269\u5C55\u70B9", expected) : conflict(path2, "\u5BA2\u6237\u4FEE\u6539\u8FC7\u6A21\u5757\u6269\u5C55\u70B9\uFF0C\u62D2\u7EDD\u5378\u8F7D", expected);
|
|
8655
|
+
}
|
|
8656
|
+
if (!source || !target || !ours || !theirs) {
|
|
8657
|
+
return ready(path2, "preserve", "\u9879\u76EE\u62E5\u6709\uFF0C\u6A21\u5757\u7EC4\u5408\u672A\u6539\u53D8", expected);
|
|
8658
|
+
}
|
|
8659
|
+
if (hashContent(ours) === target.hash) {
|
|
8660
|
+
return ready(path2, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u6A21\u5757\u7EC4\u5408", expected);
|
|
8661
|
+
}
|
|
8662
|
+
if (source.hash === target.hash) {
|
|
8663
|
+
return ready(path2, "preserve", "\u6A21\u5757\u7EC4\u5408\u672A\u6539\u53D8", expected);
|
|
8664
|
+
}
|
|
8665
|
+
return hashContent(ours) === source.hash ? ready(path2, "update", "\u66F4\u65B0\u672A\u4FEE\u6539\u7684\u6A21\u5757\u7EC4\u5408\u6269\u5C55\u70B9", expected, theirs) : conflict(path2, "\u5BA2\u6237\u4FEE\u6539\u8FC7\u6A21\u5757\u7EC4\u5408\u6269\u5C55\u70B9", expected);
|
|
8666
|
+
}
|
|
8667
|
+
function ready(path2, action, reason, expectedProjectContent, content) {
|
|
8668
|
+
return {
|
|
8669
|
+
path: path2,
|
|
8670
|
+
ownership: "project-owned",
|
|
8671
|
+
action,
|
|
8672
|
+
reason,
|
|
8673
|
+
expectedProjectContent,
|
|
8674
|
+
content
|
|
8675
|
+
};
|
|
8676
|
+
}
|
|
8677
|
+
function conflict(path2, reason, expectedProjectContent) {
|
|
8678
|
+
return {
|
|
8679
|
+
path: path2,
|
|
8680
|
+
ownership: "project-owned",
|
|
8681
|
+
action: "preserve",
|
|
8682
|
+
reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
|
|
8683
|
+
expectedProjectContent,
|
|
8684
|
+
conflict: reason
|
|
8685
|
+
};
|
|
8686
|
+
}
|
|
8687
|
+
|
|
8369
8688
|
// src/update/planner-file.ts
|
|
8370
|
-
async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride) {
|
|
8689
|
+
async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride, manageGeneratedProjectOwned = false) {
|
|
8371
8690
|
const [base, theirs] = await Promise.all([
|
|
8372
8691
|
readOptional(join19(baseRoot, path2)),
|
|
8373
8692
|
targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional(join19(targetRoot, path2))
|
|
@@ -8375,6 +8694,9 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
|
|
|
8375
8694
|
const ownership = source?.ownership === "project-owned" ? source.ownership : target?.ownership || source?.ownership || classifyOwnership(path2);
|
|
8376
8695
|
const expected = expectationForSnapshot(ours);
|
|
8377
8696
|
if (ownership === "project-owned") {
|
|
8697
|
+
if (manageGeneratedProjectOwned) {
|
|
8698
|
+
return planGeneratedProjectOwned(path2, source, target, ours, theirs, expected);
|
|
8699
|
+
}
|
|
8378
8700
|
return !source && !ours && theirs ? readyPlannedFile(path2, ownership, "create", "\u65B0\u589E\u9879\u76EE\u6269\u5C55\u70B9", expected, theirs) : readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u62E5\u6709\uFF0CWindy \u4E0D\u8986\u76D6", expected);
|
|
8379
8701
|
}
|
|
8380
8702
|
const repaired = ours && theirs ? repairKnownDerivedFile({
|
|
@@ -8389,26 +8711,26 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
|
|
|
8389
8711
|
}
|
|
8390
8712
|
if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
|
|
8391
8713
|
if (source && !target) {
|
|
8392
|
-
return
|
|
8714
|
+
return conflict2(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
|
|
8393
8715
|
}
|
|
8394
8716
|
if (source && target && source.hash !== target.hash) {
|
|
8395
|
-
return
|
|
8717
|
+
return conflict2(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
|
|
8396
8718
|
}
|
|
8397
8719
|
}
|
|
8398
8720
|
if (!source && target) {
|
|
8399
8721
|
if (!ours) {
|
|
8400
8722
|
return readyPlannedFile(path2, ownership, "create", "\u76EE\u6807\u7248\u672C\u65B0\u589E", expected, theirs);
|
|
8401
8723
|
}
|
|
8402
|
-
return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) :
|
|
8724
|
+
return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict2(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
|
|
8403
8725
|
}
|
|
8404
8726
|
if (source && !target) {
|
|
8405
8727
|
if (!ours) {
|
|
8406
8728
|
return readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
|
|
8407
8729
|
}
|
|
8408
|
-
return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) :
|
|
8730
|
+
return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict2(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
|
|
8409
8731
|
}
|
|
8410
8732
|
if (!source || !target || !ours || !theirs) {
|
|
8411
|
-
return
|
|
8733
|
+
return conflict2(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
|
|
8412
8734
|
}
|
|
8413
8735
|
const oursChanged = hashContent(ours) !== source.hash;
|
|
8414
8736
|
const sourceArtifactHash = artifactHashOf(source);
|
|
@@ -8428,13 +8750,13 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
|
|
|
8428
8750
|
}
|
|
8429
8751
|
if (path2.endsWith("package.json") && base) {
|
|
8430
8752
|
const merged = mergePackageJson(base, ours, theirs);
|
|
8431
|
-
return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) :
|
|
8753
|
+
return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict2(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
|
|
8432
8754
|
}
|
|
8433
8755
|
if (ownership === "shared-scaffold" && base) {
|
|
8434
8756
|
const merged = await mergeTextFile(base, ours, theirs);
|
|
8435
|
-
return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) :
|
|
8757
|
+
return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict2(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
|
|
8436
8758
|
}
|
|
8437
|
-
return
|
|
8759
|
+
return conflict2(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
|
|
8438
8760
|
}
|
|
8439
8761
|
function targetChangedSinceBase(sourceHash, base, target) {
|
|
8440
8762
|
return base && target ? hashContent(base) !== hashContent(target) : !!target && hashContent(target) !== sourceHash;
|
|
@@ -8452,7 +8774,7 @@ function readyPlannedFile(path2, ownership, action, reason, expectedProjectConte
|
|
|
8452
8774
|
function expectationForSnapshot(content) {
|
|
8453
8775
|
return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
|
|
8454
8776
|
}
|
|
8455
|
-
function
|
|
8777
|
+
function conflict2(path2, ownership, reason, expectedProjectContent) {
|
|
8456
8778
|
return {
|
|
8457
8779
|
path: path2,
|
|
8458
8780
|
ownership,
|
|
@@ -8633,7 +8955,10 @@ var recipes = [
|
|
|
8633
8955
|
{ id: "starter-0.2.33-to-0.2.34", from: "0.2.33", to: "0.2.34" },
|
|
8634
8956
|
{ id: "starter-0.2.34-to-0.3.0", from: "0.2.34", to: "0.3.0" },
|
|
8635
8957
|
{ id: "starter-0.3.0-to-0.3.1", from: "0.3.0", to: "0.3.1" },
|
|
8636
|
-
{ id: "starter-0.3.1-to-0.3.2", from: "0.3.1", to: "0.3.2" }
|
|
8958
|
+
{ id: "starter-0.3.1-to-0.3.2", from: "0.3.1", to: "0.3.2" },
|
|
8959
|
+
{ id: "starter-0.3.2-to-0.3.3", from: "0.3.2", to: "0.3.3" },
|
|
8960
|
+
{ id: "starter-0.3.3-to-0.3.4", from: "0.3.3", to: "0.3.4" },
|
|
8961
|
+
{ id: "starter-0.3.4-to-0.3.5", from: "0.3.4", to: "0.3.5" }
|
|
8637
8962
|
];
|
|
8638
8963
|
function resolveRecipeChain(sourceVersion, targetVersion) {
|
|
8639
8964
|
if (sourceVersion === targetVersion)
|
|
@@ -8674,13 +8999,15 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8674
8999
|
const expectedManifestHash = hashContent(await readFile17(manifestPath));
|
|
8675
9000
|
const generationSnapshot = await readGenerationProvenanceSnapshot(request.projectDirectory);
|
|
8676
9001
|
const provenance = generationSnapshot.provenance;
|
|
8677
|
-
const artifactSet = await artifacts.prepare(request.projectDirectory, provenance);
|
|
9002
|
+
const artifactSet = await artifacts.prepare(request.projectDirectory, provenance, request.targetModules);
|
|
8678
9003
|
const targetProvenance = await readGenerationProvenance(artifactSet.targetDirectory);
|
|
8679
9004
|
const targetVersion = request.targetVersion || targetProvenance.generatorVersion;
|
|
8680
9005
|
if (targetVersion !== targetProvenance.generatorVersion) {
|
|
8681
9006
|
throw new Error(`\u5F53\u524D CLI \u53EA\u80FD\u66F4\u65B0\u5230 ${targetProvenance.generatorVersion}\uFF0C\u8BF7\u8FD0\u884C create-windy@${targetVersion}`);
|
|
8682
9007
|
}
|
|
8683
|
-
const
|
|
9008
|
+
const versionRecipes = resolveRecipeChain(provenance.windyVersion, targetVersion);
|
|
9009
|
+
const moduleRecipes = resolveModuleRecipeIds(request);
|
|
9010
|
+
const recipes2 = [...versionRecipes.map(({ id }) => id), ...moduleRecipes];
|
|
8684
9011
|
const [rawSourceManifest, rawTargetManifest] = await Promise.all([
|
|
8685
9012
|
readManagedFilesManifest(request.projectDirectory),
|
|
8686
9013
|
readManagedFilesManifest(artifactSet.targetDirectory)
|
|
@@ -8693,6 +9020,7 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8693
9020
|
...generatedTargetManifest.files.map(({ path: path2 }) => path2)
|
|
8694
9021
|
]);
|
|
8695
9022
|
const workspaceSnapshot = await snapshotWorkspacePackages(request.projectDirectory, { allowMissingRoot: true });
|
|
9023
|
+
const targetWorkspaceSnapshot = await snapshotWorkspacePackages(artifactSet.targetDirectory, { allowMissingRoot: true });
|
|
8696
9024
|
const projectSnapshots = await snapshotProjectFiles(request.projectDirectory, initialPaths, workspaceSnapshot.manifests);
|
|
8697
9025
|
projectSnapshots.set(generationMetadataFile, generationSnapshot.content);
|
|
8698
9026
|
const projectModes = await snapshotProjectModes(request.projectDirectory, initialPaths);
|
|
@@ -8706,8 +9034,7 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8706
9034
|
});
|
|
8707
9035
|
const targetManifest = await carryReconciledBaselines(sourceManifest, migrations.targetManifest, projectSnapshots, artifactSet.targetDirectory);
|
|
8708
9036
|
targetProvenance.appliedRecipes = [
|
|
8709
|
-
...provenance.appliedRecipes,
|
|
8710
|
-
...recipes2.map(({ id }) => id)
|
|
9037
|
+
...new Set([...provenance.appliedRecipes, ...recipes2])
|
|
8711
9038
|
];
|
|
8712
9039
|
const sourceEntries = new Map(sourceManifest.files.map((item) => [item.path, item]));
|
|
8713
9040
|
const targetEntries = new Map(targetManifest.files.map((item) => [item.path, item]));
|
|
@@ -8725,7 +9052,8 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8725
9052
|
targetEntries,
|
|
8726
9053
|
migrations,
|
|
8727
9054
|
artifactSet,
|
|
8728
|
-
provenance
|
|
9055
|
+
provenance,
|
|
9056
|
+
manageGeneratedProjectOwned: request.targetModules !== undefined
|
|
8729
9057
|
});
|
|
8730
9058
|
deriveWebDockerfilePlan(files, projectSnapshots, new Set([...paths, ...workspaceSnapshot.manifests.keys()]));
|
|
8731
9059
|
for (const file of files) {
|
|
@@ -8772,18 +9100,33 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8772
9100
|
projectDirectory: request.projectDirectory,
|
|
8773
9101
|
sourceVersion: provenance.windyVersion,
|
|
8774
9102
|
targetVersion,
|
|
8775
|
-
recipes: recipes2
|
|
9103
|
+
recipes: recipes2,
|
|
8776
9104
|
files,
|
|
8777
9105
|
dependencyExpectations,
|
|
8778
9106
|
workspaceMembershipExpectations: workspaceSnapshot.membershipExpectations,
|
|
9107
|
+
finalWorkspaceMembershipExpectations: targetWorkspaceSnapshot.membershipExpectations,
|
|
8779
9108
|
conflicts,
|
|
8780
9109
|
detachedToolchain,
|
|
8781
9110
|
targetProvenance,
|
|
8782
9111
|
sourceManifest,
|
|
8783
9112
|
targetManifest,
|
|
8784
|
-
temporaryRoot: artifactSet.temporaryRoot
|
|
9113
|
+
temporaryRoot: artifactSet.temporaryRoot,
|
|
9114
|
+
lifecycle: request.lifecycle
|
|
8785
9115
|
};
|
|
8786
9116
|
}
|
|
9117
|
+
function resolveModuleRecipeIds(request) {
|
|
9118
|
+
const lifecycle = request.lifecycle;
|
|
9119
|
+
if (!lifecycle)
|
|
9120
|
+
return [];
|
|
9121
|
+
const catalog = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
9122
|
+
if (lifecycle.action === "add") {
|
|
9123
|
+
return lifecycle.addedModules.map((name) => catalog.get(name).installRecipe);
|
|
9124
|
+
}
|
|
9125
|
+
if (lifecycle.action === "remove") {
|
|
9126
|
+
return lifecycle.removedModules.map((name) => catalog.get(name).uninstallRecipe);
|
|
9127
|
+
}
|
|
9128
|
+
return lifecycle.updatedModules.flatMap((name) => catalog.get(name).updateRecipes);
|
|
9129
|
+
}
|
|
8787
9130
|
async function planFiles(input) {
|
|
8788
9131
|
const files = [];
|
|
8789
9132
|
for (const path2 of [...input.paths].sort()) {
|
|
@@ -8797,7 +9140,7 @@ async function planFiles(input) {
|
|
|
8797
9140
|
} else if (forcedContent) {
|
|
8798
9141
|
files.push(readyPlannedFile(path2, input.targetEntries.get(path2)?.ownership ?? input.sourceEntries.get(path2)?.ownership ?? classifyOwnership(path2), "update", "\u5408\u5E76\u5E73\u53F0\u4E0E\u4E0B\u6E38 migration \u5386\u53F2", expected, forcedContent));
|
|
8799
9142
|
} else {
|
|
8800
|
-
files.push(await planFile(path2, input.artifactSet.baseDirectory, input.artifactSet.targetDirectory, input.sourceEntries.get(path2), input.targetEntries.get(path2), ours, input.provenance, input.migrations.contentOverrides.get(path2)));
|
|
9143
|
+
files.push(await planFile(path2, input.artifactSet.baseDirectory, input.artifactSet.targetDirectory, input.sourceEntries.get(path2), input.targetEntries.get(path2), ours, input.provenance, input.migrations.contentOverrides.get(path2), input.manageGeneratedProjectOwned));
|
|
8801
9144
|
}
|
|
8802
9145
|
}
|
|
8803
9146
|
return files;
|
|
@@ -9514,23 +9857,113 @@ async function diagnoseProject(projectDirectory, repair = false) {
|
|
|
9514
9857
|
}
|
|
9515
9858
|
|
|
9516
9859
|
// src/update/updater.ts
|
|
9517
|
-
import { readFile as
|
|
9518
|
-
import { join as
|
|
9860
|
+
import { readFile as readFile24, rm as rm9 } from "fs/promises";
|
|
9861
|
+
import { join as join31 } from "path";
|
|
9519
9862
|
|
|
9520
9863
|
// src/update/artifacts.ts
|
|
9521
|
-
import { mkdtemp as mkdtemp3, readFile as
|
|
9864
|
+
import { mkdtemp as mkdtemp3, readFile as readFile22 } from "fs/promises";
|
|
9522
9865
|
import { tmpdir as tmpdir3 } from "os";
|
|
9523
|
-
import { basename as basename8, join as
|
|
9866
|
+
import { basename as basename8, join as join29 } from "path";
|
|
9867
|
+
|
|
9868
|
+
// src/module-history.ts
|
|
9869
|
+
import {
|
|
9870
|
+
lstat as lstat5,
|
|
9871
|
+
mkdir as mkdir7,
|
|
9872
|
+
readdir as readdir8,
|
|
9873
|
+
readFile as readFile21,
|
|
9874
|
+
writeFile as writeFile11
|
|
9875
|
+
} from "fs/promises";
|
|
9876
|
+
import { dirname as dirname7, join as join28, relative as relative4, sep as sep4 } from "path";
|
|
9877
|
+
async function archiveRemovedModuleMigrations(input) {
|
|
9878
|
+
await assertExistingHistoryIntegrity(input.projectDirectory);
|
|
9879
|
+
let changed = await copyMigrationTree(input.projectDirectory, ".windy/module-history", join28(input.targetDirectory, ".windy/module-history"));
|
|
9880
|
+
const target = new Set(input.targetModules);
|
|
9881
|
+
const removed = moduleDistributionCatalog.filter(({ name }) => input.sourceModules.includes(name) && !target.has(name));
|
|
9882
|
+
for (const manifest of removed) {
|
|
9883
|
+
for (const root of manifest.migrationRoots) {
|
|
9884
|
+
changed = await copyMigrationTree(input.projectDirectory, root, join28(input.targetDirectory, ".windy/module-history", manifest.name, root)) || changed;
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
if (changed) {
|
|
9888
|
+
await writeManagedFilesManifest(input.targetDirectory, input.generatorVersion);
|
|
9889
|
+
}
|
|
9890
|
+
}
|
|
9891
|
+
async function assertExistingHistoryIntegrity(projectDirectory) {
|
|
9892
|
+
const historyRoot = join28(projectDirectory, ".windy/module-history");
|
|
9893
|
+
const metadata = await readOptionalMetadata(historyRoot);
|
|
9894
|
+
if (!metadata)
|
|
9895
|
+
return;
|
|
9896
|
+
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
9897
|
+
throw new Error("\u6A21\u5757 migration \u5386\u53F2\u76EE\u5F55\u65E0\u6548");
|
|
9898
|
+
}
|
|
9899
|
+
const manifest = await readManagedFilesManifest(projectDirectory);
|
|
9900
|
+
const expected = new Map(manifest.files.map((entry) => [entry.path, entry]));
|
|
9901
|
+
for (const path2 of await collectRegularFiles(historyRoot)) {
|
|
9902
|
+
const relativePath2 = relative4(projectDirectory, path2).split(sep4).join("/");
|
|
9903
|
+
const entry = expected.get(relativePath2);
|
|
9904
|
+
if (!entry || isMissingManagedFile(entry)) {
|
|
9905
|
+
throw new Error(`\u6A21\u5757 migration \u5386\u53F2\u672A\u767B\u8BB0\u5230\u53D7\u7BA1\u6E05\u5355\uFF1A${relativePath2}`);
|
|
9906
|
+
}
|
|
9907
|
+
if (hashContent(await readFile21(path2)) !== entry.hash) {
|
|
9908
|
+
throw new Error(`\u6A21\u5757 migration \u5386\u53F2\u5DF2\u88AB\u4FEE\u6539\uFF1A${relativePath2}`);
|
|
9909
|
+
}
|
|
9910
|
+
}
|
|
9911
|
+
}
|
|
9912
|
+
async function copyMigrationTree(projectRoot, relativeRoot, targetRoot) {
|
|
9913
|
+
const sourceRoot = join28(projectRoot, relativeRoot);
|
|
9914
|
+
const rootMetadata = await readOptionalMetadata(sourceRoot);
|
|
9915
|
+
if (!rootMetadata)
|
|
9916
|
+
return false;
|
|
9917
|
+
if (rootMetadata.isSymbolicLink() || !rootMetadata.isDirectory()) {
|
|
9918
|
+
throw new Error(`\u6A21\u5757 migration \u6839\u76EE\u5F55\u65E0\u6548\uFF1A${relativeRoot}`);
|
|
9919
|
+
}
|
|
9920
|
+
for (const source of await collectRegularFiles(sourceRoot)) {
|
|
9921
|
+
const target = join28(targetRoot, relative4(sourceRoot, source).split(sep4).join("/"));
|
|
9922
|
+
await mkdir7(dirname7(target), { recursive: true });
|
|
9923
|
+
await writeFile11(target, await readFile21(source));
|
|
9924
|
+
}
|
|
9925
|
+
return true;
|
|
9926
|
+
}
|
|
9927
|
+
async function collectRegularFiles(root) {
|
|
9928
|
+
const files = [];
|
|
9929
|
+
await visit(root);
|
|
9930
|
+
return files.sort();
|
|
9931
|
+
async function visit(directory) {
|
|
9932
|
+
for (const name of (await readdir8(directory)).sort()) {
|
|
9933
|
+
const path2 = join28(directory, name);
|
|
9934
|
+
const metadata = await lstat5(path2);
|
|
9935
|
+
if (metadata.isSymbolicLink()) {
|
|
9936
|
+
throw new Error(`\u6A21\u5757 migration \u4E0D\u5141\u8BB8\u7B26\u53F7\u94FE\u63A5\uFF1A${path2}`);
|
|
9937
|
+
}
|
|
9938
|
+
if (metadata.isDirectory())
|
|
9939
|
+
await visit(path2);
|
|
9940
|
+
else if (metadata.isFile())
|
|
9941
|
+
files.push(path2);
|
|
9942
|
+
}
|
|
9943
|
+
}
|
|
9944
|
+
}
|
|
9945
|
+
async function readOptionalMetadata(path2) {
|
|
9946
|
+
try {
|
|
9947
|
+
return await lstat5(path2);
|
|
9948
|
+
} catch (error) {
|
|
9949
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
9950
|
+
return;
|
|
9951
|
+
}
|
|
9952
|
+
throw error;
|
|
9953
|
+
}
|
|
9954
|
+
}
|
|
9955
|
+
|
|
9956
|
+
// src/update/artifacts.ts
|
|
9524
9957
|
class PublishedArtifactProvider {
|
|
9525
9958
|
#fetch;
|
|
9526
9959
|
constructor(fetcher = globalThis.fetch) {
|
|
9527
9960
|
this.#fetch = fetcher;
|
|
9528
9961
|
}
|
|
9529
|
-
async prepare(projectDirectory, provenance) {
|
|
9530
|
-
const temporaryRoot = await mkdtemp3(
|
|
9962
|
+
async prepare(projectDirectory, provenance, targetModules) {
|
|
9963
|
+
const temporaryRoot = await mkdtemp3(join29(tmpdir3(), "windy-update-"));
|
|
9531
9964
|
const projectName = await readProjectName3(projectDirectory);
|
|
9532
|
-
const baseDirectory =
|
|
9533
|
-
const targetDirectory =
|
|
9965
|
+
const baseDirectory = join29(temporaryRoot, "base", projectName);
|
|
9966
|
+
const targetDirectory = join29(temporaryRoot, "target", projectName);
|
|
9534
9967
|
const baseArtifact = await downloadPublicArtifact(temporaryRoot, "base", provenance.generatorVersion, undefined, this.#fetch);
|
|
9535
9968
|
if (baseArtifact.identity.templateCommit !== provenance.templateCommit) {
|
|
9536
9969
|
throw new Error("Project Lock \u4E0E\u6765\u6E90 registry artifact \u7684 template commit \u4E0D\u4E00\u81F4");
|
|
@@ -9540,18 +9973,25 @@ class PublishedArtifactProvider {
|
|
|
9540
9973
|
sourceRoot: await resolveTemplateRoot(),
|
|
9541
9974
|
targetDirectory,
|
|
9542
9975
|
projectName,
|
|
9543
|
-
selectedModules: provenance.modules.map(({ name }) => name),
|
|
9544
|
-
includeExample: provenance.
|
|
9976
|
+
selectedModules: targetModules ?? provenance.modules.map(({ name }) => name),
|
|
9977
|
+
includeExample: (targetModules ?? provenance.modules.map(({ name }) => name)).includes("work-order"),
|
|
9545
9978
|
includeOxc: provenance.choices.includeOxc,
|
|
9546
9979
|
projectLicense: provenance.legalLicense,
|
|
9547
9980
|
licenseHolder: provenance.legalLicense === "MIT" ? "Windy project owner" : undefined,
|
|
9548
9981
|
profile: provenance.profile
|
|
9549
9982
|
});
|
|
9983
|
+
await archiveRemovedModuleMigrations({
|
|
9984
|
+
projectDirectory,
|
|
9985
|
+
targetDirectory,
|
|
9986
|
+
sourceModules: provenance.modules.map(({ name }) => name),
|
|
9987
|
+
targetModules: targetModules ?? provenance.modules.map(({ name }) => name),
|
|
9988
|
+
generatorVersion: (await readGenerationProvenance(targetDirectory)).generatorVersion
|
|
9989
|
+
});
|
|
9550
9990
|
return { temporaryRoot, baseDirectory, targetDirectory };
|
|
9551
9991
|
}
|
|
9552
9992
|
}
|
|
9553
9993
|
async function readProjectName3(projectDirectory) {
|
|
9554
|
-
const source = JSON.parse(await
|
|
9994
|
+
const source = JSON.parse(await readFile22(join29(projectDirectory, "package.json"), "utf8"));
|
|
9555
9995
|
return source.name || basename8(projectDirectory);
|
|
9556
9996
|
}
|
|
9557
9997
|
|
|
@@ -9618,9 +10058,9 @@ function frozenManifestHash(file, finalizedHashes) {
|
|
|
9618
10058
|
}
|
|
9619
10059
|
|
|
9620
10060
|
// src/update/format-stabilizer.ts
|
|
9621
|
-
import { mkdir as
|
|
10061
|
+
import { mkdir as mkdir8, mkdtemp as mkdtemp4, readFile as readFile23, rm as rm8, writeFile as writeFile12 } from "fs/promises";
|
|
9622
10062
|
import { tmpdir as tmpdir4 } from "os";
|
|
9623
|
-
import { dirname as
|
|
10063
|
+
import { dirname as dirname8, extname as extname4, join as join30, resolve as resolve6, sep as sep5 } from "path";
|
|
9624
10064
|
var formattedExtensions = new Set([
|
|
9625
10065
|
".cjs",
|
|
9626
10066
|
".css",
|
|
@@ -9659,7 +10099,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
9659
10099
|
}
|
|
9660
10100
|
}
|
|
9661
10101
|
inputs.set(".windy/generation.json", new TextEncoder().encode(generationContent));
|
|
9662
|
-
const temporaryRoot = await mkdtemp4(
|
|
10102
|
+
const temporaryRoot = await mkdtemp4(join30(tmpdir4(), "windy-update-format-"));
|
|
9663
10103
|
try {
|
|
9664
10104
|
const stagedPaths = await stageInputs(temporaryRoot, inputs);
|
|
9665
10105
|
for (let offset = 0;offset < stagedPaths.length; offset += 80) {
|
|
@@ -9667,14 +10107,14 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
9667
10107
|
"x",
|
|
9668
10108
|
"oxfmt",
|
|
9669
10109
|
"--write",
|
|
9670
|
-
`--config=${
|
|
10110
|
+
`--config=${join30(result2.plan.projectDirectory, ".oxfmtrc.json")}`,
|
|
9671
10111
|
...stagedPaths.slice(offset, offset + 80)
|
|
9672
10112
|
], result2.plan.projectDirectory);
|
|
9673
10113
|
}
|
|
9674
10114
|
const hashes = plannedContentHashes(result2);
|
|
9675
10115
|
let formattedGeneration = generationContent;
|
|
9676
10116
|
for (const [path2, original] of inputs) {
|
|
9677
|
-
const formatted = await
|
|
10117
|
+
const formatted = await readFile23(safeTemporaryPath(temporaryRoot, path2));
|
|
9678
10118
|
if (path2 === ".windy/generation.json") {
|
|
9679
10119
|
formattedGeneration = formatted.toString();
|
|
9680
10120
|
continue;
|
|
@@ -9700,15 +10140,15 @@ async function stageInputs(temporaryRoot, inputs) {
|
|
|
9700
10140
|
const paths = [];
|
|
9701
10141
|
for (const [path2, content] of inputs) {
|
|
9702
10142
|
const target = safeTemporaryPath(temporaryRoot, path2);
|
|
9703
|
-
await
|
|
9704
|
-
await
|
|
10143
|
+
await mkdir8(dirname8(target), { recursive: true });
|
|
10144
|
+
await writeFile12(target, content);
|
|
9705
10145
|
paths.push(target);
|
|
9706
10146
|
}
|
|
9707
10147
|
return paths;
|
|
9708
10148
|
}
|
|
9709
10149
|
function safeTemporaryPath(root, path2) {
|
|
9710
10150
|
const target = resolve6(root, path2);
|
|
9711
|
-
if (!target.startsWith(`${resolve6(root)}${
|
|
10151
|
+
if (!target.startsWith(`${resolve6(root)}${sep5}`)) {
|
|
9712
10152
|
throw new Error(`\u683C\u5F0F\u5316\u8DEF\u5F84\u8D8A\u51FA\u4E34\u65F6\u76EE\u5F55\uFF1A${path2}`);
|
|
9713
10153
|
}
|
|
9714
10154
|
return target;
|
|
@@ -9771,7 +10211,7 @@ class DefaultStarterUpdater {
|
|
|
9771
10211
|
const plannedPaths = new Set(result2.plan.files.map(({ path: path2 }) => path2));
|
|
9772
10212
|
replaceExpectations(result2, verificationSnapshot.filter(({ path: path2 }) => !metadataPaths2.has(path2) && !plannedPaths.has(path2)));
|
|
9773
10213
|
verificationExpectationsFrozen = true;
|
|
9774
|
-
const packageJson = JSON.parse(await
|
|
10214
|
+
const packageJson = JSON.parse(await readFile24(join31(result2.plan.projectDirectory, "package.json"), "utf8"));
|
|
9775
10215
|
for (const name of ["lint", "typecheck", "test", "build"]) {
|
|
9776
10216
|
if (!packageJson.scripts?.[name]) {
|
|
9777
10217
|
steps.push({ name: `bun run ${name}`, status: "skipped" });
|
|
@@ -9790,7 +10230,7 @@ class DefaultStarterUpdater {
|
|
|
9790
10230
|
projectDirectory: result2.plan.projectDirectory,
|
|
9791
10231
|
ownerToken: result2.transactionOwnerToken,
|
|
9792
10232
|
expectations: result2.finalizationExpectations,
|
|
9793
|
-
workspaceMembershipExpectations: result2.plan.workspaceMembershipExpectations
|
|
10233
|
+
workspaceMembershipExpectations: result2.plan.finalWorkspaceMembershipExpectations ?? result2.plan.workspaceMembershipExpectations
|
|
9794
10234
|
});
|
|
9795
10235
|
return { updateId: result2.plan.id, status: "passed", steps, reportPath };
|
|
9796
10236
|
} catch (error) {
|
|
@@ -9854,6 +10294,12 @@ async function writeReport(result2, steps, relativePath2) {
|
|
|
9854
10294
|
`- \u6765\u6E90\u7248\u672C\uFF1A${result2.plan.sourceVersion}`,
|
|
9855
10295
|
`- \u76EE\u6807\u7248\u672C\uFF1A${result2.plan.targetVersion}`,
|
|
9856
10296
|
`- Recipe\uFF1A${result2.plan.recipes.join("\u3001") || "\u65E0"}`,
|
|
10297
|
+
...result2.plan.lifecycle ? [
|
|
10298
|
+
`- \u6A21\u5757\u52A8\u4F5C\uFF1A${result2.plan.lifecycle.action}`,
|
|
10299
|
+
`- \u8BF7\u6C42\u6A21\u5757\uFF1A${result2.plan.lifecycle.requestedModules.join("\u3001")}`,
|
|
10300
|
+
`- \u6570\u636E\u5904\u7F6E\uFF1A${result2.plan.lifecycle.dataDisposition ?? "\u4E0D\u9002\u7528"}`,
|
|
10301
|
+
`- \u6570\u636E\u5904\u7F6E\u6587\u6863\uFF1A${result2.plan.lifecycle.dataPlan ?? "\u65E0"}`
|
|
10302
|
+
] : [],
|
|
9857
10303
|
`- \u4FEE\u6539\u6587\u4EF6\uFF1A${result2.changedFiles.length}`,
|
|
9858
10304
|
`- Oxc \u4EE3\u7BA1\uFF1A${result2.plan.detachedToolchain ? "\u5DF2\u68C0\u6D4B\u5230\u5BA2\u6237\u63A5\u7BA1\u5E76\u4FDD\u7559" : "\u4FDD\u6301"}`,
|
|
9859
10305
|
"",
|
|
@@ -9877,13 +10323,275 @@ function expectedForPath(result2, path2) {
|
|
|
9877
10323
|
return expectation2.expected;
|
|
9878
10324
|
}
|
|
9879
10325
|
|
|
10326
|
+
// src/module-lifecycle.ts
|
|
10327
|
+
import { access as access2, rm as rm10 } from "fs/promises";
|
|
10328
|
+
import { resolve as resolve7 } from "path";
|
|
10329
|
+
|
|
10330
|
+
// src/module-version-range.ts
|
|
10331
|
+
function isVersionInCaretRange(version, range) {
|
|
10332
|
+
const current = parseVersion2(version);
|
|
10333
|
+
const base = range.startsWith("^") ? parseVersion2(range.slice(1)) : undefined;
|
|
10334
|
+
if (!current || !base || compareVersion(current, base) < 0)
|
|
10335
|
+
return false;
|
|
10336
|
+
const upper = base[0] > 0 ? [base[0] + 1, 0, 0] : base[1] > 0 ? [0, base[1] + 1, 0] : [0, 0, base[2] + 1];
|
|
10337
|
+
return compareVersion(current, upper) < 0;
|
|
10338
|
+
}
|
|
10339
|
+
function parseVersion2(value) {
|
|
10340
|
+
const match = value.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
10341
|
+
if (!match)
|
|
10342
|
+
return;
|
|
10343
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
10344
|
+
}
|
|
10345
|
+
function compareVersion(left, right) {
|
|
10346
|
+
for (let index = 0;index < 3; index += 1) {
|
|
10347
|
+
const difference = left[index] - right[index];
|
|
10348
|
+
if (difference)
|
|
10349
|
+
return difference;
|
|
10350
|
+
}
|
|
10351
|
+
return 0;
|
|
10352
|
+
}
|
|
10353
|
+
|
|
10354
|
+
// src/module-lifecycle.ts
|
|
10355
|
+
async function runModuleLifecycleCommand(args, projectDirectory, dependencies = {}) {
|
|
10356
|
+
const action = args[0];
|
|
10357
|
+
if (!isAction(action)) {
|
|
10358
|
+
throw new Error("module \u53EA\u652F\u6301 list\u3001add\u3001update\u3001remove");
|
|
10359
|
+
}
|
|
10360
|
+
const log = dependencies.log ?? console.log;
|
|
10361
|
+
const provenance = await readGenerationProvenance(projectDirectory);
|
|
10362
|
+
const installed = provenance.modules.map(({ name }) => name);
|
|
10363
|
+
if (action === "list") {
|
|
10364
|
+
printModuleList(provenance.modules, log);
|
|
10365
|
+
return;
|
|
10366
|
+
}
|
|
10367
|
+
const cliVersion = dependencies.cliVersion ?? (await readTemplateMetadata(await resolveTemplateRoot())).generatorVersion;
|
|
10368
|
+
if (provenance.generatorVersion !== cliVersion || provenance.windyVersion !== cliVersion) {
|
|
10369
|
+
throw new Error(`module \u547D\u4EE4\u8981\u6C42 CLI \u4E0E\u9879\u76EE Windy \u7248\u672C\u4E00\u81F4\uFF1A\u9879\u76EE ${provenance.windyVersion}\uFF0CCLI ${cliVersion}\uFF1B\u8BF7\u5148\u8FD0\u884C bun run windy update`);
|
|
10370
|
+
}
|
|
10371
|
+
const requested = positionalModules(args.slice(1));
|
|
10372
|
+
const lifecycle = await resolveLifecyclePlan({
|
|
10373
|
+
action,
|
|
10374
|
+
requested,
|
|
10375
|
+
installed,
|
|
10376
|
+
windyVersion: provenance.windyVersion,
|
|
10377
|
+
args,
|
|
10378
|
+
projectDirectory
|
|
10379
|
+
});
|
|
10380
|
+
printDataPlan(lifecycle, log);
|
|
10381
|
+
if (!hasChanges(lifecycle)) {
|
|
10382
|
+
log("\u6A21\u5757\u96C6\u5408\u5DF2\u6EE1\u8DB3\u8BF7\u6C42\uFF0C\u65E0\u9700\u4FEE\u6539");
|
|
10383
|
+
return;
|
|
10384
|
+
}
|
|
10385
|
+
const targetModules = resolveTargetModules(installed, lifecycle);
|
|
10386
|
+
const updater = dependencies.updater ?? new DefaultStarterUpdater;
|
|
10387
|
+
const plan = await updater.plan({
|
|
10388
|
+
projectDirectory,
|
|
10389
|
+
targetVersion: provenance.windyVersion,
|
|
10390
|
+
targetModules,
|
|
10391
|
+
lifecycle
|
|
10392
|
+
});
|
|
10393
|
+
printModulePlan(plan, log);
|
|
10394
|
+
if (args.includes("--dry-run")) {
|
|
10395
|
+
await rm10(plan.temporaryRoot, { recursive: true, force: true });
|
|
10396
|
+
log(`
|
|
10397
|
+
\u6F14\u7EC3\u5B8C\u6210\uFF1A\u672A\u5199\u5165\u9879\u76EE\u6587\u4EF6`);
|
|
10398
|
+
return;
|
|
10399
|
+
}
|
|
10400
|
+
if (action === "remove" && !args.includes("--confirm-data-disposition")) {
|
|
10401
|
+
await rm10(plan.temporaryRoot, { recursive: true, force: true });
|
|
10402
|
+
throw new Error("\u5378\u8F7D\u524D\u5FC5\u987B\u5BA1\u9605\u6570\u636E\u5904\u7F6E\u8BA1\u5212\u5E76\u4F20\u5165 --confirm-data-disposition");
|
|
10403
|
+
}
|
|
10404
|
+
if (plan.conflicts.length) {
|
|
10405
|
+
await rm10(plan.temporaryRoot, { recursive: true, force: true });
|
|
10406
|
+
throw new Error("\u5B58\u5728\u6A21\u5757\u751F\u547D\u5468\u671F\u51B2\u7A81\uFF0C\u9879\u76EE\u672A\u88AB\u4FEE\u6539");
|
|
10407
|
+
}
|
|
10408
|
+
const result2 = await updater.apply(plan);
|
|
10409
|
+
const report = await updater.verify(result2);
|
|
10410
|
+
log(`
|
|
10411
|
+
\u6A21\u5757${actionLabel(action)}\u5B8C\u6210\uFF1A${requested.join("\u3001")}`);
|
|
10412
|
+
log(`\u62A5\u544A\uFF1A${report.reportPath}`);
|
|
10413
|
+
}
|
|
10414
|
+
async function resolveLifecyclePlan(input) {
|
|
10415
|
+
const known = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
10416
|
+
const requested = input.action === "update" && input.requested.length === 0 ? [...input.installed] : input.requested;
|
|
10417
|
+
if (!requested.length) {
|
|
10418
|
+
throw new Error(`module ${input.action} \u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u6A21\u5757 key`);
|
|
10419
|
+
}
|
|
10420
|
+
for (const name of requested) {
|
|
10421
|
+
const manifest = known.get(name);
|
|
10422
|
+
if (!manifest)
|
|
10423
|
+
throw new Error(`\u672A\u77E5\u6A21\u5757\uFF1A${name}`);
|
|
10424
|
+
assertWindyCompatible(input.windyVersion, manifest.windyRange, name);
|
|
10425
|
+
}
|
|
10426
|
+
if (input.action === "add") {
|
|
10427
|
+
const target = resolveModuleSelection({
|
|
10428
|
+
requested: [...input.installed, ...requested],
|
|
10429
|
+
includeRecommended: false
|
|
10430
|
+
});
|
|
10431
|
+
for (const name of target) {
|
|
10432
|
+
const manifest = known.get(name);
|
|
10433
|
+
assertWindyCompatible(input.windyVersion, manifest.windyRange, manifest.name);
|
|
10434
|
+
}
|
|
10435
|
+
return {
|
|
10436
|
+
action: input.action,
|
|
10437
|
+
requestedModules: requested,
|
|
10438
|
+
addedModules: target.filter((name) => !input.installed.includes(name)),
|
|
10439
|
+
updatedModules: [],
|
|
10440
|
+
removedModules: []
|
|
10441
|
+
};
|
|
10442
|
+
}
|
|
10443
|
+
if (input.action === "update") {
|
|
10444
|
+
const absent = requested.filter((name) => !input.installed.includes(name));
|
|
10445
|
+
if (absent.length) {
|
|
10446
|
+
throw new Error(`\u672A\u5B89\u88C5\u6A21\u5757\u4E0D\u80FD\u66F4\u65B0\uFF1A${absent.join("\u3001")}`);
|
|
10447
|
+
}
|
|
10448
|
+
return {
|
|
10449
|
+
action: input.action,
|
|
10450
|
+
requestedModules: requested,
|
|
10451
|
+
addedModules: [],
|
|
10452
|
+
updatedModules: requested,
|
|
10453
|
+
removedModules: []
|
|
10454
|
+
};
|
|
10455
|
+
}
|
|
10456
|
+
const required = requested.filter((name) => requiredModuleNames.includes(name));
|
|
10457
|
+
if (required.length) {
|
|
10458
|
+
throw new Error(`\u6838\u5FC3\u6A21\u5757\u4E0D\u53EF\u5378\u8F7D\uFF1A${required.join("\u3001")}`);
|
|
10459
|
+
}
|
|
10460
|
+
const removed = requested.filter((name) => input.installed.includes(name));
|
|
10461
|
+
assertRemovalDependencies(input.installed, removed);
|
|
10462
|
+
const dataDisposition = resolveDataDisposition(removed.map((name) => known.get(name).uninstallPolicy), readValue2(input.args, "--data-disposition"));
|
|
10463
|
+
const dataPlan = readValue2(input.args, "--data-plan");
|
|
10464
|
+
if (dataDisposition !== "retain-data") {
|
|
10465
|
+
if (!dataPlan) {
|
|
10466
|
+
throw new Error(`${dataDisposition} \u5378\u8F7D\u5FC5\u987B\u901A\u8FC7 --data-plan \u63D0\u4F9B\u5DF2\u5BA1\u9605\u7684\u5904\u7F6E\u6587\u6863`);
|
|
10467
|
+
}
|
|
10468
|
+
await access2(resolve7(input.projectDirectory, dataPlan));
|
|
10469
|
+
}
|
|
10470
|
+
return {
|
|
10471
|
+
action: input.action,
|
|
10472
|
+
requestedModules: requested,
|
|
10473
|
+
addedModules: [],
|
|
10474
|
+
updatedModules: [],
|
|
10475
|
+
removedModules: removed,
|
|
10476
|
+
dataDisposition,
|
|
10477
|
+
dataPlan
|
|
10478
|
+
};
|
|
10479
|
+
}
|
|
10480
|
+
function resolveTargetModules(installed, lifecycle) {
|
|
10481
|
+
if (lifecycle.action === "add") {
|
|
10482
|
+
return resolveModuleSelection({
|
|
10483
|
+
requested: [...installed, ...lifecycle.addedModules],
|
|
10484
|
+
includeRecommended: false
|
|
10485
|
+
});
|
|
10486
|
+
}
|
|
10487
|
+
if (lifecycle.action === "remove") {
|
|
10488
|
+
const removed = new Set(lifecycle.removedModules);
|
|
10489
|
+
return installed.filter((name) => !removed.has(name));
|
|
10490
|
+
}
|
|
10491
|
+
return installed;
|
|
10492
|
+
}
|
|
10493
|
+
function resolveDataDisposition(policies, requested) {
|
|
10494
|
+
const disposition = requested ?? strongestPolicy(policies);
|
|
10495
|
+
if (disposition !== "retain-data" && disposition !== "archive-data" && disposition !== "manual") {
|
|
10496
|
+
throw new Error(`\u4E0D\u652F\u6301\u7684\u6570\u636E\u5904\u7F6E\u7B56\u7565\uFF1A${disposition}`);
|
|
10497
|
+
}
|
|
10498
|
+
const minimum = strongestPolicy(policies);
|
|
10499
|
+
const rank = {
|
|
10500
|
+
"retain-data": 0,
|
|
10501
|
+
"archive-data": 1,
|
|
10502
|
+
manual: 2
|
|
10503
|
+
};
|
|
10504
|
+
if (rank[disposition] < rank[minimum]) {
|
|
10505
|
+
throw new Error(`\u6A21\u5757\u76EE\u5F55\u8981\u6C42 ${minimum}\uFF0C\u4E0D\u80FD\u964D\u7EA7\u4E3A ${disposition}`);
|
|
10506
|
+
}
|
|
10507
|
+
return disposition;
|
|
10508
|
+
}
|
|
10509
|
+
function strongestPolicy(policies) {
|
|
10510
|
+
if (policies.includes("manual"))
|
|
10511
|
+
return "manual";
|
|
10512
|
+
if (policies.includes("archive-data"))
|
|
10513
|
+
return "archive-data";
|
|
10514
|
+
return "retain-data";
|
|
10515
|
+
}
|
|
10516
|
+
function assertRemovalDependencies(installed, removed) {
|
|
10517
|
+
const removedSet = new Set(removed);
|
|
10518
|
+
const blockers = moduleDistributionCatalog.filter(({ name, dependencies }) => installed.includes(name) && !removedSet.has(name) && dependencies.some((dependency) => removedSet.has(dependency))).map(({ name }) => name);
|
|
10519
|
+
if (blockers.length) {
|
|
10520
|
+
throw new Error(`\u4ECD\u6709\u5DF2\u5B89\u88C5\u6A21\u5757\u4F9D\u8D56\u5F85\u5378\u8F7D\u6A21\u5757\uFF1A${blockers.join("\u3001")}`);
|
|
10521
|
+
}
|
|
10522
|
+
}
|
|
10523
|
+
function assertWindyCompatible(version, range, moduleName) {
|
|
10524
|
+
if (!isVersionInCaretRange(version, range)) {
|
|
10525
|
+
throw new Error(`${moduleName} \u8981\u6C42 Windy ${range}\uFF0C\u5F53\u524D\u4E3A ${version}`);
|
|
10526
|
+
}
|
|
10527
|
+
}
|
|
10528
|
+
function positionalModules(args) {
|
|
10529
|
+
const valueFlags = new Set(["--data-disposition", "--data-plan", "--cwd"]);
|
|
10530
|
+
const output = [];
|
|
10531
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
10532
|
+
const value = args[index];
|
|
10533
|
+
if (valueFlags.has(value)) {
|
|
10534
|
+
index += 1;
|
|
10535
|
+
} else if (!value.startsWith("-")) {
|
|
10536
|
+
output.push(value);
|
|
10537
|
+
}
|
|
10538
|
+
}
|
|
10539
|
+
return [...new Set(output)];
|
|
10540
|
+
}
|
|
10541
|
+
function printModuleList(installed, log) {
|
|
10542
|
+
const installedVersions = new Map(installed.map(({ name, version }) => [name, version]));
|
|
10543
|
+
log("Windy \u6A21\u5757\uFF1A");
|
|
10544
|
+
for (const manifest of moduleDistributionCatalog) {
|
|
10545
|
+
const installedVersion = installedVersions.get(manifest.name);
|
|
10546
|
+
const status = installedVersion ? "installed" : "available";
|
|
10547
|
+
const version = installedVersion ? `${manifest.name}@${installedVersion}\uFF08catalog ${manifest.version}\uFF09` : `${manifest.name}@${manifest.version}`;
|
|
10548
|
+
log(` ${status.padEnd(9)} ${version}`);
|
|
10549
|
+
}
|
|
10550
|
+
}
|
|
10551
|
+
function printDataPlan(lifecycle, log) {
|
|
10552
|
+
if (lifecycle.action !== "remove")
|
|
10553
|
+
return;
|
|
10554
|
+
log("\u6A21\u5757\u5378\u8F7D\u6570\u636E\u5904\u7F6E\u8BA1\u5212\uFF1A");
|
|
10555
|
+
log(` \u6A21\u5757\uFF1A${lifecycle.removedModules.join("\u3001") || "\u5747\u672A\u5B89\u88C5"}`);
|
|
10556
|
+
log(` \u6570\u636E\uFF1A${lifecycle.dataDisposition ?? "retain-data"}`);
|
|
10557
|
+
log(" migration\uFF1A\u4FDD\u7559\u5230 .windy/module-history\uFF0C\u4E0D\u6267\u884C down migration");
|
|
10558
|
+
if (lifecycle.dataPlan)
|
|
10559
|
+
log(` \u8FD0\u7EF4\u5904\u7F6E\u6587\u6863\uFF1A${lifecycle.dataPlan}`);
|
|
10560
|
+
}
|
|
10561
|
+
function printModulePlan(plan, log) {
|
|
10562
|
+
const changed = plan.files.filter(({ action }) => action !== "preserve");
|
|
10563
|
+
log(`\u6A21\u5757\u6587\u4EF6\u8BA1\u5212\uFF1A${changed.length} \u4E2A\u53D8\u66F4\uFF1B${plan.conflicts.length} \u4E2A\u51B2\u7A81`);
|
|
10564
|
+
for (const file of changed) {
|
|
10565
|
+
log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
|
|
10566
|
+
}
|
|
10567
|
+
for (const conflict3 of plan.conflicts)
|
|
10568
|
+
log(` conflict ${conflict3}`);
|
|
10569
|
+
}
|
|
10570
|
+
function hasChanges(lifecycle) {
|
|
10571
|
+
return lifecycle.addedModules.length > 0 || lifecycle.updatedModules.length > 0 || lifecycle.removedModules.length > 0;
|
|
10572
|
+
}
|
|
10573
|
+
function readValue2(args, flag) {
|
|
10574
|
+
const index = args.indexOf(flag);
|
|
10575
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
10576
|
+
}
|
|
10577
|
+
function isAction(value) {
|
|
10578
|
+
return value === "list" || value === "add" || value === "update" || value === "remove";
|
|
10579
|
+
}
|
|
10580
|
+
function actionLabel(action) {
|
|
10581
|
+
return action === "add" ? "\u5B89\u88C5" : action === "update" ? "\u66F4\u65B0" : "\u5378\u8F7D";
|
|
10582
|
+
}
|
|
10583
|
+
|
|
9880
10584
|
// src/update/cli.ts
|
|
9881
10585
|
async function runLifecycleCommand(args) {
|
|
9882
10586
|
const command = args[0];
|
|
9883
|
-
if (command !== "doctor" && command !== "update" && command !== "reconcile" && command !== "sync-docker") {
|
|
10587
|
+
if (command !== "doctor" && command !== "update" && command !== "module" && command !== "reconcile" && command !== "sync-docker") {
|
|
9884
10588
|
return false;
|
|
9885
10589
|
}
|
|
9886
|
-
const projectDirectory =
|
|
10590
|
+
const projectDirectory = resolve8(readValue3(args, "--cwd") || process.cwd());
|
|
10591
|
+
if (command === "module") {
|
|
10592
|
+
await runModuleLifecycleCommand(args.slice(1), projectDirectory);
|
|
10593
|
+
return true;
|
|
10594
|
+
}
|
|
9887
10595
|
if (command === "sync-docker") {
|
|
9888
10596
|
const result2 = await planWebDockerfileInProject(projectDirectory, {
|
|
9889
10597
|
requireAnchors: true
|
|
@@ -9940,7 +10648,7 @@ async function runReconcile(args, projectDirectory) {
|
|
|
9940
10648
|
});
|
|
9941
10649
|
const plan = await reconciler.plan({
|
|
9942
10650
|
projectDirectory,
|
|
9943
|
-
targetVersion:
|
|
10651
|
+
targetVersion: readValue3(args, "--to") ?? ""
|
|
9944
10652
|
});
|
|
9945
10653
|
console.log(`Windy \u5BF9\u8D26\u8BA1\u5212\uFF1A${plan.sourceVersion} \u2192 ${plan.targetVersion}\uFF1B\u53EF\u8BC1\u660E ${plan.reconciled.length}\uFF1B\u4FDD\u5B88\u672A\u51B3 ${plan.unresolved.length}`);
|
|
9946
10654
|
for (const item of plan.reconciled) {
|
|
@@ -9950,7 +10658,7 @@ async function runReconcile(args, projectDirectory) {
|
|
|
9950
10658
|
console.log(` unresolved ${item.path}\uFF08${item.reason}\uFF09`);
|
|
9951
10659
|
}
|
|
9952
10660
|
if (!args.includes("--apply")) {
|
|
9953
|
-
await
|
|
10661
|
+
await rm11(plan.temporaryRoot, { recursive: true, force: true });
|
|
9954
10662
|
console.log(`
|
|
9955
10663
|
\u6F14\u7EC3\u5B8C\u6210\uFF1A\u672A\u5199\u5165\u9879\u76EE\u6587\u4EF6\uFF1B\u4F7F\u7528 --apply \u4EC5\u63D0\u4EA4\u5BF9\u8D26\u5143\u6570\u636E`);
|
|
9956
10664
|
return;
|
|
@@ -9961,12 +10669,12 @@ async function runReconcile(args, projectDirectory) {
|
|
|
9961
10669
|
\u5BF9\u8D26\u5B8C\u6210\uFF1AProject Lock \u4ECD\u4E3A ${plan.sourceVersion}`);
|
|
9962
10670
|
console.log(`\u62A5\u544A\uFF1A${result2.reportPath}`);
|
|
9963
10671
|
} finally {
|
|
9964
|
-
await
|
|
10672
|
+
await rm11(plan.temporaryRoot, { recursive: true, force: true });
|
|
9965
10673
|
}
|
|
9966
10674
|
}
|
|
9967
10675
|
async function runUpdate(args, projectDirectory) {
|
|
9968
10676
|
const template = await readTemplateMetadata(await resolveTemplateRoot());
|
|
9969
|
-
const requested =
|
|
10677
|
+
const requested = readValue3(args, "--to");
|
|
9970
10678
|
const registryVersion = requested ? undefined : await readRegistryLatest();
|
|
9971
10679
|
if (registryVersion && compareVersions2(registryVersion, template.generatorVersion) > 0 && !args.includes("--no-delegate")) {
|
|
9972
10680
|
if (args.includes("--check")) {
|
|
@@ -9996,13 +10704,13 @@ async function runUpdate(args, projectDirectory) {
|
|
|
9996
10704
|
const plan = await updater.plan({ projectDirectory, targetVersion: target });
|
|
9997
10705
|
printPlan(plan);
|
|
9998
10706
|
if (args.includes("--dry-run")) {
|
|
9999
|
-
await
|
|
10707
|
+
await rm11(plan.temporaryRoot, { recursive: true, force: true });
|
|
10000
10708
|
console.log(`
|
|
10001
10709
|
\u6F14\u7EC3\u5B8C\u6210\uFF1A\u672A\u5199\u5165\u9879\u76EE\u6587\u4EF6`);
|
|
10002
10710
|
return;
|
|
10003
10711
|
}
|
|
10004
10712
|
if (plan.conflicts.length) {
|
|
10005
|
-
await
|
|
10713
|
+
await rm11(plan.temporaryRoot, { recursive: true, force: true });
|
|
10006
10714
|
throw new Error("\u5B58\u5728\u66F4\u65B0\u51B2\u7A81\uFF1B\u8BF7\u6309\u4E0A\u65B9\u6E05\u5355\u5904\u7406\u540E\u91CD\u65B0\u8FD0\u884C\uFF0C\u9879\u76EE\u672A\u88AB\u4FEE\u6539");
|
|
10007
10715
|
}
|
|
10008
10716
|
const result2 = await updater.apply(plan);
|
|
@@ -10036,8 +10744,8 @@ function printPlan(plan) {
|
|
|
10036
10744
|
console.log(`\u8BA1\u5212\u6539\u52A8\uFF1A${changed.length} \u4E2A\u6587\u4EF6\uFF1B\u51B2\u7A81\uFF1A${plan.conflicts.length}`);
|
|
10037
10745
|
for (const file of changed)
|
|
10038
10746
|
console.log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
|
|
10039
|
-
for (const
|
|
10040
|
-
console.log(` conflict ${
|
|
10747
|
+
for (const conflict3 of plan.conflicts)
|
|
10748
|
+
console.log(` conflict ${conflict3}`);
|
|
10041
10749
|
if (plan.detachedToolchain)
|
|
10042
10750
|
console.log("Oxc\uFF1A\u68C0\u6D4B\u5230\u5BA2\u6237\u63A5\u7BA1\uFF0C\u76F8\u5173\u914D\u7F6E\u4FDD\u6301\u4E0D\u53D8");
|
|
10043
10751
|
}
|
|
@@ -10060,7 +10768,7 @@ function printDoctor(report) {
|
|
|
10060
10768
|
console.log("\u6062\u590D\uFF1A\u5DF2\u4ECE\u4E8B\u52A1\u5907\u4EFD\u56DE\u6EDA");
|
|
10061
10769
|
}
|
|
10062
10770
|
}
|
|
10063
|
-
function
|
|
10771
|
+
function readValue3(args, flag) {
|
|
10064
10772
|
const index = args.indexOf(flag);
|
|
10065
10773
|
return index >= 0 ? args[index + 1] : undefined;
|
|
10066
10774
|
}
|
|
@@ -10087,28 +10795,28 @@ function compareVersions2(left, right) {
|
|
|
10087
10795
|
}
|
|
10088
10796
|
|
|
10089
10797
|
// src/module-schema/cli.ts
|
|
10090
|
-
import { resolve as
|
|
10798
|
+
import { resolve as resolve10 } from "path";
|
|
10091
10799
|
|
|
10092
10800
|
// src/module-schema/handoff.ts
|
|
10093
10801
|
import {
|
|
10094
|
-
access as
|
|
10802
|
+
access as access3,
|
|
10095
10803
|
cp,
|
|
10096
|
-
mkdir as
|
|
10804
|
+
mkdir as mkdir9,
|
|
10097
10805
|
mkdtemp as mkdtemp5,
|
|
10098
|
-
readFile as
|
|
10099
|
-
readdir as
|
|
10806
|
+
readFile as readFile26,
|
|
10807
|
+
readdir as readdir9,
|
|
10100
10808
|
rename,
|
|
10101
|
-
rm as
|
|
10102
|
-
writeFile as
|
|
10809
|
+
rm as rm12,
|
|
10810
|
+
writeFile as writeFile13
|
|
10103
10811
|
} from "fs/promises";
|
|
10104
|
-
import { dirname as
|
|
10812
|
+
import { dirname as dirname9, join as join32, relative as relative6 } from "path";
|
|
10105
10813
|
|
|
10106
10814
|
// src/module-schema/config.ts
|
|
10107
|
-
import { readFile as
|
|
10108
|
-
import { isAbsolute as isAbsolute2, relative as
|
|
10815
|
+
import { readFile as readFile25 } from "fs/promises";
|
|
10816
|
+
import { isAbsolute as isAbsolute2, relative as relative5, resolve as resolve9 } from "path";
|
|
10109
10817
|
async function readModuleSchemaLineageConfig(projectDirectory, configPath) {
|
|
10110
10818
|
const absolutePath = resolveProjectPath(projectDirectory, configPath);
|
|
10111
|
-
const parsed = JSON.parse(await
|
|
10819
|
+
const parsed = JSON.parse(await readFile25(absolutePath, "utf8"));
|
|
10112
10820
|
if (!isConfig(parsed)) {
|
|
10113
10821
|
throw new Error("Module schema lineage \u914D\u7F6E\u65E0\u6548");
|
|
10114
10822
|
}
|
|
@@ -10122,8 +10830,8 @@ async function readModuleSchemaLineageConfig(projectDirectory, configPath) {
|
|
|
10122
10830
|
function resolveProjectPath(projectDirectory, path2) {
|
|
10123
10831
|
if (isAbsolute2(path2))
|
|
10124
10832
|
throw new Error(`\u8DEF\u5F84\u5FC5\u987B\u76F8\u5BF9\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${path2}`);
|
|
10125
|
-
const resolved =
|
|
10126
|
-
const projectRelative =
|
|
10833
|
+
const resolved = resolve9(projectDirectory, path2);
|
|
10834
|
+
const projectRelative = relative5(projectDirectory, resolved);
|
|
10127
10835
|
if (projectRelative.startsWith("..") || isAbsolute2(projectRelative)) {
|
|
10128
10836
|
throw new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${path2}`);
|
|
10129
10837
|
}
|
|
@@ -10232,7 +10940,7 @@ async function handoffModuleSchemaLineages(options) {
|
|
|
10232
10940
|
const stagedPlatform = await stagePlatformLineage(project, temporaryRoot, config, execute);
|
|
10233
10941
|
await installStagedLineages(project, temporaryRoot, config, stagedModules, stagedPlatform);
|
|
10234
10942
|
} finally {
|
|
10235
|
-
await
|
|
10943
|
+
await rm12(temporaryRoot, { recursive: true, force: true });
|
|
10236
10944
|
}
|
|
10237
10945
|
return {
|
|
10238
10946
|
moduleCount: config.modules.length,
|
|
@@ -10242,17 +10950,17 @@ async function handoffModuleSchemaLineages(options) {
|
|
|
10242
10950
|
async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
10243
10951
|
const outputs = [];
|
|
10244
10952
|
for (const [index, module3] of config.modules.entries()) {
|
|
10245
|
-
const output =
|
|
10246
|
-
await
|
|
10247
|
-
const generatedConfig =
|
|
10248
|
-
await writeDrizzleConfig(generatedConfig, project, module3.schema,
|
|
10953
|
+
const output = join32(temporaryRoot, `module-${index}`);
|
|
10954
|
+
await mkdir9(output, { recursive: true });
|
|
10955
|
+
const generatedConfig = join32(temporaryRoot, `module-${index}.config.ts`);
|
|
10956
|
+
await writeDrizzleConfig(generatedConfig, project, module3.schema, relative6(temporaryRoot, output));
|
|
10249
10957
|
await execute(generatedConfig, temporaryRoot);
|
|
10250
10958
|
const sqlFiles = await listSqlFiles(output);
|
|
10251
10959
|
if (sqlFiles.length !== 1) {
|
|
10252
10960
|
throw new Error(`${module3.key} baseline \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration`);
|
|
10253
10961
|
}
|
|
10254
|
-
await
|
|
10255
|
-
await
|
|
10962
|
+
await writeFile13(join32(output, sqlFiles[0]), metadataOnlySql("module"));
|
|
10963
|
+
await writeFile13(join32(output, "lineage.json"), `${JSON.stringify({
|
|
10256
10964
|
schemaVersion: 1,
|
|
10257
10965
|
moduleKey: module3.key,
|
|
10258
10966
|
schema: module3.schema,
|
|
@@ -10266,25 +10974,25 @@ async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
|
10266
10974
|
}
|
|
10267
10975
|
async function stagePlatformLineage(project, temporaryRoot, config, execute) {
|
|
10268
10976
|
const source = resolveProjectPath(project, config.platform.out);
|
|
10269
|
-
const output =
|
|
10977
|
+
const output = join32(temporaryRoot, "platform");
|
|
10270
10978
|
await cp(source, output, { recursive: true });
|
|
10271
10979
|
const before = new Set(await listSqlFiles(output));
|
|
10272
|
-
const generatedConfig =
|
|
10273
|
-
await writeDrizzleConfig(generatedConfig, project, config.platform.schema,
|
|
10980
|
+
const generatedConfig = join32(temporaryRoot, "platform.config.ts");
|
|
10981
|
+
await writeDrizzleConfig(generatedConfig, project, config.platform.schema, relative6(temporaryRoot, output));
|
|
10274
10982
|
await execute(generatedConfig, temporaryRoot);
|
|
10275
10983
|
const created = (await listSqlFiles(output)).filter((path2) => !before.has(path2));
|
|
10276
10984
|
if (created.length !== 1) {
|
|
10277
10985
|
throw new Error("\u5E73\u53F0 lineage handoff \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration");
|
|
10278
10986
|
}
|
|
10279
|
-
const sqlPath =
|
|
10987
|
+
const sqlPath = join32(output, created[0]);
|
|
10280
10988
|
const allowed = config.modules.flatMap(({ legacyPlatformTables }) => legacyPlatformTables);
|
|
10281
|
-
validatePlatformHandoffSql(await
|
|
10282
|
-
await
|
|
10989
|
+
validatePlatformHandoffSql(await readFile26(sqlPath, "utf8"), allowed);
|
|
10990
|
+
await writeFile13(sqlPath, metadataOnlySql("platform"));
|
|
10283
10991
|
return output;
|
|
10284
10992
|
}
|
|
10285
10993
|
async function installStagedLineages(project, temporaryRoot, config, stagedModules, stagedPlatform) {
|
|
10286
10994
|
const platform = resolveProjectPath(project, config.platform.out);
|
|
10287
|
-
const backup =
|
|
10995
|
+
const backup = join32(temporaryRoot, "platform-backup");
|
|
10288
10996
|
const installed = [];
|
|
10289
10997
|
await rename(platform, backup);
|
|
10290
10998
|
try {
|
|
@@ -10294,21 +11002,21 @@ async function installStagedLineages(project, temporaryRoot, config, stagedModul
|
|
|
10294
11002
|
if (await exists(output)) {
|
|
10295
11003
|
throw new Error(`${module3.key} lineage \u8F93\u51FA\u5DF2\u5B58\u5728\uFF0C\u7981\u6B62\u8986\u76D6`);
|
|
10296
11004
|
}
|
|
10297
|
-
await
|
|
11005
|
+
await mkdir9(dirname9(output), { recursive: true });
|
|
10298
11006
|
await rename(stagedModules[index], output);
|
|
10299
11007
|
installed.push(output);
|
|
10300
11008
|
}
|
|
10301
11009
|
} catch (error) {
|
|
10302
|
-
await
|
|
11010
|
+
await rm12(platform, { recursive: true, force: true });
|
|
10303
11011
|
await rename(backup, platform);
|
|
10304
11012
|
for (const output of installed)
|
|
10305
|
-
await
|
|
11013
|
+
await rm12(output, { recursive: true, force: true });
|
|
10306
11014
|
throw error;
|
|
10307
11015
|
}
|
|
10308
11016
|
}
|
|
10309
11017
|
async function writeDrizzleConfig(path2, project, schemas, out) {
|
|
10310
11018
|
const absoluteSchemas = schemas.map((schema) => resolveProjectPath(project, schema));
|
|
10311
|
-
await
|
|
11019
|
+
await writeFile13(path2, `import { defineConfig } from "drizzle-kit";
|
|
10312
11020
|
export default defineConfig(${JSON.stringify({
|
|
10313
11021
|
dialect: "postgresql",
|
|
10314
11022
|
schema: absoluteSchemas,
|
|
@@ -10322,7 +11030,7 @@ async function validateSchemaSources(project, config) {
|
|
|
10322
11030
|
...config.platform.schema,
|
|
10323
11031
|
...config.modules.flatMap(({ schema: schema2 }) => schema2)
|
|
10324
11032
|
]) {
|
|
10325
|
-
await
|
|
11033
|
+
await access3(resolveProjectPath(project, schema));
|
|
10326
11034
|
}
|
|
10327
11035
|
for (const module3 of config.modules) {
|
|
10328
11036
|
if (await exists(resolveProjectPath(project, module3.out))) {
|
|
@@ -10331,12 +11039,12 @@ async function validateSchemaSources(project, config) {
|
|
|
10331
11039
|
}
|
|
10332
11040
|
}
|
|
10333
11041
|
async function createTemporaryRoot(project) {
|
|
10334
|
-
const windy =
|
|
10335
|
-
await
|
|
10336
|
-
return await mkdtemp5(
|
|
11042
|
+
const windy = join32(project, ".windy");
|
|
11043
|
+
await mkdir9(windy, { recursive: true });
|
|
11044
|
+
return await mkdtemp5(join32(windy, "module-schema-handoff-"));
|
|
10337
11045
|
}
|
|
10338
11046
|
async function listSqlFiles(root) {
|
|
10339
|
-
return (await
|
|
11047
|
+
return (await readdir9(root)).filter((path2) => path2.endsWith(".sql")).sort();
|
|
10340
11048
|
}
|
|
10341
11049
|
async function executeDrizzleGenerate(configPath, cwd) {
|
|
10342
11050
|
await assertProcess("bunx", ["--bun", "drizzle-kit", "generate", "--config", configPath], cwd, true);
|
|
@@ -10349,7 +11057,7 @@ async function assertCleanGit(project) {
|
|
|
10349
11057
|
}
|
|
10350
11058
|
async function exists(path2) {
|
|
10351
11059
|
try {
|
|
10352
|
-
await
|
|
11060
|
+
await access3(path2);
|
|
10353
11061
|
return true;
|
|
10354
11062
|
} catch {
|
|
10355
11063
|
return false;
|
|
@@ -10363,15 +11071,15 @@ async function runModuleSchemaCommand(args) {
|
|
|
10363
11071
|
if (args[1] !== "handoff") {
|
|
10364
11072
|
throw new Error("\u5F53\u524D schema \u547D\u4EE4\u53EA\u652F\u6301 handoff");
|
|
10365
11073
|
}
|
|
10366
|
-
const projectDirectory =
|
|
11074
|
+
const projectDirectory = resolve10(readValue4(args, "--cwd") || process.cwd());
|
|
10367
11075
|
const result2 = await handoffModuleSchemaLineages({
|
|
10368
11076
|
projectDirectory,
|
|
10369
|
-
configPath:
|
|
11077
|
+
configPath: readValue4(args, "--config")
|
|
10370
11078
|
});
|
|
10371
11079
|
console.log(`Module schema lineage \u4EA4\u63A5\u5B8C\u6210\uFF1A${result2.moduleCount} \u4E2A\u6A21\u5757\u3001${result2.tableCount} \u5F20\u65E7\u5E73\u53F0 snapshot \u8868`);
|
|
10372
11080
|
return true;
|
|
10373
11081
|
}
|
|
10374
|
-
function
|
|
11082
|
+
function readValue4(args, flag) {
|
|
10375
11083
|
const index = args.indexOf(flag);
|
|
10376
11084
|
return index >= 0 ? args[index + 1] : undefined;
|
|
10377
11085
|
}
|