create-windy 0.9.1 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1691 -1151
- package/package.json +2 -2
- package/template/.agents/skills/windy-business-module/SKILL.md +33 -1
- package/template/.windy-template.json +6 -2
- package/template/AGENTS.md +4 -0
- package/template/README.md +2 -0
- package/template/apps/agent-server/Dockerfile +1 -1
- package/template/apps/agent-server/README.md +1 -1
- package/template/apps/agent-server/native/EXTENSIONS.md +2 -2
- package/template/apps/agent-server/native/parallel-harness.ts +2 -0
- package/template/apps/agent-server/native/storage-lifecycle.test.ts +2 -1
- package/template/apps/agent-server/package.json +42 -41
- package/template/apps/agent-server/plugins/downloads/README.md +1 -1
- package/template/apps/agent-server/plugins/drop-overlay/README.md +1 -1
- package/template/apps/agent-server/plugins/settings/README.md +1 -1
- package/template/apps/agent-server/plugins/skill-library/client-chunks.test.ts +4 -1
- package/template/apps/agent-server/plugins/theme/README.md +5 -1
- package/template/apps/agent-server/plugins/theme/source-tokens.ts +0 -1
- package/template/apps/agent-server/plugins/theme/tokens.json +0 -4
- package/template/apps/agent-server/plugins/tool-catalog/README.md +6 -3
- package/template/apps/agent-server/plugins/tool-catalog/discovery.mjs +13 -10
- package/template/apps/agent-server/plugins/tool-catalog/discovery.test.ts +68 -6
- package/template/apps/agent-server/runtime/compatibility.ts +7 -1
- package/template/apps/agent-server/runtime/dsh-engine.ts +2 -0
- package/template/apps/agent-server/runtime/questions-workflow.nodecheck.ts +2 -0
- package/template/apps/server/Dockerfile +2 -1
- package/template/apps/server/package.json +11 -11
- package/template/apps/server/scripts/validate-module-composition-once.ts +2 -0
- package/template/apps/server/scripts/validate-module-composition.ts +8 -4
- package/template/apps/server/src/admin/routes.test.ts +29 -1
- package/template/apps/server/src/admin/routes.ts +20 -2
- package/template/apps/server/src/agent/client-session/completion.ts +1 -1
- package/template/apps/server/src/agent/client-session/manifest-admission.ts +1 -1
- package/template/apps/server/src/agent/client-session/request.ts +1 -1
- package/template/apps/server/src/agent/context-version-routes.ts +37 -13
- package/template/apps/server/src/agent/run-facade.ts +1 -1
- package/template/apps/server/src/agent/run-input-verification.ts +1 -1
- package/template/apps/server/src/agent/run-routes.ts +1 -14
- package/template/apps/server/src/agent/run-start-preparation.ts +1 -1
- package/template/apps/server/src/agent/runtime-bootstrap-input.ts +2 -0
- package/template/apps/server/src/agent/runtime-bootstrap.ts +49 -157
- package/template/apps/server/src/agent/runtime-disabled-composition.ts +2 -1
- package/template/apps/server/src/agent/session-invalidation/authorization-revocation.ts +54 -0
- package/template/apps/server/src/agent/session-runtime-composition.ts +1 -51
- package/template/apps/server/src/agent/unavailable-routes.ts +13 -2
- package/template/apps/server/src/agent-workflow/runtime-composition.ts +3 -0
- package/template/apps/server/src/agent-workflow/service.ts +17 -1
- package/template/apps/server/src/ai-artifact/media-resource-route.test.ts +134 -0
- package/template/apps/server/src/ai-artifact/routes.ts +1 -1
- package/template/apps/server/src/ai-artifact/runtime.ts +12 -0
- package/template/apps/server/src/ai-runtime-readiness/operation-port.test-support.ts +1 -1
- package/template/apps/server/src/ai-runtime-readiness/operation-port.ts +8 -0
- package/template/apps/server/src/ai-runtime-security/internal-token.ts +14 -0
- package/template/apps/server/src/app/antivirus-composition.test.ts +63 -0
- package/template/apps/server/src/app/antivirus-composition.ts +29 -0
- package/template/apps/server/src/app/dsh-workbench-socket-audit.test.ts +2 -1
- package/template/apps/server/src/configuration/definition.ts +15 -11
- package/template/apps/server/src/document/facade-support.ts +2 -2
- package/template/apps/server/src/document/facade.ts +2 -2
- package/template/apps/server/src/document/output-artifact-composition.ts +9 -5
- package/template/apps/server/src/document/output-artifact.test-support.ts +1 -1
- package/template/apps/server/src/embedding/facade.ts +1 -1
- package/template/apps/server/src/embedding/input.ts +1 -1
- package/template/apps/server/src/embedding/routes.ts +1 -1
- package/template/apps/server/src/index.ts +60 -60
- package/template/apps/server/src/license/routes.ts +4 -1
- package/template/apps/server/src/license/runtime-business-access.test.ts +261 -0
- package/template/apps/server/src/media-runtime/composition.ts +157 -0
- package/template/apps/server/src/media-runtime/media-only-composition.ts +44 -0
- package/template/apps/server/src/media-runtime/module-ai-port-factory.test.ts +69 -0
- package/template/apps/server/src/media-runtime/module-ai-port-factory.ts +72 -0
- package/template/apps/server/src/{agent → media-runtime}/runtime-readiness-sources.ts +14 -6
- package/template/apps/server/src/media-runtime/shared-composition.ts +104 -0
- package/template/apps/server/src/module-composition.test.ts +22 -0
- package/template/apps/server/src/module-composition.ts +48 -0
- package/template/apps/server/src/module-host/ai-operation-port.ts +97 -30
- package/template/apps/server/src/module-host/ai-operation-speech-normalize.test.ts +1 -1
- package/template/apps/server/src/module-host/http-runtime.ts +9 -3
- package/template/apps/server/src/module-host/static-route-authorization.test.ts +6 -3
- package/template/apps/server/src/module-host/storage-authorization-binding.test.ts +4 -0
- package/template/apps/server/src/module-runtime-validation.ts +2 -0
- package/template/apps/server/src/observability/diagnostic-index.ts +26 -1
- package/template/apps/server/src/observability/diagnostic-repository.ts +40 -11
- package/template/apps/server/src/platform-http-runtime.ts +1 -1
- package/template/apps/server/src/runtime-feature.ts +5 -1
- package/template/apps/server/src/runtime.ts +3 -0
- package/template/apps/server/src/settings/drizzle-watermark-repository.ts +35 -4
- package/template/apps/server/src/settings/watermark-repository.ts +14 -0
- package/template/apps/server/src/settings/watermark-routes.test.ts +84 -2
- package/template/apps/server/src/settings/watermark-routes.ts +109 -0
- package/template/apps/server/src/settings/watermark-transfer.ts +79 -0
- package/template/apps/server/src/speech/facade-validation.ts +1 -1
- package/template/apps/server/src/speech/facade.ts +2 -2
- package/template/apps/server/src/startup-composition-validation.test.ts +32 -0
- package/template/apps/server/src/startup-finalization.ts +2 -0
- package/template/apps/server/src/startup-runtime.ts +77 -0
- package/template/apps/server/src/system/ai-runtime-build.ts +3 -0
- package/template/apps/server/src/system/ai-runtime-configuration.test.ts +36 -0
- package/template/apps/server/src/system/ai-runtime-configuration.ts +58 -0
- package/template/apps/server/src/system/diagnostic-routes.test.ts +45 -0
- package/template/apps/server/src/system/diagnostic-routes.ts +35 -0
- package/template/apps/server/src/system/environment-policy-reader.test.ts +74 -0
- package/template/apps/server/src/system/environment-policy-reader.ts +62 -0
- package/template/apps/server/src/system/feature-environment-assessment.test.ts +148 -0
- package/template/apps/server/src/system/feature-environment-assessment.ts +179 -0
- package/template/apps/server/src/system/host-diagnostics.test.ts +155 -0
- package/template/apps/server/src/system/host-diagnostics.ts +225 -0
- package/template/apps/server/src/system/menu-registry.test.ts +26 -0
- package/template/apps/server/src/system/menu-registry.ts +9 -7
- package/template/apps/server/src/system/operations.test.ts +5 -0
- package/template/apps/server/src/system/operations.ts +36 -12
- package/template/apps/server/src/system/role-authorization-postgres.integration.test.ts +181 -0
- package/template/apps/web/Dockerfile +7 -3
- package/template/apps/web/dev/dev-port.test.ts +6 -6
- package/template/apps/web/dev/dev-port.ts +1 -1
- package/template/apps/web/dev/start.ts +6 -1
- package/template/apps/web/index.html +1 -0
- package/template/apps/web/package.json +16 -16
- package/template/apps/web/runtime-server.test.ts +22 -1
- package/template/apps/web/runtime-server.ts +6 -0
- package/template/apps/web/src/App.vue +6 -3
- package/template/apps/web/src/assets/windy.svg +4 -0
- package/template/apps/web/src/components/auth/LoginForm.vue +2 -2
- package/template/apps/web/src/components/auth/PasswordChangeForm.vue +14 -3
- package/template/apps/web/src/components/common/FormDialog.vue +1 -1
- package/template/apps/web/src/components/license/LicenseFlow.webtest.ts +3 -0
- package/template/apps/web/src/components/license/LicenseMachineCodeQr.vue +99 -0
- package/template/apps/web/src/components/license/LicenseMachineCodeQr.webtest.ts +83 -0
- package/template/apps/web/src/components/license/LicensePairingCard.vue +1 -1
- package/template/apps/web/src/components/license/LicenseStatusCard.vue +14 -2
- package/template/apps/web/src/composables/useLoginFlow.ts +2 -2
- package/template/apps/web/src/composables/usePlatformSettings.ts +1 -1
- package/template/apps/web/src/composables/useWatermarkSettings.ts +1 -0
- package/template/apps/web/src/layout/AppSidebar.vue +5 -9
- package/template/apps/web/src/layout/AppSidebar.webtest.ts +4 -1
- package/template/apps/web/src/pages/auth/ChangePasswordPage.vue +67 -6
- package/template/apps/web/src/pages/auth/LoginPage.vue +3 -12
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.vue +30 -0
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationWorkbench.vue +25 -14
- package/template/apps/web/src/pages/configuration/components/TimeZoneSelect.vue +55 -0
- package/template/apps/web/src/pages/profile/PersonalSettingsPage.vue +64 -11
- package/template/apps/web/src/pages/profile/PersonalSettingsPage.webtest.ts +21 -1
- package/template/apps/web/src/pages/settings/BrandingSettingsSection.vue +7 -18
- package/template/apps/web/src/pages/settings/BrandingSettingsSection.webtest.ts +9 -4
- package/template/apps/web/src/pages/settings/GlobalSettingsPage.vue +51 -6
- package/template/apps/web/src/pages/settings/GlobalSettingsPage.webtest.ts +19 -3
- package/template/apps/web/src/pages/settings/WatermarkSettingsSection.vue +1 -0
- package/template/apps/web/src/pages/settings/WatermarkYamlTransfer.vue +211 -0
- package/template/apps/web/src/pages/system/DiagnosticLookupPage.vue +18 -3
- package/template/apps/web/src/pages/system/DiagnosticLookupPage.webtest.ts +4 -1
- package/template/apps/web/src/pages/system/SystemOperationsPage.vue +23 -0
- package/template/apps/web/src/pages/system/components/DiagnosticLogList.vue +120 -0
- package/template/apps/web/src/pages/system/components/OperationEnvironmentPanel.vue +237 -0
- package/template/apps/web/src/pages/system/components/OperationFeatureAssessmentPanel.vue +131 -0
- package/template/apps/web/src/pages/system/components/PagedSelectionList.vue +31 -24
- package/template/apps/web/src/pages/system/components/SystemResourceActions.vue +2 -1
- package/template/apps/web/src/pages/system/components/SystemResourceEditor.vue +11 -2
- package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +1 -0
- package/template/apps/web/src/pages/system/components/SystemResourcePage.webtest.ts +6 -2
- package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillImportDialog.vue +18 -9
- package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.vue +18 -9
- package/template/apps/web/src/pages/system/components/agent-workbench/TestRunComposer.vue +66 -34
- package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.vue +48 -33
- package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.webtest.ts +9 -2
- package/template/apps/web/src/pages/system/components/agent-workbench/ToolRuleDetail.vue +23 -16
- package/template/apps/web/src/pages/system/components/dictionary-bulk/DictionaryBulkJobDetail.vue +10 -7
- package/template/apps/web/src/pages/system/components/user-account/RolePermissionSummary.vue +81 -57
- package/template/apps/web/src/pages/system/components/user-account/UserRoleSelector.vue +6 -4
- package/template/apps/web/src/pages/system/components/user-account/UserRoleSelector.webtest.ts +20 -4
- package/template/apps/web/src/pages/system/resource-config.ts +9 -0
- package/template/apps/web/src/pages/work-orders/WorkOrderListPage.vue +1 -1
- package/template/apps/web/src/router/disabled-feature-loading.webtest.ts +78 -0
- package/template/apps/web/src/router/index.ts +3 -6
- package/template/apps/web/src/router/manifest-routes.ts +2 -3
- package/template/apps/web/src/router/platform-admin-pages.ts +21 -62
- package/template/apps/web/src/router/platform-admin-route-bindings.ts +4 -4
- package/template/apps/web/src/services/diagnostics-api.ts +13 -1
- package/template/apps/web/src/services/operations-api.ts +4 -0
- package/template/apps/web/src/services/platform-settings-api.ts +35 -1
- package/template/apps/web/vite.config.ts +9 -3
- package/template/deploy/environment/windy.environment.example.yaml +53 -0
- package/template/docker-compose.yml +4 -2
- package/template/docs/architecture/agent-admin-workbench-implementation.md +1 -1
- package/template/docs/architecture/agent-admin-workbench-plan.md +1 -1
- package/template/docs/architecture/agent-workflow.md +8 -0
- package/template/docs/architecture/durable-jobs.md +17 -0
- package/template/docs/architecture/embedded-dsh-integration.md +1 -1
- package/template/docs/development/dsh-plugins.md +1 -1
- package/template/docs/development/performance-engineering.md +24 -0
- package/template/docs/operations/admin-settings-yaml.md +29 -0
- package/template/docs/operations/dsh-agent-migration.md +2 -2
- package/template/docs/operations/environment-capabilities.md +185 -0
- package/template/docs/platform/module-configuration.md +18 -3
- package/template/docs/platform/platform-authentication.md +1 -1
- package/template/package.json +10 -8
- package/template/packages/config/package.json +2 -2
- package/template/packages/config/src/definition.ts +14 -4
- package/template/packages/config/src/environment-loader.ts +27 -3
- package/template/packages/config/src/platform-ai-runtime.test.ts +94 -0
- package/template/packages/config/src/platform.ts +5 -2
- package/template/packages/database/drizzle/0065_durable_job_lease_snapshot_lookup.sql +1 -0
- package/template/packages/database/drizzle/0066_agent_source_sequence_bigint.sql +3 -0
- package/template/packages/database/drizzle/0067_media_runtime_access.sql +46 -0
- package/template/packages/database/drizzle/meta/0065_snapshot.json +15370 -0
- package/template/packages/database/drizzle/meta/0066_snapshot.json +15370 -0
- package/template/packages/database/drizzle/meta/0067_snapshot.json +15370 -0
- package/template/packages/database/drizzle/meta/_journal.json +21 -0
- package/template/packages/database/package.json +3 -3
- package/template/packages/database/src/schema/agent-session.ts +4 -3
- package/template/packages/database/src/schema/durable-jobs.ts +4 -0
- package/template/packages/database/src/schema/index.ts +3 -1
- package/template/packages/database/src/schema-durable-recovery.test.ts +21 -1
- package/template/packages/database/src/schema-source-sequence.test.ts +24 -0
- package/template/packages/example-work-order/package.json +2 -2
- package/template/packages/modules/package.json +1 -1
- package/template/packages/modules/src/admin-ui-boundary.test.ts +33 -0
- package/template/packages/modules/src/composition.ts +11 -28
- package/template/packages/modules/src/manifest.ts +2 -0
- package/template/packages/modules/src/menu-composition.ts +24 -0
- package/template/packages/modules/src/system-admin-routes.ts +2 -2
- package/template/packages/modules/src/system-admin-ui-catalog.ts +6 -1
- package/template/packages/modules/src/system-ai-api-bindings.ts +0 -16
- package/template/packages/modules/src/system-api-control-plane.ts +9 -1
- package/template/packages/modules/src/system-api-permissions.ts +7 -0
- package/template/packages/modules/src/system-api-watermark.ts +21 -0
- package/template/packages/modules/src/system-audit-actions.ts +3 -1
- package/template/packages/modules/src/system-features.ts +21 -3
- package/template/packages/modules/src/system-media-api-bindings.ts +97 -0
- package/template/packages/modules/src/system-module-audit-selection.ts +2 -0
- package/template/packages/modules/src/system-module-catalog.test.ts +13 -6
- package/template/packages/modules/src/system-module-catalog.ts +6 -241
- package/template/packages/modules/src/system-module-definitions.ts +260 -0
- package/template/packages/modules/src/system-modules-access.test.ts +2 -0
- package/template/packages/modules/src/system-modules.test.ts +7 -1
- package/template/packages/modules/src/system-modules.ts +25 -13
- package/template/packages/modules/src/system-permissions.ts +12 -0
- package/template/packages/server-sdk/package.json +1 -1
- package/template/packages/shared/index.ts +3 -0
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/environment-assessment.ts +68 -0
- package/template/packages/shared/src/environment-policy.ts +205 -0
- package/template/packages/shared/src/license-console-capabilities.ts +7 -0
- package/template/packages/shared/src/license.ts +1 -0
- package/template/packages/shared/src/module-configuration.ts +2 -1
- package/template/scripts/operations/collect-device-info.py +230 -0
- package/template/apps/server/src/agent/module-ai-port-factory.ts +0 -41
- /package/template/apps/server/src/{agent → ai-runtime-security}/execution-grants.ts +0 -0
- /package/template/apps/server/src/{agent → ai-runtime-security}/idempotency-key.test.ts +0 -0
- /package/template/apps/server/src/{agent → ai-runtime-security}/idempotency-key.ts +0 -0
- /package/template/apps/server/src/{agent → ai-runtime-security}/provider-input-governance.test.ts +0 -0
- /package/template/apps/server/src/{agent → ai-runtime-security}/provider-input-governance.ts +0 -0
- /package/template/apps/server/src/{agent → media-runtime}/required-environment.ts +0 -0
- /package/template/apps/server/src/{agent → media-runtime}/runtime-readiness-sources.test.ts +0 -0
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
33
33
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
34
|
var __require = import.meta.require;
|
|
35
35
|
|
|
36
|
-
// ../../node_modules
|
|
36
|
+
// ../../node_modules/cli-width/index.js
|
|
37
37
|
var require_cli_width = __commonJS((exports, module2) => {
|
|
38
38
|
module2.exports = cliWidth;
|
|
39
39
|
function normalizeOpts(options) {
|
|
@@ -73,7 +73,7 @@ var require_cli_width = __commonJS((exports, module2) => {
|
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
// ../../node_modules
|
|
76
|
+
// ../../node_modules/mute-stream/lib/index.js
|
|
77
77
|
var require_lib = __commonJS((exports, module2) => {
|
|
78
78
|
var Stream = __require("stream");
|
|
79
79
|
|
|
@@ -310,6 +310,48 @@ function optionalModule(name, label, description, dependencies) {
|
|
|
310
310
|
};
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
+
// src/optional-module-media.ts
|
|
314
|
+
var mediaOptionalModule = {
|
|
315
|
+
...optionalModule("system.media-runtime", "\u5A92\u4F53\u8FD0\u884C\u65F6", "\u53D7\u6CBB\u7406\u7684\u6587\u6863\u3001\u8BED\u97F3\u3001\u5D4C\u5165\u4E0E\u516C\u5171\u6587\u4EF6\u5F15\u7528\u3002", ["system", "system.audit", "system.storage"]),
|
|
316
|
+
runtimeActivation: "physical-only",
|
|
317
|
+
fileRoots: [
|
|
318
|
+
"apps/document-server",
|
|
319
|
+
"apps/speech-server",
|
|
320
|
+
"apps/embedding-server",
|
|
321
|
+
"apps/server/src/ai-runtime-readiness",
|
|
322
|
+
"apps/server/src/app/document-output-artifact-bindings.ts",
|
|
323
|
+
"apps/server/src/app/speech-output-artifact-bindings.ts",
|
|
324
|
+
"apps/server/src/ai-artifact",
|
|
325
|
+
"apps/server/src/ai-runtime-security",
|
|
326
|
+
"apps/server/src/media-runtime",
|
|
327
|
+
"apps/server/src/ai-output-artifact",
|
|
328
|
+
"apps/server/src/document",
|
|
329
|
+
"apps/server/src/speech",
|
|
330
|
+
"apps/server/src/embedding",
|
|
331
|
+
"apps/server/src/module-host/ai-operation-port.ts",
|
|
332
|
+
"apps/server/src/module-host/ai-operation-port.test.ts",
|
|
333
|
+
"scripts/provision-speech-readiness.ts",
|
|
334
|
+
"packages/database/src/ai-output-artifacts.test.ts",
|
|
335
|
+
"packages/modules/src/system-media-api-bindings.ts"
|
|
336
|
+
],
|
|
337
|
+
documentation: [
|
|
338
|
+
"docs/architecture/ai-runtime-readiness.md",
|
|
339
|
+
"docs/platform/document-ai-runtime.md",
|
|
340
|
+
"docs/platform/speech-ai-runtime.md",
|
|
341
|
+
"docs/platform/embedding-ai-runtime.md"
|
|
342
|
+
],
|
|
343
|
+
schemaFiles: [
|
|
344
|
+
"packages/database/src/schema/embedding-runtime.ts",
|
|
345
|
+
"packages/database/src/schema/ai-output-artifacts.ts"
|
|
346
|
+
],
|
|
347
|
+
databaseStatementTokens: ["windy_media_runtime_access"],
|
|
348
|
+
databaseTables: [
|
|
349
|
+
"embedding_run_bindings",
|
|
350
|
+
"ai_output_artifact_scopes",
|
|
351
|
+
"ai_output_artifacts"
|
|
352
|
+
]
|
|
353
|
+
};
|
|
354
|
+
|
|
313
355
|
// src/optional-module-agent.ts
|
|
314
356
|
var agentOptionalModule = {
|
|
315
357
|
...optionalModule("system.agent", "Agent Tool", "\u53D7\u63A7 Agent \u5DE5\u5177\u5BBF\u4E3B\u3002", [
|
|
@@ -317,7 +359,8 @@ var agentOptionalModule = {
|
|
|
317
359
|
"system.audit",
|
|
318
360
|
"system.storage",
|
|
319
361
|
"system.scheduler",
|
|
320
|
-
"system.workflow"
|
|
362
|
+
"system.workflow",
|
|
363
|
+
"system.media-runtime"
|
|
321
364
|
]),
|
|
322
365
|
registryDependencies: [
|
|
323
366
|
{ sourceName: "fflate", name: "fflate", version: "0.8.3" },
|
|
@@ -336,15 +379,11 @@ var agentOptionalModule = {
|
|
|
336
379
|
fileRoots: [
|
|
337
380
|
"apps/agent-server",
|
|
338
381
|
"apps/server/scripts/check-dsh-platform-example.ts",
|
|
339
|
-
"apps/document-server",
|
|
340
|
-
"apps/speech-server",
|
|
341
|
-
"apps/embedding-server",
|
|
342
382
|
"apps/server/src/agent",
|
|
343
383
|
"apps/server/src/agent-skills",
|
|
344
384
|
"deploy/dsh",
|
|
345
385
|
"apps/server/src/agent-workflow",
|
|
346
386
|
"apps/server/src/ai-runtime-report",
|
|
347
|
-
"apps/server/src/ai-runtime-readiness",
|
|
348
387
|
"apps/server/src/app/ai-screenshot-intake-binding.ts",
|
|
349
388
|
"apps/server/src/app/agent-runtime-composition.ts",
|
|
350
389
|
"apps/server/src/app/workbench-public-origin.ts",
|
|
@@ -370,16 +409,7 @@ var agentOptionalModule = {
|
|
|
370
409
|
"apps/server/src/app/dsh-workbench.ts",
|
|
371
410
|
"apps/server/src/app/client-agent-host-auth-binding.ts",
|
|
372
411
|
"apps/server/src/app/client-agent-workflow-artifact-binding.ts",
|
|
373
|
-
"apps/server/src/app/document-output-artifact-bindings.ts",
|
|
374
|
-
"apps/server/src/app/speech-output-artifact-bindings.ts",
|
|
375
|
-
"apps/server/src/ai-artifact",
|
|
376
|
-
"apps/server/src/ai-output-artifact",
|
|
377
|
-
"apps/server/src/document",
|
|
378
|
-
"apps/server/src/speech",
|
|
379
|
-
"apps/server/src/embedding",
|
|
380
412
|
"apps/server/src/mcp",
|
|
381
|
-
"apps/server/src/module-host/ai-operation-port.ts",
|
|
382
|
-
"apps/server/src/module-host/ai-operation-port.test.ts",
|
|
383
413
|
"apps/server/src/module-host/agent-session-memory-port.ts",
|
|
384
414
|
"apps/server/src/module-host/agent-source-invalidation-port.ts",
|
|
385
415
|
"apps/server/src/module-host/workflow-input-artifact-port.ts",
|
|
@@ -395,12 +425,12 @@ var agentOptionalModule = {
|
|
|
395
425
|
"apps/web/src/pages/system/AiRuntimePage.vue",
|
|
396
426
|
"apps/web/src/pages/system/AgentToolsPage.vue",
|
|
397
427
|
"apps/web/src/pages/system/SystemAgentSkillsPage.vue",
|
|
398
|
-
"apps/web/src/pages/system/SystemAgentSkillsPage.webtest.ts",
|
|
399
428
|
"apps/web/src/pages/system/components/agent-skills",
|
|
400
429
|
"apps/web/src/pages/system/composables/useAgentSkillsGovernance.ts",
|
|
401
430
|
"apps/web/src/pages/system/composables/useAgentWorkflowPresets.ts",
|
|
402
431
|
"apps/web/src/services/agent-skills-api.ts",
|
|
403
432
|
"apps/web/src/pages/system/AgentDebugPage.vue",
|
|
433
|
+
"apps/web/src/pages/system/AgentNativePage.vue",
|
|
404
434
|
"apps/web/src/pages/system/components/agent-workbench",
|
|
405
435
|
"apps/web/src/pages/system/composables/useAgentWorkbench.ts",
|
|
406
436
|
"apps/web/src/pages/system/composables/useAgentWorkbench.webtest.ts",
|
|
@@ -426,7 +456,6 @@ var agentOptionalModule = {
|
|
|
426
456
|
"apps/web/src/services/agent-session-api.webtest.ts",
|
|
427
457
|
"apps/web/src/services/ai-runtime-api.ts",
|
|
428
458
|
"apps/web/src/services/ai-runtime-api.webtest.ts",
|
|
429
|
-
"scripts/provision-speech-readiness.ts",
|
|
430
459
|
"packages/modules/src/system-agent-admin-registration.test.ts",
|
|
431
460
|
"packages/modules/src/system-agent-admin-menus.ts",
|
|
432
461
|
"packages/modules/src/system-agent-admin-bindings.ts",
|
|
@@ -445,7 +474,6 @@ var agentOptionalModule = {
|
|
|
445
474
|
"packages/server-sdk/src/workflow-input-artifact-validation.contract.test.ts",
|
|
446
475
|
"packages/server-sdk/src/workflow-input-materialization-handler.ts",
|
|
447
476
|
"packages/database/src/agent-runtime-schema.test.ts",
|
|
448
|
-
"packages/database/src/ai-output-artifacts.test.ts",
|
|
449
477
|
"packages/shared/src/agent-admin-catalog.ts",
|
|
450
478
|
"packages/shared/src/agent-workbench.ts",
|
|
451
479
|
"packages/shared/src/agent-skills.ts",
|
|
@@ -472,9 +500,7 @@ var agentOptionalModule = {
|
|
|
472
500
|
"docs/development/dsh-plugins.md",
|
|
473
501
|
"docs/architecture/agent-runtime-compatibility.md",
|
|
474
502
|
"docs/architecture/agent-workflow.md",
|
|
475
|
-
"docs/architecture/durable-jobs.md",
|
|
476
503
|
"docs/architecture/ai-egress.md",
|
|
477
|
-
"docs/architecture/ai-runtime-readiness.md",
|
|
478
504
|
"docs/architecture/ai-runtime.md",
|
|
479
505
|
"docs/architecture/mcp-business-capabilities.md",
|
|
480
506
|
"docs/operations/agent-session-memory.md",
|
|
@@ -492,10 +518,7 @@ var agentOptionalModule = {
|
|
|
492
518
|
"docs/platform/agent-tool-sandbox.md",
|
|
493
519
|
"docs/platform/agent-production-store.md",
|
|
494
520
|
"docs/platform/agent-run-reattachment.md",
|
|
495
|
-
"docs/platform/background-ai-operations.md"
|
|
496
|
-
"docs/platform/document-ai-runtime.md",
|
|
497
|
-
"docs/platform/speech-ai-runtime.md",
|
|
498
|
-
"docs/platform/embedding-ai-runtime.md"
|
|
521
|
+
"docs/platform/background-ai-operations.md"
|
|
499
522
|
],
|
|
500
523
|
schemaFiles: [
|
|
501
524
|
"packages/database/src/schema/agent-runtime.ts",
|
|
@@ -508,9 +531,7 @@ var agentOptionalModule = {
|
|
|
508
531
|
"packages/database/src/schema/agent-workflow-effects.ts",
|
|
509
532
|
"packages/database/src/schema/agent-workflow-evaluation.ts",
|
|
510
533
|
"packages/database/src/schema/client-agent.ts",
|
|
511
|
-
"packages/database/src/schema/client-agent-workflow-artifact.ts"
|
|
512
|
-
"packages/database/src/schema/embedding-runtime.ts",
|
|
513
|
-
"packages/database/src/schema/ai-output-artifacts.ts"
|
|
534
|
+
"packages/database/src/schema/client-agent-workflow-artifact.ts"
|
|
514
535
|
],
|
|
515
536
|
databaseTables: [
|
|
516
537
|
"agent_operation_releases",
|
|
@@ -526,9 +547,6 @@ var agentOptionalModule = {
|
|
|
526
547
|
"client_agent_sessions",
|
|
527
548
|
"client_agent_receipts",
|
|
528
549
|
"client_agent_workflow_artifacts",
|
|
529
|
-
"embedding_run_bindings",
|
|
530
|
-
"ai_output_artifact_scopes",
|
|
531
|
-
"ai_output_artifacts",
|
|
532
550
|
"agent_sessions",
|
|
533
551
|
"agent_session_events",
|
|
534
552
|
"agent_session_checkpoints",
|
|
@@ -612,6 +630,7 @@ var storageOptionalModule = {
|
|
|
612
630
|
// src/optional-module-distribution.ts
|
|
613
631
|
var optionalModuleManifests = [
|
|
614
632
|
storageOptionalModule,
|
|
633
|
+
mediaOptionalModule,
|
|
615
634
|
agentOptionalModule,
|
|
616
635
|
{
|
|
617
636
|
...optionalModule("system.scheduler", "\u4EFB\u52A1\u8C03\u5EA6", "\u4EFB\u52A1\u3001\u91CD\u8BD5\u3001\u5386\u53F2\u548C\u6062\u590D\u3002", ["system", "system.audit"]),
|
|
@@ -808,6 +827,9 @@ var platformModules = [
|
|
|
808
827
|
{
|
|
809
828
|
...module("system.settings", "\u5E73\u53F0\u8BBE\u7F6E", "\u54C1\u724C\u3001Logo \u4E0E\u6C34\u5370\u3002", "recommended", ["system"]),
|
|
810
829
|
runtimeActivation: "physical-only",
|
|
830
|
+
registryDependencies: [
|
|
831
|
+
{ sourceName: "yaml", name: "yaml", version: "2.9.0" }
|
|
832
|
+
],
|
|
811
833
|
fileRoots: [
|
|
812
834
|
"apps/server/src/settings",
|
|
813
835
|
"apps/web/src/pages/settings",
|
|
@@ -822,7 +844,10 @@ var platformModules = [
|
|
|
822
844
|
"packages/modules/src/system-api-watermark.ts",
|
|
823
845
|
"packages/modules/src/system-watermark-policy.test.ts"
|
|
824
846
|
],
|
|
825
|
-
documentation: [
|
|
847
|
+
documentation: [
|
|
848
|
+
"docs/platform/platform-shell-settings.md",
|
|
849
|
+
"docs/operations/admin-settings-yaml.md"
|
|
850
|
+
],
|
|
826
851
|
databaseTables: [
|
|
827
852
|
"platform_branding_settings",
|
|
828
853
|
"platform_watermark_policies"
|
|
@@ -1025,6 +1050,170 @@ function module(name, label, description, selection, dependencies = []) {
|
|
|
1025
1050
|
};
|
|
1026
1051
|
}
|
|
1027
1052
|
|
|
1053
|
+
// src/environment-profile.ts
|
|
1054
|
+
import { readFileSync, statSync } from "fs";
|
|
1055
|
+
|
|
1056
|
+
// ../shared/src/environment-policy.ts
|
|
1057
|
+
var AI_RUNTIME_KINDS = [
|
|
1058
|
+
"agent",
|
|
1059
|
+
"document",
|
|
1060
|
+
"speech",
|
|
1061
|
+
"embedding"
|
|
1062
|
+
];
|
|
1063
|
+
function object(value, required, optional = []) {
|
|
1064
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
1065
|
+
throw new Error("\u73AF\u5883\u9884\u8BBE\u5FC5\u987B\u4E3A\u5BF9\u8C61");
|
|
1066
|
+
const record = value;
|
|
1067
|
+
if (required.some((key) => !Object.hasOwn(record, key)) || Object.keys(record).some((key) => ![...required, ...optional].includes(key)))
|
|
1068
|
+
throw new Error("\u73AF\u5883\u9884\u8BBE\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5\u6216\u5305\u542B\u672A\u77E5\u5B57\u6BB5");
|
|
1069
|
+
return record;
|
|
1070
|
+
}
|
|
1071
|
+
function strings(value, pattern, max = 128) {
|
|
1072
|
+
if (!Array.isArray(value) || value.length > max || value.some((item) => typeof item !== "string" || item.length > 128 || !pattern.test(item)) || new Set(value).size !== value.length)
|
|
1073
|
+
throw new Error("\u73AF\u5883\u9884\u8BBE\u5217\u8868\u65E0\u6548\u6216\u91CD\u590D");
|
|
1074
|
+
return value;
|
|
1075
|
+
}
|
|
1076
|
+
function parseEnvironmentPolicy(value) {
|
|
1077
|
+
const root = object(value, ["schemaVersion", "build", "features"], ["runtime", "antivirus"]);
|
|
1078
|
+
if (root.schemaVersion !== 1)
|
|
1079
|
+
throw new Error("\u4E0D\u652F\u6301\u7684\u73AF\u5883\u9884\u8BBE\u7248\u672C");
|
|
1080
|
+
const build = object(root.build, ["modules"], ["runtimes"]);
|
|
1081
|
+
const modules = strings(build.modules, /^[a-z][a-z0-9.-]*$/);
|
|
1082
|
+
if (!Array.isArray(root.features) || root.features.length > 128)
|
|
1083
|
+
throw new Error("\u529F\u80FD\u8BC4\u4F30\u914D\u7F6E\u8D85\u51FA\u4E0A\u9650");
|
|
1084
|
+
const features = root.features.map((value2) => {
|
|
1085
|
+
const row = object(value2, ["key", "title", "execution"], [
|
|
1086
|
+
"recommendedEnabled",
|
|
1087
|
+
"supportedPlatforms",
|
|
1088
|
+
"supportedArchitectures",
|
|
1089
|
+
"minMemoryGiB",
|
|
1090
|
+
"requiredEnvironmentKeys"
|
|
1091
|
+
]);
|
|
1092
|
+
const [key] = strings([row.key], /^[a-z][a-z0-9.-]*$/);
|
|
1093
|
+
if (typeof row.title !== "string" || !row.title.trim() || row.title.length > 120)
|
|
1094
|
+
throw new Error("\u529F\u80FD\u8BC4\u4F30\u6807\u9898\u65E0\u6548");
|
|
1095
|
+
if (!["none", "cpu", "local-gpu", "remote"].includes(String(row.execution)))
|
|
1096
|
+
throw new Error("\u529F\u80FD\u6267\u884C\u65B9\u5F0F\u65E0\u6548");
|
|
1097
|
+
if (row.recommendedEnabled !== undefined && typeof row.recommendedEnabled !== "boolean")
|
|
1098
|
+
throw new Error("\u63A8\u8350\u5F00\u5173\u5FC5\u987B\u4E3A\u5E03\u5C14\u503C");
|
|
1099
|
+
if (row.minMemoryGiB !== undefined && (typeof row.minMemoryGiB !== "number" || !Number.isFinite(row.minMemoryGiB) || row.minMemoryGiB <= 0 || row.minMemoryGiB > 65536))
|
|
1100
|
+
throw new Error("\u6700\u4F4E\u5185\u5B58\u8981\u6C42\u65E0\u6548");
|
|
1101
|
+
return {
|
|
1102
|
+
key,
|
|
1103
|
+
title: row.title,
|
|
1104
|
+
execution: row.execution,
|
|
1105
|
+
...row.recommendedEnabled === undefined ? {} : { recommendedEnabled: row.recommendedEnabled },
|
|
1106
|
+
...row.minMemoryGiB === undefined ? {} : { minMemoryGiB: row.minMemoryGiB },
|
|
1107
|
+
...row.supportedPlatforms === undefined ? {} : {
|
|
1108
|
+
supportedPlatforms: strings(row.supportedPlatforms, /^(linux|darwin|win32)$/)
|
|
1109
|
+
},
|
|
1110
|
+
...row.supportedArchitectures === undefined ? {} : {
|
|
1111
|
+
supportedArchitectures: strings(row.supportedArchitectures, /^(x64|arm64|arm|ia32|ppc64|s390x|riscv64|loong64)$/)
|
|
1112
|
+
},
|
|
1113
|
+
...row.requiredEnvironmentKeys === undefined ? {} : {
|
|
1114
|
+
requiredEnvironmentKeys: strings(row.requiredEnvironmentKeys, /^[A-Z][A-Z0-9_]*$/)
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
});
|
|
1118
|
+
if (new Set(features.map(({ key }) => key)).size !== features.length)
|
|
1119
|
+
throw new Error("\u529F\u80FD\u8BC4\u4F30 Key \u91CD\u590D");
|
|
1120
|
+
const runtime = Object.hasOwn(root, "runtime") ? parseRuntimeSwitches(root.runtime) : undefined;
|
|
1121
|
+
const runtimes = Object.hasOwn(build, "runtimes") ? parseRuntimeSwitches(build.runtimes) : undefined;
|
|
1122
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
1123
|
+
if (runtimes?.[kind] === false && runtime?.[kind] === true)
|
|
1124
|
+
throw new Error(`\u8FD0\u884C\u65F6\u672A\u968F\u5305\u4EA4\u4ED8\uFF1A${kind}`);
|
|
1125
|
+
}
|
|
1126
|
+
const antivirus = Object.hasOwn(root, "antivirus") ? parseAntivirusPolicy(root.antivirus) : undefined;
|
|
1127
|
+
return {
|
|
1128
|
+
schemaVersion: 1,
|
|
1129
|
+
build: { modules, ...runtimes ? { runtimes } : {} },
|
|
1130
|
+
features,
|
|
1131
|
+
...runtime ? { runtime } : {},
|
|
1132
|
+
...antivirus ? { antivirus } : {}
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
function parseRuntimeSwitches(value) {
|
|
1136
|
+
const switches = object(value, [], [...AI_RUNTIME_KINDS]);
|
|
1137
|
+
const runtime = {};
|
|
1138
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
1139
|
+
if (!Object.hasOwn(switches, kind))
|
|
1140
|
+
continue;
|
|
1141
|
+
const enabled = switches[kind];
|
|
1142
|
+
if (typeof enabled !== "boolean")
|
|
1143
|
+
throw new Error("\u8FD0\u884C\u65F6\u5F00\u5173\u5FC5\u987B\u4E3A\u5E03\u5C14\u503C");
|
|
1144
|
+
runtime[kind] = enabled;
|
|
1145
|
+
}
|
|
1146
|
+
return runtime;
|
|
1147
|
+
}
|
|
1148
|
+
function parseAntivirusPolicy(value) {
|
|
1149
|
+
const { packaged, enabled } = object(value, ["packaged", "enabled"]);
|
|
1150
|
+
if (typeof packaged !== "boolean" || typeof enabled !== "boolean")
|
|
1151
|
+
throw new Error("\u75C5\u6BD2\u626B\u63CF\u4EA4\u4ED8\u548C\u542F\u7528\u8BBE\u7F6E\u5FC5\u987B\u4E3A\u5E03\u5C14\u503C");
|
|
1152
|
+
if (enabled && !packaged)
|
|
1153
|
+
throw new Error("\u75C5\u6BD2\u626B\u63CF\u672A\u968F\u9879\u76EE\u4EA4\u4ED8\uFF0C\u4E0D\u80FD\u542F\u7528");
|
|
1154
|
+
return { packaged, enabled };
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// src/environment-profile.ts
|
|
1158
|
+
function readEnvironmentProfile(path) {
|
|
1159
|
+
const metadata = statSync(path);
|
|
1160
|
+
if (!metadata.isFile() || metadata.size > 128 * 1024)
|
|
1161
|
+
throw new Error("\u73AF\u5883\u9884\u8BBE\u5FC5\u987B\u4E3A\u4E0D\u8D85\u8FC7 128 KiB \u7684\u666E\u901A\u6587\u4EF6");
|
|
1162
|
+
const source = readFileSync(path, "utf8");
|
|
1163
|
+
if (Buffer.byteLength(source, "utf8") > 128 * 1024)
|
|
1164
|
+
throw new Error("\u73AF\u5883\u9884\u8BBE\u6587\u4EF6\u4E0D\u80FD\u8D85\u8FC7 128 KiB");
|
|
1165
|
+
return parseEnvironmentPolicy(Bun.YAML.parse(source));
|
|
1166
|
+
}
|
|
1167
|
+
function environmentProfileModules(profile) {
|
|
1168
|
+
const selected = resolveModuleSelection({
|
|
1169
|
+
requested: profile.build.modules,
|
|
1170
|
+
includeRecommended: false
|
|
1171
|
+
});
|
|
1172
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
1173
|
+
const module2 = runtimeDistributionModule(kind);
|
|
1174
|
+
if (!selected.includes(module2) && (profile.build.runtimes?.[kind] === true || profile.runtime?.[kind] === true))
|
|
1175
|
+
throw new Error(`\u8FD0\u884C\u65F6 ${kind} \u9700\u8981\u9009\u62E9 ${module2} \u6A21\u5757`);
|
|
1176
|
+
}
|
|
1177
|
+
return selected;
|
|
1178
|
+
}
|
|
1179
|
+
function runtimeDistributionModule(kind) {
|
|
1180
|
+
return kind === "agent" ? "system.agent" : "system.media-runtime";
|
|
1181
|
+
}
|
|
1182
|
+
function starterEnvironmentProfile(selectedModules, profile) {
|
|
1183
|
+
const source = `# Windy \u73AF\u5883\u4E0E\u529F\u80FD\u9884\u8BBE\uFF08\u9879\u76EE\u6240\u6709\u8005\u7EF4\u62A4\uFF09
|
|
1184
|
+
# build.modules \u4EC5\u5728 create-windy --environment-profile \u9996\u6B21\u751F\u6210\u65F6\u7528\u4E8E\u7269\u7406\u88C1\u526A\u3002
|
|
1185
|
+
# \u5FC5\u9700\u6A21\u5757\u4E0E\u4F9D\u8D56\u4F1A\u81EA\u52A8\u8865\u9F50\uFF1B\u8FD9\u91CC\u8BB0\u5F55\u5B9E\u9645\u4EA4\u4ED8\u96C6\u5408\u3002
|
|
1186
|
+
# \u4FEE\u6539\u5DF2\u6709\u9879\u76EE\u7684\u6B64\u6587\u4EF6\u4E0D\u4F1A\u5220\u9664\u5DF2\u6784\u5EFA\u4EE3\u7801\uFF0C\u540E\u7EED\u88C1\u526A\u9700\u8D70\u6B63\u5F0F\u751F\u6210/\u5347\u7EA7\u6D41\u7A0B\u3002
|
|
1187
|
+
# features \u662F\u73AF\u5883\u8BC4\u4F30\u5EFA\u8BAE\uFF0C\u4E0D\u81EA\u52A8\u5F00\u5173\u529F\u80FD\uFF1B\u7BA1\u7406\u5458\u786E\u8BA4\u540E\u901A\u8FC7 Feature \u7BA1\u7406\u5E94\u7528\u3002
|
|
1188
|
+
# Server \u4EC5\u5728 WINDY_ENVIRONMENT_PROFILE_FILE \u663E\u5F0F\u6307\u5411\u6B64\u6587\u4EF6\u65F6\u52A0\u8F7D\u8BC4\u4F30\u7B56\u7565\u3002
|
|
1189
|
+
# CPU OCR \u9009\u62E9 system.media-runtime\uFF0C\u901A\u8FC7 build.runtimes \u548C runtime \u542F\u7528 document\u3002
|
|
1190
|
+
# PLATFORM_ENABLE_AI_RUNTIME \u63A7\u5236\u5171\u4EAB\u8FD0\u884C\u65F6\uFF0C\u4E0D\u80FD\u5F53\u4F5C\u7EAF Agent \u5F00\u5173\u3002
|
|
1191
|
+
# \u75C5\u6BD2\u626B\u63CF\u662F\u72EC\u7ACB\u53EF\u9009\u80FD\u529B\uFF0C\u6309\u660E\u786E\u9884\u8BBE\u9009\u62E9\u626B\u63CF\u6216\u4E0D\u626B\u63CF\uFF0C\u4E0E GPU \u72B6\u6001\u65E0\u5173\u3002
|
|
1192
|
+
${Bun.YAML.stringify({
|
|
1193
|
+
schemaVersion: 1,
|
|
1194
|
+
build: {
|
|
1195
|
+
modules: [...selectedModules],
|
|
1196
|
+
...profile?.build.runtimes ? { runtimes: profile.build.runtimes } : {}
|
|
1197
|
+
},
|
|
1198
|
+
...profile?.runtime ? { runtime: profile.runtime } : {},
|
|
1199
|
+
...profile?.antivirus ? { antivirus: profile.antivirus } : {},
|
|
1200
|
+
features: profile?.features ?? []
|
|
1201
|
+
})}
|
|
1202
|
+
# features \u793A\u4F8B\uFF08\u66FF\u6362\u4E3A\u672C\u9879\u76EE Manifest \u4E2D\u771F\u5B9E\u5B58\u5728\u7684 Feature Key \u540E\u518D\u586B\u5199\uFF09\uFF1A
|
|
1203
|
+
# - key: example.cpu-ocr
|
|
1204
|
+
# title: CPU \u6587\u6863\u8BC6\u522B
|
|
1205
|
+
# execution: cpu
|
|
1206
|
+
# recommendedEnabled: true
|
|
1207
|
+
# supportedPlatforms: [linux]
|
|
1208
|
+
# supportedArchitectures: [arm64, x64]
|
|
1209
|
+
# requiredEnvironmentKeys: [DOCUMENT_SERVER_URL]
|
|
1210
|
+
# \u8BBE\u5907\u63A2\u6D4B\u3001\u8F6F\u4EF6\u9002\u914D\u3001\u670D\u52A1 readiness \u4E0E\u8BC6\u522B\u8D28\u91CF\u662F\u4E0D\u540C\u8BC1\u636E\uFF1B\u672A\u77E5\u4E0D\u7B49\u4E8E\u4E0D\u652F\u6301\u3002
|
|
1211
|
+
`;
|
|
1212
|
+
if (Buffer.byteLength(source, "utf8") > 128 * 1024)
|
|
1213
|
+
throw new Error("\u751F\u6210\u7684\u73AF\u5883\u9884\u8BBE\u4E0D\u80FD\u8D85\u8FC7 128 KiB\uFF0C\u8BF7\u7F29\u51CF\u529F\u80FD\u8BC4\u4F30\u6761\u76EE");
|
|
1214
|
+
return source;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1028
1217
|
// src/arguments.ts
|
|
1029
1218
|
function parseArguments(args) {
|
|
1030
1219
|
if (args.includes("--help") || args.includes("-h"))
|
|
@@ -1042,13 +1231,19 @@ function parseArguments(args) {
|
|
|
1042
1231
|
if (includeAll && noOptionalModules) {
|
|
1043
1232
|
throw new Error("--all-modules \u4E0D\u80FD\u4E0E --no-optional-modules \u540C\u65F6\u4F7F\u7528");
|
|
1044
1233
|
}
|
|
1234
|
+
const environmentProfilePath = readValue(args, "--environment-profile");
|
|
1235
|
+
if (args.includes("--environment-profile") && (!environmentProfilePath || environmentProfilePath.startsWith("--")))
|
|
1236
|
+
throw new Error("--environment-profile \u9700\u8981 YAML \u6216 JSON \u6587\u4EF6\u8DEF\u5F84");
|
|
1237
|
+
if (environmentProfilePath && (requestedModules.length || includeAll || noOptionalModules))
|
|
1238
|
+
throw new Error("--environment-profile \u4E0D\u80FD\u4E0E\u6A21\u5757\u9009\u62E9\u53C2\u6570\u540C\u65F6\u4F7F\u7528");
|
|
1239
|
+
const environmentProfile = environmentProfilePath ? readEnvironmentProfile(environmentProfilePath) : undefined;
|
|
1045
1240
|
const projectLicense = readProjectLicense(args);
|
|
1046
|
-
const selectedModules = resolveModuleSelection({
|
|
1241
|
+
const selectedModules = environmentProfile ? environmentProfileModules(environmentProfile) : resolveModuleSelection({
|
|
1047
1242
|
requested: requestedModules,
|
|
1048
1243
|
includeRecommended: !noOptionalModules,
|
|
1049
1244
|
includeAll
|
|
1050
1245
|
});
|
|
1051
|
-
const explicitSelection = requestedModules.length > 0 || includeAll || noOptionalModules;
|
|
1246
|
+
const explicitSelection = requestedModules.length > 0 || includeAll || noOptionalModules || Boolean(environmentProfile);
|
|
1052
1247
|
return {
|
|
1053
1248
|
projectName,
|
|
1054
1249
|
targetDirectory: resolve(process.cwd(), projectName),
|
|
@@ -1057,6 +1252,7 @@ function parseArguments(args) {
|
|
|
1057
1252
|
verify: args.includes("--verify"),
|
|
1058
1253
|
keepOnError: args.includes("--keep-on-error"),
|
|
1059
1254
|
selectedModules,
|
|
1255
|
+
...environmentProfile ? { environmentProfile } : {},
|
|
1060
1256
|
includeExample: selectedModules.includes("work-order"),
|
|
1061
1257
|
includeOxc: !args.includes("--no-oxc"),
|
|
1062
1258
|
projectLicense,
|
|
@@ -1068,6 +1264,7 @@ function parseArguments(args) {
|
|
|
1068
1264
|
function readProjectName(args) {
|
|
1069
1265
|
const flagsWithValues = new Set([
|
|
1070
1266
|
"--profile",
|
|
1267
|
+
"--environment-profile",
|
|
1071
1268
|
"--module",
|
|
1072
1269
|
"--license",
|
|
1073
1270
|
"--license-holder"
|
|
@@ -1117,6 +1314,7 @@ var helpText = `create-windy <\u9879\u76EE\u540D> [\u9009\u9879]
|
|
|
1117
1314
|
|
|
1118
1315
|
\u9009\u9879\uFF1A
|
|
1119
1316
|
--profile private-enterprise \u5355\u7EC4\u7EC7\u3001\u5355\u79DF\u6237\u3001\u79C1\u6709\u90E8\u7F72 profile
|
|
1317
|
+
--environment-profile <\u6587\u4EF6> \u4ECE YAML/JSON build.modules \u9009\u62E9\u6A21\u5757\u5E76\u53D1\u653E\u73AF\u5883\u8BC4\u4F30\u5EFA\u8BAE
|
|
1120
1318
|
--skip-install \u751F\u6210\u6216\u66F4\u65B0\u65F6\u4E0D\u6267\u884C bun install
|
|
1121
1319
|
--verify \u5B89\u88C5\u540E\u6267\u884C lint\uFF08\u82E5\u6709\uFF09\u3001typecheck\u3001test \u548C build
|
|
1122
1320
|
--keep-on-error \u5931\u8D25\u65F6\u4FDD\u7559\u65B0\u751F\u6210\u76EE\u5F55\u7528\u4E8E\u8BCA\u65AD
|
|
@@ -1585,6 +1783,7 @@ var ignoredFiles = new Set([
|
|
|
1585
1783
|
".windy/update-state.json"
|
|
1586
1784
|
]);
|
|
1587
1785
|
var projectOwnedRoots = [
|
|
1786
|
+
"windy.environment.yaml",
|
|
1588
1787
|
"windy.modules.json",
|
|
1589
1788
|
"module-schema.lineages.json",
|
|
1590
1789
|
"module-schema",
|
|
@@ -1735,7 +1934,7 @@ import {
|
|
|
1735
1934
|
fchmodSync,
|
|
1736
1935
|
fstatSync as fstatSync2,
|
|
1737
1936
|
fsyncSync as fsyncSync2,
|
|
1738
|
-
readFileSync,
|
|
1937
|
+
readFileSync as readFileSync2,
|
|
1739
1938
|
writeSync
|
|
1740
1939
|
} from "fs";
|
|
1741
1940
|
import { open as open3 } from "fs/promises";
|
|
@@ -2189,7 +2388,7 @@ function readFileAt(parent) {
|
|
|
2189
2388
|
const info = fstatSync2(fd);
|
|
2190
2389
|
if (!info.isFile())
|
|
2191
2390
|
throw new Error(`\u4E8B\u52A1\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6\uFF1A${parent.leaf}`);
|
|
2192
|
-
return
|
|
2391
|
+
return readFileSync2(fd);
|
|
2193
2392
|
} finally {
|
|
2194
2393
|
closeSync2(fd);
|
|
2195
2394
|
}
|
|
@@ -3100,16 +3299,26 @@ var textExtensions = new Set([
|
|
|
3100
3299
|
".yaml",
|
|
3101
3300
|
".yml"
|
|
3102
3301
|
]);
|
|
3103
|
-
async function materializeSelectedModules(targetDirectory, selectedNames) {
|
|
3104
|
-
selectedModuleManifests(selectedNames);
|
|
3302
|
+
async function materializeSelectedModules(targetDirectory, selectedNames, excludedRuntimeApps = []) {
|
|
3303
|
+
const retainedDependencies = new Set(selectedModuleManifests(selectedNames).flatMap(({ registryDependencies }) => registryDependencies).flatMap(({ sourceName, name }) => [sourceName, name]));
|
|
3105
3304
|
const selected = new Set(selectedNames);
|
|
3106
3305
|
const removed = moduleDistributionCatalog.filter(({ name }) => !selected.has(name));
|
|
3107
|
-
const removedPackageNames = await readRemovedPackageNames(targetDirectory,
|
|
3306
|
+
const removedPackageNames = await readRemovedPackageNames(targetDirectory, [
|
|
3307
|
+
...removed.flatMap(({ packages }) => packages),
|
|
3308
|
+
...excludedRuntimeApps
|
|
3309
|
+
]);
|
|
3108
3310
|
for (const dependency of removed.flatMap(({ registryDependencies }) => registryDependencies)) {
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3311
|
+
if (!retainedDependencies.has(dependency.sourceName))
|
|
3312
|
+
removedPackageNames.add(dependency.sourceName);
|
|
3313
|
+
if (!retainedDependencies.has(dependency.name))
|
|
3314
|
+
removedPackageNames.add(dependency.name);
|
|
3315
|
+
}
|
|
3316
|
+
const agent = moduleDistributionCatalog.find(({ name }) => name === "system.agent");
|
|
3317
|
+
const includeAgentUi = selected.has("system.agent") && !excludedRuntimeApps.includes("apps/agent-server");
|
|
3318
|
+
const sourceTags = new Set(selected);
|
|
3319
|
+
if (includeAgentUi)
|
|
3320
|
+
sourceTags.add("system.agent-ui");
|
|
3321
|
+
await stripModuleBlocks(targetDirectory, sourceTags);
|
|
3113
3322
|
await pruneDatabaseArtifacts(targetDirectory, [
|
|
3114
3323
|
...removed.flatMap(({ databaseTables, transientDatabaseTables }) => [
|
|
3115
3324
|
...databaseTables,
|
|
@@ -3117,12 +3326,16 @@ async function materializeSelectedModules(targetDirectory, selectedNames) {
|
|
|
3117
3326
|
]),
|
|
3118
3327
|
...moduleDistributionCatalog.filter(({ databaseLineageOwner }) => databaseLineageOwner === "module").flatMap(({ databaseTables }) => databaseTables)
|
|
3119
3328
|
], removed.flatMap(({ databaseStatementTokens }) => databaseStatementTokens));
|
|
3120
|
-
const removedRoots = collapseRemovalRoots(
|
|
3121
|
-
...manifest
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3329
|
+
const removedRoots = collapseRemovalRoots([
|
|
3330
|
+
...removed.flatMap((manifest) => [
|
|
3331
|
+
...manifest.packages,
|
|
3332
|
+
...manifest.fileRoots,
|
|
3333
|
+
...manifest.documentation,
|
|
3334
|
+
...manifest.schemaFiles
|
|
3335
|
+
]),
|
|
3336
|
+
...excludedRuntimeApps,
|
|
3337
|
+
...!includeAgentUi && agent ? agent.fileRoots.filter((path) => path.startsWith("apps/web/src/") || path === "packages/modules/src/system-agent-admin-menus.ts" || path === "packages/modules/src/system-agent-admin-registration.test.ts") : []
|
|
3338
|
+
]);
|
|
3126
3339
|
await Promise.all([...new Set(removedRoots)].map((path) => rm3(join8(targetDirectory, path), { recursive: true, force: true })));
|
|
3127
3340
|
await pruneWorkspaceReferences(targetDirectory, removedPackageNames, removedRoots);
|
|
3128
3341
|
}
|
|
@@ -3178,7 +3391,10 @@ async function readRemovedPackageNames(root, roots) {
|
|
|
3178
3391
|
const names = new Set;
|
|
3179
3392
|
for (const packageRoot2 of roots) {
|
|
3180
3393
|
try {
|
|
3181
|
-
const
|
|
3394
|
+
const directory = join8(root, packageRoot2);
|
|
3395
|
+
if (!(await lstat3(directory)).isDirectory())
|
|
3396
|
+
continue;
|
|
3397
|
+
const value = JSON.parse(await readFile6(join8(directory, "package.json"), "utf8"));
|
|
3182
3398
|
if (value.name)
|
|
3183
3399
|
names.add(value.name);
|
|
3184
3400
|
} catch (error) {
|
|
@@ -3211,7 +3427,12 @@ async function pruneWorkspaceReferences(root, removedPackages, removedRoots) {
|
|
|
3211
3427
|
continue;
|
|
3212
3428
|
const source = await readFile6(path, "utf8");
|
|
3213
3429
|
const output = source.split(`
|
|
3214
|
-
`).
|
|
3430
|
+
`).map((line) => {
|
|
3431
|
+
for (const removed of removedRoots) {
|
|
3432
|
+
line = line.replaceAll(`,"--filter","!./${removed}"`, "");
|
|
3433
|
+
}
|
|
3434
|
+
return line;
|
|
3435
|
+
}).filter((line) => !removedRoots.some((root2) => line.includes(root2))).join(`
|
|
3215
3436
|
`);
|
|
3216
3437
|
if (output !== source)
|
|
3217
3438
|
await writeFile5(path, output);
|
|
@@ -3327,15 +3548,12 @@ var starterServerBuild = ` build:
|
|
|
3327
3548
|
function agentWorkflowServerEnvironment(includeAgent) {
|
|
3328
3549
|
return includeAgent ? " WINDY_AGENT_WORKFLOW_MODEL_PRICING_JSON: ${WINDY_AGENT_WORKFLOW_MODEL_PRICING_JSON:-}" : "";
|
|
3329
3550
|
}
|
|
3330
|
-
function optionalComposeVolumes(
|
|
3551
|
+
function optionalComposeVolumes(include, includeSearch, includeStorage) {
|
|
3331
3552
|
return [
|
|
3332
|
-
...
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
" speech-run-data:",
|
|
3337
|
-
" embedding-run-data:"
|
|
3338
|
-
] : [],
|
|
3553
|
+
...include("agent") ? [" agent-run-data:", " tool-sandbox-ipc:"] : [],
|
|
3554
|
+
...include("document") ? [" document-run-data:"] : [],
|
|
3555
|
+
...include("speech") ? [" speech-run-data:"] : [],
|
|
3556
|
+
...include("embedding") ? [" embedding-run-data:"] : [],
|
|
3339
3557
|
...includeSearch ? [" opensearch-data:"] : [],
|
|
3340
3558
|
...includeStorage ? [" server-storage-data:"] : []
|
|
3341
3559
|
].join(`
|
|
@@ -3442,7 +3660,8 @@ ${starterServerBuild}
|
|
|
3442
3660
|
condition: service_completed_successfully
|
|
3443
3661
|
server:
|
|
3444
3662
|
condition: service_started
|
|
3445
|
-
|
|
3663
|
+
`;
|
|
3664
|
+
var documentComposeService = ` document-server:
|
|
3446
3665
|
profiles: ["document"]
|
|
3447
3666
|
build:
|
|
3448
3667
|
context: .
|
|
@@ -3466,7 +3685,8 @@ ${starterServerBuild}
|
|
|
3466
3685
|
server:
|
|
3467
3686
|
condition: service_started
|
|
3468
3687
|
|
|
3469
|
-
|
|
3688
|
+
`;
|
|
3689
|
+
var speechComposeService = ` speech-server:
|
|
3470
3690
|
profiles: ["speech"]
|
|
3471
3691
|
build:
|
|
3472
3692
|
context: .
|
|
@@ -3498,7 +3718,8 @@ ${starterServerBuild}
|
|
|
3498
3718
|
server:
|
|
3499
3719
|
condition: service_started
|
|
3500
3720
|
|
|
3501
|
-
|
|
3721
|
+
`;
|
|
3722
|
+
var embeddingComposeService = ` embedding-server:
|
|
3502
3723
|
profiles: ["embedding"]
|
|
3503
3724
|
build:
|
|
3504
3725
|
context: .
|
|
@@ -3606,10 +3827,10 @@ __STORAGE_SERVER_ENV__
|
|
|
3606
3827
|
WINDY_CONTAINERIZED: "1"
|
|
3607
3828
|
BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD: "true"
|
|
3608
3829
|
WINDY_SYSTEM_USAGE_PATHS: /app/data/audit
|
|
3609
|
-
|
|
3610
|
-
|
|
3830
|
+
PLATFORM_ENABLE_AI_RUNTIME: \${PLATFORM_ENABLE_AI_RUNTIME:-\${PLATFORM_ENABLE_AI:-false}}
|
|
3831
|
+
__ENVIRONMENT_PROFILE_ENV__
|
|
3832
|
+
__AGENT_SERVER_ENV__
|
|
3611
3833
|
WINDY_PUBLIC_BASE_URL: "\${WINDY_PUBLIC_BASE_URL:-}"
|
|
3612
|
-
AGENT_TOOL_HOST_URL: http://server:9747
|
|
3613
3834
|
__TOOL_SANDBOX_SERVER_ENV__
|
|
3614
3835
|
AGENT_SERVER_INTERNAL_TOKEN: \${AGENT_SERVER_INTERNAL_TOKEN:-}
|
|
3615
3836
|
__AGENT_WORKFLOW_SERVER_ENV__
|
|
@@ -3628,6 +3849,7 @@ __OPENSEARCH_SERVER_ENV__
|
|
|
3628
3849
|
- ./apps/server:/app/apps/server
|
|
3629
3850
|
- ./packages:/app/packages
|
|
3630
3851
|
- server-audit-data:/app/data/audit
|
|
3852
|
+
__ENVIRONMENT_PROFILE_VOLUME__
|
|
3631
3853
|
__STORAGE_SERVER_VOLUME__
|
|
3632
3854
|
__TOOL_SANDBOX_SERVER_VOLUME__
|
|
3633
3855
|
depends_on:
|
|
@@ -3670,17 +3892,30 @@ volumes:
|
|
|
3670
3892
|
server-audit-data:
|
|
3671
3893
|
__OPTIONAL_VOLUMES__
|
|
3672
3894
|
`;
|
|
3673
|
-
function starterComposeFor(includeAgent, includeSearch = true, includeStorage = true) {
|
|
3895
|
+
function starterComposeFor(includeAgent, includeSearch = true, includeStorage = true, profile, includeMedia = includeAgent) {
|
|
3896
|
+
const include = (kind) => (kind === "agent" ? includeAgent : includeMedia) && profile?.build?.[kind] !== false;
|
|
3897
|
+
const starts = (kind) => include(kind) && profile?.runtime?.[kind] === true;
|
|
3898
|
+
const services = [
|
|
3899
|
+
["agent", agentComposeService],
|
|
3900
|
+
["document", documentComposeService],
|
|
3901
|
+
["speech", speechComposeService],
|
|
3902
|
+
["embedding", embeddingComposeService]
|
|
3903
|
+
];
|
|
3904
|
+
const aiServices = services.filter(([kind]) => include(kind)).map(([kind, source]) => starts(kind) ? source.replaceAll(` profiles: ["${kind}"]
|
|
3905
|
+
`, "") : source).join("");
|
|
3906
|
+
const hasProfile = !!(profile?.build || profile?.runtime || profile?.mountEnvironment);
|
|
3907
|
+
const startAi = services.some(([kind]) => starts(kind));
|
|
3674
3908
|
return starterComposeBase.replace(` web:
|
|
3675
|
-
`, `${
|
|
3676
|
-
`).replace("
|
|
3909
|
+
`, `${aiServices} web:
|
|
3910
|
+
`).replace("__ENVIRONMENT_PROFILE_ENV__", hasProfile ? " WINDY_ENVIRONMENT_PROFILE_FILE: /app/windy.environment.yaml" : "").replace("__ENVIRONMENT_PROFILE_VOLUME__", hasProfile ? " - ./windy.environment.yaml:/app/windy.environment.yaml:ro" : "").replace("__AGENT_SERVER_ENV__", include("agent") ? ` AGENT_SERVER_URL: http://agent-server:8080
|
|
3911
|
+
AGENT_TOOL_HOST_URL: http://server:9747` : "").replace("${PLATFORM_ENABLE_AI:-false}", startAi ? "${PLATFORM_ENABLE_AI:-true}" : "${PLATFORM_ENABLE_AI:-false}").replace("${DOCUMENT_SERVER_URL:-}", starts("document") ? "${DOCUMENT_SERVER_URL:-http://document-server:8090}" : "${DOCUMENT_SERVER_URL:-}").replace("${SPEECH_SERVER_URL:-}", starts("speech") ? "${SPEECH_SERVER_URL:-http://speech-server:8091}" : "${SPEECH_SERVER_URL:-}").replace("${EMBEDDING_SERVER_URL:-}", starts("embedding") ? "${EMBEDDING_SERVER_URL:-http://embedding-server:8092}" : "${EMBEDDING_SERVER_URL:-}").replace("__TOOL_SANDBOX_SERVER_ENV__", include("agent") ? " TOOL_SANDBOX_SOCKET: /run/windy-tool-sandbox/worker.sock" : "").replace("__AGENT_WORKFLOW_SERVER_ENV__", agentWorkflowServerEnvironment(include("agent"))).replace("__TOOL_SANDBOX_SERVER_VOLUME__", include("agent") ? " - tool-sandbox-ipc:/run/windy-tool-sandbox" : "").replace("__STORAGE_SERVER_ENV__", includeStorage ? " WINDY_STORAGE_ROOT: /app/data/storage" : "").replace("__STORAGE_SERVER_VOLUME__", includeStorage ? " - server-storage-data:/app/data/storage" : "").replace("__OPENSEARCH_SERVER_ENV__", includeSearch ? ` OPENSEARCH_URL: \${OPENSEARCH_URL:-}
|
|
3677
3912
|
OPENSEARCH_USERNAME: \${OPENSEARCH_USERNAME:-}
|
|
3678
3913
|
OPENSEARCH_PASSWORD: \${OPENSEARCH_PASSWORD:-}
|
|
3679
|
-
OPENSEARCH_WORK_ORDER_INDEX: \${OPENSEARCH_WORK_ORDER_INDEX:-windy-work-orders-v1}` : "").replace("__OPENSEARCH_SERVICE__", includeSearch ? openSearchComposeService : "").replace("__OPTIONAL_VOLUMES__", optionalComposeVolumes(
|
|
3914
|
+
OPENSEARCH_WORK_ORDER_INDEX: \${OPENSEARCH_WORK_ORDER_INDEX:-windy-work-orders-v1}` : "").replace("__OPENSEARCH_SERVICE__", includeSearch ? openSearchComposeService : "").replace("__OPTIONAL_VOLUMES__", optionalComposeVolumes(include, includeSearch, includeStorage));
|
|
3680
3915
|
}
|
|
3681
3916
|
var starterCompose = starterComposeFor(true);
|
|
3682
3917
|
// src/runtime-environment-example.ts
|
|
3683
|
-
function environmentExample(includeExample,
|
|
3918
|
+
function environmentExample(includeExample, includeMedia = true, includeSearch = true, includeStorage = true, excludedRuntimes = []) {
|
|
3684
3919
|
return `# \u590D\u5236\u4E3A .env \u540E\u586B\u5199\u3002\u4E0D\u8981\u63D0\u4EA4\u771F\u5B9E\u5BC6\u7801\u3002
|
|
3685
3920
|
POSTGRES_PASSWORD=
|
|
3686
3921
|
WINDY_BOOTSTRAP_ADMIN_PASSWORD=
|
|
@@ -3689,11 +3924,14 @@ ${includeStorage ? `
|
|
|
3689
3924
|
# \u5982\u9700\u72EC\u7ACB\u6302\u8F7D\u62A5\u544A\u6682\u5B58\u76EE\u5F55\uFF0C\u8BF7\u540C\u65F6\u4FEE\u6539 Compose volume\u3002
|
|
3690
3925
|
# WINDY_REPORT_STAGING_ROOT=/app/data/storage/report-staging
|
|
3691
3926
|
` : ""}
|
|
3692
|
-
${
|
|
3693
|
-
#
|
|
3694
|
-
PLATFORM_ENABLE_AI
|
|
3927
|
+
${includeMedia ? `
|
|
3928
|
+
# \u5171\u4EAB AI Runtime \u5305\u62EC CPU OCR \u7684 Document Runtime\uFF1B\u4E0D\u662F\u4EC5\u63A7\u5236\u5927\u6A21\u578B\u3002
|
|
3929
|
+
# \u65E7\u540D PLATFORM_ENABLE_AI \u4ECD\u517C\u5BB9\uFF0C\u5EFA\u8BAE\u53EA\u914D\u7F6E\u5176\u4E2D\u4E00\u4E2A\uFF1B\u4E0D\u8981\u4F7F\u7528 VITE_ \u524D\u7F00\u3002
|
|
3930
|
+
# \u7559\u7A7A\u65F6\u4F7F\u7528\u751F\u6210\u7684 Compose \u9ED8\u8BA4\u503C\uFF1B\u9700\u8981\u8986\u76D6\u65F6\u518D\u53D6\u6D88\u6CE8\u91CA\u3002
|
|
3931
|
+
# PLATFORM_ENABLE_AI_RUNTIME=false
|
|
3695
3932
|
AGENT_SERVER_INTERNAL_TOKEN=
|
|
3696
|
-
|
|
3933
|
+
AI_ARTIFACT_ENCRYPTION_SECRET=
|
|
3934
|
+
${!excludedRuntimes.includes("agent") ? `AGENT_INTERNAL_OUTPUT_ENCRYPTION_SECRET=
|
|
3697
3935
|
# Model \u8282\u70B9\u542F\u7528\u524D\u5FC5\u987B\u586B\u5165\u7531\u8FD0\u7EF4\u51BB\u7ED3\u7684 deployment/model \u4EF7\u683C\u76EE\u5F55\uFF1B\u7F3A\u5931\u65F6 readiness \u660E\u786E unavailable\u3002
|
|
3698
3936
|
WINDY_AGENT_WORKFLOW_MODEL_PRICING_JSON=
|
|
3699
3937
|
# \u975E Compose \u90E8\u7F72\u9700\u6307\u5411 Windy Server\uFF1B\u957F\u671F Session \u7684\u6A21\u578B\u8C03\u7528\u4F1A fail closed\u3002
|
|
@@ -3710,12 +3948,16 @@ AGENT_DSH_USER_EXTENSIONS=1
|
|
|
3710
3948
|
# \u6784\u5EFA\u671F\u955C\u50CF\u6E90\u4ECD\u9700\u7B26\u5408\u9501\u6587\u4EF6\u7684hash\uFF1B\u8FD0\u884C\u65F6\u4E0D\u4E0B\u8F7D\u539F\u751F\u4F9D\u8D56\u3002
|
|
3711
3949
|
# WINDY_AGENT_NATIVE_REGISTRY=https://registry.npmjs.org
|
|
3712
3950
|
# WINDY_PYPI_INDEX_URL=https://pypi.org/simple
|
|
3713
|
-
AI_ARTIFACT_ENCRYPTION_SECRET=
|
|
3714
3951
|
# \u5F00\u53D1\u7559\u7A7A\u65F6\u5DE5\u4F5C\u53F0\u8DDF\u968F\u6D4F\u89C8\u5668\u540C\u6E90 Host\uFF0C\u652F\u6301 Web \u7AEF\u53E3\u548C\u52A8\u6001\u5C40\u57DF\u7F51\u5730\u5740\u3002
|
|
3715
3952
|
# HTTPS \u53CD\u5411\u4EE3\u7406\u6216\u751F\u4EA7 Client Agent Session \u5FC5\u987B\u586B\u5199\u7528\u6237\u5B9E\u9645\u8BBF\u95EE\u7684 Web origin\u3002
|
|
3716
3953
|
# WINDY_PUBLIC_BASE_URL=https://windy.example
|
|
3717
3954
|
WINDY_PUBLIC_BASE_URL=
|
|
3718
|
-
|
|
3955
|
+
` : ""}
|
|
3956
|
+
${!excludedRuntimes.includes("document") || !excludedRuntimes.includes("speech") ? `AI_OUTPUT_ARTIFACT_REFERENCE_SECRET=
|
|
3957
|
+
DOCUMENT_OUTPUT_ARTIFACT_SINK_IDENTITY=
|
|
3958
|
+
DOCUMENT_OUTPUT_ARTIFACT_SINK_RELEASE_DIGEST=
|
|
3959
|
+
` : ""}
|
|
3960
|
+
${!excludedRuntimes.includes("document") ? `DOCUMENT_SERVER_URL=
|
|
3719
3961
|
DOCUMENT_ARTIFACT_URL=
|
|
3720
3962
|
DOCUMENT_OUTPUT_ARTIFACT_URL=
|
|
3721
3963
|
DOCUMENT_ADAPTER_URL=
|
|
@@ -3724,12 +3966,10 @@ DOCUMENT_DEPLOYMENT_KEY=
|
|
|
3724
3966
|
DOCUMENT_DEPLOYMENT_IDENTITY=
|
|
3725
3967
|
DOCUMENT_RELEASE_DIGEST=
|
|
3726
3968
|
DOCUMENT_OFFERS_DIGEST=
|
|
3727
|
-
AI_OUTPUT_ARTIFACT_REFERENCE_SECRET=
|
|
3728
|
-
DOCUMENT_OUTPUT_ARTIFACT_SINK_IDENTITY=
|
|
3729
|
-
DOCUMENT_OUTPUT_ARTIFACT_SINK_RELEASE_DIGEST=
|
|
3730
3969
|
# DOCUMENT_ADAPTER_CAPABILITIES=document.ocr,document.layout,document.table
|
|
3731
3970
|
# DOCUMENT_MAX_UNITS=500
|
|
3732
|
-
|
|
3971
|
+
` : ""}
|
|
3972
|
+
${!excludedRuntimes.includes("speech") ? `SPEECH_SERVER_URL=
|
|
3733
3973
|
SPEECH_ARTIFACT_URL=
|
|
3734
3974
|
SPEECH_OUTPUT_ARTIFACT_URL=
|
|
3735
3975
|
SPEECH_ADAPTER_URL=
|
|
@@ -3748,7 +3988,8 @@ SPEECH_OFFERS_DIGEST=
|
|
|
3748
3988
|
# SPEECH_MAX_QUEUE_DEPTH=0
|
|
3749
3989
|
# SPEECH_READINESS_TIMEOUT_SECONDS=5
|
|
3750
3990
|
# SPEECH_READINESS_TTL_SECONDS=60
|
|
3751
|
-
|
|
3991
|
+
` : ""}
|
|
3992
|
+
${!excludedRuntimes.includes("embedding") ? `EMBEDDING_SERVER_URL=
|
|
3752
3993
|
EMBEDDING_ARTIFACT_URL=
|
|
3753
3994
|
EMBEDDING_RUN_ARTIFACT_URL=
|
|
3754
3995
|
EMBEDDING_ADAPTER_URL=
|
|
@@ -3775,7 +4016,8 @@ EMBEDDING_RUN_ENCRYPTION_SECRET=
|
|
|
3775
4016
|
# EMBEDDING_READINESS_TIMEOUT_SECONDS=5
|
|
3776
4017
|
# EMBEDDING_READINESS_TTL_SECONDS=60
|
|
3777
4018
|
# EMBEDDING_RUN_TERMINAL_TTL_SECONDS=604800
|
|
3778
|
-
|
|
4019
|
+
` : ""}
|
|
4020
|
+
${!excludedRuntimes.includes("agent") ? `QWEN_API_URL=
|
|
3779
4021
|
QWEN_API_KEY=
|
|
3780
4022
|
QWEN_MODEL=
|
|
3781
4023
|
# QWEN_STRUCTURED_OUTPUT_MODE=json_schema
|
|
@@ -3800,6 +4042,7 @@ AI_PROVIDER_HTTPS_HOST_ALLOWLIST=
|
|
|
3800
4042
|
# AI_PROVIDER_MAX_ARTIFACTS=16
|
|
3801
4043
|
# AI_PROVIDER_MAX_PIXELS_PER_ARTIFACT=100000000
|
|
3802
4044
|
` : ""}
|
|
4045
|
+
` : ""}
|
|
3803
4046
|
|
|
3804
4047
|
${includeSearch ? `# OpenSearch profile \u9ED8\u8BA4\u4E0D\u542F\u52A8\uFF1Bbun run dev:search \u4F1A\u53EA\u5411 Server \u6CE8\u5165\u5BB9\u5668\u5185\u5730\u5740\u3002
|
|
3805
4048
|
OPENSEARCH_URL=
|
|
@@ -3818,7 +4061,7 @@ OPENSEARCH_PASSWORD=
|
|
|
3818
4061
|
`;
|
|
3819
4062
|
}
|
|
3820
4063
|
// src/starter-docs-readme.ts
|
|
3821
|
-
function starterDocsReadme(includeOfflineLicense = true, includeAgent = true, includeOperations = true, includeStorage = true) {
|
|
4064
|
+
function starterDocsReadme(includeOfflineLicense = true, includeAgent = true, includeOperations = true, includeStorage = true, includeMedia = includeAgent) {
|
|
3822
4065
|
return `# Windy Starter \u6587\u6863
|
|
3823
4066
|
|
|
3824
4067
|
\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
|
|
@@ -3830,20 +4073,22 @@ License \u7B7E\u53D1\u4E2D\u5FC3\u3001\u72EC\u7ACB\u7B7E\u540D\u670D\u52A1\u3001
|
|
|
3830
4073
|
- \u6570\u636E\u5E93\uFF1A\u4E1A\u52A1\u8868\u4F7F\u7528 [Migration Bundle \u4E0E\u72EC\u7ACB Drizzle lineage](./architecture/migration-bundle.md)\u3002
|
|
3831
4074
|
- \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
|
|
3832
4075
|
- Web \u4E1A\u52A1\u9875\u9762\uFF1A[project-owned \u4E1A\u52A1 Web \u8DEF\u7531](./development/business-web-routes.md)\u3002
|
|
4076
|
+
- \u73AF\u5883\u9002\u914D\uFF1A[\u73AF\u5883\u80FD\u529B\u8BC4\u4F30\u4E0E\u6784\u5EFA\u9884\u8BBE](./operations/environment-capabilities.md)\u3002
|
|
3833
4077
|
- \u90E8\u7F72\u671F\u6A21\u5757\u7BA1\u7406\uFF1A[\u6A21\u5757\u751F\u547D\u5468\u671F](./development/module-lifecycle.md)\u3002
|
|
3834
4078
|
- \u4E1A\u52A1\u6A21\u5757\u5F00\u53D1\uFF1A[windy-business-module Skill](../.agents/skills/windy-business-module/SKILL.md)\u3002
|
|
3835
4079
|
${includeStorage ? "- \u5927\u62A5\u544A\u5BFC\u5165\uFF1A[\u53D7\u6CBB\u7406\u7684\u5927\u62A5\u544A\u6682\u5B58](./architecture/report-staging.md)\u3002" : ""}
|
|
3836
4080
|
${includeOfflineLicense ? "- License \u6D88\u8D39\u7AEF\uFF1A[\u79BB\u7EBF\u6FC0\u6D3B\u4E0E\u5B89\u88C5\u534F\u8BAE](./license/license-offline-activation-code.md)\u4E0E[\u624B\u673A\u626B\u7801\u914D\u5BF9\u6FC0\u6D3B](./license/license-pairing-activation.md)\uFF1B\u8FD0\u884C\u65F6\u80FD\u529B\u7531 npm \u4F9D\u8D56 `@southwind-ai/license` \u63D0\u4F9B\u3002" : ""}
|
|
3837
4081
|
- \u8FD0\u7EF4\uFF1A[\u53EF\u89C2\u6D4B\u6027](./operations/observability.md)${includeOperations ? " \u4E0E [\u8FD0\u7EF4\u603B\u89C8](./platform/operations-overview.md)" : ""}\u3002
|
|
3838
4082
|
- \u4EA4\u4ED8\uFF1A[\u6309 registry digest \u4E0E OCI blob \u5DEE\u91CF\u53D1\u5E03](./operations/incremental-delivery.md)\u3002
|
|
3839
|
-
${includeAgent ? "- Agent
|
|
4083
|
+
${includeAgent ? "- Agent \u4E0E MCP\uFF1A[Agent Harness](./architecture/agent-harness.md)\u3001[Agent Runtime \u63A5\u5165](./platform/agent-runtime.md)\u3001[Session/Memory \u8FD0\u7EF4](./operations/agent-session-memory.md)\u3001[Session \u6545\u969C\u901F\u67E5](./operations/agent-session-troubleshooting.md)\u3001[Agent Workflow](./architecture/agent-workflow.md)\u3001[Workflow \u6062\u590D\u8FD0\u7EF4](./operations/agent-workflow-recovery.md)\u3001[\u53D7\u63A7\u5DE5\u5177](./platform/agent-tools.md)\u4E0E[MCP \u4E1A\u52A1\u80FD\u529B](./architecture/mcp-business-capabilities.md)\u3002" : ""}
|
|
4084
|
+
${includeMedia ? "- \u5A92\u4F53\u8FD0\u884C\u65F6\uFF1A[Document/OCR](./platform/document-ai-runtime.md)\u3001[Speech](./platform/speech-ai-runtime.md)\u4E0E [Embedding](./platform/embedding-ai-runtime.md)\u3002" : ""}
|
|
3840
4085
|
- \u6570\u636E\u8FC1\u79FB\uFF1A[\u65E7\u7CFB\u7EDF\u6570\u636E\u8FC1\u79FB\u7B56\u7565](./operations/legacy-data-migration.md)\u3002
|
|
3841
4086
|
`;
|
|
3842
4087
|
}
|
|
3843
4088
|
// src/project-files.ts
|
|
3844
|
-
function starterReadme(projectName, includeExample = true, includeOxc = true, projectLicense = "UNLICENSED", selectedModules = []) {
|
|
4089
|
+
function starterReadme(projectName, includeExample = true, includeOxc = true, projectLicense = "UNLICENSED", selectedModules = [], includeAgentRuntime = selectedModules.includes("system.agent"), excludedRuntimes = []) {
|
|
3845
4090
|
const selected = new Set(selectedModules);
|
|
3846
|
-
const includeAgent =
|
|
4091
|
+
const includeAgent = includeAgentRuntime;
|
|
3847
4092
|
const includeSearch = selected.has("system.search");
|
|
3848
4093
|
const toggleableModule = moduleDistributionCatalog.find(({ name, selection, runtimeActivation }) => selected.has(name) && selection !== "required" && runtimeActivation === "toggle" && !moduleDistributionCatalog.some((candidate) => selected.has(candidate.name) && candidate.dependencies.includes(name)))?.name;
|
|
3849
4094
|
const moduleActivationCommands = toggleableModule ? [
|
|
@@ -3919,7 +4164,7 @@ ${includeAgent ? `
|
|
|
3919
4164
|
## DSH Agent profile
|
|
3920
4165
|
|
|
3921
4166
|
Agent Runtime \u9ED8\u8BA4\u4E0D\u542F\u52A8\u3002\u5148\u5728\u4EC5\u4F9B\u672C\u673A\u4F7F\u7528\u7684 \`.env\` \u4E2D\u8BBE\u7F6E
|
|
3922
|
-
\`
|
|
4167
|
+
\`PLATFORM_ENABLE_AI_RUNTIME=true\`\u3001\`AGENT_SERVER_INTERNAL_TOKEN\`\u3001\`QWEN_API_URL\`\u3001
|
|
3923
4168
|
\`QWEN_API_KEY\` \u4E0E \`QWEN_MODEL\`\uFF0C\u518D\u8FD0\u884C\uFF1A
|
|
3924
4169
|
|
|
3925
4170
|
\`\`\`bash
|
|
@@ -3931,39 +4176,28 @@ bun run dev:agent
|
|
|
3931
4176
|
\u73AF\u5883\u6216\u8FD4\u56DE\u7ED9\u5BA2\u6237\u7AEF\u3002\u516C\u7F51 HTTPS Endpoint \u7684\u4E3B\u673A\u5FC5\u987B\u663E\u5F0F\u52A0\u5165
|
|
3932
4177
|
\`AI_PROVIDER_HTTPS_HOST_ALLOWLIST\`\u3002\u8FD0\u884C\u4E0E\u6A21\u5757
|
|
3933
4178
|
\u63A5\u5165\u7EC6\u8282\u89C1 [Agent Runtime \u63A5\u5165](./docs/platform/agent-runtime.md)\u53CA
|
|
3934
|
-
[DSH \u90E8\u7F72\u4E0E\u8FC1\u79FB](./docs/operations/dsh-agent-migration.md)\u3002Agent Server \u4EE5 Node 24.
|
|
4179
|
+
[DSH \u90E8\u7F72\u4E0E\u8FC1\u79FB](./docs/operations/dsh-agent-migration.md)\u3002Agent Server \u4EE5 Node 24.9+
|
|
3935
4180
|
\u6267\u884C\uFF0C\u4F7F\u7528\u65B0 SQLite \u6570\u636E\u8DEF\u5F84\uFF1B\u539F\u751F\u5DE5\u4F5C\u53F0\u9700\u8981 Linux \u9694\u79BB\u80FD\u529B\u3002\u5168\u5C40\u5BB9\u91CF\u9ED8\u8BA4 1 \u65F6\u4E3A\u65E2\u6709
|
|
3936
4181
|
\u8C03\u7528\u94FE\u9884\u7559\uFF0C\u5DE5\u4F5C\u53F0\u4F1A\u660E\u786E\u663E\u793A\u5BB9\u91CF\u672A\u5F00\u653E\u3002\u4E2A\u4EBA\u6269\u5C55\u9ED8\u8BA4\u5F00\u653E\uFF0C\u7531\u90E8\u7F72\u5F00\u5173\u63A7\u5236\u3002
|
|
3937
4182
|
|
|
3938
|
-
Document Runtime \u540C\u6837\u9ED8\u8BA4\u5173\u95ED\u3002\u914D\u7F6E\u81F3\u5C11 32 \u5B57\u7B26\u7684
|
|
3939
|
-
\`AI_ARTIFACT_ENCRYPTION_SECRET\`\u3001\u672C\u5730\u6216\u5185\u7F51 \`DOCUMENT_ADAPTER_URL\` \u53CA\u5176
|
|
3940
|
-
capability \u540E\u8FD0\u884C\uFF1A
|
|
3941
|
-
|
|
3942
|
-
\`\`\`bash
|
|
3943
|
-
bun run dev:document
|
|
3944
|
-
\`\`\`
|
|
3945
|
-
|
|
3946
|
-
\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
|
|
3947
|
-
\u4EFB\u610F\u516C\u7F51 URL\u3002\u672A\u914D\u7F6E Document Adapter \u65F6\u4EC5\u5BF9\u5E94 Operation \u8FD4\u56DE\u7A33\u5B9A unavailable\uFF0C
|
|
3948
|
-
\u666E\u901A\u4E1A\u52A1\u4E0E\u6587\u672C Agent \u4E0D\u53D7\u5F71\u54CD\u3002\u8BE6\u89C1
|
|
3949
|
-
[Document AI Runtime](./docs/platform/document-ai-runtime.md)\u3002
|
|
3950
|
-
|
|
3951
|
-
\u6279\u91CF\u8BED\u97F3\u8F6C\u5199\u4F7F\u7528\u72EC\u7ACB Speech profile\u3002\u914D\u7F6E\u672C\u5730/\u5185\u7F51
|
|
3952
|
-
\`SPEECH_ADAPTER_URL\` \u4E0E capability \u540E\u8FD0\u884C\uFF1A
|
|
3953
|
-
|
|
3954
|
-
\`\`\`bash
|
|
3955
|
-
bun run dev:speech
|
|
3956
|
-
\`\`\`
|
|
3957
|
-
|
|
3958
|
-
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
|
|
3959
|
-
Artifact\uFF1B\u5B9E\u65F6 ASR\u3001TTS \u548C Dictation \u5C1A\u672A\u5F00\u653E\u3002\u8BE6\u89C1
|
|
3960
|
-
[Speech AI Runtime](./docs/platform/speech-ai-runtime.md)\u3002
|
|
3961
|
-
|
|
3962
4183
|
\u5F00\u53D1\u4E0E\u5BA1\u8BA1\u7EDF\u4E00\u4F7F\u7528 Windy \u4E3B\u7AD9\uFF1A\`/admin/system/ai-runtime\` \u63D0\u4F9B\u53D7\u6743\u9650\u4FDD\u62A4\u7684 Run\u3001
|
|
3963
4184
|
Provider Attempt \u4E0E\u8131\u654F Trajectory\uFF1B\u4E1A\u52A1\u6A21\u5757\u53EF\u901A\u8FC7 \`registerAgentSessionProviders()\`
|
|
3964
4185
|
\u6CE8\u518C\u5386\u53F2\u4F1A\u8BDD\u53EA\u8BFB\u6295\u5F71\u3002\u4E24\u8005\u5747\u590D\u7528\u5F53\u524D\u767B\u5F55\u8EAB\u4EFD\u3001Manifest Feature/RBAC \u4E0E Audit\uFF0C\u4E0D\u521B\u5EFA
|
|
3965
4186
|
\u7B2C\u4E8C\u79CD\u8C03\u8BD5 Token\uFF0C\u4E5F\u4E0D\u4F1A\u5C55\u793A\u8F93\u5165\u8F93\u51FA\u6B63\u6587\u3001Tool \u53C2\u6570\u6216 Provider \u539F\u59CB\u54CD\u5E94\u3002
|
|
3966
4187
|
` : ""}
|
|
4188
|
+
${selected.has("system.media-runtime") ? `
|
|
4189
|
+
## \u5A92\u4F53\u8FD0\u884C\u65F6
|
|
4190
|
+
|
|
4191
|
+
\u5728 \`windy.environment.yaml\` \u4E2D\u8BBE\u7F6E\u5DF2\u4EA4\u4ED8\u80FD\u529B\u7684 \`runtime\` \u5F00\u5173\u3002\u4FEE\u6539\u540E\u91CD\u542F Server\u3002
|
|
4192
|
+
\u53EA\u5728\u672C\u5730 \`.env\` \u914D\u7F6E\u5171\u4EAB\u5185\u90E8\u4EE4\u724C \`AGENT_SERVER_INTERNAL_TOKEN\`\u3001\u81F3\u5C11 32 \u5B57\u7B26\u7684
|
|
4193
|
+
\`AI_ARTIFACT_ENCRYPTION_SECRET\` \u548C\u5404 Adapter \u7684\u8FDE\u63A5\u4FE1\u606F\u3002\u4E1A\u52A1\u4EC5\u4F20\u5E73\u53F0\u7B7E\u53D1\u7684 ArtifactRef\u3002
|
|
4194
|
+
${!excludedRuntimes.includes("document") ? "- Document/OCR\uFF1A\u914D\u7F6E `DOCUMENT_ADAPTER_URL`\uFF0C\u4F7F\u7528 `bun run dev:document`\u3002\u8BE6\u89C1 [Document AI Runtime](./docs/platform/document-ai-runtime.md)\u3002" : ""}
|
|
4195
|
+
${!excludedRuntimes.includes("speech") ? "- Speech\uFF1A\u914D\u7F6E `SPEECH_ADAPTER_URL`\uFF0C\u4F7F\u7528 `bun run dev:speech`\u3002\u8BE6\u89C1 [Speech AI Runtime](./docs/platform/speech-ai-runtime.md)\u3002" : ""}
|
|
4196
|
+
${!excludedRuntimes.includes("embedding") ? "- Embedding\uFF1A\u914D\u7F6E `EMBEDDING_ADAPTER_URL`\u3002\u8BE6\u89C1 [Embedding AI Runtime](./docs/platform/embedding-ai-runtime.md)\u3002" : ""}
|
|
4197
|
+
|
|
4198
|
+
\u4EE5 YAML \u663E\u5F0F\u5F00\u542F\u5E76\u751F\u6210\u7684\u670D\u52A1\u968F\u9ED8\u8BA4 Compose \u542F\u52A8\u3002\u8BE6\u89C1
|
|
4199
|
+
[\u73AF\u5883\u9884\u8BBE\u4E0E\u4EA4\u4ED8\u8FB9\u754C](./docs/operations/environment-capabilities.md)\u3002
|
|
4200
|
+
` : ""}
|
|
3967
4201
|
${includeSearch ? `
|
|
3968
4202
|
## OpenSearch \u641C\u7D22 profile
|
|
3969
4203
|
|
|
@@ -4114,7 +4348,8 @@ var migrationCliDependencies = {
|
|
|
4114
4348
|
"drizzle-orm": "^0.45.2",
|
|
4115
4349
|
pg: "^8.22.0"
|
|
4116
4350
|
};
|
|
4117
|
-
function createStarterPackage(source, projectName, includeOxc = true, projectLicense = "UNLICENSED", selectedModules = [], generatorVersion) {
|
|
4351
|
+
function createStarterPackage(source, projectName, includeOxc = true, projectLicense = "UNLICENSED", selectedModules = [], generatorVersion, disabledRuntimes = []) {
|
|
4352
|
+
const includeRuntime = (kind) => selectedModules.includes(kind === "agent" ? "system.agent" : "system.media-runtime") && !disabledRuntimes.includes(kind);
|
|
4118
4353
|
const { "lint-staged": sourceLintStaged, ...sourceWithoutLintStaged } = source;
|
|
4119
4354
|
const devDependencies = { ...source.devDependencies };
|
|
4120
4355
|
if (!includeOxc) {
|
|
@@ -4129,7 +4364,11 @@ function createStarterPackage(source, projectName, includeOxc = true, projectLic
|
|
|
4129
4364
|
private: true,
|
|
4130
4365
|
license: projectLicense,
|
|
4131
4366
|
packageManager: "bun@1.3.14",
|
|
4132
|
-
engines: {
|
|
4367
|
+
engines: {
|
|
4368
|
+
...source.engines,
|
|
4369
|
+
bun: ">=1.3.14",
|
|
4370
|
+
node: selectedModules.includes("system.agent") ? ">=24.9.0" : ">=24.7.0"
|
|
4371
|
+
},
|
|
4133
4372
|
...includeOxc ? { "lint-staged": sourceLintStaged ?? defaultLintStaged } : {},
|
|
4134
4373
|
scripts: {
|
|
4135
4374
|
...includeOxc ? {
|
|
@@ -4141,24 +4380,32 @@ function createStarterPackage(source, projectName, includeOxc = true, projectLic
|
|
|
4141
4380
|
...selectedModules.includes("system.search") ? {
|
|
4142
4381
|
"dev:search": "OPENSEARCH_URL=http://opensearch:9200 docker compose --profile search up --build"
|
|
4143
4382
|
} : {},
|
|
4144
|
-
...
|
|
4383
|
+
...includeRuntime("agent") ? {
|
|
4145
4384
|
"dev:agent": "bun run docker:sync && docker compose --profile agent up --build",
|
|
4146
4385
|
"check:agent": "bun run --cwd apps/agent-server typecheck",
|
|
4147
|
-
"test:agent": "bun run --cwd apps/agent-server test"
|
|
4148
|
-
|
|
4386
|
+
"test:agent": "bun run --cwd apps/agent-server test"
|
|
4387
|
+
} : {},
|
|
4388
|
+
...includeRuntime("speech") ? {
|
|
4389
|
+
"dev:speech": "PLATFORM_ENABLE_AI_RUNTIME=true SPEECH_SERVER_URL=http://speech-server:8091 docker compose --profile speech up --build",
|
|
4149
4390
|
"speech:pins": "bun run scripts/provision-speech-readiness.ts"
|
|
4150
4391
|
} : {},
|
|
4392
|
+
...includeRuntime("document") ? {
|
|
4393
|
+
"dev:document": "PLATFORM_ENABLE_AI_RUNTIME=true DOCUMENT_SERVER_URL=http://document-server:8090 docker compose --profile document up --build"
|
|
4394
|
+
} : {},
|
|
4395
|
+
...includeRuntime("embedding") ? {
|
|
4396
|
+
"dev:embedding": "PLATFORM_ENABLE_AI_RUNTIME=true EMBEDDING_SERVER_URL=http://embedding-server:8092 docker compose --profile embedding up --build"
|
|
4397
|
+
} : {},
|
|
4151
4398
|
...generatorVersion ? { windy: "create-windy" } : {},
|
|
4152
4399
|
"dev:web": "bun run --cwd apps/web dev",
|
|
4153
4400
|
"dev:server": "bun run --cwd apps/server dev",
|
|
4154
|
-
build:
|
|
4401
|
+
build: includeRuntime("agent") ? "bun run --cwd apps/agent-server build && bun run --cwd apps/web build" : "bun run --cwd apps/web build",
|
|
4155
4402
|
"db:generate": "drizzle-kit generate --config drizzle.config.ts",
|
|
4156
4403
|
"db:migrate": "drizzle-kit migrate --config drizzle.config.ts",
|
|
4157
4404
|
"generate:crud": "bun run packages/crud-generator/src/cli.ts",
|
|
4158
4405
|
typecheck: [
|
|
4159
4406
|
"bun run --cwd apps/web typecheck",
|
|
4160
4407
|
"bun run --cwd apps/server typecheck",
|
|
4161
|
-
...
|
|
4408
|
+
...includeRuntime("agent") ? ["bun run --cwd apps/agent-server typecheck"] : [],
|
|
4162
4409
|
"bun run --cwd packages/ai-client typecheck",
|
|
4163
4410
|
"bun run --cwd packages/jobs typecheck",
|
|
4164
4411
|
"bun run --cwd packages/shared typecheck",
|
|
@@ -4172,7 +4419,7 @@ function createStarterPackage(source, projectName, includeOxc = true, projectLic
|
|
|
4172
4419
|
format: "oxfmt",
|
|
4173
4420
|
"format:staged": "lint-staged"
|
|
4174
4421
|
} : {},
|
|
4175
|
-
test: "bun test && bun run --cwd apps/web test" + (
|
|
4422
|
+
test: "bun test && bun run --cwd apps/web test" + (includeRuntime("agent") ? " && bun run test:agent" : "")
|
|
4176
4423
|
},
|
|
4177
4424
|
devDependencies: {
|
|
4178
4425
|
...migrationCliDependencies,
|
|
@@ -4198,7 +4445,9 @@ var templateRootFiles = [
|
|
|
4198
4445
|
"package.json",
|
|
4199
4446
|
"scripts/notification-postgres-regression.ts",
|
|
4200
4447
|
"scripts/lib/postgres-regression.ts",
|
|
4201
|
-
"scripts/provision-speech-readiness.ts"
|
|
4448
|
+
"scripts/provision-speech-readiness.ts",
|
|
4449
|
+
"scripts/operations/collect-device-info.py",
|
|
4450
|
+
"deploy/environment/windy.environment.example.yaml"
|
|
4202
4451
|
];
|
|
4203
4452
|
var templateDirectories = [
|
|
4204
4453
|
".agents/skills/windy-business-module",
|
|
@@ -4223,6 +4472,7 @@ var templateDirectories = [
|
|
|
4223
4472
|
"packages/storage"
|
|
4224
4473
|
];
|
|
4225
4474
|
var templateDocumentationFiles = [
|
|
4475
|
+
"docs/operations/environment-capabilities.md",
|
|
4226
4476
|
"docs/operations/legacy-data-migration.md",
|
|
4227
4477
|
"docs/adr/0003-agent-session-event-source.md",
|
|
4228
4478
|
"docs/adr/0004-embedded-dsh-runtime.md",
|
|
@@ -4261,6 +4511,7 @@ var templateDocumentationFiles = [
|
|
|
4261
4511
|
"docs/development/custom-error-pages.md",
|
|
4262
4512
|
"docs/development/custom-login-page.md",
|
|
4263
4513
|
"docs/development/module-lifecycle.md",
|
|
4514
|
+
"docs/development/performance-engineering.md",
|
|
4264
4515
|
"docs/development/ui-component-gallery.md",
|
|
4265
4516
|
"docs/license/license-offline-activation-code.md",
|
|
4266
4517
|
"docs/license/license-pairing-activation.md",
|
|
@@ -4295,6 +4546,7 @@ var templateDocumentationFiles = [
|
|
|
4295
4546
|
"docs/platform/organization-membership.md",
|
|
4296
4547
|
"docs/platform/platform-authentication.md",
|
|
4297
4548
|
"docs/platform/platform-shell-settings.md",
|
|
4549
|
+
"docs/operations/admin-settings-yaml.md",
|
|
4298
4550
|
"docs/platform/scheduled-task-executor.md",
|
|
4299
4551
|
"docs/platform/speech-ai-runtime.md",
|
|
4300
4552
|
"docs/platform/system-crud-api.md",
|
|
@@ -4369,7 +4621,7 @@ function parseGenerationProvenance(content) {
|
|
|
4369
4621
|
}
|
|
4370
4622
|
return parsed;
|
|
4371
4623
|
}
|
|
4372
|
-
async function writeGenerationProvenance(targetDirectory, metadata, profile, selectedModules, includeOxc, legalLicense) {
|
|
4624
|
+
async function writeGenerationProvenance(targetDirectory, metadata, profile, selectedModules, includeOxc, legalLicense, environmentProfile) {
|
|
4373
4625
|
const requested = selectedModuleManifests(selectedModules);
|
|
4374
4626
|
const versions = new Map(metadata.modules.map((item) => [item.name, item]));
|
|
4375
4627
|
const modules = requested.map(({ name }) => {
|
|
@@ -4388,6 +4640,7 @@ async function writeGenerationProvenance(targetDirectory, metadata, profile, sel
|
|
|
4388
4640
|
codeQuality: includeOxc ? "oxc" : "none"
|
|
4389
4641
|
},
|
|
4390
4642
|
legalLicense,
|
|
4643
|
+
...environmentProfile ? { environmentProfile: parseEnvironmentPolicy(environmentProfile) } : {},
|
|
4391
4644
|
appliedRecipes: [],
|
|
4392
4645
|
managedFilesManifest: ".windy/files.json",
|
|
4393
4646
|
choices: {
|
|
@@ -4411,6 +4664,13 @@ function isGenerationProvenance(value) {
|
|
|
4411
4664
|
return false;
|
|
4412
4665
|
const metadata = value;
|
|
4413
4666
|
const toolchain = metadata.toolchain;
|
|
4667
|
+
if (Object.hasOwn(metadata, "environmentProfile")) {
|
|
4668
|
+
try {
|
|
4669
|
+
parseEnvironmentPolicy(metadata.environmentProfile);
|
|
4670
|
+
} catch {
|
|
4671
|
+
return false;
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4414
4674
|
const choices = metadata.choices;
|
|
4415
4675
|
return typeof metadata.windyVersion === "string" && metadata.profile === "private-enterprise" && toolchain?.runtime === "bun" && (toolchain?.codeQuality === "oxc" || toolchain?.codeQuality === "none") && (metadata.legalLicense === "UNLICENSED" || metadata.legalLicense === "MIT" || metadata.legalLicense === "Apache-2.0") && Array.isArray(metadata.appliedRecipes) && metadata.appliedRecipes.every((item) => typeof item === "string") && metadata.managedFilesManifest === ".windy/files.json" && typeof choices?.includeExample === "boolean" && typeof choices.includeOxc === "boolean";
|
|
4416
4676
|
}
|
|
@@ -4608,26 +4868,46 @@ async function generateProject(input) {
|
|
|
4608
4868
|
const includeOxc = input.includeOxc ?? true;
|
|
4609
4869
|
const projectLicense = input.projectLicense ?? "UNLICENSED";
|
|
4610
4870
|
const templateMetadata = await readTemplateMetadata(input.sourceRoot);
|
|
4611
|
-
|
|
4871
|
+
if (input.environmentProfile?.antivirus?.packaged) {
|
|
4872
|
+
throw new Error("Windy \u901A\u7528\u751F\u6210\u5668\u4E0D\u5305\u542B\u75C5\u6BD2\u626B\u63CF\u5668\uFF0C\u8BF7\u7531\u9879\u76EE\u4EA4\u4ED8\u626B\u63CF\u5668\u540E\u914D\u7F6E\u73AF\u5883\u9884\u8BBE");
|
|
4873
|
+
}
|
|
4874
|
+
const selectedModules = (input.environmentProfile ? environmentProfileModules(input.environmentProfile) : input.selectedModules) ?? templateMetadata.modules.filter(({ name }) => requestedIncludeExample || name !== "work-order").map(({ name }) => name);
|
|
4612
4875
|
const includeExample = selectedModules.includes("work-order");
|
|
4613
4876
|
for (const relativePath2 of generationTemplatePaths(true, includeOxc)) {
|
|
4614
4877
|
await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join12(input.targetDirectory, relativePath2));
|
|
4615
4878
|
}
|
|
4616
|
-
|
|
4879
|
+
const disabledRuntimes = AI_RUNTIME_KINDS.filter((kind) => !selectedModules.includes(runtimeDistributionModule(kind)) || input.environmentProfile?.build.runtimes?.[kind] === false);
|
|
4880
|
+
await materializeSelectedModules(input.targetDirectory, selectedModules, disabledRuntimes.flatMap((kind) => kind === "agent" ? [
|
|
4881
|
+
"apps/agent-server",
|
|
4882
|
+
"apps/server/scripts/check-dsh-platform-example.ts"
|
|
4883
|
+
] : [`apps/${kind}-server`]));
|
|
4884
|
+
await mkdir3(join12(input.targetDirectory, "apps/server/src/system"), {
|
|
4885
|
+
recursive: true
|
|
4886
|
+
});
|
|
4887
|
+
await writeFile9(join12(input.targetDirectory, "apps/server/src/system/ai-runtime-build.ts"), `// Generated by create-windy from the runtime delivery selection.
|
|
4888
|
+
` + `import type { AiRuntimeKind } from "@southwind-ai/shared";
|
|
4889
|
+
|
|
4890
|
+
` + `export const excludedAiRuntimes: readonly AiRuntimeKind[] = ${JSON.stringify(disabledRuntimes)};
|
|
4891
|
+
`);
|
|
4617
4892
|
await materializeRegistryDependencies(input.targetDirectory, selectedModuleManifests(selectedModules).flatMap(({ registryDependencies }) => registryDependencies));
|
|
4618
4893
|
const packagePath = join12(input.targetDirectory, "package.json");
|
|
4619
4894
|
const packageJson = JSON.parse(await readFile10(packagePath, "utf8"));
|
|
4620
|
-
await writeFile9(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules, templateMetadata.generatorVersion), null, 2)}
|
|
4895
|
+
await writeFile9(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules, templateMetadata.generatorVersion, disabledRuntimes), null, 2)}
|
|
4621
4896
|
`);
|
|
4622
|
-
await writeFile9(join12(input.targetDirectory, "docker-compose.yml"), starterComposeFor(selectedModules.includes("system.agent"), selectedModules.includes("system.search"), selectedModules.includes("system.storage")
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4897
|
+
await writeFile9(join12(input.targetDirectory, "docker-compose.yml"), starterComposeFor(selectedModules.includes("system.agent"), selectedModules.includes("system.search"), selectedModules.includes("system.storage"), {
|
|
4898
|
+
build: input.environmentProfile?.build.runtimes,
|
|
4899
|
+
runtime: input.environmentProfile?.runtime,
|
|
4900
|
+
mountEnvironment: true
|
|
4901
|
+
}, selectedModules.includes("system.media-runtime")));
|
|
4902
|
+
await writeFile9(join12(input.targetDirectory, ".env.example"), environmentExample(includeExample, selectedModules.includes("system.media-runtime"), selectedModules.includes("system.search"), selectedModules.includes("system.storage"), disabledRuntimes));
|
|
4903
|
+
await writeFile9(join12(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules, !disabledRuntimes.includes("agent"), disabledRuntimes));
|
|
4904
|
+
await writeFile9(join12(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license"), !disabledRuntimes.includes("agent"), selectedModules.includes("system.operations"), selectedModules.includes("system.storage"), selectedModules.includes("system.media-runtime")));
|
|
4905
|
+
await writeFile9(join12(input.targetDirectory, "windy.environment.yaml"), starterEnvironmentProfile(selectedModules, input.environmentProfile));
|
|
4626
4906
|
await reflectCodeQualityChoice(input.targetDirectory, includeOxc);
|
|
4627
4907
|
await applyWindyBaseLicense(input.targetDirectory);
|
|
4628
4908
|
await applyProjectLicense(input.targetDirectory, projectLicense, input.licenseHolder);
|
|
4629
4909
|
await prepareCustomerDockerfiles(input.targetDirectory);
|
|
4630
|
-
await writeGenerationProvenance(input.targetDirectory, templateMetadata, input.profile ?? starterProfile.key, selectedModules, includeOxc, projectLicense);
|
|
4910
|
+
await writeGenerationProvenance(input.targetDirectory, templateMetadata, input.profile ?? starterProfile.key, selectedModules, includeOxc, projectLicense, input.environmentProfile);
|
|
4631
4911
|
await writeInitialProjectModuleRegistry(input.targetDirectory, selectedModules);
|
|
4632
4912
|
await rm4(join12(input.targetDirectory, "bun.lock"), { force: true });
|
|
4633
4913
|
await writeManagedFilesManifest(input.targetDirectory, templateMetadata.generatorVersion);
|
|
@@ -4741,6 +5021,7 @@ async function createProject(options, dependencies = {}) {
|
|
|
4741
5021
|
includeExample: options.includeExample,
|
|
4742
5022
|
includeOxc: options.includeOxc,
|
|
4743
5023
|
selectedModules: options.selectedModules,
|
|
5024
|
+
environmentProfile: options.environmentProfile,
|
|
4744
5025
|
projectLicense: options.projectLicense,
|
|
4745
5026
|
licenseHolder: options.licenseHolder,
|
|
4746
5027
|
profile: options.profile
|
|
@@ -4814,7 +5095,7 @@ function isMissing6(error) {
|
|
|
4814
5095
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
4815
5096
|
import { stdin, stdout } from "process";
|
|
4816
5097
|
|
|
4817
|
-
// ../../node_modules
|
|
5098
|
+
// ../../node_modules/@inquirer/core/dist/lib/key.js
|
|
4818
5099
|
var keybindings = ["emacs", "vim"];
|
|
4819
5100
|
var keybindingLookup = new Set(keybindings);
|
|
4820
5101
|
function isKeybinding(value) {
|
|
@@ -4831,7 +5112,7 @@ var isDownKey = (key, keybindings2 = []) => key.name === "down" || keybindings2.
|
|
|
4831
5112
|
var isSpaceKey = (key) => key.name === "space";
|
|
4832
5113
|
var isNumberKey = (key) => "1234567890".includes(key.name);
|
|
4833
5114
|
var isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
4834
|
-
// ../../node_modules
|
|
5115
|
+
// ../../node_modules/@inquirer/core/dist/lib/errors.js
|
|
4835
5116
|
class AbortPromptError extends Error {
|
|
4836
5117
|
name = "AbortPromptError";
|
|
4837
5118
|
message = "Prompt was aborted";
|
|
@@ -4857,10 +5138,10 @@ class HookError extends Error {
|
|
|
4857
5138
|
class ValidationError extends Error {
|
|
4858
5139
|
name = "ValidationError";
|
|
4859
5140
|
}
|
|
4860
|
-
// ../../node_modules
|
|
5141
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-state.js
|
|
4861
5142
|
import { AsyncResource as AsyncResource2 } from "async_hooks";
|
|
4862
5143
|
|
|
4863
|
-
// ../../node_modules
|
|
5144
|
+
// ../../node_modules/@inquirer/core/dist/lib/hook-engine.js
|
|
4864
5145
|
import { AsyncLocalStorage, AsyncResource } from "async_hooks";
|
|
4865
5146
|
var hookStorage = new AsyncLocalStorage;
|
|
4866
5147
|
function createStore(rl) {
|
|
@@ -4876,16 +5157,14 @@ function createStore(rl) {
|
|
|
4876
5157
|
}
|
|
4877
5158
|
function withHooks(rl, cb) {
|
|
4878
5159
|
const store = createStore(rl);
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
store.
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
return cb(cycle);
|
|
4888
|
-
});
|
|
5160
|
+
function cycle(render) {
|
|
5161
|
+
store.handleChange = () => {
|
|
5162
|
+
store.index = 0;
|
|
5163
|
+
render();
|
|
5164
|
+
};
|
|
5165
|
+
store.handleChange();
|
|
5166
|
+
}
|
|
5167
|
+
return hookStorage.run(store, () => cb(cycle));
|
|
4889
5168
|
}
|
|
4890
5169
|
function getStore() {
|
|
4891
5170
|
const store = hookStorage.getStore();
|
|
@@ -4965,15 +5244,20 @@ var effectScheduler = {
|
|
|
4965
5244
|
}
|
|
4966
5245
|
};
|
|
4967
5246
|
|
|
4968
|
-
// ../../node_modules
|
|
5247
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-state.js
|
|
4969
5248
|
function isFactory(value) {
|
|
4970
5249
|
return typeof value === "function";
|
|
4971
5250
|
}
|
|
5251
|
+
function isReducer(value) {
|
|
5252
|
+
return typeof value === "function";
|
|
5253
|
+
}
|
|
4972
5254
|
function useState(defaultValue) {
|
|
4973
5255
|
return withPointer((pointer) => {
|
|
4974
5256
|
const setState = AsyncResource2.bind(function setState2(newValue) {
|
|
4975
|
-
|
|
4976
|
-
|
|
5257
|
+
const currentValue = pointer.get();
|
|
5258
|
+
const nextValue = isReducer(newValue) ? newValue(currentValue) : newValue;
|
|
5259
|
+
if (!Object.is(currentValue, nextValue)) {
|
|
5260
|
+
pointer.set(nextValue);
|
|
4977
5261
|
handleChange();
|
|
4978
5262
|
}
|
|
4979
5263
|
});
|
|
@@ -4986,7 +5270,7 @@ function useState(defaultValue) {
|
|
|
4986
5270
|
});
|
|
4987
5271
|
}
|
|
4988
5272
|
|
|
4989
|
-
// ../../node_modules
|
|
5273
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-effect.js
|
|
4990
5274
|
function useEffect(cb, depArray) {
|
|
4991
5275
|
withPointer((pointer) => {
|
|
4992
5276
|
const oldDeps = pointer.get();
|
|
@@ -4998,10 +5282,10 @@ function useEffect(cb, depArray) {
|
|
|
4998
5282
|
});
|
|
4999
5283
|
}
|
|
5000
5284
|
|
|
5001
|
-
// ../../node_modules
|
|
5285
|
+
// ../../node_modules/@inquirer/core/dist/lib/theme.js
|
|
5002
5286
|
import { styleText } from "util";
|
|
5003
5287
|
|
|
5004
|
-
// ../../node_modules
|
|
5288
|
+
// ../../node_modules/@inquirer/figures/dist/index.js
|
|
5005
5289
|
import process2 from "process";
|
|
5006
5290
|
function isUnicodeSupported() {
|
|
5007
5291
|
if (!process2.platform.startsWith("win")) {
|
|
@@ -5290,7 +5574,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
|
5290
5574
|
var dist_default = figures;
|
|
5291
5575
|
var replacements = Object.entries(specialMainSymbols);
|
|
5292
5576
|
|
|
5293
|
-
// ../../node_modules
|
|
5577
|
+
// ../../node_modules/@inquirer/core/dist/lib/theme.js
|
|
5294
5578
|
var defaultTheme = {
|
|
5295
5579
|
prefix: {
|
|
5296
5580
|
idle: styleText("blue", "?"),
|
|
@@ -5318,7 +5602,7 @@ function getDefaultTheme() {
|
|
|
5318
5602
|
};
|
|
5319
5603
|
}
|
|
5320
5604
|
|
|
5321
|
-
// ../../node_modules
|
|
5605
|
+
// ../../node_modules/@inquirer/core/dist/lib/make-theme.js
|
|
5322
5606
|
function isPlainObject(value) {
|
|
5323
5607
|
if (typeof value !== "object" || value === null)
|
|
5324
5608
|
return false;
|
|
@@ -5346,7 +5630,7 @@ function makeTheme(...themes) {
|
|
|
5346
5630
|
return deepMerge(...themesToMerge);
|
|
5347
5631
|
}
|
|
5348
5632
|
|
|
5349
|
-
// ../../node_modules
|
|
5633
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-prefix.js
|
|
5350
5634
|
function usePrefix({ status = "idle", theme }) {
|
|
5351
5635
|
const [showLoader, setShowLoader] = useState(false);
|
|
5352
5636
|
const [tick, setTick] = useState(0);
|
|
@@ -5376,11 +5660,11 @@ function usePrefix({ status = "idle", theme }) {
|
|
|
5376
5660
|
const iconName = status === "loading" ? "idle" : status;
|
|
5377
5661
|
return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
|
|
5378
5662
|
}
|
|
5379
|
-
// ../../node_modules
|
|
5663
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-memo.js
|
|
5380
5664
|
function useMemo(fn, dependencies) {
|
|
5381
5665
|
return withPointer((pointer) => {
|
|
5382
5666
|
const prev = pointer.get();
|
|
5383
|
-
if (!
|
|
5667
|
+
if (!pointer.initialized || prev.dependencies.length !== dependencies.length || prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
|
|
5384
5668
|
const value = fn();
|
|
5385
5669
|
pointer.set({ value, dependencies });
|
|
5386
5670
|
return value;
|
|
@@ -5388,12 +5672,12 @@ function useMemo(fn, dependencies) {
|
|
|
5388
5672
|
return prev.value;
|
|
5389
5673
|
});
|
|
5390
5674
|
}
|
|
5391
|
-
// ../../node_modules
|
|
5675
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-ref.js
|
|
5392
5676
|
function useRef(val) {
|
|
5393
5677
|
return useState({ current: val })[0];
|
|
5394
5678
|
}
|
|
5395
5679
|
|
|
5396
|
-
// ../../node_modules
|
|
5680
|
+
// ../../node_modules/@inquirer/core/dist/lib/use-keypress.js
|
|
5397
5681
|
function useKeypress(userHandler) {
|
|
5398
5682
|
const signal = useRef(userHandler);
|
|
5399
5683
|
signal.current = userHandler;
|
|
@@ -5411,10 +5695,10 @@ function useKeypress(userHandler) {
|
|
|
5411
5695
|
};
|
|
5412
5696
|
}, []);
|
|
5413
5697
|
}
|
|
5414
|
-
// ../../node_modules
|
|
5698
|
+
// ../../node_modules/@inquirer/core/dist/lib/utils.js
|
|
5415
5699
|
var import_cli_width = __toESM(require_cli_width(), 1);
|
|
5416
5700
|
|
|
5417
|
-
// ../../node_modules
|
|
5701
|
+
// ../../node_modules/fast-string-truncated-width/dist/utils.js
|
|
5418
5702
|
var getCodePointsLength = (() => {
|
|
5419
5703
|
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
5420
5704
|
return (input) => {
|
|
@@ -5433,7 +5717,7 @@ var isWideNotCJKTNotEmoji = (x) => {
|
|
|
5433
5717
|
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
5434
5718
|
};
|
|
5435
5719
|
|
|
5436
|
-
// ../../node_modules
|
|
5720
|
+
// ../../node_modules/fast-string-truncated-width/dist/index.js
|
|
5437
5721
|
var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
5438
5722
|
var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
5439
5723
|
var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
|
|
@@ -5532,7 +5816,7 @@ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {})
|
|
|
5532
5816
|
};
|
|
5533
5817
|
var dist_default2 = getStringTruncatedWidth;
|
|
5534
5818
|
|
|
5535
|
-
// ../../node_modules
|
|
5819
|
+
// ../../node_modules/fast-string-width/dist/index.js
|
|
5536
5820
|
var NO_TRUNCATION2 = {
|
|
5537
5821
|
limit: Infinity,
|
|
5538
5822
|
ellipsis: "",
|
|
@@ -5543,7 +5827,7 @@ var fastStringWidth = (input, options = {}) => {
|
|
|
5543
5827
|
};
|
|
5544
5828
|
var dist_default3 = fastStringWidth;
|
|
5545
5829
|
|
|
5546
|
-
// ../../node_modules
|
|
5830
|
+
// ../../node_modules/fast-wrap-ansi/lib/main.js
|
|
5547
5831
|
var ESC = "\x1B";
|
|
5548
5832
|
var CSI = "\x9B";
|
|
5549
5833
|
var END_CODE = 39;
|
|
@@ -5755,7 +6039,7 @@ function wrapAnsi(string, columns, options) {
|
|
|
5755
6039
|
`);
|
|
5756
6040
|
}
|
|
5757
6041
|
|
|
5758
|
-
// ../../node_modules
|
|
6042
|
+
// ../../node_modules/@inquirer/core/dist/lib/utils.js
|
|
5759
6043
|
function breakLines(content, width) {
|
|
5760
6044
|
return content.split(`
|
|
5761
6045
|
`).flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split(`
|
|
@@ -5766,7 +6050,7 @@ function readlineWidth() {
|
|
|
5766
6050
|
return import_cli_width.default({ defaultWidth: 80, output: readline().output });
|
|
5767
6051
|
}
|
|
5768
6052
|
|
|
5769
|
-
// ../../node_modules
|
|
6053
|
+
// ../../node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
|
|
5770
6054
|
function usePointerPosition({ active, renderedItems, pageSize, loop }) {
|
|
5771
6055
|
const state = useRef({
|
|
5772
6056
|
lastPointer: active,
|
|
@@ -5832,12 +6116,25 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
|
|
|
5832
6116
|
return pageBuffer.filter((line) => typeof line === "string").join(`
|
|
5833
6117
|
`);
|
|
5834
6118
|
}
|
|
5835
|
-
// ../../node_modules
|
|
5836
|
-
var import_mute_stream = __toESM(require_lib(), 1);
|
|
6119
|
+
// ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
5837
6120
|
import * as readline2 from "readline";
|
|
5838
6121
|
import { AsyncResource as AsyncResource3 } from "async_hooks";
|
|
5839
6122
|
|
|
5840
|
-
// ../../node_modules
|
|
6123
|
+
// ../../node_modules/@inquirer/type/dist/utils.js
|
|
6124
|
+
function withResolver() {
|
|
6125
|
+
let resolve6;
|
|
6126
|
+
let reject;
|
|
6127
|
+
const promise = new Promise((res, rej) => {
|
|
6128
|
+
resolve6 = res;
|
|
6129
|
+
reject = rej;
|
|
6130
|
+
});
|
|
6131
|
+
return { promise, resolve: resolve6, reject };
|
|
6132
|
+
}
|
|
6133
|
+
|
|
6134
|
+
// ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
6135
|
+
var import_mute_stream = __toESM(require_lib(), 1);
|
|
6136
|
+
|
|
6137
|
+
// ../../node_modules/signal-exit/dist/mjs/signals.js
|
|
5841
6138
|
var signals = [];
|
|
5842
6139
|
signals.push("SIGHUP", "SIGINT", "SIGTERM");
|
|
5843
6140
|
if (process.platform !== "win32") {
|
|
@@ -5847,7 +6144,7 @@ if (process.platform === "linux") {
|
|
|
5847
6144
|
signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
|
|
5848
6145
|
}
|
|
5849
6146
|
|
|
5850
|
-
// ../../node_modules
|
|
6147
|
+
// ../../node_modules/signal-exit/dist/mjs/index.js
|
|
5851
6148
|
var processOk = (process3) => !!process3 && typeof process3 === "object" && typeof process3.removeListener === "function" && typeof process3.emit === "function" && typeof process3.reallyExit === "function" && typeof process3.listeners === "function" && typeof process3.kill === "function" && typeof process3.pid === "number" && typeof process3.on === "function";
|
|
5852
6149
|
var kExitEmitter = Symbol.for("signal-exit emitter");
|
|
5853
6150
|
var global = globalThis;
|
|
@@ -6045,10 +6342,10 @@ var {
|
|
|
6045
6342
|
unload
|
|
6046
6343
|
} = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
|
|
6047
6344
|
|
|
6048
|
-
// ../../node_modules
|
|
6345
|
+
// ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
6049
6346
|
import { stripVTControlCharacters } from "util";
|
|
6050
6347
|
|
|
6051
|
-
// ../../node_modules
|
|
6348
|
+
// ../../node_modules/@inquirer/ansi/dist/index.js
|
|
6052
6349
|
var ESC2 = "\x1B[";
|
|
6053
6350
|
var cursorLeft = ESC2 + "G";
|
|
6054
6351
|
var cursorHide = ESC2 + "?25l";
|
|
@@ -6064,7 +6361,7 @@ var cursorTo = (x, y) => {
|
|
|
6064
6361
|
var eraseLine = ESC2 + "2K";
|
|
6065
6362
|
var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
|
|
6066
6363
|
|
|
6067
|
-
// ../../node_modules
|
|
6364
|
+
// ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
6068
6365
|
var height = (content) => content.split(`
|
|
6069
6366
|
`).length;
|
|
6070
6367
|
var lastLine = (content) => content.split(`
|
|
@@ -6130,22 +6427,18 @@ class ScreenManager {
|
|
|
6130
6427
|
}
|
|
6131
6428
|
}
|
|
6132
6429
|
|
|
6133
|
-
// ../../node_modules
|
|
6134
|
-
class PromisePolyfill extends Promise {
|
|
6135
|
-
static withResolver() {
|
|
6136
|
-
let resolve6;
|
|
6137
|
-
let reject;
|
|
6138
|
-
const promise = new Promise((res, rej) => {
|
|
6139
|
-
resolve6 = res;
|
|
6140
|
-
reject = rej;
|
|
6141
|
-
});
|
|
6142
|
-
return { promise, resolve: resolve6, reject };
|
|
6143
|
-
}
|
|
6144
|
-
}
|
|
6145
|
-
|
|
6146
|
-
// ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
6430
|
+
// ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
6147
6431
|
import path from "path";
|
|
6148
6432
|
var nativeSetImmediate = globalThis.setImmediate;
|
|
6433
|
+
var nativeClearImmediate = globalThis.clearImmediate;
|
|
6434
|
+
function listenTo(target, event, listener) {
|
|
6435
|
+
if ("on" in target) {
|
|
6436
|
+
target.on(event, listener);
|
|
6437
|
+
return () => target.removeListener(event, listener);
|
|
6438
|
+
}
|
|
6439
|
+
target.addEventListener(event, listener);
|
|
6440
|
+
return () => target.removeEventListener(event, listener);
|
|
6441
|
+
}
|
|
6149
6442
|
function getCallSites() {
|
|
6150
6443
|
const savedPrepareStackTrace = Error.prepareStackTrace;
|
|
6151
6444
|
let result = [];
|
|
@@ -6176,38 +6469,46 @@ function createPrompt(view) {
|
|
|
6176
6469
|
});
|
|
6177
6470
|
output.mute();
|
|
6178
6471
|
const screen = new ScreenManager(rl);
|
|
6179
|
-
const { promise, resolve: resolve6, reject } =
|
|
6180
|
-
const cancel = () => reject(new CancelPromptError);
|
|
6181
|
-
if (signal) {
|
|
6182
|
-
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
6183
|
-
if (signal.aborted) {
|
|
6184
|
-
abort();
|
|
6185
|
-
return Object.assign(promise, { cancel });
|
|
6186
|
-
}
|
|
6187
|
-
signal.addEventListener("abort", abort);
|
|
6188
|
-
cleanups.add(() => signal.removeEventListener("abort", abort));
|
|
6189
|
-
}
|
|
6190
|
-
cleanups.add(onExit((code, signal2) => {
|
|
6191
|
-
reject(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
|
|
6192
|
-
}));
|
|
6193
|
-
const sigint = () => reject(new ExitPromptError(`User force closed the prompt with SIGINT`));
|
|
6194
|
-
rl.on("SIGINT", sigint);
|
|
6195
|
-
cleanups.add(() => rl.removeListener("SIGINT", sigint));
|
|
6472
|
+
const { promise, resolve: resolve6, reject } = withResolver();
|
|
6196
6473
|
return withHooks(rl, (cycle) => {
|
|
6197
|
-
const
|
|
6198
|
-
|
|
6199
|
-
|
|
6474
|
+
const clearEffects = AsyncResource3.bind(() => effectScheduler.clearAll());
|
|
6475
|
+
const settlePrompt = (settle) => {
|
|
6476
|
+
try {
|
|
6477
|
+
clearEffects();
|
|
6478
|
+
settle();
|
|
6479
|
+
} catch (error) {
|
|
6480
|
+
reject(error);
|
|
6481
|
+
}
|
|
6482
|
+
};
|
|
6483
|
+
const resolvePrompt = (value) => settlePrompt(() => resolve6(value));
|
|
6484
|
+
const rejectPrompt = (error) => settlePrompt(() => reject(error));
|
|
6485
|
+
const promptPromise = Object.assign(promise.finally(() => {
|
|
6486
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
6487
|
+
screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
|
|
6488
|
+
output.end();
|
|
6489
|
+
}).then(() => promise), { cancel: () => rejectPrompt(new CancelPromptError) });
|
|
6490
|
+
if (signal) {
|
|
6491
|
+
const abort = () => rejectPrompt(new AbortPromptError({ cause: signal.reason }));
|
|
6492
|
+
if (signal.aborted) {
|
|
6493
|
+
abort();
|
|
6494
|
+
return promptPromise;
|
|
6495
|
+
}
|
|
6496
|
+
cleanups.add(listenTo(signal, "abort", abort));
|
|
6497
|
+
}
|
|
6498
|
+
cleanups.add(onExit((code, signal2) => {
|
|
6499
|
+
rejectPrompt(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
|
|
6500
|
+
}));
|
|
6501
|
+
cleanups.add(listenTo(rl, "SIGINT", () => rejectPrompt(new ExitPromptError(`User force closed the prompt with SIGINT`))));
|
|
6502
|
+
cleanups.add(listenTo(rl, "close", clearEffects));
|
|
6200
6503
|
const startCycle = () => {
|
|
6201
|
-
|
|
6202
|
-
rl.input.on("keypress", checkCursorPos);
|
|
6203
|
-
cleanups.add(() => rl.input.removeListener("keypress", checkCursorPos));
|
|
6504
|
+
cleanups.add(listenTo(rl.input, "keypress", () => screen.checkCursorPos()));
|
|
6204
6505
|
let pendingDone = null;
|
|
6205
6506
|
cycle(() => {
|
|
6206
6507
|
let effectsSettled = false;
|
|
6207
6508
|
try {
|
|
6208
6509
|
const nextView = view(config, (value) => {
|
|
6209
6510
|
if (effectsSettled) {
|
|
6210
|
-
|
|
6511
|
+
resolvePrompt(value);
|
|
6211
6512
|
} else {
|
|
6212
6513
|
pendingDone = { value };
|
|
6213
6514
|
}
|
|
@@ -6224,37 +6525,28 @@ function createPrompt(view) {
|
|
|
6224
6525
|
screen.render(content, bottomContent);
|
|
6225
6526
|
effectScheduler.run();
|
|
6226
6527
|
} catch (error) {
|
|
6227
|
-
|
|
6528
|
+
rejectPrompt(error);
|
|
6228
6529
|
}
|
|
6229
6530
|
effectsSettled = true;
|
|
6230
6531
|
if (pendingDone !== null) {
|
|
6231
6532
|
const { value } = pendingDone;
|
|
6232
6533
|
pendingDone = null;
|
|
6233
|
-
|
|
6534
|
+
resolvePrompt(value);
|
|
6234
6535
|
}
|
|
6235
6536
|
});
|
|
6236
6537
|
};
|
|
6237
|
-
if ("readableFlowing" in input) {
|
|
6238
|
-
nativeSetImmediate(startCycle);
|
|
6538
|
+
if ("readableFlowing" in input && input.isTTY) {
|
|
6539
|
+
const immediate = nativeSetImmediate(startCycle);
|
|
6540
|
+
cleanups.add(() => nativeClearImmediate(immediate));
|
|
6239
6541
|
} else {
|
|
6240
6542
|
startCycle();
|
|
6241
6543
|
}
|
|
6242
|
-
return
|
|
6243
|
-
effectScheduler.clearAll();
|
|
6244
|
-
return answer;
|
|
6245
|
-
}, (error) => {
|
|
6246
|
-
effectScheduler.clearAll();
|
|
6247
|
-
throw error;
|
|
6248
|
-
}).finally(() => {
|
|
6249
|
-
cleanups.forEach((cleanup) => cleanup());
|
|
6250
|
-
screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
|
|
6251
|
-
output.end();
|
|
6252
|
-
}).then(() => promise), { cancel });
|
|
6544
|
+
return promptPromise;
|
|
6253
6545
|
});
|
|
6254
6546
|
};
|
|
6255
6547
|
return prompt;
|
|
6256
6548
|
}
|
|
6257
|
-
// ../../node_modules
|
|
6549
|
+
// ../../node_modules/@inquirer/core/dist/lib/Separator.js
|
|
6258
6550
|
import { styleText as styleText2 } from "util";
|
|
6259
6551
|
class Separator {
|
|
6260
6552
|
separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
|
|
@@ -6268,7 +6560,7 @@ class Separator {
|
|
|
6268
6560
|
return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
|
|
6269
6561
|
}
|
|
6270
6562
|
}
|
|
6271
|
-
// ../../node_modules
|
|
6563
|
+
// ../../node_modules/@inquirer/checkbox/dist/index.js
|
|
6272
6564
|
import { styleText as styleText3 } from "util";
|
|
6273
6565
|
var checkboxTheme = {
|
|
6274
6566
|
icon: {
|
|
@@ -6352,9 +6644,13 @@ var dist_default4 = createPrompt((config, done) => {
|
|
|
6352
6644
|
const [active, setActive] = useState(bounds.first);
|
|
6353
6645
|
const [errorMsg, setError] = useState();
|
|
6354
6646
|
useKeypress(async (key) => {
|
|
6647
|
+
if (status !== "idle")
|
|
6648
|
+
return;
|
|
6355
6649
|
if (isEnterKey(key)) {
|
|
6650
|
+
setStatus("loading");
|
|
6356
6651
|
const selection = items.filter(isChecked);
|
|
6357
6652
|
const isValid = await validate([...selection]);
|
|
6653
|
+
setStatus("idle");
|
|
6358
6654
|
if (required && !selection.length) {
|
|
6359
6655
|
setError("At least one choice must be selected");
|
|
6360
6656
|
} else if (isValid === true) {
|
|
@@ -8715,7 +9011,9 @@ var recipes = [
|
|
|
8715
9011
|
{ id: "starter-0.8.1-to-0.8.2", from: "0.8.1", to: "0.8.2" },
|
|
8716
9012
|
{ id: "starter-0.8.2-to-0.8.3", from: "0.8.2", to: "0.8.3" },
|
|
8717
9013
|
{ id: "starter-0.8.3-to-0.9.0", from: "0.8.3", to: "0.9.0" },
|
|
8718
|
-
{ id: "starter-0.9.0-to-0.9.1", from: "0.9.0", to: "0.9.1" }
|
|
9014
|
+
{ id: "starter-0.9.0-to-0.9.1", from: "0.9.0", to: "0.9.1" },
|
|
9015
|
+
{ id: "starter-0.9.1-to-0.10.0", from: "0.9.1", to: "0.10.0" },
|
|
9016
|
+
{ id: "starter-0.10.0-to-0.10.1", from: "0.10.0", to: "0.10.1" }
|
|
8719
9017
|
];
|
|
8720
9018
|
function resolveRecipeChain(sourceVersion, targetVersion) {
|
|
8721
9019
|
if (compareVersions2(sourceVersion, minimumSupportedUpdateVersion) < 0) {
|
|
@@ -8762,6 +9060,33 @@ function parseVersion2(version) {
|
|
|
8762
9060
|
// src/update/updater.ts
|
|
8763
9061
|
import { rm as rm8 } from "fs/promises";
|
|
8764
9062
|
|
|
9063
|
+
// src/update/module-selection.ts
|
|
9064
|
+
function resolveUpdateTargetModules(sourceModules, explicitTarget) {
|
|
9065
|
+
return explicitTarget ? [...explicitTarget] : resolveModuleSelection({
|
|
9066
|
+
requested: sourceModules,
|
|
9067
|
+
includeRecommended: false
|
|
9068
|
+
});
|
|
9069
|
+
}
|
|
9070
|
+
function environmentProfileForUpdate(profile, selectedModules) {
|
|
9071
|
+
if (!profile)
|
|
9072
|
+
return;
|
|
9073
|
+
const runtimes = profile.build.runtimes ? { ...profile.build.runtimes } : undefined;
|
|
9074
|
+
const runtime = profile.runtime ? { ...profile.runtime } : undefined;
|
|
9075
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
9076
|
+
if (selectedModules.includes(runtimeDistributionModule(kind)))
|
|
9077
|
+
continue;
|
|
9078
|
+
if (runtimes)
|
|
9079
|
+
delete runtimes[kind];
|
|
9080
|
+
if (runtime)
|
|
9081
|
+
delete runtime[kind];
|
|
9082
|
+
}
|
|
9083
|
+
return {
|
|
9084
|
+
...profile,
|
|
9085
|
+
build: { modules: [...selectedModules], ...runtimes ? { runtimes } : {} },
|
|
9086
|
+
...runtime ? { runtime } : {}
|
|
9087
|
+
};
|
|
9088
|
+
}
|
|
9089
|
+
|
|
8765
9090
|
// src/update/artifacts.ts
|
|
8766
9091
|
import { mkdtemp, readFile as readFile15 } from "fs/promises";
|
|
8767
9092
|
import { tmpdir } from "os";
|
|
@@ -8972,7 +9297,6 @@ async function generatePublicArtifactProject(temporaryRoot, label, projectName,
|
|
|
8972
9297
|
"--yes",
|
|
8973
9298
|
"--skip-install",
|
|
8974
9299
|
"--no-git",
|
|
8975
|
-
"--no-optional-modules",
|
|
8976
9300
|
"--license",
|
|
8977
9301
|
provenance.legalLicense
|
|
8978
9302
|
];
|
|
@@ -8981,9 +9305,16 @@ async function generatePublicArtifactProject(temporaryRoot, label, projectName,
|
|
|
8981
9305
|
if (provenance.legalLicense === "MIT") {
|
|
8982
9306
|
args.push("--license-holder", "Windy project owner");
|
|
8983
9307
|
}
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
9308
|
+
if (provenance.environmentProfile) {
|
|
9309
|
+
const path2 = join18(temporaryRoot, `${label}.environment.json`);
|
|
9310
|
+
await writeFile10(path2, JSON.stringify(provenance.environmentProfile));
|
|
9311
|
+
args.push("--environment-profile", path2);
|
|
9312
|
+
} else {
|
|
9313
|
+
args.push("--no-optional-modules");
|
|
9314
|
+
for (const { name } of provenance.modules) {
|
|
9315
|
+
if (!requiredModuleNames.includes(name)) {
|
|
9316
|
+
args.push("--module", name);
|
|
9317
|
+
}
|
|
8987
9318
|
}
|
|
8988
9319
|
}
|
|
8989
9320
|
await assertProcess("bun", args, parent);
|
|
@@ -9094,12 +9425,14 @@ class PublishedArtifactProvider {
|
|
|
9094
9425
|
throw new Error("Project Lock \u4E0E\u6765\u6E90 registry artifact \u7684 template commit \u4E0D\u4E00\u81F4");
|
|
9095
9426
|
}
|
|
9096
9427
|
await generatePublicArtifactProject(temporaryRoot, "base", projectName, baseArtifact.root, provenance);
|
|
9428
|
+
const selectedModules = targetModules ?? provenance.modules.map(({ name }) => name);
|
|
9097
9429
|
await generateProject({
|
|
9098
9430
|
sourceRoot: await resolveTemplateRoot(),
|
|
9099
9431
|
targetDirectory,
|
|
9100
9432
|
projectName,
|
|
9101
|
-
selectedModules
|
|
9102
|
-
|
|
9433
|
+
selectedModules,
|
|
9434
|
+
environmentProfile: environmentProfileForUpdate(provenance.environmentProfile, selectedModules),
|
|
9435
|
+
includeExample: selectedModules.includes("work-order"),
|
|
9103
9436
|
includeOxc: provenance.choices.includeOxc,
|
|
9104
9437
|
projectLicense: provenance.legalLicense,
|
|
9105
9438
|
licenseHolder: provenance.legalLicense === "MIT" ? "Windy project owner" : undefined,
|
|
@@ -9120,660 +9453,262 @@ async function readProjectName2(projectDirectory) {
|
|
|
9120
9453
|
return source.name || basename10(projectDirectory);
|
|
9121
9454
|
}
|
|
9122
9455
|
|
|
9123
|
-
// src/update/
|
|
9124
|
-
import {
|
|
9125
|
-
import { dirname as dirname9, join as join29 } from "path";
|
|
9456
|
+
// src/update/admin-settings-yaml-plan.ts
|
|
9457
|
+
import { join as join25 } from "path";
|
|
9126
9458
|
|
|
9127
|
-
// src/update/
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
const
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
],
|
|
9155
|
-
workspaceDependencies: Object.entries({
|
|
9156
|
-
...manifest.dependencies,
|
|
9157
|
-
...manifest.devDependencies
|
|
9158
|
-
}).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name)
|
|
9159
|
-
});
|
|
9459
|
+
// src/update/planner-snapshots.ts
|
|
9460
|
+
import { readFile as readFile17, stat as stat2 } from "fs/promises";
|
|
9461
|
+
import { join as join24 } from "path";
|
|
9462
|
+
|
|
9463
|
+
// src/update/recipe-admin-api.ts
|
|
9464
|
+
var apiRecipes = [
|
|
9465
|
+
{
|
|
9466
|
+
path: "apps/web/src/services/platform-settings-api.ts",
|
|
9467
|
+
beforeImport: 'import { apiRequest } from "./http";',
|
|
9468
|
+
afterImport: 'import { apiRequest, apiResponse } from "./http";',
|
|
9469
|
+
addedImport: "apiResponse",
|
|
9470
|
+
marker: 'const WATERMARK_YAML_PATH = "/system/settings/watermark/yaml";',
|
|
9471
|
+
symbols: [
|
|
9472
|
+
"WATERMARK_YAML_PATH",
|
|
9473
|
+
"WatermarkYamlPreview",
|
|
9474
|
+
"exportWatermarkYaml",
|
|
9475
|
+
"previewWatermarkYaml",
|
|
9476
|
+
"importWatermarkYaml"
|
|
9477
|
+
]
|
|
9478
|
+
},
|
|
9479
|
+
{
|
|
9480
|
+
path: "apps/web/src/services/diagnostics-api.ts",
|
|
9481
|
+
beforeImport: 'import type { DiagnosticRecord } from "@southwind-ai/shared";',
|
|
9482
|
+
afterImport: 'import type { DiagnosticRecord, PageResult } from "@southwind-ai/shared";',
|
|
9483
|
+
addedImport: "PageResult",
|
|
9484
|
+
marker: "export function listDiagnostics(",
|
|
9485
|
+
symbols: ["listDiagnostics"]
|
|
9160
9486
|
}
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9487
|
+
];
|
|
9488
|
+
var adminApiRecipePaths = apiRecipes.map(({ path: path2 }) => path2);
|
|
9489
|
+
function isAdminApiRecipePath(path2) {
|
|
9490
|
+
return adminApiRecipePaths.includes(path2);
|
|
9491
|
+
}
|
|
9492
|
+
function addAdminApiExports(path2, source, target) {
|
|
9493
|
+
const recipe = apiRecipes.find((item) => item.path === path2);
|
|
9494
|
+
if (!recipe || !target)
|
|
9495
|
+
return { error: "Admin API recipe \u76EE\u6807\u7F3A\u5931" };
|
|
9496
|
+
if (occurrences(target, recipe.marker) !== 1 || occurrences(target, recipe.afterImport) !== 1) {
|
|
9497
|
+
return { error: "Admin API recipe \u76EE\u6807\u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
9498
|
+
}
|
|
9499
|
+
const block = target.slice(target.indexOf(recipe.marker)).trimEnd();
|
|
9500
|
+
if (recipe.symbols.some((symbol) => !block.includes(symbol))) {
|
|
9501
|
+
return { error: "Admin API recipe \u76EE\u6807\u5BFC\u51FA\u4E0D\u5B8C\u6574" };
|
|
9502
|
+
}
|
|
9503
|
+
if (recipe.symbols.some((symbol) => source.includes(symbol))) {
|
|
9504
|
+
const blockIndex = source.indexOf(block);
|
|
9505
|
+
const remainder = blockIndex < 0 ? source : source.slice(0, blockIndex) + source.slice(blockIndex + block.length);
|
|
9506
|
+
if (blockIndex < 0 || occurrences(source, block) !== 1 || occurrences(source, recipe.afterImport) !== 1 || occurrences(source, recipe.beforeImport) !== 0 || recipe.symbols.some((symbol) => remainder.includes(symbol))) {
|
|
9507
|
+
return { error: "Admin API recipe \u5DF2\u6709\u5BFC\u51FA\u4E0D\u5B8C\u6574\u3001\u91CD\u590D\u6216\u5DF2\u88AB\u4FEE\u6539" };
|
|
9180
9508
|
}
|
|
9181
|
-
|
|
9182
|
-
continue;
|
|
9183
|
-
dockerPlan.action = "update";
|
|
9184
|
-
dockerPlan.reason = "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355";
|
|
9185
|
-
dockerPlan.content = new TextEncoder().encode(next);
|
|
9509
|
+
return { content: source };
|
|
9186
9510
|
}
|
|
9187
|
-
}
|
|
9188
|
-
|
|
9189
|
-
const plan = files.find((item) => item.path === path2);
|
|
9190
|
-
return plan ? virtualContent(plan, snapshots) : snapshots.get(path2) ?? targetWorkspaceManifests.get(path2);
|
|
9191
|
-
}
|
|
9192
|
-
function virtualContent(plan, snapshots) {
|
|
9193
|
-
if (plan.action === "delete")
|
|
9194
|
-
return;
|
|
9195
|
-
if (plan.action === "create" || plan.action === "update")
|
|
9196
|
-
return plan.content;
|
|
9197
|
-
return snapshots.get(plan.path);
|
|
9198
|
-
}
|
|
9199
|
-
function parsePackage(content, path2) {
|
|
9200
|
-
try {
|
|
9201
|
-
return JSON.parse(new TextDecoder().decode(content));
|
|
9202
|
-
} catch (error) {
|
|
9203
|
-
throw new Error(`\u65E0\u6CD5\u89E3\u6790 Docker workspace \u8F93\u5165\uFF1A${path2}`, {
|
|
9204
|
-
cause: error
|
|
9205
|
-
});
|
|
9511
|
+
if (occurrences(source, recipe.beforeImport) !== 1 || occurrences(source, recipe.afterImport) !== 0 || new RegExp(`\\b${recipe.addedImport}\\b`).test(source)) {
|
|
9512
|
+
return { error: "Admin API recipe \u539F\u59CB import \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
9206
9513
|
}
|
|
9514
|
+
return {
|
|
9515
|
+
content: source.replace(recipe.beforeImport, recipe.afterImport) + `${source.endsWith(`
|
|
9516
|
+
`) ? `
|
|
9517
|
+
` : `
|
|
9518
|
+
|
|
9519
|
+
`}${block}
|
|
9520
|
+
`
|
|
9521
|
+
};
|
|
9207
9522
|
}
|
|
9208
|
-
function
|
|
9209
|
-
return
|
|
9523
|
+
function occurrences(source, value) {
|
|
9524
|
+
return source.split(value).length - 1;
|
|
9210
9525
|
}
|
|
9211
9526
|
|
|
9212
|
-
// src/update/
|
|
9213
|
-
import { readFile as
|
|
9527
|
+
// src/update/planner-file.ts
|
|
9528
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
9214
9529
|
import { join as join23 } from "path";
|
|
9215
9530
|
|
|
9216
|
-
// src/update/
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
const error = new Error(`\u5F53\u524D\u9879\u76EE\u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
9227
|
-
error.code = "ENOENT";
|
|
9228
|
-
throw error;
|
|
9229
|
-
}
|
|
9230
|
-
return JSON.parse(new TextDecoder().decode(content));
|
|
9531
|
+
// src/update/planner-file-support.ts
|
|
9532
|
+
function readyPlannedFile(path2, ownership, action, reason, expectedProjectContent, content) {
|
|
9533
|
+
return {
|
|
9534
|
+
path: path2,
|
|
9535
|
+
ownership,
|
|
9536
|
+
action,
|
|
9537
|
+
reason,
|
|
9538
|
+
expectedProjectContent,
|
|
9539
|
+
content
|
|
9540
|
+
};
|
|
9231
9541
|
}
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
return input.projectSnapshots.get(path2);
|
|
9235
|
-
}
|
|
9236
|
-
let content;
|
|
9237
|
-
try {
|
|
9238
|
-
content = await readFile16(join21(input.projectDirectory, path2));
|
|
9239
|
-
} catch (error) {
|
|
9240
|
-
if (!isMissingFileError(error))
|
|
9241
|
-
throw error;
|
|
9242
|
-
}
|
|
9243
|
-
if (input.projectSnapshots) {
|
|
9244
|
-
input.projectSnapshots.set(path2, content);
|
|
9245
|
-
}
|
|
9246
|
-
return content;
|
|
9542
|
+
function expectationForSnapshot(content) {
|
|
9543
|
+
return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
|
|
9247
9544
|
}
|
|
9248
|
-
function
|
|
9249
|
-
return
|
|
9545
|
+
function conflict(path2, ownership, reason, expectedProjectContent) {
|
|
9546
|
+
return {
|
|
9547
|
+
path: path2,
|
|
9548
|
+
ownership,
|
|
9549
|
+
action: "preserve",
|
|
9550
|
+
reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
|
|
9551
|
+
expectedProjectContent,
|
|
9552
|
+
conflict: reason
|
|
9553
|
+
};
|
|
9250
9554
|
}
|
|
9555
|
+
// src/update/merge.ts
|
|
9556
|
+
import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile12 } from "fs/promises";
|
|
9557
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
9558
|
+
import { join as join21 } from "path";
|
|
9251
9559
|
|
|
9252
|
-
// src/update/
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9560
|
+
// src/update/merge-convergent-additions.ts
|
|
9561
|
+
async function reconcileConvergentAdditions(input) {
|
|
9562
|
+
const [oursDiff, theirsDiff] = await Promise.all([
|
|
9563
|
+
diff(input.root, input.basePath, input.oursPath),
|
|
9564
|
+
diff(input.root, input.basePath, input.theirsPath)
|
|
9565
|
+
]);
|
|
9566
|
+
if (oursDiff === undefined || theirsDiff === undefined)
|
|
9567
|
+
return;
|
|
9568
|
+
const oursAdditions = pureAdditions(oursDiff);
|
|
9569
|
+
const theirsAdditions = pureAdditions(theirsDiff);
|
|
9570
|
+
const oursByContent = new Map;
|
|
9571
|
+
for (const addition of oursAdditions) {
|
|
9572
|
+
const key = addition.lines.join(`
|
|
9573
|
+
`);
|
|
9574
|
+
oursByContent.set(key, [...oursByContent.get(key) ?? [], addition]);
|
|
9261
9575
|
}
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
const
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9576
|
+
const decode = (content) => new TextDecoder().decode(content);
|
|
9577
|
+
const baseLines = decode(input.base).split(`
|
|
9578
|
+
`);
|
|
9579
|
+
const oursLines = decode(input.ours).split(`
|
|
9580
|
+
`);
|
|
9581
|
+
const theirsLines = decode(input.theirs).split(`
|
|
9582
|
+
`);
|
|
9583
|
+
const mergedLines = input.merged.split(`
|
|
9584
|
+
`);
|
|
9585
|
+
const convergent = theirsAdditions.flatMap((addition) => {
|
|
9586
|
+
if (!isSubstantial(addition.lines) || !isNamedClassMethod(addition.lines)) {
|
|
9587
|
+
return [];
|
|
9270
9588
|
}
|
|
9271
|
-
|
|
9589
|
+
const key = addition.lines.join(`
|
|
9590
|
+
`);
|
|
9591
|
+
const matchingOurs = oursByContent.get(key);
|
|
9592
|
+
if (matchingOurs?.length !== 1)
|
|
9593
|
+
return [];
|
|
9594
|
+
if (theirsAdditions.filter((candidate2) => candidate2.lines.join(`
|
|
9595
|
+
`) === key).length !== 1) {
|
|
9596
|
+
return [];
|
|
9597
|
+
}
|
|
9598
|
+
const oursContainer = enclosingClass(oursLines, matchingOurs[0]);
|
|
9599
|
+
const theirsContainer = enclosingClass(theirsLines, addition);
|
|
9600
|
+
if (!oursContainer || oursContainer !== theirsContainer)
|
|
9601
|
+
return [];
|
|
9602
|
+
return countSequence(baseLines, addition.lines) === 0 && countSequence(oursLines, addition.lines) === 1 && countSequence(theirsLines, addition.lines) === 1 && countSequence(mergedLines, addition.lines) > 1 ? [{ ours: matchingOurs[0], theirs: addition }] : [];
|
|
9603
|
+
});
|
|
9604
|
+
if (convergent.length !== 1)
|
|
9605
|
+
return;
|
|
9606
|
+
const candidate = convergent[0];
|
|
9607
|
+
if (!candidate)
|
|
9608
|
+
return;
|
|
9609
|
+
const oursWithout = withoutAddition(oursLines, candidate.ours);
|
|
9610
|
+
const theirsWithout = withoutAddition(theirsLines, candidate.theirs);
|
|
9611
|
+
if (!oursWithout || !theirsWithout || !sameLines(oursWithout, theirsWithout)) {
|
|
9612
|
+
return;
|
|
9272
9613
|
}
|
|
9614
|
+
return input.ours;
|
|
9273
9615
|
}
|
|
9274
|
-
function
|
|
9275
|
-
|
|
9616
|
+
async function diff(root, basePath, branchPath) {
|
|
9617
|
+
const result = await captureProcess("git", ["diff", "--no-index", "--unified=0", "--no-color", basePath, branchPath], root);
|
|
9618
|
+
return result.code === 0 || result.code === 1 ? result.stdout : undefined;
|
|
9276
9619
|
}
|
|
9277
|
-
function
|
|
9278
|
-
|
|
9620
|
+
function pureAdditions(diff2) {
|
|
9621
|
+
const lines = diff2.split(`
|
|
9622
|
+
`);
|
|
9623
|
+
const additions = [];
|
|
9624
|
+
for (let index = 0;index < lines.length; index += 1) {
|
|
9625
|
+
const match = /^@@ -\d+(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(lines[index] ?? "");
|
|
9626
|
+
if (!match)
|
|
9627
|
+
continue;
|
|
9628
|
+
const oldCount = match[1] === undefined ? 1 : Number(match[1]);
|
|
9629
|
+
const start = Number(match[2]);
|
|
9630
|
+
const newCount = match[3] === undefined ? 1 : Number(match[3]);
|
|
9631
|
+
if (oldCount !== 0 || newCount === 0)
|
|
9632
|
+
continue;
|
|
9633
|
+
const added = [];
|
|
9634
|
+
for (let cursor = index + 1;cursor < lines.length; cursor += 1) {
|
|
9635
|
+
const line = lines[cursor] ?? "";
|
|
9636
|
+
if (line.startsWith("@@ "))
|
|
9637
|
+
break;
|
|
9638
|
+
if (line.startsWith("+"))
|
|
9639
|
+
added.push(line.slice(1));
|
|
9640
|
+
}
|
|
9641
|
+
if (added.length === newCount)
|
|
9642
|
+
additions.push({ start, lines: added });
|
|
9643
|
+
}
|
|
9644
|
+
return additions;
|
|
9279
9645
|
}
|
|
9280
|
-
function
|
|
9281
|
-
return
|
|
9646
|
+
function isSubstantial(lines) {
|
|
9647
|
+
return lines.filter((line) => line.trim()).length >= 3 && lines.join(`
|
|
9648
|
+
`).length >= 32;
|
|
9282
9649
|
}
|
|
9283
|
-
function
|
|
9284
|
-
|
|
9650
|
+
function isNamedClassMethod(lines) {
|
|
9651
|
+
const first = lines.find((line) => line.trim())?.trim() ?? "";
|
|
9652
|
+
const last = [...lines].reverse().find((line) => line.trim())?.trim() ?? "";
|
|
9653
|
+
return /^(?:(?:public|protected|private|static|abstract|override|async|declare|get|set)\s+)*(?:\*\s*)?[A-Za-z_$][\w$]*\s*(?:<[^>{}]*>)?\s*\(/.test(first) && lines.some((line) => line.includes("{")) && /^}\s*;?$/.test(last);
|
|
9285
9654
|
}
|
|
9286
|
-
function
|
|
9287
|
-
|
|
9655
|
+
function enclosingClass(lines, addition) {
|
|
9656
|
+
const memberIndent = leadingWhitespace(addition.lines.find((line) => line.trim()) ?? "");
|
|
9657
|
+
for (let index = addition.start - 2;index >= 0; index -= 1) {
|
|
9658
|
+
const line = lines[index] ?? "";
|
|
9659
|
+
if (!line.trim() || leadingWhitespace(line) >= memberIndent)
|
|
9660
|
+
continue;
|
|
9661
|
+
const match = /^(\s*)(?:(?:export|default|abstract|declare)\s+)*class\s+([A-Za-z_$][\w$]*)\b/.exec(line);
|
|
9662
|
+
if (!match)
|
|
9663
|
+
return;
|
|
9664
|
+
const name = match[2] ?? "";
|
|
9665
|
+
const ordinal = lines.slice(0, index + 1).filter((candidate) => new RegExp(`^\\s*(?:(?:export|default|abstract|declare)\\s+)*class\\s+${escapeRegExp2(name)}\\b`).test(candidate)).length;
|
|
9666
|
+
return `${name}#${ordinal}`;
|
|
9667
|
+
}
|
|
9288
9668
|
}
|
|
9289
|
-
function
|
|
9290
|
-
return
|
|
9669
|
+
function leadingWhitespace(line) {
|
|
9670
|
+
return /^\s*/.exec(line)?.[0].length ?? 0;
|
|
9291
9671
|
}
|
|
9292
|
-
function
|
|
9293
|
-
return {
|
|
9672
|
+
function escapeRegExp2(value) {
|
|
9673
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9294
9674
|
}
|
|
9295
|
-
function
|
|
9296
|
-
|
|
9675
|
+
function countSequence(lines, sequence) {
|
|
9676
|
+
let count = 0;
|
|
9677
|
+
for (let index = 0;index <= lines.length - sequence.length; index += 1) {
|
|
9678
|
+
if (sameLines(lines.slice(index, index + sequence.length), sequence)) {
|
|
9679
|
+
count += 1;
|
|
9680
|
+
}
|
|
9681
|
+
}
|
|
9682
|
+
return count;
|
|
9297
9683
|
}
|
|
9298
|
-
function
|
|
9299
|
-
|
|
9300
|
-
|
|
9684
|
+
function withoutAddition(lines, addition) {
|
|
9685
|
+
const index = addition.start - 1;
|
|
9686
|
+
if (!sameLines(lines.slice(index, index + addition.lines.length), addition.lines)) {
|
|
9687
|
+
return;
|
|
9688
|
+
}
|
|
9689
|
+
return [
|
|
9690
|
+
...lines.slice(0, index),
|
|
9691
|
+
...lines.slice(index + addition.lines.length)
|
|
9692
|
+
];
|
|
9301
9693
|
}
|
|
9302
|
-
|
|
9303
|
-
return
|
|
9304
|
-
}
|
|
9305
|
-
|
|
9306
|
-
// src/update/snapshot-delta.ts
|
|
9307
|
-
function applySnapshotDelta(before, after, current, path2, conflicts, conflictPath) {
|
|
9308
|
-
if (deepEqual(before, after))
|
|
9309
|
-
return structuredClone(current);
|
|
9310
|
-
if (!isRecord(before) || !isRecord(after) || !isRecord(current)) {
|
|
9311
|
-
if (deepEqual(current, before) || deepEqual(current, after)) {
|
|
9312
|
-
return structuredClone(after);
|
|
9313
|
-
}
|
|
9314
|
-
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u4E0E\u4E1A\u52A1\u540C\u65F6\u4FEE\u6539 snapshot \u8282\u70B9 ${path2.join(".") || "<root>"}`);
|
|
9315
|
-
return structuredClone(current);
|
|
9316
|
-
}
|
|
9317
|
-
const merged = structuredClone(current);
|
|
9318
|
-
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
9319
|
-
for (const key of keys) {
|
|
9320
|
-
if (path2.length === 0 && (key === "id" || key === "prevId"))
|
|
9321
|
-
continue;
|
|
9322
|
-
const nextPath = [...path2, key];
|
|
9323
|
-
if (!(key in after)) {
|
|
9324
|
-
if (!(key in current))
|
|
9325
|
-
continue;
|
|
9326
|
-
if (deepEqual(current[key], before[key]))
|
|
9327
|
-
delete merged[key];
|
|
9328
|
-
else
|
|
9329
|
-
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u5220\u9664\u4E86\u4E1A\u52A1\u5DF2\u4FEE\u6539\u7684 snapshot \u8282\u70B9 ${nextPath.join(".")}`);
|
|
9330
|
-
continue;
|
|
9331
|
-
}
|
|
9332
|
-
if (!(key in before)) {
|
|
9333
|
-
if (!(key in current) || deepEqual(current[key], after[key])) {
|
|
9334
|
-
merged[key] = structuredClone(after[key]);
|
|
9335
|
-
} else {
|
|
9336
|
-
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u65B0\u589E\u7684 snapshot \u8282\u70B9\u5DF2\u88AB\u4E1A\u52A1\u5360\u7528 ${nextPath.join(".")}`);
|
|
9337
|
-
}
|
|
9338
|
-
continue;
|
|
9339
|
-
}
|
|
9340
|
-
merged[key] = applySnapshotDelta(before[key], after[key], current[key], nextPath, conflicts, conflictPath);
|
|
9341
|
-
}
|
|
9342
|
-
return merged;
|
|
9343
|
-
}
|
|
9344
|
-
function isRecord(value) {
|
|
9345
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
9346
|
-
}
|
|
9347
|
-
function deepEqual(left, right) {
|
|
9348
|
-
return JSON.stringify(left) === JSON.stringify(right);
|
|
9349
|
-
}
|
|
9350
|
-
|
|
9351
|
-
// src/update/migration-adoption.ts
|
|
9352
|
-
async function inspectPreexistingMigrationAdoptions(input) {
|
|
9353
|
-
const conflicts = [];
|
|
9354
|
-
const adoptions = [];
|
|
9355
|
-
const projectByName = new Map(input.project.entries.map((entry) => [stableName(entry.tag), entry]));
|
|
9356
|
-
for (const candidate of input.candidates) {
|
|
9357
|
-
const name = stableName(candidate.tag);
|
|
9358
|
-
const projectEntry = projectByName.get(name);
|
|
9359
|
-
if (!projectEntry || input.managedNames.has(name))
|
|
9360
|
-
continue;
|
|
9361
|
-
const targetPosition = input.target.entries.indexOf(candidate);
|
|
9362
|
-
const projectPosition = input.project.entries.indexOf(projectEntry);
|
|
9363
|
-
const previousTarget = input.target.entries[targetPosition - 1];
|
|
9364
|
-
const previousProject = input.project.entries[projectPosition - 1];
|
|
9365
|
-
if (!previousTarget || !previousProject) {
|
|
9366
|
-
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C\u7F3A\u5C11\u524D\u7F6E\u5386\u53F2`);
|
|
9367
|
-
continue;
|
|
9368
|
-
}
|
|
9369
|
-
const projectSqlPath = `${drizzleRoot}/${projectEntry.tag}.sql`;
|
|
9370
|
-
const projectSnapshotPath = snapshotPath(projectEntry.tag);
|
|
9371
|
-
const [
|
|
9372
|
-
targetSql,
|
|
9373
|
-
projectSql,
|
|
9374
|
-
targetBefore,
|
|
9375
|
-
targetAfter,
|
|
9376
|
-
projectBeforeBytes,
|
|
9377
|
-
projectAfterBytes
|
|
9378
|
-
] = await Promise.all([
|
|
9379
|
-
readFile18(join22(input.targetDirectory, `${drizzleRoot}/${candidate.tag}.sql`)),
|
|
9380
|
-
readProjectFile(input, projectSqlPath),
|
|
9381
|
-
readJson(join22(input.targetDirectory, snapshotPath(previousTarget.tag))),
|
|
9382
|
-
readJson(join22(input.targetDirectory, snapshotPath(candidate.tag))),
|
|
9383
|
-
readProjectFile(input, snapshotPath(previousProject.tag)),
|
|
9384
|
-
readProjectFile(input, projectSnapshotPath)
|
|
9385
|
-
]);
|
|
9386
|
-
if (!projectSql || !projectBeforeBytes || !projectAfterBytes) {
|
|
9387
|
-
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C\u9879\u76EE migration \u6587\u4EF6\u4E0D\u5B8C\u6574`);
|
|
9388
|
-
continue;
|
|
9389
|
-
}
|
|
9390
|
-
const projectBefore = decodeSnapshot(projectBeforeBytes);
|
|
9391
|
-
const projectAfter = decodeSnapshot(projectAfterBytes);
|
|
9392
|
-
const reason = validateAdoption({
|
|
9393
|
-
targetSql,
|
|
9394
|
-
projectSql,
|
|
9395
|
-
targetBefore,
|
|
9396
|
-
targetAfter,
|
|
9397
|
-
projectBefore,
|
|
9398
|
-
projectAfter
|
|
9399
|
-
});
|
|
9400
|
-
if (reason) {
|
|
9401
|
-
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C${reason}`);
|
|
9402
|
-
continue;
|
|
9403
|
-
}
|
|
9404
|
-
adoptions.push({
|
|
9405
|
-
sqlPath: projectSqlPath,
|
|
9406
|
-
snapshotPath: projectSnapshotPath,
|
|
9407
|
-
sql: projectSql,
|
|
9408
|
-
snapshot: projectAfterBytes
|
|
9409
|
-
});
|
|
9410
|
-
}
|
|
9411
|
-
return { adoptions, conflicts };
|
|
9412
|
-
}
|
|
9413
|
-
function validateAdoption(input) {
|
|
9414
|
-
if (!equalBytes(input.targetSql, input.projectSql)) {
|
|
9415
|
-
return "SQL \u5185\u5BB9\u4E0D\u4E00\u81F4";
|
|
9416
|
-
}
|
|
9417
|
-
if (input.projectAfter.prevId !== input.projectBefore.id) {
|
|
9418
|
-
return "\u9879\u76EE snapshot lineage \u4E0D\u8FDE\u7EED";
|
|
9419
|
-
}
|
|
9420
|
-
const deltaConflicts = [];
|
|
9421
|
-
const expected = applySnapshotDelta(input.targetBefore, input.targetAfter, input.projectBefore, [], deltaConflicts, journalPath);
|
|
9422
|
-
if (deltaConflicts.length || canonicalSnapshot(expected) !== canonicalSnapshot(input.projectAfter)) {
|
|
9423
|
-
return "snapshot delta \u4E0E\u9879\u76EE\u5386\u53F2\u4E0D\u4E00\u81F4";
|
|
9424
|
-
}
|
|
9425
|
-
}
|
|
9426
|
-
function decodeSnapshot(content) {
|
|
9427
|
-
return JSON.parse(new TextDecoder().decode(content));
|
|
9428
|
-
}
|
|
9429
|
-
function equalBytes(left, right) {
|
|
9430
|
-
return left.byteLength === right.byteLength && left.every((value, index) => value === right[index]);
|
|
9431
|
-
}
|
|
9432
|
-
function canonicalSnapshot(value) {
|
|
9433
|
-
return JSON.stringify(canonicalize(value, true));
|
|
9434
|
-
}
|
|
9435
|
-
function canonicalize(value, root = false) {
|
|
9436
|
-
if (Array.isArray(value))
|
|
9437
|
-
return value.map((item) => canonicalize(item));
|
|
9438
|
-
if (!value || typeof value !== "object")
|
|
9439
|
-
return value;
|
|
9440
|
-
return Object.fromEntries(Object.entries(value).filter(([key]) => !root || key !== "id" && key !== "prevId").sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, canonicalize(item)]));
|
|
9441
|
-
}
|
|
9442
|
-
|
|
9443
|
-
// src/update/migration-reconciler.ts
|
|
9444
|
-
async function reconcileDrizzleMigrations(input) {
|
|
9445
|
-
const journals = await readJournals(input);
|
|
9446
|
-
if (!journals) {
|
|
9447
|
-
return unchanged(input.targetManifest);
|
|
9448
|
-
}
|
|
9449
|
-
const { base, project, target } = journals;
|
|
9450
|
-
const conflicts = [];
|
|
9451
|
-
validateUniqueNames(base, "\u6765\u6E90\u6A21\u677F", conflicts);
|
|
9452
|
-
validateUniqueNames(project, "\u5F53\u524D\u9879\u76EE", conflicts);
|
|
9453
|
-
validateUniqueNames(target, "\u76EE\u6807\u6A21\u677F", conflicts);
|
|
9454
|
-
if (conflicts.length) {
|
|
9455
|
-
return { ...unchanged(input.targetManifest), conflicts };
|
|
9456
|
-
}
|
|
9457
|
-
const baseNames = new Set(base.entries.map(({ tag }) => stableName(tag)));
|
|
9458
|
-
const projectNames = new Set(project.entries.map(({ tag }) => stableName(tag)));
|
|
9459
|
-
const managedNames = new Set(input.sourceManifest.files.filter(({ path: path2 }) => isSqlMigration(path2)).map(({ path: path2 }) => stableName(path2.slice(drizzleRoot.length + 1, -4))));
|
|
9460
|
-
const candidates = target.entries.filter(({ tag }) => !baseNames.has(stableName(tag)));
|
|
9461
|
-
const adoption = await inspectPreexistingMigrationAdoptions({
|
|
9462
|
-
...input,
|
|
9463
|
-
project,
|
|
9464
|
-
target,
|
|
9465
|
-
candidates,
|
|
9466
|
-
managedNames
|
|
9467
|
-
});
|
|
9468
|
-
conflicts.push(...adoption.conflicts);
|
|
9469
|
-
const additions = candidates.filter(({ tag }) => !projectNames.has(stableName(tag)));
|
|
9470
|
-
const contentOverrides = new Map;
|
|
9471
|
-
const files = await preservePublishedHistory(input.sourceManifest, input, contentOverrides);
|
|
9472
|
-
const publishedPaths = new Set(files.map(({ path: path2 }) => path2));
|
|
9473
|
-
for (const adopted of adoption.adoptions) {
|
|
9474
|
-
contentOverrides.set(adopted.sqlPath, adopted.sql);
|
|
9475
|
-
contentOverrides.set(adopted.snapshotPath, adopted.snapshot);
|
|
9476
|
-
files.push(managedEntry(adopted.sqlPath, adopted.sql), managedEntry(adopted.snapshotPath, adopted.snapshot));
|
|
9477
|
-
publishedPaths.add(adopted.sqlPath);
|
|
9478
|
-
publishedPaths.add(adopted.snapshotPath);
|
|
9479
|
-
}
|
|
9480
|
-
files.push(...input.targetManifest.files.filter(({ path: path2 }) => !isDrizzleHistoryPath(path2)));
|
|
9481
|
-
if (!additions.length) {
|
|
9482
|
-
const journalContent2 = encodeJson(project);
|
|
9483
|
-
contentOverrides.set(journalPath, journalContent2);
|
|
9484
|
-
files.push(managedEntry(journalPath, journalContent2));
|
|
9485
|
-
return result(input.targetManifest, files, contentOverrides, publishedPaths, conflicts);
|
|
9486
|
-
}
|
|
9487
|
-
let nextPrefix = highestPrefix(project) + 1;
|
|
9488
|
-
let nextIndex = highestIndex(project) + 1;
|
|
9489
|
-
let previousWhen = project.entries.at(-1)?.when ?? 0;
|
|
9490
|
-
let currentSnapshot = await readLatestSnapshot(input, project);
|
|
9491
|
-
const mergedJournal = structuredClone(project);
|
|
9492
|
-
for (const addition of additions) {
|
|
9493
|
-
const targetPosition = target.entries.indexOf(addition);
|
|
9494
|
-
const previousTarget = target.entries[targetPosition - 1];
|
|
9495
|
-
if (!previousTarget) {
|
|
9496
|
-
conflicts.push(`${journalPath}\uFF1A\u76EE\u6807 migration \u7F3A\u5C11\u524D\u7F6E\u5FEB\u7167`);
|
|
9497
|
-
break;
|
|
9498
|
-
}
|
|
9499
|
-
const targetBefore = await readSnapshot(input.targetDirectory, previousTarget.tag);
|
|
9500
|
-
const targetAfter = await readSnapshot(input.targetDirectory, addition.tag);
|
|
9501
|
-
const merged = applySnapshotDelta(targetBefore, targetAfter, currentSnapshot, [], conflicts, journalPath);
|
|
9502
|
-
if (conflicts.length)
|
|
9503
|
-
break;
|
|
9504
|
-
const prefix = String(nextPrefix).padStart(4, "0");
|
|
9505
|
-
const name = stableName(addition.tag);
|
|
9506
|
-
const tag = `${prefix}_${name}`;
|
|
9507
|
-
const sqlPath = `${drizzleRoot}/${tag}.sql`;
|
|
9508
|
-
const snapshotPath2 = `${drizzleRoot}/meta/${prefix}_snapshot.json`;
|
|
9509
|
-
const sql = await readFile19(join23(input.targetDirectory, `${drizzleRoot}/${addition.tag}.sql`));
|
|
9510
|
-
merged.id = targetAfter.id;
|
|
9511
|
-
merged.prevId = currentSnapshot.id;
|
|
9512
|
-
const snapshot2 = encodeJson(merged);
|
|
9513
|
-
contentOverrides.set(sqlPath, sql);
|
|
9514
|
-
contentOverrides.set(snapshotPath2, snapshot2);
|
|
9515
|
-
files.push(managedEntry(sqlPath, sql), managedEntry(snapshotPath2, snapshot2));
|
|
9516
|
-
previousWhen = Math.max(previousWhen + 1, addition.when);
|
|
9517
|
-
mergedJournal.entries.push({
|
|
9518
|
-
...addition,
|
|
9519
|
-
idx: nextIndex,
|
|
9520
|
-
when: previousWhen,
|
|
9521
|
-
tag
|
|
9522
|
-
});
|
|
9523
|
-
currentSnapshot = merged;
|
|
9524
|
-
nextPrefix += 1;
|
|
9525
|
-
nextIndex += 1;
|
|
9526
|
-
}
|
|
9527
|
-
const journalContent = encodeJson(mergedJournal);
|
|
9528
|
-
contentOverrides.set(journalPath, journalContent);
|
|
9529
|
-
files.push(managedEntry(journalPath, journalContent));
|
|
9530
|
-
return result(input.targetManifest, files, contentOverrides, publishedPaths, conflicts);
|
|
9531
|
-
}
|
|
9532
|
-
function result(targetManifest, files, contentOverrides, forcePreserves, conflicts) {
|
|
9533
|
-
return {
|
|
9534
|
-
targetManifest: {
|
|
9535
|
-
...targetManifest,
|
|
9536
|
-
files: deduplicate(files).sort((left, right) => left.path.localeCompare(right.path))
|
|
9537
|
-
},
|
|
9538
|
-
contentOverrides,
|
|
9539
|
-
forceUpdates: new Set([journalPath]),
|
|
9540
|
-
forcePreserves,
|
|
9541
|
-
conflicts
|
|
9542
|
-
};
|
|
9543
|
-
}
|
|
9544
|
-
function unchanged(targetManifest) {
|
|
9545
|
-
return {
|
|
9546
|
-
targetManifest,
|
|
9547
|
-
contentOverrides: new Map,
|
|
9548
|
-
forceUpdates: new Set,
|
|
9549
|
-
forcePreserves: new Set,
|
|
9550
|
-
conflicts: []
|
|
9551
|
-
};
|
|
9552
|
-
}
|
|
9553
|
-
async function readJournals(input) {
|
|
9554
|
-
try {
|
|
9555
|
-
const [base, project, target] = await Promise.all([
|
|
9556
|
-
readJson(join23(input.baseDirectory, journalPath)),
|
|
9557
|
-
readProjectJson(input, journalPath),
|
|
9558
|
-
readJson(join23(input.targetDirectory, journalPath))
|
|
9559
|
-
]);
|
|
9560
|
-
return { base, project, target };
|
|
9561
|
-
} catch (error) {
|
|
9562
|
-
if (isMissingFileError(error))
|
|
9563
|
-
return;
|
|
9564
|
-
throw error;
|
|
9565
|
-
}
|
|
9566
|
-
}
|
|
9567
|
-
async function preservePublishedHistory(manifest, input, overrides) {
|
|
9568
|
-
const entries = manifest.files.filter(({ path: path2 }) => isMigrationArtifact(path2) && path2 !== journalPath);
|
|
9569
|
-
await Promise.all(entries.map(async ({ path: path2 }) => {
|
|
9570
|
-
const content = await readProjectFile(input, path2);
|
|
9571
|
-
if (!content)
|
|
9572
|
-
throw new Error(`\u5F53\u524D\u9879\u76EE migration \u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
9573
|
-
overrides.set(path2, content);
|
|
9574
|
-
}));
|
|
9575
|
-
return entries;
|
|
9576
|
-
}
|
|
9577
|
-
async function readLatestSnapshot(input, journal) {
|
|
9578
|
-
const latest = journal.entries.at(-1);
|
|
9579
|
-
if (!latest)
|
|
9580
|
-
throw new Error(`${journalPath}\uFF1A\u5F53\u524D\u9879\u76EE\u6CA1\u6709 migration`);
|
|
9581
|
-
const path2 = snapshotPath(latest.tag);
|
|
9582
|
-
const content = await readProjectFile(input, path2);
|
|
9583
|
-
if (!content) {
|
|
9584
|
-
throw new Error(`\u5F53\u524D\u9879\u76EE migration \u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
9585
|
-
}
|
|
9586
|
-
return JSON.parse(new TextDecoder().decode(content));
|
|
9587
|
-
}
|
|
9588
|
-
async function readSnapshot(root, tag) {
|
|
9589
|
-
return await readJson(join23(root, snapshotPath(tag)));
|
|
9590
|
-
}
|
|
9591
|
-
|
|
9592
|
-
// src/update/planner-file.ts
|
|
9593
|
-
import { readFile as readFile21 } from "fs/promises";
|
|
9594
|
-
import { join as join27 } from "path";
|
|
9595
|
-
|
|
9596
|
-
// src/update/planner-file-support.ts
|
|
9597
|
-
function readyPlannedFile(path2, ownership, action, reason, expectedProjectContent, content) {
|
|
9598
|
-
return {
|
|
9599
|
-
path: path2,
|
|
9600
|
-
ownership,
|
|
9601
|
-
action,
|
|
9602
|
-
reason,
|
|
9603
|
-
expectedProjectContent,
|
|
9604
|
-
content
|
|
9605
|
-
};
|
|
9606
|
-
}
|
|
9607
|
-
function expectationForSnapshot(content) {
|
|
9608
|
-
return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
|
|
9609
|
-
}
|
|
9610
|
-
function conflict(path2, ownership, reason, expectedProjectContent) {
|
|
9611
|
-
return {
|
|
9612
|
-
path: path2,
|
|
9613
|
-
ownership,
|
|
9614
|
-
action: "preserve",
|
|
9615
|
-
reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
|
|
9616
|
-
expectedProjectContent,
|
|
9617
|
-
conflict: reason
|
|
9618
|
-
};
|
|
9619
|
-
}
|
|
9620
|
-
// src/update/merge.ts
|
|
9621
|
-
import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile12 } from "fs/promises";
|
|
9622
|
-
import { tmpdir as tmpdir2 } from "os";
|
|
9623
|
-
import { join as join24 } from "path";
|
|
9624
|
-
|
|
9625
|
-
// src/update/merge-convergent-additions.ts
|
|
9626
|
-
async function reconcileConvergentAdditions(input) {
|
|
9627
|
-
const [oursDiff, theirsDiff] = await Promise.all([
|
|
9628
|
-
diff(input.root, input.basePath, input.oursPath),
|
|
9629
|
-
diff(input.root, input.basePath, input.theirsPath)
|
|
9630
|
-
]);
|
|
9631
|
-
if (oursDiff === undefined || theirsDiff === undefined)
|
|
9632
|
-
return;
|
|
9633
|
-
const oursAdditions = pureAdditions(oursDiff);
|
|
9634
|
-
const theirsAdditions = pureAdditions(theirsDiff);
|
|
9635
|
-
const oursByContent = new Map;
|
|
9636
|
-
for (const addition of oursAdditions) {
|
|
9637
|
-
const key = addition.lines.join(`
|
|
9638
|
-
`);
|
|
9639
|
-
oursByContent.set(key, [...oursByContent.get(key) ?? [], addition]);
|
|
9640
|
-
}
|
|
9641
|
-
const decode = (content) => new TextDecoder().decode(content);
|
|
9642
|
-
const baseLines = decode(input.base).split(`
|
|
9643
|
-
`);
|
|
9644
|
-
const oursLines = decode(input.ours).split(`
|
|
9645
|
-
`);
|
|
9646
|
-
const theirsLines = decode(input.theirs).split(`
|
|
9647
|
-
`);
|
|
9648
|
-
const mergedLines = input.merged.split(`
|
|
9649
|
-
`);
|
|
9650
|
-
const convergent = theirsAdditions.flatMap((addition) => {
|
|
9651
|
-
if (!isSubstantial(addition.lines) || !isNamedClassMethod(addition.lines)) {
|
|
9652
|
-
return [];
|
|
9653
|
-
}
|
|
9654
|
-
const key = addition.lines.join(`
|
|
9655
|
-
`);
|
|
9656
|
-
const matchingOurs = oursByContent.get(key);
|
|
9657
|
-
if (matchingOurs?.length !== 1)
|
|
9658
|
-
return [];
|
|
9659
|
-
if (theirsAdditions.filter((candidate2) => candidate2.lines.join(`
|
|
9660
|
-
`) === key).length !== 1) {
|
|
9661
|
-
return [];
|
|
9662
|
-
}
|
|
9663
|
-
const oursContainer = enclosingClass(oursLines, matchingOurs[0]);
|
|
9664
|
-
const theirsContainer = enclosingClass(theirsLines, addition);
|
|
9665
|
-
if (!oursContainer || oursContainer !== theirsContainer)
|
|
9666
|
-
return [];
|
|
9667
|
-
return countSequence(baseLines, addition.lines) === 0 && countSequence(oursLines, addition.lines) === 1 && countSequence(theirsLines, addition.lines) === 1 && countSequence(mergedLines, addition.lines) > 1 ? [{ ours: matchingOurs[0], theirs: addition }] : [];
|
|
9668
|
-
});
|
|
9669
|
-
if (convergent.length !== 1)
|
|
9670
|
-
return;
|
|
9671
|
-
const candidate = convergent[0];
|
|
9672
|
-
if (!candidate)
|
|
9673
|
-
return;
|
|
9674
|
-
const oursWithout = withoutAddition(oursLines, candidate.ours);
|
|
9675
|
-
const theirsWithout = withoutAddition(theirsLines, candidate.theirs);
|
|
9676
|
-
if (!oursWithout || !theirsWithout || !sameLines(oursWithout, theirsWithout)) {
|
|
9677
|
-
return;
|
|
9678
|
-
}
|
|
9679
|
-
return input.ours;
|
|
9680
|
-
}
|
|
9681
|
-
async function diff(root, basePath, branchPath) {
|
|
9682
|
-
const result2 = await captureProcess("git", ["diff", "--no-index", "--unified=0", "--no-color", basePath, branchPath], root);
|
|
9683
|
-
return result2.code === 0 || result2.code === 1 ? result2.stdout : undefined;
|
|
9684
|
-
}
|
|
9685
|
-
function pureAdditions(diff2) {
|
|
9686
|
-
const lines = diff2.split(`
|
|
9687
|
-
`);
|
|
9688
|
-
const additions = [];
|
|
9689
|
-
for (let index = 0;index < lines.length; index += 1) {
|
|
9690
|
-
const match = /^@@ -\d+(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(lines[index] ?? "");
|
|
9691
|
-
if (!match)
|
|
9692
|
-
continue;
|
|
9693
|
-
const oldCount = match[1] === undefined ? 1 : Number(match[1]);
|
|
9694
|
-
const start = Number(match[2]);
|
|
9695
|
-
const newCount = match[3] === undefined ? 1 : Number(match[3]);
|
|
9696
|
-
if (oldCount !== 0 || newCount === 0)
|
|
9697
|
-
continue;
|
|
9698
|
-
const added = [];
|
|
9699
|
-
for (let cursor = index + 1;cursor < lines.length; cursor += 1) {
|
|
9700
|
-
const line = lines[cursor] ?? "";
|
|
9701
|
-
if (line.startsWith("@@ "))
|
|
9702
|
-
break;
|
|
9703
|
-
if (line.startsWith("+"))
|
|
9704
|
-
added.push(line.slice(1));
|
|
9705
|
-
}
|
|
9706
|
-
if (added.length === newCount)
|
|
9707
|
-
additions.push({ start, lines: added });
|
|
9708
|
-
}
|
|
9709
|
-
return additions;
|
|
9710
|
-
}
|
|
9711
|
-
function isSubstantial(lines) {
|
|
9712
|
-
return lines.filter((line) => line.trim()).length >= 3 && lines.join(`
|
|
9713
|
-
`).length >= 32;
|
|
9714
|
-
}
|
|
9715
|
-
function isNamedClassMethod(lines) {
|
|
9716
|
-
const first = lines.find((line) => line.trim())?.trim() ?? "";
|
|
9717
|
-
const last = [...lines].reverse().find((line) => line.trim())?.trim() ?? "";
|
|
9718
|
-
return /^(?:(?:public|protected|private|static|abstract|override|async|declare|get|set)\s+)*(?:\*\s*)?[A-Za-z_$][\w$]*\s*(?:<[^>{}]*>)?\s*\(/.test(first) && lines.some((line) => line.includes("{")) && /^}\s*;?$/.test(last);
|
|
9719
|
-
}
|
|
9720
|
-
function enclosingClass(lines, addition) {
|
|
9721
|
-
const memberIndent = leadingWhitespace(addition.lines.find((line) => line.trim()) ?? "");
|
|
9722
|
-
for (let index = addition.start - 2;index >= 0; index -= 1) {
|
|
9723
|
-
const line = lines[index] ?? "";
|
|
9724
|
-
if (!line.trim() || leadingWhitespace(line) >= memberIndent)
|
|
9725
|
-
continue;
|
|
9726
|
-
const match = /^(\s*)(?:(?:export|default|abstract|declare)\s+)*class\s+([A-Za-z_$][\w$]*)\b/.exec(line);
|
|
9727
|
-
if (!match)
|
|
9728
|
-
return;
|
|
9729
|
-
const name = match[2] ?? "";
|
|
9730
|
-
const ordinal = lines.slice(0, index + 1).filter((candidate) => new RegExp(`^\\s*(?:(?:export|default|abstract|declare)\\s+)*class\\s+${escapeRegExp2(name)}\\b`).test(candidate)).length;
|
|
9731
|
-
return `${name}#${ordinal}`;
|
|
9732
|
-
}
|
|
9733
|
-
}
|
|
9734
|
-
function leadingWhitespace(line) {
|
|
9735
|
-
return /^\s*/.exec(line)?.[0].length ?? 0;
|
|
9736
|
-
}
|
|
9737
|
-
function escapeRegExp2(value) {
|
|
9738
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9739
|
-
}
|
|
9740
|
-
function countSequence(lines, sequence) {
|
|
9741
|
-
let count = 0;
|
|
9742
|
-
for (let index = 0;index <= lines.length - sequence.length; index += 1) {
|
|
9743
|
-
if (sameLines(lines.slice(index, index + sequence.length), sequence)) {
|
|
9744
|
-
count += 1;
|
|
9745
|
-
}
|
|
9746
|
-
}
|
|
9747
|
-
return count;
|
|
9748
|
-
}
|
|
9749
|
-
function withoutAddition(lines, addition) {
|
|
9750
|
-
const index = addition.start - 1;
|
|
9751
|
-
if (!sameLines(lines.slice(index, index + addition.lines.length), addition.lines)) {
|
|
9752
|
-
return;
|
|
9753
|
-
}
|
|
9754
|
-
return [
|
|
9755
|
-
...lines.slice(0, index),
|
|
9756
|
-
...lines.slice(index + addition.lines.length)
|
|
9757
|
-
];
|
|
9758
|
-
}
|
|
9759
|
-
function sameLines(left, right) {
|
|
9760
|
-
return left.length === right.length && left.every((line, index) => line === right[index]);
|
|
9694
|
+
function sameLines(left, right) {
|
|
9695
|
+
return left.length === right.length && left.every((line, index) => line === right[index]);
|
|
9761
9696
|
}
|
|
9762
9697
|
|
|
9763
9698
|
// src/update/merge.ts
|
|
9764
9699
|
async function mergeTextFile(base, ours, theirs) {
|
|
9765
|
-
const root = await mkdtemp2(
|
|
9700
|
+
const root = await mkdtemp2(join21(tmpdir2(), "windy-merge-"));
|
|
9766
9701
|
try {
|
|
9767
|
-
const oursPath =
|
|
9768
|
-
const basePath =
|
|
9769
|
-
const theirsPath =
|
|
9702
|
+
const oursPath = join21(root, "ours");
|
|
9703
|
+
const basePath = join21(root, "base");
|
|
9704
|
+
const theirsPath = join21(root, "theirs");
|
|
9770
9705
|
await Promise.all([
|
|
9771
9706
|
writeFile12(oursPath, ours),
|
|
9772
9707
|
writeFile12(basePath, base),
|
|
9773
9708
|
writeFile12(theirsPath, theirs)
|
|
9774
9709
|
]);
|
|
9775
|
-
const
|
|
9776
|
-
if (
|
|
9710
|
+
const result = await captureProcess("git", ["merge-file", "-p", "--diff3", oursPath, basePath, theirsPath], root);
|
|
9711
|
+
if (result.code === 0) {
|
|
9777
9712
|
const reconciledContent = await reconcileConvergentAdditions({
|
|
9778
9713
|
root,
|
|
9779
9714
|
basePath,
|
|
@@ -9782,18 +9717,18 @@ async function mergeTextFile(base, ours, theirs) {
|
|
|
9782
9717
|
base,
|
|
9783
9718
|
ours,
|
|
9784
9719
|
theirs,
|
|
9785
|
-
merged:
|
|
9720
|
+
merged: result.stdout
|
|
9786
9721
|
});
|
|
9787
9722
|
if (reconciledContent !== undefined) {
|
|
9788
9723
|
return { content: reconciledContent };
|
|
9789
9724
|
}
|
|
9790
|
-
return { content: new TextEncoder().encode(
|
|
9725
|
+
return { content: new TextEncoder().encode(result.stdout) };
|
|
9791
9726
|
}
|
|
9792
|
-
if (
|
|
9793
|
-
const resolved = resolveConservativeConflicts(
|
|
9727
|
+
if (result.code > 0 && result.code <= 127) {
|
|
9728
|
+
const resolved = resolveConservativeConflicts(result.stdout);
|
|
9794
9729
|
return resolved ? { content: new TextEncoder().encode(resolved) } : { conflict: "\u4E09\u65B9\u5408\u5E76\u5B58\u5728\u91CD\u53E0\u4FEE\u6539" };
|
|
9795
9730
|
}
|
|
9796
|
-
return { conflict:
|
|
9731
|
+
return { conflict: result.stderr.trim() || "git merge-file \u6267\u884C\u5931\u8D25" };
|
|
9797
9732
|
} finally {
|
|
9798
9733
|
await rm6(root, { recursive: true, force: true });
|
|
9799
9734
|
}
|
|
@@ -10197,7 +10132,7 @@ ${workflowArtifactProperty}`
|
|
|
10197
10132
|
];
|
|
10198
10133
|
let content = source;
|
|
10199
10134
|
for (const replacement of replacements2) {
|
|
10200
|
-
if (
|
|
10135
|
+
if (occurrences2(content, replacement.anchor) !== 1) {
|
|
10201
10136
|
return conflict3(input, `Agent Runtime Composition \u951A\u70B9\u4E0D\u552F\u4E00\uFF1A${replacement.anchor}`);
|
|
10202
10137
|
}
|
|
10203
10138
|
content = content.replace(replacement.anchor, replacement.value);
|
|
@@ -10227,7 +10162,7 @@ function conflict3(input, message) {
|
|
|
10227
10162
|
function decode(content) {
|
|
10228
10163
|
return new TextDecoder().decode(content);
|
|
10229
10164
|
}
|
|
10230
|
-
function
|
|
10165
|
+
function occurrences2(source, value) {
|
|
10231
10166
|
return source.split(value).length - 1;
|
|
10232
10167
|
}
|
|
10233
10168
|
function validateLegacyRuntimeObject(source) {
|
|
@@ -10235,22 +10170,22 @@ function validateLegacyRuntimeObject(source) {
|
|
|
10235
10170
|
...input,`;
|
|
10236
10171
|
const endAnchor = `
|
|
10237
10172
|
});`;
|
|
10238
|
-
if (
|
|
10173
|
+
if (occurrences2(source, startAnchor) !== 1 || occurrences2(source, endAnchor) !== 1) {
|
|
10239
10174
|
return "Agent Runtime register object \u951A\u70B9\u4E0D\u552F\u4E00";
|
|
10240
10175
|
}
|
|
10241
10176
|
const start = source.indexOf(startAnchor);
|
|
10242
10177
|
const end = source.indexOf(endAnchor, start + startAnchor.length);
|
|
10243
10178
|
if (end < 0)
|
|
10244
10179
|
return "Agent Runtime register object \u7ED3\u675F\u951A\u70B9\u7F3A\u5931";
|
|
10245
|
-
const
|
|
10246
|
-
const host =
|
|
10180
|
+
const object2 = source.slice(start, end);
|
|
10181
|
+
const host = object2.indexOf(hostAuthProperty);
|
|
10247
10182
|
if (host < 0)
|
|
10248
10183
|
return "Agent Runtime Host Auth property \u951A\u70B9\u7F3A\u5931";
|
|
10249
|
-
const tail =
|
|
10184
|
+
const tail = object2.slice(host + hostAuthProperty.length);
|
|
10250
10185
|
if (/^\s*\.\.\./m.test(tail)) {
|
|
10251
10186
|
return "Workflow binding \u63D2\u5165\u70B9\u540E\u5B58\u5728\u53EF\u8986\u76D6\u5B83\u7684 spread";
|
|
10252
10187
|
}
|
|
10253
|
-
if (/["']clientAgentWorkflowArtifactBindings["']\s*:/.test(
|
|
10188
|
+
if (/["']clientAgentWorkflowArtifactBindings["']\s*:/.test(object2) || /\[\s*["']clientAgentWorkflowArtifactBindings["']\s*\]/.test(object2)) {
|
|
10254
10189
|
return "Agent Runtime \u5DF2\u5B58\u5728\u52A8\u6001 Workflow binding property";
|
|
10255
10190
|
}
|
|
10256
10191
|
return;
|
|
@@ -10287,6 +10222,7 @@ function addAiRuntimeTrajectoryTestFixture(source) {
|
|
|
10287
10222
|
|
|
10288
10223
|
// src/update/recipe-project-owned.ts
|
|
10289
10224
|
var managedPathsByRecipe = {
|
|
10225
|
+
"starter-0.9.1-to-0.10.0": adminApiRecipePaths,
|
|
10290
10226
|
"starter-0.6.8-to-0.6.9": [
|
|
10291
10227
|
"apps/web/src/router/index.ts",
|
|
10292
10228
|
"apps/web/src/router/platform-admin-route-bindings.ts"
|
|
@@ -10330,6 +10266,8 @@ async function planRecipeProjectOwned(input) {
|
|
|
10330
10266
|
return update(input, new TextEncoder().encode(transformed.content));
|
|
10331
10267
|
}
|
|
10332
10268
|
function transformProjectOwnedAnchor(path2, source, target) {
|
|
10269
|
+
if (isAdminApiRecipePath(path2))
|
|
10270
|
+
return addAdminApiExports(path2, source, target);
|
|
10333
10271
|
if (path2 === "apps/web/src/router/index.ts") {
|
|
10334
10272
|
return addComponentPageLoader(source, target);
|
|
10335
10273
|
}
|
|
@@ -10449,102 +10387,284 @@ function addComponentRouteBinding(source, target) {
|
|
|
10449
10387
|
if (unionStart < 0 || interfaceStart < 0) {
|
|
10450
10388
|
return { error: "\u627E\u4E0D\u5230 PlatformAdminPageKey \u9879\u76EE\u951A\u70B9" };
|
|
10451
10389
|
}
|
|
10452
|
-
const desiredPages = [
|
|
10453
|
-
"ui-components",
|
|
10454
|
-
...target?.includes('routeKey: "system.agent-session"') ? ["agent-session", "agent-workflow"] : []
|
|
10455
|
-
];
|
|
10456
|
-
let content = source;
|
|
10457
|
-
const union = content.slice(unionStart, interfaceStart);
|
|
10458
|
-
const missingPages = desiredPages.filter((page) => !union.includes(`"${page}"`));
|
|
10459
|
-
if (missingPages.length) {
|
|
10460
|
-
const semicolon = content.lastIndexOf(";", interfaceStart);
|
|
10461
|
-
if (semicolon < unionStart) {
|
|
10462
|
-
return { error: "PlatformAdminPageKey \u7ED3\u675F\u951A\u70B9\u7F3A\u5931" };
|
|
10463
|
-
}
|
|
10464
|
-
content = `${content.slice(0, semicolon)}
|
|
10465
|
-
${missingPages.map((page) => ` | "${page}"`).join(`
|
|
10466
|
-
`)}${content.slice(semicolon)}`;
|
|
10390
|
+
const desiredPages = [
|
|
10391
|
+
"ui-components",
|
|
10392
|
+
...target?.includes('routeKey: "system.agent-session"') ? ["agent-session", "agent-workflow"] : []
|
|
10393
|
+
];
|
|
10394
|
+
let content = source;
|
|
10395
|
+
const union = content.slice(unionStart, interfaceStart);
|
|
10396
|
+
const missingPages = desiredPages.filter((page) => !union.includes(`"${page}"`));
|
|
10397
|
+
if (missingPages.length) {
|
|
10398
|
+
const semicolon = content.lastIndexOf(";", interfaceStart);
|
|
10399
|
+
if (semicolon < unionStart) {
|
|
10400
|
+
return { error: "PlatformAdminPageKey \u7ED3\u675F\u951A\u70B9\u7F3A\u5931" };
|
|
10401
|
+
}
|
|
10402
|
+
content = `${content.slice(0, semicolon)}
|
|
10403
|
+
${missingPages.map((page) => ` | "${page}"`).join(`
|
|
10404
|
+
`)}${content.slice(semicolon)}`;
|
|
10405
|
+
}
|
|
10406
|
+
const desiredBindings = [
|
|
10407
|
+
{ routeKey: "system.ui-components", page: "ui-components" },
|
|
10408
|
+
...target?.includes('routeKey: "system.agent-session"') ? [
|
|
10409
|
+
{ routeKey: "system.agent-session", page: "agent-session" },
|
|
10410
|
+
{ routeKey: "system.agent-workflow", page: "agent-workflow" }
|
|
10411
|
+
] : []
|
|
10412
|
+
];
|
|
10413
|
+
const missingBindings = desiredBindings.filter(({ routeKey }) => !content.includes(`routeKey: "${routeKey}"`));
|
|
10414
|
+
if (!missingBindings.length)
|
|
10415
|
+
return { content };
|
|
10416
|
+
const features = [
|
|
10417
|
+
...content.matchAll(/^(\s*)\{ routeKey: "system\.feature", page: "resource", resourceKey: "features" \},$/gm)
|
|
10418
|
+
];
|
|
10419
|
+
if (features.length !== 1) {
|
|
10420
|
+
return { error: "system.feature Admin Route \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10421
|
+
}
|
|
10422
|
+
const feature = features[0];
|
|
10423
|
+
return {
|
|
10424
|
+
content: content.replace(feature[0], [
|
|
10425
|
+
feature[0],
|
|
10426
|
+
...missingBindings.map(({ routeKey, page }) => `${feature[1]}{ routeKey: "${routeKey}", page: "${page}" },`)
|
|
10427
|
+
].join(`
|
|
10428
|
+
`))
|
|
10429
|
+
};
|
|
10430
|
+
}
|
|
10431
|
+
function preserve(input, reason) {
|
|
10432
|
+
return {
|
|
10433
|
+
path: input.path,
|
|
10434
|
+
ownership: "project-owned",
|
|
10435
|
+
action: "preserve",
|
|
10436
|
+
reason,
|
|
10437
|
+
expectedProjectContent: input.expected
|
|
10438
|
+
};
|
|
10439
|
+
}
|
|
10440
|
+
function update(input, content) {
|
|
10441
|
+
return {
|
|
10442
|
+
path: input.path,
|
|
10443
|
+
ownership: "project-owned",
|
|
10444
|
+
action: "update",
|
|
10445
|
+
reason: "\u7248\u672C recipe \u66F4\u65B0\u9879\u76EE\u6269\u5C55\u951A\u70B9",
|
|
10446
|
+
expectedProjectContent: input.expected,
|
|
10447
|
+
content
|
|
10448
|
+
};
|
|
10449
|
+
}
|
|
10450
|
+
function conflict4(input, message) {
|
|
10451
|
+
return {
|
|
10452
|
+
path: input.path,
|
|
10453
|
+
ownership: "project-owned",
|
|
10454
|
+
action: "preserve",
|
|
10455
|
+
reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
|
|
10456
|
+
expectedProjectContent: input.expected,
|
|
10457
|
+
conflict: message
|
|
10458
|
+
};
|
|
10459
|
+
}
|
|
10460
|
+
|
|
10461
|
+
// src/update/dsh-platform-recipe.ts
|
|
10462
|
+
import { join as join22 } from "path";
|
|
10463
|
+
var dshPlatformRecipeId = "dsh-platform-v1";
|
|
10464
|
+
var dshPlatformRecipePaths = new Set([
|
|
10465
|
+
"apps/server/src/app/agent-workflow-presets.ts",
|
|
10466
|
+
"apps/server/src/app/workbench-public-origin.ts",
|
|
10467
|
+
"apps/web/src/router/index.ts",
|
|
10468
|
+
"apps/web/src/router/platform-admin-pages.ts",
|
|
10469
|
+
"apps/web/src/router/platform-admin-route-bindings.ts",
|
|
10470
|
+
"apps/web/src/composables/useLoginFlow.ts",
|
|
10471
|
+
"apps/web/src/pages/system/AgentWorkflowPage.vue",
|
|
10472
|
+
"apps/web/src/services/agent-workflow-api.ts",
|
|
10473
|
+
"apps/web/vite.config.ts",
|
|
10474
|
+
"apps/web/server.ts",
|
|
10475
|
+
"apps/web/runtime-server.ts",
|
|
10476
|
+
"apps/web/dev/start.ts"
|
|
10477
|
+
]);
|
|
10478
|
+
function isDshPlatformRecipePath(path2) {
|
|
10479
|
+
return dshPlatformRecipePaths.has(path2) || path2.startsWith("apps/server/src/app/dsh-") && path2.endsWith(".ts");
|
|
10480
|
+
}
|
|
10481
|
+
async function isDshPlatformTransition(input) {
|
|
10482
|
+
if (!input.sourceModules.includes("system.agent") || !input.targetModules.includes("system.agent"))
|
|
10483
|
+
return false;
|
|
10484
|
+
const path2 = "apps/agent-server/package.json";
|
|
10485
|
+
const [base, target] = await Promise.all([
|
|
10486
|
+
readOptional(join22(input.baseDirectory, path2)),
|
|
10487
|
+
readOptional(join22(input.targetDirectory, path2))
|
|
10488
|
+
]);
|
|
10489
|
+
return hasDsh(target) && !hasDsh(base);
|
|
10490
|
+
}
|
|
10491
|
+
function planDshPlatformFile(input) {
|
|
10492
|
+
const common2 = {
|
|
10493
|
+
path: input.path,
|
|
10494
|
+
ownership: input.ownership,
|
|
10495
|
+
expectedProjectContent: input.expected
|
|
10496
|
+
};
|
|
10497
|
+
if (input.target && input.ours && hashContent(input.ours) === hashContent(input.target)) {
|
|
10498
|
+
return {
|
|
10499
|
+
...common2,
|
|
10500
|
+
action: "preserve",
|
|
10501
|
+
reason: "\u5DF2\u5305\u542B DSH \u5E73\u53F0\u63A5\u7EBF\u76EE\u6807\u5185\u5BB9"
|
|
10502
|
+
};
|
|
10503
|
+
}
|
|
10504
|
+
if (input.target && !input.ours && !input.base) {
|
|
10505
|
+
return {
|
|
10506
|
+
...common2,
|
|
10507
|
+
action: "create",
|
|
10508
|
+
reason: "DSH \u5E73\u53F0\u65B0\u589E\u9879\u76EE\u6269\u5C55\u70B9",
|
|
10509
|
+
content: input.target
|
|
10510
|
+
};
|
|
10511
|
+
}
|
|
10512
|
+
if (input.target && input.base && input.ours && hashContent(input.ours) === hashContent(input.base)) {
|
|
10513
|
+
return {
|
|
10514
|
+
...common2,
|
|
10515
|
+
action: "update",
|
|
10516
|
+
reason: "DSH \u5E73\u53F0\u5347\u7EA7\u7CBE\u786E\u6765\u6E90\u63A5\u7EBF",
|
|
10517
|
+
content: input.target
|
|
10518
|
+
};
|
|
10519
|
+
}
|
|
10520
|
+
return {
|
|
10521
|
+
...common2,
|
|
10522
|
+
action: "preserve",
|
|
10523
|
+
reason: "\u4FDD\u7559\u5BA2\u6237 DSH \u63A5\u7EBF",
|
|
10524
|
+
conflict: "DSH \u5E73\u53F0\u63A5\u7EBF\u4E0E\u7CBE\u786E\u6765\u6E90\u6216\u76EE\u6807\u4E0D\u4E00\u81F4\uFF1B\u8BF7\u5BA1\u6838\u9879\u76EE\u4FEE\u6539\u540E\u663E\u5F0F\u96C6\u6210\uFF0C\u7981\u6B62\u731C\u6D4B\u8986\u76D6"
|
|
10525
|
+
};
|
|
10526
|
+
}
|
|
10527
|
+
function hasDsh(content) {
|
|
10528
|
+
if (!content)
|
|
10529
|
+
return false;
|
|
10530
|
+
const value = JSON.parse(new TextDecoder().decode(content));
|
|
10531
|
+
return typeof value.dependencies?.["@deepseek-ai/dsh"] === "string";
|
|
10532
|
+
}
|
|
10533
|
+
|
|
10534
|
+
// src/update/planner-file.ts
|
|
10535
|
+
async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride, manageGeneratedProjectOwned = false, forcePlatformBaseline = false, manageRecipeProjectOwned = false, migrateDshPlatform = false) {
|
|
10536
|
+
const [base, theirs] = await Promise.all([
|
|
10537
|
+
readOptional2(join23(baseRoot, path2)),
|
|
10538
|
+
targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional2(join23(targetRoot, path2))
|
|
10539
|
+
]);
|
|
10540
|
+
const ownership = source?.ownership ?? target?.ownership ?? classifyOwnership(path2);
|
|
10541
|
+
const expected = expectationForSnapshot(ours);
|
|
10542
|
+
if (migrateDshPlatform && isDshPlatformRecipePath(path2)) {
|
|
10543
|
+
return planDshPlatformFile({
|
|
10544
|
+
path: path2,
|
|
10545
|
+
ownership,
|
|
10546
|
+
ours,
|
|
10547
|
+
base,
|
|
10548
|
+
target: theirs,
|
|
10549
|
+
expected
|
|
10550
|
+
});
|
|
10551
|
+
}
|
|
10552
|
+
if (ownership === "project-owned") {
|
|
10553
|
+
const hasExistingRecipeSource = source !== undefined && source.state !== "missing" && ours !== undefined;
|
|
10554
|
+
if (manageRecipeProjectOwned && target && (hasExistingRecipeSource || source !== undefined && isAdminApiRecipePath(path2) || recipeCanManageMissingProjectOwnedPath(path2))) {
|
|
10555
|
+
return planRecipeProjectOwned({ path: path2, ours, target: theirs, expected });
|
|
10556
|
+
}
|
|
10557
|
+
if (manageGeneratedProjectOwned) {
|
|
10558
|
+
return planGeneratedProjectOwned(path2, source, target, ours, theirs, expected);
|
|
10559
|
+
}
|
|
10560
|
+
return !source && !ours && theirs ? readyPlannedFile(path2, ownership, "create", "\u65B0\u589E\u9879\u76EE\u6269\u5C55\u70B9", expected, theirs) : readyPlannedFile(path2, ownership, "preserve", "\u9ED8\u8BA4\u4FDD\u7559\u9879\u76EE\u7248\u672C", expected);
|
|
10561
|
+
}
|
|
10562
|
+
if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
|
|
10563
|
+
if (source && !target) {
|
|
10564
|
+
return conflict(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
|
|
10565
|
+
}
|
|
10566
|
+
if (source && target && source.hash !== target.hash) {
|
|
10567
|
+
return conflict(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
|
|
10568
|
+
}
|
|
10569
|
+
}
|
|
10570
|
+
if (!source && target) {
|
|
10571
|
+
if (!ours) {
|
|
10572
|
+
return readyPlannedFile(path2, ownership, "create", "\u76EE\u6807\u7248\u672C\u65B0\u589E", expected, theirs);
|
|
10573
|
+
}
|
|
10574
|
+
return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
|
|
10575
|
+
}
|
|
10576
|
+
if (source && !target) {
|
|
10577
|
+
if (!ours) {
|
|
10578
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
|
|
10579
|
+
}
|
|
10580
|
+
return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
|
|
10581
|
+
}
|
|
10582
|
+
if (source && target && !ours) {
|
|
10583
|
+
return readyPlannedFile(path2, "project-owned", "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
|
|
10584
|
+
}
|
|
10585
|
+
if (!source || !target || !ours || !theirs) {
|
|
10586
|
+
return conflict(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
|
|
10587
|
+
}
|
|
10588
|
+
const oursChanged = hashContent(ours) !== source.hash;
|
|
10589
|
+
const sourceArtifactHash = artifactHashOf(source);
|
|
10590
|
+
const targetChanged = targetChangedSinceBase(sourceArtifactHash, base, theirs);
|
|
10591
|
+
const adoptedProjectDelta = source.artifactHash !== undefined && source.artifactHash !== source.hash;
|
|
10592
|
+
const forceTargetBaseline = !adoptedProjectDelta && shouldForcePlatformBaseline({
|
|
10593
|
+
forcePlatformBaseline,
|
|
10594
|
+
oursChanged,
|
|
10595
|
+
sourceArtifactHash,
|
|
10596
|
+
base
|
|
10597
|
+
});
|
|
10598
|
+
if (forceTargetBaseline && path2.endsWith("package.json") && base) {
|
|
10599
|
+
const merged = mergePackageJson(base, ours, theirs);
|
|
10600
|
+
return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
|
|
10601
|
+
}
|
|
10602
|
+
if (forceTargetBaseline) {
|
|
10603
|
+
return readyPlannedFile(path2, ownership, "update", "\u5F3A\u5236\u91C7\u7528\u76EE\u6807\u5E73\u53F0\u57FA\u7EBF", expected, theirs);
|
|
10604
|
+
}
|
|
10605
|
+
if (!oursChanged && !targetChanged) {
|
|
10606
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u53CC\u65B9\u672A\u4FEE\u6539", expected);
|
|
10607
|
+
}
|
|
10608
|
+
if (targetChanged && path2.endsWith("package.json") && base) {
|
|
10609
|
+
const merged = mergePackageJson(base, ours, theirs);
|
|
10610
|
+
return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
|
|
10467
10611
|
}
|
|
10468
|
-
|
|
10469
|
-
|
|
10470
|
-
|
|
10471
|
-
{ routeKey: "system.agent-session", page: "agent-session" },
|
|
10472
|
-
{ routeKey: "system.agent-workflow", page: "agent-workflow" }
|
|
10473
|
-
] : []
|
|
10474
|
-
];
|
|
10475
|
-
const missingBindings = desiredBindings.filter(({ routeKey }) => !content.includes(`routeKey: "${routeKey}"`));
|
|
10476
|
-
if (!missingBindings.length)
|
|
10477
|
-
return { content };
|
|
10478
|
-
const features = [
|
|
10479
|
-
...content.matchAll(/^(\s*)\{ routeKey: "system\.feature", page: "resource", resourceKey: "features" \},$/gm)
|
|
10480
|
-
];
|
|
10481
|
-
if (features.length !== 1) {
|
|
10482
|
-
return { error: "system.feature Admin Route \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10612
|
+
if (!oursChanged && targetChanged && adoptedProjectDelta && base) {
|
|
10613
|
+
const merged = await mergeTextFile(base, ours, theirs);
|
|
10614
|
+
return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
|
|
10483
10615
|
}
|
|
10484
|
-
|
|
10485
|
-
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10616
|
+
if (!oursChanged) {
|
|
10617
|
+
return readyPlannedFile(path2, ownership, "update", "\u4EC5 Windy \u4FEE\u6539", expected, theirs);
|
|
10618
|
+
}
|
|
10619
|
+
if (!targetChanged) {
|
|
10620
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u5BA2\u6237\u5DF2\u4FEE\u6539", expected);
|
|
10621
|
+
}
|
|
10622
|
+
if (hashContent(ours) === target.hash) {
|
|
10623
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected);
|
|
10624
|
+
}
|
|
10625
|
+
if (base) {
|
|
10626
|
+
const merged = await mergeTextFile(base, ours, theirs);
|
|
10627
|
+
return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
|
|
10628
|
+
}
|
|
10629
|
+
return conflict(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
|
|
10492
10630
|
}
|
|
10493
|
-
function
|
|
10494
|
-
return
|
|
10495
|
-
path: input.path,
|
|
10496
|
-
ownership: "project-owned",
|
|
10497
|
-
action: "preserve",
|
|
10498
|
-
reason,
|
|
10499
|
-
expectedProjectContent: input.expected
|
|
10500
|
-
};
|
|
10631
|
+
function shouldForcePlatformBaseline(input) {
|
|
10632
|
+
return input.forcePlatformBaseline && !input.oursChanged && input.base !== undefined && hashContent(input.base) !== input.sourceArtifactHash;
|
|
10501
10633
|
}
|
|
10502
|
-
function
|
|
10503
|
-
return
|
|
10504
|
-
path: input.path,
|
|
10505
|
-
ownership: "project-owned",
|
|
10506
|
-
action: "update",
|
|
10507
|
-
reason: "\u7248\u672C recipe \u66F4\u65B0\u9879\u76EE\u6269\u5C55\u951A\u70B9",
|
|
10508
|
-
expectedProjectContent: input.expected,
|
|
10509
|
-
content
|
|
10510
|
-
};
|
|
10634
|
+
function targetChangedSinceBase(sourceHash, base, target) {
|
|
10635
|
+
return base && target ? hashContent(base) !== hashContent(target) : !!target && hashContent(target) !== sourceHash;
|
|
10511
10636
|
}
|
|
10512
|
-
function
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
}
|
|
10637
|
+
async function readOptional2(path2) {
|
|
10638
|
+
try {
|
|
10639
|
+
return await readFile16(path2);
|
|
10640
|
+
} catch (error) {
|
|
10641
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
10642
|
+
return;
|
|
10643
|
+
}
|
|
10644
|
+
throw error;
|
|
10645
|
+
}
|
|
10521
10646
|
}
|
|
10522
10647
|
|
|
10523
|
-
// src/update/dsh-platform-recipe.ts
|
|
10524
|
-
import { join as join26 } from "path";
|
|
10525
|
-
|
|
10526
10648
|
// src/update/planner-snapshots.ts
|
|
10527
|
-
import { readFile as readFile20, stat as stat2 } from "fs/promises";
|
|
10528
|
-
import { join as join25 } from "path";
|
|
10529
10649
|
async function snapshotProjectFiles(project, paths, seed) {
|
|
10530
10650
|
const snapshots = new Map(seed);
|
|
10531
10651
|
await Promise.all([...paths].filter((path2) => !snapshots.has(path2)).map(async (path2) => {
|
|
10532
|
-
snapshots.set(path2, await readOptional(
|
|
10652
|
+
snapshots.set(path2, await readOptional(join24(project, path2)));
|
|
10533
10653
|
}));
|
|
10534
10654
|
return snapshots;
|
|
10535
10655
|
}
|
|
10536
10656
|
async function snapshotProjectModes(project, paths) {
|
|
10537
|
-
return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(
|
|
10657
|
+
return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(join24(project, path2))])));
|
|
10538
10658
|
}
|
|
10539
10659
|
async function assertPlanSnapshots(project, expectations) {
|
|
10540
10660
|
const changed = [];
|
|
10541
10661
|
for (const expectation2 of expectations) {
|
|
10542
|
-
const actual = expectationForSnapshot(await readOptional(
|
|
10662
|
+
const actual = expectationForSnapshot(await readOptional(join24(project, expectation2.path)));
|
|
10543
10663
|
if (JSON.stringify(actual) !== JSON.stringify(expectation2.expected)) {
|
|
10544
10664
|
changed.push(expectation2.path);
|
|
10545
10665
|
continue;
|
|
10546
10666
|
}
|
|
10547
|
-
if ("mode" in expectation2 && await readModeOptional(
|
|
10667
|
+
if ("mode" in expectation2 && await readModeOptional(join24(project, expectation2.path)) !== expectation2.mode) {
|
|
10548
10668
|
changed.push(expectation2.path);
|
|
10549
10669
|
}
|
|
10550
10670
|
}
|
|
@@ -10552,226 +10672,642 @@ async function assertPlanSnapshots(project, expectations) {
|
|
|
10552
10672
|
throw new Error(`\u751F\u6210\u66F4\u65B0\u8BA1\u5212\u671F\u95F4\u5019\u9009\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${changed.join("\u3001")}`);
|
|
10553
10673
|
}
|
|
10554
10674
|
}
|
|
10555
|
-
async function readModeOptional(path2) {
|
|
10675
|
+
async function readModeOptional(path2) {
|
|
10676
|
+
try {
|
|
10677
|
+
return (await stat2(path2)).mode & 511;
|
|
10678
|
+
} catch (error) {
|
|
10679
|
+
if (isMissing7(error))
|
|
10680
|
+
return;
|
|
10681
|
+
throw error;
|
|
10682
|
+
}
|
|
10683
|
+
}
|
|
10684
|
+
async function readSourceParentMode(path2) {
|
|
10685
|
+
try {
|
|
10686
|
+
const info = await stat2(path2);
|
|
10687
|
+
if (!info.isDirectory()) {
|
|
10688
|
+
throw new Error(`artifact \u6E90\u7801\u7236\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${path2}`);
|
|
10689
|
+
}
|
|
10690
|
+
return info.mode & 493 | 493;
|
|
10691
|
+
} catch (error) {
|
|
10692
|
+
if (isMissing7(error))
|
|
10693
|
+
return 493;
|
|
10694
|
+
throw error;
|
|
10695
|
+
}
|
|
10696
|
+
}
|
|
10697
|
+
async function readOptional(path2) {
|
|
10698
|
+
try {
|
|
10699
|
+
return await readFile17(path2);
|
|
10700
|
+
} catch (error) {
|
|
10701
|
+
if (isMissing7(error))
|
|
10702
|
+
return;
|
|
10703
|
+
throw error;
|
|
10704
|
+
}
|
|
10705
|
+
}
|
|
10706
|
+
function isMissing7(error) {
|
|
10707
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
10708
|
+
}
|
|
10709
|
+
|
|
10710
|
+
// src/update/admin-settings-yaml-plan.ts
|
|
10711
|
+
var transferPath = "apps/web/src/pages/settings/WatermarkYamlTransfer.vue";
|
|
10712
|
+
var settingsPaths = [
|
|
10713
|
+
"apps/web/src/composables/useWatermarkSettings.ts",
|
|
10714
|
+
"apps/web/src/pages/settings/GlobalSettingsPage.vue",
|
|
10715
|
+
"apps/web/src/pages/settings/WatermarkSettingsSection.vue",
|
|
10716
|
+
"apps/web/src/pages/settings/BrandingSettingsSection.vue"
|
|
10717
|
+
];
|
|
10718
|
+
async function reconcileAdminSettingsYamlPlan(input) {
|
|
10719
|
+
if (input.sourceEntries.has(transferPath) || !input.targetEntries.has(transferPath))
|
|
10720
|
+
return;
|
|
10721
|
+
for (const path2 of settingsPaths) {
|
|
10722
|
+
const plan = input.files.find((file) => file.path === path2);
|
|
10723
|
+
if (!plan || !input.sourceEntries.has(path2))
|
|
10724
|
+
continue;
|
|
10725
|
+
const [base, target] = await Promise.all([
|
|
10726
|
+
readOptional(join25(input.baseDirectory, path2)),
|
|
10727
|
+
readOptional(join25(input.targetDirectory, path2))
|
|
10728
|
+
]);
|
|
10729
|
+
const current = input.projectSnapshots.get(path2);
|
|
10730
|
+
if (current && target && hashContent(current) === hashContent(target))
|
|
10731
|
+
continue;
|
|
10732
|
+
if (!base || !current || !target || hashContent(base) !== hashContent(current)) {
|
|
10733
|
+
plan.conflict = "\u5168\u5C40\u8BBE\u7F6E YAML \u8FC1\u79FB\u9700\u8981\u5408\u5E76\u5DF2\u81EA\u5B9A\u4E49\u7684\u9879\u76EE\u6587\u4EF6";
|
|
10734
|
+
continue;
|
|
10735
|
+
}
|
|
10736
|
+
plan.action = "update";
|
|
10737
|
+
plan.reason = "\u8865\u9F50\u5168\u5C40\u8BBE\u7F6E YAML \u7684\u914D\u5957\u9875\u9762\u4E0E API";
|
|
10738
|
+
plan.content = target;
|
|
10739
|
+
delete plan.conflict;
|
|
10740
|
+
}
|
|
10741
|
+
}
|
|
10742
|
+
|
|
10743
|
+
// src/update/environment-mount-plan.ts
|
|
10744
|
+
var environmentProfile = "windy.environment.yaml";
|
|
10745
|
+
var generatedMount = "./windy.environment.yaml:/app/windy.environment.yaml:ro";
|
|
10746
|
+
function validateEnvironmentMountPlan(files, currentProfile) {
|
|
10747
|
+
const compose = files.find(({ path: path2 }) => path2 === "docker-compose.yml");
|
|
10748
|
+
if (!compose?.content || compose.action !== "create" && compose.action !== "update" || compose.conflict || !new TextDecoder().decode(compose.content).includes(generatedMount))
|
|
10749
|
+
return;
|
|
10750
|
+
const profile = files.find(({ path: path2 }) => path2 === environmentProfile);
|
|
10751
|
+
const available = profile?.action === "create" || profile?.action === "update" ? profile.content !== undefined : profile?.action !== "delete" && currentProfile !== undefined;
|
|
10752
|
+
if (available)
|
|
10753
|
+
return;
|
|
10754
|
+
compose.action = "preserve";
|
|
10755
|
+
delete compose.content;
|
|
10756
|
+
compose.conflict = "\u76EE\u6807 Compose \u9700\u8981\u6302\u8F7D windy.environment.yaml\uFF0C\u8BF7\u5148\u6062\u590D\u9879\u76EE\u7684\u73AF\u5883\u914D\u7F6E\u6587\u4EF6";
|
|
10757
|
+
}
|
|
10758
|
+
|
|
10759
|
+
// src/update/media-runtime-registry.ts
|
|
10760
|
+
function reconcileMediaRuntimeRegistry(files, current, sourceModules, targetModules) {
|
|
10761
|
+
if (!current || !sourceModules.includes("system.agent") || sourceModules.includes("system.media-runtime") || !targetModules.includes("system.media-runtime"))
|
|
10762
|
+
return;
|
|
10763
|
+
const file = files.find(({ path: path2 }) => path2 === projectModuleRegistryPath);
|
|
10764
|
+
if (!file)
|
|
10765
|
+
throw new Error("\u5A92\u4F53\u8FD0\u884C\u65F6\u8FC1\u79FB\u7F3A\u5C11\u9879\u76EE\u6A21\u5757\u88C5\u914D\u6E05\u5355");
|
|
10766
|
+
const registry = parseProjectModuleRegistry(current);
|
|
10767
|
+
if (registry.modules.some(({ name }) => name === "system.media-runtime"))
|
|
10768
|
+
return;
|
|
10769
|
+
if (!registry.modules.find(({ name }) => name === "system.agent")?.enabled) {
|
|
10770
|
+
file.conflict = "\u65E7 Agent \u88C5\u914D\u5DF2\u505C\u7528\u6216\u7F3A\u5931\uFF0C\u8BF7\u5148\u660E\u786E\u5A92\u4F53\u8FD0\u884C\u65F6\u7684\u4EA4\u4ED8\u8303\u56F4";
|
|
10771
|
+
return;
|
|
10772
|
+
}
|
|
10773
|
+
const orders = new Set(registry.modules.map(({ order: order2 }) => order2));
|
|
10774
|
+
const lastOrder = Math.max(0, ...orders);
|
|
10775
|
+
let order = lastOrder + 100;
|
|
10776
|
+
if (!Number.isSafeInteger(order)) {
|
|
10777
|
+
order = 0;
|
|
10778
|
+
while (orders.has(order))
|
|
10779
|
+
order += 1;
|
|
10780
|
+
}
|
|
10781
|
+
registry.modules.push({
|
|
10782
|
+
name: "system.media-runtime",
|
|
10783
|
+
package: null,
|
|
10784
|
+
enabled: true,
|
|
10785
|
+
order,
|
|
10786
|
+
admin: { visible: true },
|
|
10787
|
+
config: {}
|
|
10788
|
+
});
|
|
10789
|
+
file.action = "update";
|
|
10790
|
+
file.reason = "\u6CE8\u518C\u65E7 Agent \u4EA4\u4ED8\u4E2D\u5DF2\u6709\u7684\u5A92\u4F53\u8FD0\u884C\u65F6";
|
|
10791
|
+
file.content = new TextEncoder().encode(`${JSON.stringify(registry, null, 2)}
|
|
10792
|
+
`);
|
|
10793
|
+
delete file.conflict;
|
|
10794
|
+
}
|
|
10795
|
+
|
|
10796
|
+
// src/update/planner.ts
|
|
10797
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
10798
|
+
import { dirname as dirname9, join as join30 } from "path";
|
|
10799
|
+
|
|
10800
|
+
// src/update/docker-copy-update-plan.ts
|
|
10801
|
+
async function deriveDockerfilePlans(files, snapshots, paths, targetWorkspaceManifests) {
|
|
10802
|
+
const rootPackage = virtualPathContent("package.json", files, snapshots, targetWorkspaceManifests);
|
|
10803
|
+
if (!rootPackage)
|
|
10804
|
+
return;
|
|
10805
|
+
const rootManifest = parsePackage(rootPackage, "package.json");
|
|
10806
|
+
const workspacePatterns = rootManifest.workspaces ?? [];
|
|
10807
|
+
const packages = [];
|
|
10808
|
+
for (const path2 of [
|
|
10809
|
+
...new Set([...paths, ...targetWorkspaceManifests.keys()])
|
|
10810
|
+
].filter((path3) => path3.endsWith("package.json"))) {
|
|
10811
|
+
const directory = path2 === "package.json" ? "." : path2.slice(0, -13);
|
|
10812
|
+
if (directory === ".")
|
|
10813
|
+
continue;
|
|
10814
|
+
if (!workspacePatterns.some((pattern) => matchesWorkspace(pattern, directory))) {
|
|
10815
|
+
continue;
|
|
10816
|
+
}
|
|
10817
|
+
const content = virtualPathContent(path2, files, snapshots, targetWorkspaceManifests);
|
|
10818
|
+
if (!content)
|
|
10819
|
+
continue;
|
|
10820
|
+
const manifest = parsePackage(content, path2);
|
|
10821
|
+
packages.push({
|
|
10822
|
+
name: manifest.name,
|
|
10823
|
+
directory,
|
|
10824
|
+
dependencies: [
|
|
10825
|
+
...Object.keys(manifest.dependencies ?? {}),
|
|
10826
|
+
...Object.keys(manifest.devDependencies ?? {})
|
|
10827
|
+
],
|
|
10828
|
+
workspaceDependencies: Object.entries({
|
|
10829
|
+
...manifest.dependencies,
|
|
10830
|
+
...manifest.devDependencies
|
|
10831
|
+
}).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name)
|
|
10832
|
+
});
|
|
10833
|
+
}
|
|
10834
|
+
packages.sort((left, right) => left.directory.localeCompare(right.directory));
|
|
10835
|
+
for (const target of dockerfileCopyTargets) {
|
|
10836
|
+
const dockerPlan = files.find(({ path: path2 }) => path2 === target.dockerfilePath);
|
|
10837
|
+
if (!dockerPlan || dockerPlan.conflict)
|
|
10838
|
+
continue;
|
|
10839
|
+
const dockerSource = virtualContent(dockerPlan, snapshots);
|
|
10840
|
+
if (!dockerSource)
|
|
10841
|
+
continue;
|
|
10842
|
+
const source = new TextDecoder().decode(dockerSource);
|
|
10843
|
+
if (!hasDockerfileCopyAnchors(source, target)) {
|
|
10844
|
+
dockerPlan.conflict = "Dockerfile \u7F3A\u5C11 0.6.6 \u57FA\u7EBF\u7684 COPY \u951A\u70B9\uFF0C\u5DF2\u505C\u6B62\u81EA\u52A8\u8FC1\u79FB\u65E7\u683C\u5F0F";
|
|
10845
|
+
continue;
|
|
10846
|
+
}
|
|
10847
|
+
let next;
|
|
10848
|
+
try {
|
|
10849
|
+
next = syncDockerfileSource(source, target, packages);
|
|
10850
|
+
} catch (error) {
|
|
10851
|
+
dockerPlan.conflict = error instanceof Error ? error.message : "Docker COPY \u951A\u70B9\u65E0\u6548";
|
|
10852
|
+
continue;
|
|
10853
|
+
}
|
|
10854
|
+
if (next === source)
|
|
10855
|
+
continue;
|
|
10856
|
+
dockerPlan.action = "update";
|
|
10857
|
+
dockerPlan.reason = "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355";
|
|
10858
|
+
dockerPlan.content = new TextEncoder().encode(next);
|
|
10859
|
+
}
|
|
10860
|
+
}
|
|
10861
|
+
function virtualPathContent(path2, files, snapshots, targetWorkspaceManifests) {
|
|
10862
|
+
const plan = files.find((item) => item.path === path2);
|
|
10863
|
+
return plan ? virtualContent(plan, snapshots) : snapshots.get(path2) ?? targetWorkspaceManifests.get(path2);
|
|
10864
|
+
}
|
|
10865
|
+
function virtualContent(plan, snapshots) {
|
|
10866
|
+
if (plan.action === "delete")
|
|
10867
|
+
return;
|
|
10868
|
+
if (plan.action === "create" || plan.action === "update")
|
|
10869
|
+
return plan.content;
|
|
10870
|
+
return snapshots.get(plan.path);
|
|
10871
|
+
}
|
|
10872
|
+
function parsePackage(content, path2) {
|
|
10873
|
+
try {
|
|
10874
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
10875
|
+
} catch (error) {
|
|
10876
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790 Docker workspace \u8F93\u5165\uFF1A${path2}`, {
|
|
10877
|
+
cause: error
|
|
10878
|
+
});
|
|
10879
|
+
}
|
|
10880
|
+
}
|
|
10881
|
+
function matchesWorkspace(pattern, directory) {
|
|
10882
|
+
return pattern.endsWith("/*") && directory.startsWith(pattern.slice(0, -1));
|
|
10883
|
+
}
|
|
10884
|
+
|
|
10885
|
+
// src/update/migration-reconciler.ts
|
|
10886
|
+
import { readFile as readFile21 } from "fs/promises";
|
|
10887
|
+
import { join as join28 } from "path";
|
|
10888
|
+
|
|
10889
|
+
// src/update/migration-adoption.ts
|
|
10890
|
+
import { readFile as readFile20 } from "fs/promises";
|
|
10891
|
+
import { join as join27 } from "path";
|
|
10892
|
+
|
|
10893
|
+
// src/update/migration-project-file.ts
|
|
10894
|
+
import { readFile as readFile18 } from "fs/promises";
|
|
10895
|
+
import { join as join26 } from "path";
|
|
10896
|
+
async function readProjectJson(input, path2) {
|
|
10897
|
+
const content = await readProjectFile(input, path2);
|
|
10898
|
+
if (!content) {
|
|
10899
|
+
const error = new Error(`\u5F53\u524D\u9879\u76EE\u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
10900
|
+
error.code = "ENOENT";
|
|
10901
|
+
throw error;
|
|
10902
|
+
}
|
|
10903
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
10904
|
+
}
|
|
10905
|
+
async function readProjectFile(input, path2) {
|
|
10906
|
+
if (input.projectSnapshots?.has(path2)) {
|
|
10907
|
+
return input.projectSnapshots.get(path2);
|
|
10908
|
+
}
|
|
10909
|
+
let content;
|
|
10556
10910
|
try {
|
|
10557
|
-
|
|
10911
|
+
content = await readFile18(join26(input.projectDirectory, path2));
|
|
10558
10912
|
} catch (error) {
|
|
10559
|
-
if (
|
|
10560
|
-
|
|
10561
|
-
|
|
10913
|
+
if (!isMissingFileError(error))
|
|
10914
|
+
throw error;
|
|
10915
|
+
}
|
|
10916
|
+
if (input.projectSnapshots) {
|
|
10917
|
+
input.projectSnapshots.set(path2, content);
|
|
10562
10918
|
}
|
|
10919
|
+
return content;
|
|
10563
10920
|
}
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
|
|
10921
|
+
function isMissingFileError(error) {
|
|
10922
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
10923
|
+
}
|
|
10924
|
+
|
|
10925
|
+
// src/update/migration-history.ts
|
|
10926
|
+
import { readFile as readFile19 } from "fs/promises";
|
|
10927
|
+
var drizzleRoot = "packages/database/drizzle";
|
|
10928
|
+
var journalPath = `${drizzleRoot}/meta/_journal.json`;
|
|
10929
|
+
var migrationPattern = /^(\d{4})_(.+)$/;
|
|
10930
|
+
function snapshotPath(tag) {
|
|
10931
|
+
const match = migrationPattern.exec(tag);
|
|
10932
|
+
if (!match) {
|
|
10933
|
+
throw new Error(`${journalPath}\uFF1Amigration tag \u683C\u5F0F\u65E0\u6548\uFF1A${tag}`);
|
|
10575
10934
|
}
|
|
10935
|
+
return `${drizzleRoot}/meta/${match[1]}_snapshot.json`;
|
|
10576
10936
|
}
|
|
10577
|
-
|
|
10578
|
-
|
|
10579
|
-
|
|
10580
|
-
|
|
10581
|
-
if (
|
|
10582
|
-
|
|
10583
|
-
|
|
10937
|
+
function validateUniqueNames(journal, label, conflicts) {
|
|
10938
|
+
const seen = new Set;
|
|
10939
|
+
for (const { tag } of journal.entries) {
|
|
10940
|
+
const name = stableName(tag);
|
|
10941
|
+
if (seen.has(name)) {
|
|
10942
|
+
conflicts.push(`${journalPath}\uFF1A${label}\u5B58\u5728\u91CD\u590D migration \u540D\u79F0 ${name}`);
|
|
10943
|
+
}
|
|
10944
|
+
seen.add(name);
|
|
10584
10945
|
}
|
|
10585
10946
|
}
|
|
10586
|
-
function
|
|
10587
|
-
return
|
|
10947
|
+
function stableName(tag) {
|
|
10948
|
+
return migrationPattern.exec(tag)?.[2] ?? tag;
|
|
10949
|
+
}
|
|
10950
|
+
function highestPrefix(journal) {
|
|
10951
|
+
return Math.max(-1, ...journal.entries.map(({ tag }) => Number(migrationPattern.exec(tag)?.[1] ?? -1)));
|
|
10952
|
+
}
|
|
10953
|
+
function highestIndex(journal) {
|
|
10954
|
+
return Math.max(-1, ...journal.entries.map(({ idx }) => idx));
|
|
10955
|
+
}
|
|
10956
|
+
function isDrizzleHistoryPath(path2) {
|
|
10957
|
+
return path2 === journalPath || isMigrationArtifact(path2);
|
|
10958
|
+
}
|
|
10959
|
+
function isMigrationArtifact(path2) {
|
|
10960
|
+
return isSqlMigration(path2) || new RegExp(`^${drizzleRoot}/meta/\\d{4}_snapshot\\.json$`).test(path2);
|
|
10961
|
+
}
|
|
10962
|
+
function isSqlMigration(path2) {
|
|
10963
|
+
return new RegExp(`^${drizzleRoot}/\\d{4}_.+\\.sql$`).test(path2);
|
|
10964
|
+
}
|
|
10965
|
+
function managedEntry(path2, content) {
|
|
10966
|
+
return { path: path2, ownership: "windy-managed", hash: hashContent(content) };
|
|
10967
|
+
}
|
|
10968
|
+
function deduplicate(files) {
|
|
10969
|
+
return [...new Map(files.map((entry) => [entry.path, entry])).values()];
|
|
10970
|
+
}
|
|
10971
|
+
function encodeJson(value) {
|
|
10972
|
+
return new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
|
|
10973
|
+
`);
|
|
10974
|
+
}
|
|
10975
|
+
async function readJson(path2) {
|
|
10976
|
+
return JSON.parse(await readFile19(path2, "utf8"));
|
|
10588
10977
|
}
|
|
10589
10978
|
|
|
10590
|
-
// src/update/
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
"apps/server/src/app/agent-workflow-presets.ts",
|
|
10594
|
-
"apps/server/src/app/workbench-public-origin.ts",
|
|
10595
|
-
"apps/web/src/router/index.ts",
|
|
10596
|
-
"apps/web/src/router/platform-admin-pages.ts",
|
|
10597
|
-
"apps/web/src/router/platform-admin-route-bindings.ts",
|
|
10598
|
-
"apps/web/src/composables/useLoginFlow.ts",
|
|
10599
|
-
"apps/web/src/pages/system/AgentWorkflowPage.vue",
|
|
10600
|
-
"apps/web/src/services/agent-workflow-api.ts",
|
|
10601
|
-
"apps/web/vite.config.ts",
|
|
10602
|
-
"apps/web/server.ts",
|
|
10603
|
-
"apps/web/runtime-server.ts",
|
|
10604
|
-
"apps/web/dev/start.ts"
|
|
10605
|
-
]);
|
|
10606
|
-
function isDshPlatformRecipePath(path2) {
|
|
10607
|
-
return dshPlatformRecipePaths.has(path2) || path2.startsWith("apps/server/src/app/dsh-") && path2.endsWith(".ts");
|
|
10979
|
+
// src/update/migration-snapshot.ts
|
|
10980
|
+
function canonicalSnapshot(value) {
|
|
10981
|
+
return JSON.stringify(canonicalize(value, true));
|
|
10608
10982
|
}
|
|
10609
|
-
|
|
10610
|
-
if (
|
|
10611
|
-
return
|
|
10612
|
-
|
|
10613
|
-
|
|
10614
|
-
|
|
10615
|
-
readOptional(join26(input.targetDirectory, path2))
|
|
10616
|
-
]);
|
|
10617
|
-
return hasDsh(target) && !hasDsh(base);
|
|
10983
|
+
function canonicalize(value, root = false) {
|
|
10984
|
+
if (Array.isArray(value))
|
|
10985
|
+
return value.map((item) => canonicalize(item));
|
|
10986
|
+
if (!value || typeof value !== "object")
|
|
10987
|
+
return value;
|
|
10988
|
+
return Object.fromEntries(Object.entries(value).filter(([key]) => !root || key !== "id" && key !== "prevId").sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, canonicalize(item)]));
|
|
10618
10989
|
}
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10641
|
-
|
|
10642
|
-
...common2,
|
|
10643
|
-
action: "update",
|
|
10644
|
-
reason: "DSH \u5E73\u53F0\u5347\u7EA7\u7CBE\u786E\u6765\u6E90\u63A5\u7EBF",
|
|
10645
|
-
content: input.target
|
|
10646
|
-
};
|
|
10647
|
-
}
|
|
10648
|
-
return {
|
|
10649
|
-
...common2,
|
|
10650
|
-
action: "preserve",
|
|
10651
|
-
reason: "\u4FDD\u7559\u5BA2\u6237 DSH \u63A5\u7EBF",
|
|
10652
|
-
conflict: "DSH \u5E73\u53F0\u63A5\u7EBF\u4E0E\u7CBE\u786E\u6765\u6E90\u6216\u76EE\u6807\u4E0D\u4E00\u81F4\uFF1B\u8BF7\u5BA1\u6838\u9879\u76EE\u4FEE\u6539\u540E\u663E\u5F0F\u96C6\u6210\uFF0C\u7981\u6B62\u731C\u6D4B\u8986\u76D6"
|
|
10653
|
-
};
|
|
10990
|
+
|
|
10991
|
+
// src/update/migration-adoption-equivalence.ts
|
|
10992
|
+
var migrationName = "durable_job_lease_snapshot_lookup";
|
|
10993
|
+
var tableKey = "public.durable_job_leases";
|
|
10994
|
+
var indexName = "idx_durable_job_leases_job_acquired";
|
|
10995
|
+
var targetSql = 'CREATE INDEX "idx_durable_job_leases_job_acquired" ON "durable_job_leases" USING btree ("job_id","acquired_at");';
|
|
10996
|
+
var projectSql = `CREATE INDEX IF NOT EXISTS "idx_durable_job_leases_job_acquired" ON "durable_job_leases" USING btree ("job_id","acquired_at");
|
|
10997
|
+
`;
|
|
10998
|
+
var indexDefinition = {
|
|
10999
|
+
name: indexName,
|
|
11000
|
+
columns: ["job_id", "acquired_at"].map((expression) => ({
|
|
11001
|
+
expression,
|
|
11002
|
+
isExpression: false,
|
|
11003
|
+
asc: true,
|
|
11004
|
+
nulls: "last"
|
|
11005
|
+
})),
|
|
11006
|
+
isUnique: false,
|
|
11007
|
+
concurrently: false,
|
|
11008
|
+
method: "btree",
|
|
11009
|
+
with: {}
|
|
11010
|
+
};
|
|
11011
|
+
function isReviewedMigrationEquivalent(input) {
|
|
11012
|
+
return input.name === migrationName && hashContent(input.targetSql) === hashContent(targetSql) && hashContent(input.projectSql) === hashContent(projectSql) && isExactIndexAddition(input.targetBefore, input.targetAfter) && isExactIndexAddition(input.projectBefore, input.projectAfter);
|
|
10654
11013
|
}
|
|
10655
|
-
function
|
|
10656
|
-
if (
|
|
11014
|
+
function isExactIndexAddition(before, after) {
|
|
11015
|
+
if (before.version !== "7" || after.version !== "7" || before.dialect !== "postgresql" || after.dialect !== "postgresql")
|
|
10657
11016
|
return false;
|
|
10658
|
-
const
|
|
10659
|
-
|
|
11017
|
+
const expected = structuredClone(before);
|
|
11018
|
+
if (!isRecord(expected.tables))
|
|
11019
|
+
return false;
|
|
11020
|
+
const table = expected.tables[tableKey];
|
|
11021
|
+
if (!isRecord(table) || table.name !== "durable_job_leases" || !isRecord(table.indexes))
|
|
11022
|
+
return false;
|
|
11023
|
+
if (Object.hasOwn(table.indexes, indexName))
|
|
11024
|
+
return false;
|
|
11025
|
+
table.indexes[indexName] = indexDefinition;
|
|
11026
|
+
return canonicalSnapshot(expected) === canonicalSnapshot(after);
|
|
11027
|
+
}
|
|
11028
|
+
function isRecord(value) {
|
|
11029
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
10660
11030
|
}
|
|
10661
11031
|
|
|
10662
|
-
// src/update/
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
return
|
|
10672
|
-
path: path2,
|
|
10673
|
-
ownership,
|
|
10674
|
-
ours,
|
|
10675
|
-
base,
|
|
10676
|
-
target: theirs,
|
|
10677
|
-
expected
|
|
10678
|
-
});
|
|
11032
|
+
// src/update/snapshot-delta.ts
|
|
11033
|
+
function applySnapshotDelta(before, after, current, path2, conflicts, conflictPath) {
|
|
11034
|
+
if (deepEqual(before, after))
|
|
11035
|
+
return structuredClone(current);
|
|
11036
|
+
if (!isRecord2(before) || !isRecord2(after) || !isRecord2(current)) {
|
|
11037
|
+
if (deepEqual(current, before) || deepEqual(current, after)) {
|
|
11038
|
+
return structuredClone(after);
|
|
11039
|
+
}
|
|
11040
|
+
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u4E0E\u4E1A\u52A1\u540C\u65F6\u4FEE\u6539 snapshot \u8282\u70B9 ${path2.join(".") || "<root>"}`);
|
|
11041
|
+
return structuredClone(current);
|
|
10679
11042
|
}
|
|
10680
|
-
|
|
10681
|
-
|
|
10682
|
-
|
|
10683
|
-
|
|
11043
|
+
const merged = structuredClone(current);
|
|
11044
|
+
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
11045
|
+
for (const key of keys) {
|
|
11046
|
+
if (path2.length === 0 && (key === "id" || key === "prevId"))
|
|
11047
|
+
continue;
|
|
11048
|
+
const nextPath = [...path2, key];
|
|
11049
|
+
if (!(key in after)) {
|
|
11050
|
+
if (!(key in current))
|
|
11051
|
+
continue;
|
|
11052
|
+
if (deepEqual(current[key], before[key]))
|
|
11053
|
+
delete merged[key];
|
|
11054
|
+
else
|
|
11055
|
+
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u5220\u9664\u4E86\u4E1A\u52A1\u5DF2\u4FEE\u6539\u7684 snapshot \u8282\u70B9 ${nextPath.join(".")}`);
|
|
11056
|
+
continue;
|
|
10684
11057
|
}
|
|
10685
|
-
if (
|
|
10686
|
-
|
|
11058
|
+
if (!(key in before)) {
|
|
11059
|
+
if (!(key in current) || deepEqual(current[key], after[key])) {
|
|
11060
|
+
merged[key] = structuredClone(after[key]);
|
|
11061
|
+
} else {
|
|
11062
|
+
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u65B0\u589E\u7684 snapshot \u8282\u70B9\u5DF2\u88AB\u4E1A\u52A1\u5360\u7528 ${nextPath.join(".")}`);
|
|
11063
|
+
}
|
|
11064
|
+
continue;
|
|
10687
11065
|
}
|
|
10688
|
-
|
|
11066
|
+
merged[key] = applySnapshotDelta(before[key], after[key], current[key], nextPath, conflicts, conflictPath);
|
|
10689
11067
|
}
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
11068
|
+
return merged;
|
|
11069
|
+
}
|
|
11070
|
+
function isRecord2(value) {
|
|
11071
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
11072
|
+
}
|
|
11073
|
+
function deepEqual(left, right) {
|
|
11074
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
11075
|
+
}
|
|
11076
|
+
|
|
11077
|
+
// src/update/migration-adoption.ts
|
|
11078
|
+
async function inspectPreexistingMigrationAdoptions(input) {
|
|
11079
|
+
const conflicts = [];
|
|
11080
|
+
const adoptions = [];
|
|
11081
|
+
const projectByName = new Map(input.project.entries.map((entry) => [stableName(entry.tag), entry]));
|
|
11082
|
+
for (const candidate of input.candidates) {
|
|
11083
|
+
const name = stableName(candidate.tag);
|
|
11084
|
+
const projectEntry = projectByName.get(name);
|
|
11085
|
+
if (!projectEntry || input.managedNames.has(name))
|
|
11086
|
+
continue;
|
|
11087
|
+
const targetPosition = input.target.entries.indexOf(candidate);
|
|
11088
|
+
const projectPosition = input.project.entries.indexOf(projectEntry);
|
|
11089
|
+
const previousTarget = input.target.entries[targetPosition - 1];
|
|
11090
|
+
const previousProject = input.project.entries[projectPosition - 1];
|
|
11091
|
+
if (!previousTarget || !previousProject) {
|
|
11092
|
+
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C\u7F3A\u5C11\u524D\u7F6E\u5386\u53F2`);
|
|
11093
|
+
continue;
|
|
10696
11094
|
}
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
11095
|
+
const projectSqlPath = `${drizzleRoot}/${projectEntry.tag}.sql`;
|
|
11096
|
+
const projectSnapshotPath = snapshotPath(projectEntry.tag);
|
|
11097
|
+
const [
|
|
11098
|
+
targetSql2,
|
|
11099
|
+
projectSql2,
|
|
11100
|
+
targetBefore,
|
|
11101
|
+
targetAfter,
|
|
11102
|
+
projectBeforeBytes,
|
|
11103
|
+
projectAfterBytes
|
|
11104
|
+
] = await Promise.all([
|
|
11105
|
+
readFile20(join27(input.targetDirectory, `${drizzleRoot}/${candidate.tag}.sql`)),
|
|
11106
|
+
readProjectFile(input, projectSqlPath),
|
|
11107
|
+
readJson(join27(input.targetDirectory, snapshotPath(previousTarget.tag))),
|
|
11108
|
+
readJson(join27(input.targetDirectory, snapshotPath(candidate.tag))),
|
|
11109
|
+
readProjectFile(input, snapshotPath(previousProject.tag)),
|
|
11110
|
+
readProjectFile(input, projectSnapshotPath)
|
|
11111
|
+
]);
|
|
11112
|
+
if (!projectSql2 || !projectBeforeBytes || !projectAfterBytes) {
|
|
11113
|
+
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C\u9879\u76EE migration \u6587\u4EF6\u4E0D\u5B8C\u6574`);
|
|
11114
|
+
continue;
|
|
10701
11115
|
}
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
11116
|
+
const projectBefore = decodeSnapshot(projectBeforeBytes);
|
|
11117
|
+
const projectAfter = decodeSnapshot(projectAfterBytes);
|
|
11118
|
+
const reason = validateAdoption({
|
|
11119
|
+
name,
|
|
11120
|
+
targetSql: targetSql2,
|
|
11121
|
+
projectSql: projectSql2,
|
|
11122
|
+
targetBefore,
|
|
11123
|
+
targetAfter,
|
|
11124
|
+
projectBefore,
|
|
11125
|
+
projectAfter
|
|
11126
|
+
});
|
|
11127
|
+
if (reason) {
|
|
11128
|
+
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C${reason}`);
|
|
11129
|
+
continue;
|
|
10707
11130
|
}
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
return conflict(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
|
|
11131
|
+
adoptions.push({
|
|
11132
|
+
sqlPath: projectSqlPath,
|
|
11133
|
+
snapshotPath: projectSnapshotPath,
|
|
11134
|
+
sql: projectSql2,
|
|
11135
|
+
snapshot: projectAfterBytes
|
|
11136
|
+
});
|
|
10715
11137
|
}
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
forcePlatformBaseline,
|
|
10722
|
-
oursChanged,
|
|
10723
|
-
sourceArtifactHash,
|
|
10724
|
-
base
|
|
10725
|
-
});
|
|
10726
|
-
if (forceTargetBaseline && path2.endsWith("package.json") && base) {
|
|
10727
|
-
const merged = mergePackageJson(base, ours, theirs);
|
|
10728
|
-
return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
|
|
11138
|
+
return { adoptions, conflicts };
|
|
11139
|
+
}
|
|
11140
|
+
function validateAdoption(input) {
|
|
11141
|
+
if (typeof input.targetBefore.id !== "string" || typeof input.targetAfter.id !== "string" || !input.targetBefore.id || !input.targetAfter.id || input.targetAfter.id === input.targetBefore.id || input.targetAfter.prevId !== input.targetBefore.id) {
|
|
11142
|
+
return "\u76EE\u6807 snapshot lineage \u4E0D\u8FDE\u7EED";
|
|
10729
11143
|
}
|
|
10730
|
-
if (
|
|
10731
|
-
return
|
|
11144
|
+
if (typeof input.projectBefore.id !== "string" || typeof input.projectAfter.id !== "string" || !input.projectBefore.id || !input.projectAfter.id || input.projectAfter.id === input.projectBefore.id || input.projectAfter.prevId !== input.projectBefore.id) {
|
|
11145
|
+
return "\u9879\u76EE snapshot lineage \u4E0D\u8FDE\u7EED";
|
|
10732
11146
|
}
|
|
10733
|
-
if (!
|
|
10734
|
-
return
|
|
11147
|
+
if (!equalBytes(input.targetSql, input.projectSql) && !isReviewedMigrationEquivalent(input)) {
|
|
11148
|
+
return "SQL \u5185\u5BB9\u4E0D\u4E00\u81F4\u6216\u672A\u6EE1\u8DB3\u5DF2\u5BA1\u6838\u7B49\u4EF7\u89C4\u5219";
|
|
10735
11149
|
}
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
11150
|
+
const deltaConflicts = [];
|
|
11151
|
+
const expected = applySnapshotDelta(input.targetBefore, input.targetAfter, input.projectBefore, [], deltaConflicts, journalPath);
|
|
11152
|
+
if (deltaConflicts.length || canonicalSnapshot(expected) !== canonicalSnapshot(input.projectAfter)) {
|
|
11153
|
+
return "snapshot delta \u4E0E\u9879\u76EE\u5386\u53F2\u4E0D\u4E00\u81F4";
|
|
10739
11154
|
}
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
11155
|
+
}
|
|
11156
|
+
function decodeSnapshot(content) {
|
|
11157
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
11158
|
+
}
|
|
11159
|
+
function equalBytes(left, right) {
|
|
11160
|
+
return left.byteLength === right.byteLength && left.every((value, index) => value === right[index]);
|
|
11161
|
+
}
|
|
11162
|
+
|
|
11163
|
+
// src/update/migration-reconciler.ts
|
|
11164
|
+
async function reconcileDrizzleMigrations(input) {
|
|
11165
|
+
const journals = await readJournals(input);
|
|
11166
|
+
if (!journals) {
|
|
11167
|
+
return unchanged(input.targetManifest);
|
|
10743
11168
|
}
|
|
10744
|
-
|
|
10745
|
-
|
|
11169
|
+
const { base, project, target } = journals;
|
|
11170
|
+
const conflicts = [];
|
|
11171
|
+
validateUniqueNames(base, "\u6765\u6E90\u6A21\u677F", conflicts);
|
|
11172
|
+
validateUniqueNames(project, "\u5F53\u524D\u9879\u76EE", conflicts);
|
|
11173
|
+
validateUniqueNames(target, "\u76EE\u6807\u6A21\u677F", conflicts);
|
|
11174
|
+
if (conflicts.length) {
|
|
11175
|
+
return { ...unchanged(input.targetManifest), conflicts };
|
|
10746
11176
|
}
|
|
10747
|
-
|
|
10748
|
-
|
|
11177
|
+
const baseNames = new Set(base.entries.map(({ tag }) => stableName(tag)));
|
|
11178
|
+
const projectNames = new Set(project.entries.map(({ tag }) => stableName(tag)));
|
|
11179
|
+
const managedNames = new Set(input.sourceManifest.files.filter(({ path: path2 }) => isSqlMigration(path2)).map(({ path: path2 }) => stableName(path2.slice(drizzleRoot.length + 1, -4))));
|
|
11180
|
+
const candidates = target.entries.filter(({ tag }) => !baseNames.has(stableName(tag)));
|
|
11181
|
+
const adoption = await inspectPreexistingMigrationAdoptions({
|
|
11182
|
+
...input,
|
|
11183
|
+
project,
|
|
11184
|
+
target,
|
|
11185
|
+
candidates,
|
|
11186
|
+
managedNames
|
|
11187
|
+
});
|
|
11188
|
+
conflicts.push(...adoption.conflicts);
|
|
11189
|
+
const additions = candidates.filter(({ tag }) => !projectNames.has(stableName(tag)));
|
|
11190
|
+
const contentOverrides = new Map;
|
|
11191
|
+
const files = await preservePublishedHistory(input.sourceManifest, input, contentOverrides);
|
|
11192
|
+
const publishedPaths = new Set(files.map(({ path: path2 }) => path2));
|
|
11193
|
+
for (const adopted of adoption.adoptions) {
|
|
11194
|
+
contentOverrides.set(adopted.sqlPath, adopted.sql);
|
|
11195
|
+
contentOverrides.set(adopted.snapshotPath, adopted.snapshot);
|
|
11196
|
+
files.push(managedEntry(adopted.sqlPath, adopted.sql), managedEntry(adopted.snapshotPath, adopted.snapshot));
|
|
11197
|
+
publishedPaths.add(adopted.sqlPath);
|
|
11198
|
+
publishedPaths.add(adopted.snapshotPath);
|
|
10749
11199
|
}
|
|
10750
|
-
|
|
10751
|
-
|
|
11200
|
+
files.push(...input.targetManifest.files.filter(({ path: path2 }) => !isDrizzleHistoryPath(path2)));
|
|
11201
|
+
if (!additions.length) {
|
|
11202
|
+
const journalContent2 = encodeJson(project);
|
|
11203
|
+
contentOverrides.set(journalPath, journalContent2);
|
|
11204
|
+
files.push(managedEntry(journalPath, journalContent2));
|
|
11205
|
+
return result(input.targetManifest, files, contentOverrides, publishedPaths, conflicts);
|
|
10752
11206
|
}
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
11207
|
+
let nextPrefix = highestPrefix(project) + 1;
|
|
11208
|
+
let nextIndex = highestIndex(project) + 1;
|
|
11209
|
+
let previousWhen = project.entries.at(-1)?.when ?? 0;
|
|
11210
|
+
let currentSnapshot = await readLatestSnapshot(input, project);
|
|
11211
|
+
const mergedJournal = structuredClone(project);
|
|
11212
|
+
for (const addition of additions) {
|
|
11213
|
+
const targetPosition = target.entries.indexOf(addition);
|
|
11214
|
+
const previousTarget = target.entries[targetPosition - 1];
|
|
11215
|
+
if (!previousTarget) {
|
|
11216
|
+
conflicts.push(`${journalPath}\uFF1A\u76EE\u6807 migration \u7F3A\u5C11\u524D\u7F6E\u5FEB\u7167`);
|
|
11217
|
+
break;
|
|
11218
|
+
}
|
|
11219
|
+
const targetBefore = await readSnapshot(input.targetDirectory, previousTarget.tag);
|
|
11220
|
+
const targetAfter = await readSnapshot(input.targetDirectory, addition.tag);
|
|
11221
|
+
const merged = applySnapshotDelta(targetBefore, targetAfter, currentSnapshot, [], conflicts, journalPath);
|
|
11222
|
+
if (conflicts.length)
|
|
11223
|
+
break;
|
|
11224
|
+
const prefix = String(nextPrefix).padStart(4, "0");
|
|
11225
|
+
const name = stableName(addition.tag);
|
|
11226
|
+
const tag = `${prefix}_${name}`;
|
|
11227
|
+
const sqlPath = `${drizzleRoot}/${tag}.sql`;
|
|
11228
|
+
const snapshotPath2 = `${drizzleRoot}/meta/${prefix}_snapshot.json`;
|
|
11229
|
+
const sql = await readFile21(join28(input.targetDirectory, `${drizzleRoot}/${addition.tag}.sql`));
|
|
11230
|
+
merged.id = targetAfter.id;
|
|
11231
|
+
merged.prevId = currentSnapshot.id;
|
|
11232
|
+
const snapshot2 = encodeJson(merged);
|
|
11233
|
+
contentOverrides.set(sqlPath, sql);
|
|
11234
|
+
contentOverrides.set(snapshotPath2, snapshot2);
|
|
11235
|
+
files.push(managedEntry(sqlPath, sql), managedEntry(snapshotPath2, snapshot2));
|
|
11236
|
+
previousWhen = Math.max(previousWhen + 1, addition.when);
|
|
11237
|
+
mergedJournal.entries.push({
|
|
11238
|
+
...addition,
|
|
11239
|
+
idx: nextIndex,
|
|
11240
|
+
when: previousWhen,
|
|
11241
|
+
tag
|
|
11242
|
+
});
|
|
11243
|
+
currentSnapshot = merged;
|
|
11244
|
+
nextPrefix += 1;
|
|
11245
|
+
nextIndex += 1;
|
|
10756
11246
|
}
|
|
10757
|
-
|
|
11247
|
+
const journalContent = encodeJson(mergedJournal);
|
|
11248
|
+
contentOverrides.set(journalPath, journalContent);
|
|
11249
|
+
files.push(managedEntry(journalPath, journalContent));
|
|
11250
|
+
return result(input.targetManifest, files, contentOverrides, publishedPaths, conflicts);
|
|
10758
11251
|
}
|
|
10759
|
-
function
|
|
10760
|
-
return
|
|
11252
|
+
function result(targetManifest, files, contentOverrides, forcePreserves, conflicts) {
|
|
11253
|
+
return {
|
|
11254
|
+
targetManifest: {
|
|
11255
|
+
...targetManifest,
|
|
11256
|
+
files: deduplicate(files).sort((left, right) => left.path.localeCompare(right.path))
|
|
11257
|
+
},
|
|
11258
|
+
contentOverrides,
|
|
11259
|
+
forceUpdates: new Set([journalPath]),
|
|
11260
|
+
forcePreserves,
|
|
11261
|
+
conflicts
|
|
11262
|
+
};
|
|
10761
11263
|
}
|
|
10762
|
-
function
|
|
10763
|
-
return
|
|
11264
|
+
function unchanged(targetManifest) {
|
|
11265
|
+
return {
|
|
11266
|
+
targetManifest,
|
|
11267
|
+
contentOverrides: new Map,
|
|
11268
|
+
forceUpdates: new Set,
|
|
11269
|
+
forcePreserves: new Set,
|
|
11270
|
+
conflicts: []
|
|
11271
|
+
};
|
|
10764
11272
|
}
|
|
10765
|
-
async function
|
|
11273
|
+
async function readJournals(input) {
|
|
10766
11274
|
try {
|
|
10767
|
-
|
|
11275
|
+
const [base, project, target] = await Promise.all([
|
|
11276
|
+
readJson(join28(input.baseDirectory, journalPath)),
|
|
11277
|
+
readProjectJson(input, journalPath),
|
|
11278
|
+
readJson(join28(input.targetDirectory, journalPath))
|
|
11279
|
+
]);
|
|
11280
|
+
return { base, project, target };
|
|
10768
11281
|
} catch (error) {
|
|
10769
|
-
if (error
|
|
11282
|
+
if (isMissingFileError(error))
|
|
10770
11283
|
return;
|
|
10771
|
-
}
|
|
10772
11284
|
throw error;
|
|
10773
11285
|
}
|
|
10774
11286
|
}
|
|
11287
|
+
async function preservePublishedHistory(manifest, input, overrides) {
|
|
11288
|
+
const entries = manifest.files.filter(({ path: path2 }) => isMigrationArtifact(path2) && path2 !== journalPath);
|
|
11289
|
+
await Promise.all(entries.map(async ({ path: path2 }) => {
|
|
11290
|
+
const content = await readProjectFile(input, path2);
|
|
11291
|
+
if (!content)
|
|
11292
|
+
throw new Error(`\u5F53\u524D\u9879\u76EE migration \u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
11293
|
+
overrides.set(path2, content);
|
|
11294
|
+
}));
|
|
11295
|
+
return entries;
|
|
11296
|
+
}
|
|
11297
|
+
async function readLatestSnapshot(input, journal) {
|
|
11298
|
+
const latest = journal.entries.at(-1);
|
|
11299
|
+
if (!latest)
|
|
11300
|
+
throw new Error(`${journalPath}\uFF1A\u5F53\u524D\u9879\u76EE\u6CA1\u6709 migration`);
|
|
11301
|
+
const path2 = snapshotPath(latest.tag);
|
|
11302
|
+
const content = await readProjectFile(input, path2);
|
|
11303
|
+
if (!content) {
|
|
11304
|
+
throw new Error(`\u5F53\u524D\u9879\u76EE migration \u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
11305
|
+
}
|
|
11306
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
11307
|
+
}
|
|
11308
|
+
async function readSnapshot(root, tag) {
|
|
11309
|
+
return await readJson(join28(root, snapshotPath(tag)));
|
|
11310
|
+
}
|
|
10775
11311
|
|
|
10776
11312
|
// src/update/planner-files.ts
|
|
10777
11313
|
var metadataPaths = new Set([
|
|
@@ -10852,17 +11388,9 @@ async function assertNoPendingUpdate(projectDirectory) {
|
|
|
10852
11388
|
throw new Error(`\u68C0\u6D4B\u5230\u672A\u5B8C\u6210\u66F4\u65B0\uFF08\u9636\u6BB5\uFF1A${pending.phase ?? "ready"}\uFF09\uFF0C\u8BF7\u5148\u8FD0\u884C bun run windy doctor --repair`);
|
|
10853
11389
|
}
|
|
10854
11390
|
|
|
10855
|
-
// src/update/module-selection.ts
|
|
10856
|
-
function resolveUpdateTargetModules(sourceModules, explicitTarget) {
|
|
10857
|
-
return explicitTarget ? [...explicitTarget] : resolveModuleSelection({
|
|
10858
|
-
requested: sourceModules,
|
|
10859
|
-
includeRecommended: false
|
|
10860
|
-
});
|
|
10861
|
-
}
|
|
10862
|
-
|
|
10863
11391
|
// src/update/legacy-python-agent-retirement.ts
|
|
10864
11392
|
import { lstat as lstat8, readFile as readFile22 } from "fs/promises";
|
|
10865
|
-
import { join as
|
|
11393
|
+
import { join as join29 } from "path";
|
|
10866
11394
|
var retiredKeys = [
|
|
10867
11395
|
"AGENT_DATABASE_URL",
|
|
10868
11396
|
"AGENT_RUN_STORE_PATH",
|
|
@@ -10873,7 +11401,7 @@ var retiredKeys = [
|
|
|
10873
11401
|
"OTEL_EXPORTER_OTLP_HEADERS"
|
|
10874
11402
|
];
|
|
10875
11403
|
async function inspectPythonAgentRetirement(projectDirectory) {
|
|
10876
|
-
const path2 =
|
|
11404
|
+
const path2 = join29(projectDirectory, ".env");
|
|
10877
11405
|
try {
|
|
10878
11406
|
const stat3 = await lstat8(path2);
|
|
10879
11407
|
if (stat3.isSymbolicLink() || !stat3.isFile())
|
|
@@ -10906,7 +11434,7 @@ var oxcManagedPaths = new Set([
|
|
|
10906
11434
|
]);
|
|
10907
11435
|
async function createUpdatePlan(request, artifacts, dependencies = {}) {
|
|
10908
11436
|
await assertProjectReadyForUpdate(request.projectDirectory);
|
|
10909
|
-
const manifestPath =
|
|
11437
|
+
const manifestPath = join30(request.projectDirectory, ".windy/files.json");
|
|
10910
11438
|
const expectedManifestHash = hashContent(await readFile23(manifestPath));
|
|
10911
11439
|
const generationSnapshot = await readGenerationProvenanceSnapshot(request.projectDirectory);
|
|
10912
11440
|
const provenance = generationSnapshot.provenance;
|
|
@@ -10964,10 +11492,10 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
|
|
|
10964
11492
|
const paths = new Set([...sourceEntries.keys(), ...targetEntries.keys()]);
|
|
10965
11493
|
for (const path2 of paths) {
|
|
10966
11494
|
if (!projectSnapshots.has(path2)) {
|
|
10967
|
-
projectSnapshots.set(path2, await readOptional(
|
|
11495
|
+
projectSnapshots.set(path2, await readOptional(join30(request.projectDirectory, path2)));
|
|
10968
11496
|
}
|
|
10969
11497
|
if (!projectModes.has(path2)) {
|
|
10970
|
-
projectModes.set(path2, await readModeOptional(
|
|
11498
|
+
projectModes.set(path2, await readModeOptional(join30(request.projectDirectory, path2)));
|
|
10971
11499
|
}
|
|
10972
11500
|
}
|
|
10973
11501
|
const files = await planFiles({
|
|
@@ -10983,19 +11511,31 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
|
|
|
10983
11511
|
recipeProjectOwnedPaths,
|
|
10984
11512
|
migrateDshPlatform
|
|
10985
11513
|
});
|
|
11514
|
+
if (!request.lifecycle) {
|
|
11515
|
+
reconcileMediaRuntimeRegistry(files, projectSnapshots.get(projectModuleRegistryPath), provenance.modules.map(({ name }) => name), targetProvenance.modules.map(({ name }) => name));
|
|
11516
|
+
}
|
|
11517
|
+
await reconcileAdminSettingsYamlPlan({
|
|
11518
|
+
files,
|
|
11519
|
+
sourceEntries,
|
|
11520
|
+
targetEntries,
|
|
11521
|
+
projectSnapshots,
|
|
11522
|
+
baseDirectory: artifactSet.baseDirectory,
|
|
11523
|
+
targetDirectory: artifactSet.targetDirectory
|
|
11524
|
+
});
|
|
10986
11525
|
preserveTestsForExistingProjectOwnedSources(files, sourceEntries);
|
|
10987
11526
|
await deriveDockerfilePlans(files, projectSnapshots, new Set([
|
|
10988
11527
|
...paths,
|
|
10989
11528
|
...workspaceSnapshot.manifests.keys(),
|
|
10990
11529
|
...targetWorkspaceSnapshot.manifests.keys()
|
|
10991
11530
|
]), targetWorkspaceSnapshot.manifests);
|
|
11531
|
+
validateEnvironmentMountPlan(files, projectSnapshots.get("windy.environment.yaml"));
|
|
10992
11532
|
for (const file of files) {
|
|
10993
11533
|
file.expectedProjectMode = projectModes.get(file.path);
|
|
10994
11534
|
if (file.action === "create" || file.action === "update") {
|
|
10995
|
-
file.mode = file.expectedProjectMode ?? await readModeOptional(
|
|
11535
|
+
file.mode = file.expectedProjectMode ?? await readModeOptional(join30(artifactSet.targetDirectory, file.path));
|
|
10996
11536
|
}
|
|
10997
11537
|
if (file.action === "create") {
|
|
10998
|
-
file.parentMode = await readSourceParentMode(
|
|
11538
|
+
file.parentMode = await readSourceParentMode(join30(artifactSet.targetDirectory, dirname9(file.path)));
|
|
10999
11539
|
}
|
|
11000
11540
|
}
|
|
11001
11541
|
const plannedPaths = new Set(files.map(({ path: path2 }) => path2));
|
|
@@ -11129,7 +11669,7 @@ function frozenManifestHash(file, finalizedHashes) {
|
|
|
11129
11669
|
// src/update/format-stabilizer.ts
|
|
11130
11670
|
import { mkdir as mkdir8, mkdtemp as mkdtemp3, readFile as readFile24, rm as rm7, writeFile as writeFile13 } from "fs/promises";
|
|
11131
11671
|
import { tmpdir as tmpdir3 } from "os";
|
|
11132
|
-
import { dirname as dirname10, extname as extname4, join as
|
|
11672
|
+
import { dirname as dirname10, extname as extname4, join as join31, resolve as resolve6, sep as sep5 } from "path";
|
|
11133
11673
|
var formattedExtensions = new Set([
|
|
11134
11674
|
".cjs",
|
|
11135
11675
|
".css",
|
|
@@ -11168,7 +11708,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
11168
11708
|
}
|
|
11169
11709
|
}
|
|
11170
11710
|
inputs.set(".windy/generation.json", new TextEncoder().encode(generationContent));
|
|
11171
|
-
const temporaryRoot = await mkdtemp3(
|
|
11711
|
+
const temporaryRoot = await mkdtemp3(join31(tmpdir3(), "windy-update-format-"));
|
|
11172
11712
|
try {
|
|
11173
11713
|
const stagedPaths = await stageInputs(temporaryRoot, inputs);
|
|
11174
11714
|
for (let offset = 0;offset < stagedPaths.length; offset += 80) {
|
|
@@ -11176,7 +11716,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
11176
11716
|
"x",
|
|
11177
11717
|
"oxfmt",
|
|
11178
11718
|
"--write",
|
|
11179
|
-
`--config=${
|
|
11719
|
+
`--config=${join31(result2.plan.projectDirectory, ".oxfmtrc.json")}`,
|
|
11180
11720
|
...stagedPaths.slice(offset, offset + 80)
|
|
11181
11721
|
], result2.plan.projectDirectory);
|
|
11182
11722
|
}
|
|
@@ -11225,7 +11765,7 @@ function safeTemporaryPath(root, path2) {
|
|
|
11225
11765
|
|
|
11226
11766
|
// src/update/project-quality-verification.ts
|
|
11227
11767
|
import { readFile as readFile25 } from "fs/promises";
|
|
11228
|
-
import { join as
|
|
11768
|
+
import { join as join32 } from "path";
|
|
11229
11769
|
var qualityScriptNames = ["lint", "typecheck", "test", "build"];
|
|
11230
11770
|
function skippedProjectQualityVerification() {
|
|
11231
11771
|
return {
|
|
@@ -11239,7 +11779,7 @@ function skippedProjectQualityVerification() {
|
|
|
11239
11779
|
};
|
|
11240
11780
|
}
|
|
11241
11781
|
async function runProjectQualityVerification(projectDirectory, execute) {
|
|
11242
|
-
const packageJson = JSON.parse(await readFile25(
|
|
11782
|
+
const packageJson = JSON.parse(await readFile25(join32(projectDirectory, "package.json"), "utf8"));
|
|
11243
11783
|
const steps = [];
|
|
11244
11784
|
for (const name of qualityScriptNames) {
|
|
11245
11785
|
const stepName = `bun run ${name}`;
|
|
@@ -12322,7 +12862,7 @@ import {
|
|
|
12322
12862
|
rm as rm11,
|
|
12323
12863
|
writeFile as writeFile14
|
|
12324
12864
|
} from "fs/promises";
|
|
12325
|
-
import { dirname as dirname11, join as
|
|
12865
|
+
import { dirname as dirname11, join as join33, relative as relative7 } from "path";
|
|
12326
12866
|
|
|
12327
12867
|
// src/module-schema/config.ts
|
|
12328
12868
|
import { readFile as readFile26 } from "fs/promises";
|
|
@@ -12463,17 +13003,17 @@ async function handoffModuleSchemaLineages(options) {
|
|
|
12463
13003
|
async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
12464
13004
|
const outputs = [];
|
|
12465
13005
|
for (const [index, module2] of config.modules.entries()) {
|
|
12466
|
-
const output =
|
|
13006
|
+
const output = join33(temporaryRoot, `module-${index}`);
|
|
12467
13007
|
await mkdir9(output, { recursive: true });
|
|
12468
|
-
const generatedConfig =
|
|
13008
|
+
const generatedConfig = join33(temporaryRoot, `module-${index}.config.ts`);
|
|
12469
13009
|
await writeDrizzleConfig(generatedConfig, project, module2.schema, relative7(temporaryRoot, output));
|
|
12470
13010
|
await execute(generatedConfig, temporaryRoot);
|
|
12471
13011
|
const sqlFiles = await listSqlFiles(output);
|
|
12472
13012
|
if (sqlFiles.length !== 1) {
|
|
12473
13013
|
throw new Error(`${module2.key} baseline \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration`);
|
|
12474
13014
|
}
|
|
12475
|
-
await writeFile14(
|
|
12476
|
-
await writeFile14(
|
|
13015
|
+
await writeFile14(join33(output, sqlFiles[0]), metadataOnlySql("module"));
|
|
13016
|
+
await writeFile14(join33(output, "lineage.json"), `${JSON.stringify({
|
|
12477
13017
|
schemaVersion: 1,
|
|
12478
13018
|
moduleKey: module2.key,
|
|
12479
13019
|
schema: module2.schema,
|
|
@@ -12487,17 +13027,17 @@ async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
|
12487
13027
|
}
|
|
12488
13028
|
async function stagePlatformLineage(project, temporaryRoot, config, execute) {
|
|
12489
13029
|
const source = resolveProjectPath(project, config.platform.out);
|
|
12490
|
-
const output =
|
|
13030
|
+
const output = join33(temporaryRoot, "platform");
|
|
12491
13031
|
await cp(source, output, { recursive: true });
|
|
12492
13032
|
const before = new Set(await listSqlFiles(output));
|
|
12493
|
-
const generatedConfig =
|
|
13033
|
+
const generatedConfig = join33(temporaryRoot, "platform.config.ts");
|
|
12494
13034
|
await writeDrizzleConfig(generatedConfig, project, config.platform.schema, relative7(temporaryRoot, output));
|
|
12495
13035
|
await execute(generatedConfig, temporaryRoot);
|
|
12496
13036
|
const created = (await listSqlFiles(output)).filter((path2) => !before.has(path2));
|
|
12497
13037
|
if (created.length !== 1) {
|
|
12498
13038
|
throw new Error("\u5E73\u53F0 lineage handoff \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration");
|
|
12499
13039
|
}
|
|
12500
|
-
const sqlPath =
|
|
13040
|
+
const sqlPath = join33(output, created[0]);
|
|
12501
13041
|
const allowed = config.modules.flatMap(({ legacyPlatformTables }) => legacyPlatformTables);
|
|
12502
13042
|
validatePlatformHandoffSql(await readFile27(sqlPath, "utf8"), allowed);
|
|
12503
13043
|
await writeFile14(sqlPath, metadataOnlySql("platform"));
|
|
@@ -12505,7 +13045,7 @@ async function stagePlatformLineage(project, temporaryRoot, config, execute) {
|
|
|
12505
13045
|
}
|
|
12506
13046
|
async function installStagedLineages(project, temporaryRoot, config, stagedModules, stagedPlatform) {
|
|
12507
13047
|
const platform = resolveProjectPath(project, config.platform.out);
|
|
12508
|
-
const backup =
|
|
13048
|
+
const backup = join33(temporaryRoot, "platform-backup");
|
|
12509
13049
|
const installed = [];
|
|
12510
13050
|
await rename2(platform, backup);
|
|
12511
13051
|
try {
|
|
@@ -12552,9 +13092,9 @@ async function validateSchemaSources(project, config) {
|
|
|
12552
13092
|
}
|
|
12553
13093
|
}
|
|
12554
13094
|
async function createTemporaryRoot(project) {
|
|
12555
|
-
const windy =
|
|
13095
|
+
const windy = join33(project, ".windy");
|
|
12556
13096
|
await mkdir9(windy, { recursive: true });
|
|
12557
|
-
return await mkdtemp4(
|
|
13097
|
+
return await mkdtemp4(join33(windy, "module-schema-handoff-"));
|
|
12558
13098
|
}
|
|
12559
13099
|
async function listSqlFiles(root) {
|
|
12560
13100
|
return (await readdir9(root)).filter((path2) => path2.endsWith(".sql")).sort();
|
|
@@ -12645,7 +13185,7 @@ async function readPackageConfiguration(projectDirectory) {
|
|
|
12645
13185
|
}
|
|
12646
13186
|
}
|
|
12647
13187
|
function parsePackageConfiguration(value) {
|
|
12648
|
-
const root =
|
|
13188
|
+
const root = object2(value, "windy.build.json");
|
|
12649
13189
|
rejectUnknown(root, ["schemaVersion", "product", "platforms", "profiles"], "windy.build.json");
|
|
12650
13190
|
if (root.schemaVersion !== 1)
|
|
12651
13191
|
throw new Error("windy.build.json \u53EA\u652F\u6301 schemaVersion: 1");
|
|
@@ -12671,7 +13211,7 @@ function parsePackageConfiguration(value) {
|
|
|
12671
13211
|
};
|
|
12672
13212
|
}
|
|
12673
13213
|
function parseProfile(value) {
|
|
12674
|
-
const profile =
|
|
13214
|
+
const profile = object2(value, "profile");
|
|
12675
13215
|
rejectUnknown(profile, [
|
|
12676
13216
|
"key",
|
|
12677
13217
|
"label",
|
|
@@ -12684,7 +13224,7 @@ function parseProfile(value) {
|
|
|
12684
13224
|
const key = identifier(profile.key, "profile key");
|
|
12685
13225
|
const inputs = array(profile.inputs, `profile ${key}.inputs`).map((item) => parseInput(item, key));
|
|
12686
13226
|
unique2(inputs.map(({ key: inputKey }) => inputKey), `profile ${key} input key`);
|
|
12687
|
-
const command =
|
|
13227
|
+
const command = object2(profile.command, `profile ${key}.command`);
|
|
12688
13228
|
rejectUnknown(command, ["executable", "arguments"], `profile ${key}.command`);
|
|
12689
13229
|
const executable = string(command.executable, `profile ${key}.command.executable`);
|
|
12690
13230
|
if (shellExecutables.has(executable.toLowerCase()) || shellCharacters.test(executable) || !/^[a-zA-Z0-9._-]+$/u.test(executable)) {
|
|
@@ -12698,7 +13238,7 @@ function parseProfile(value) {
|
|
|
12698
13238
|
}
|
|
12699
13239
|
return argument;
|
|
12700
13240
|
});
|
|
12701
|
-
const output =
|
|
13241
|
+
const output = object2(profile.output, `profile ${key}.output`);
|
|
12702
13242
|
rejectUnknown(output, ["directory", "artifactSuffix"], `profile ${key}.output`);
|
|
12703
13243
|
const directory = string(output.directory, `profile ${key}.output.directory`);
|
|
12704
13244
|
if (!isSafeRelativePath(directory) || !/^[a-zA-Z0-9._/-]+$/u.test(directory))
|
|
@@ -12707,7 +13247,7 @@ function parseProfile(value) {
|
|
|
12707
13247
|
if (!artifactSuffix.startsWith(".") || shellCharacters.test(artifactSuffix) || !/^\.[a-zA-Z0-9._-]+$/u.test(artifactSuffix)) {
|
|
12708
13248
|
throw new Error(`profile ${key} \u7684 output.artifactSuffix \u975E\u6CD5`);
|
|
12709
13249
|
}
|
|
12710
|
-
const requirements =
|
|
13250
|
+
const requirements = object2(profile.requirements, `profile ${key}.requirements`);
|
|
12711
13251
|
rejectUnknown(requirements, ["docker", "buildx"], `profile ${key}.requirements`);
|
|
12712
13252
|
const docker = boolean(requirements.docker, `profile ${key}.requirements.docker`);
|
|
12713
13253
|
const buildx = boolean(requirements.buildx, `profile ${key}.requirements.buildx`);
|
|
@@ -12724,7 +13264,7 @@ function parseProfile(value) {
|
|
|
12724
13264
|
};
|
|
12725
13265
|
}
|
|
12726
13266
|
function parseInput(value, profile) {
|
|
12727
|
-
const input =
|
|
13267
|
+
const input = object2(value, `profile ${profile}.input`);
|
|
12728
13268
|
rejectUnknown(input, ["key", "label", "required", "pattern"], `profile ${profile}.input`);
|
|
12729
13269
|
const key = identifier(input.key, `profile ${profile}.input.key`);
|
|
12730
13270
|
if (secretName.test(key))
|
|
@@ -12755,7 +13295,7 @@ function validatePlaceholders(value, inputs, profile) {
|
|
|
12755
13295
|
if (value.replace(placeholder, "").includes("${"))
|
|
12756
13296
|
throw new Error(`profile ${profile} \u5305\u542B\u672A\u58F0\u660E\u5360\u4F4D\u7B26`);
|
|
12757
13297
|
}
|
|
12758
|
-
function
|
|
13298
|
+
function object2(value, label) {
|
|
12759
13299
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
12760
13300
|
throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
|
|
12761
13301
|
return value;
|