create-windy 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1769 -1277
- 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,8 @@ 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" }
|
|
8719
9016
|
];
|
|
8720
9017
|
function resolveRecipeChain(sourceVersion, targetVersion) {
|
|
8721
9018
|
if (compareVersions2(sourceVersion, minimumSupportedUpdateVersion) < 0) {
|
|
@@ -8762,6 +9059,33 @@ function parseVersion2(version) {
|
|
|
8762
9059
|
// src/update/updater.ts
|
|
8763
9060
|
import { rm as rm8 } from "fs/promises";
|
|
8764
9061
|
|
|
9062
|
+
// src/update/module-selection.ts
|
|
9063
|
+
function resolveUpdateTargetModules(sourceModules, explicitTarget) {
|
|
9064
|
+
return explicitTarget ? [...explicitTarget] : resolveModuleSelection({
|
|
9065
|
+
requested: sourceModules,
|
|
9066
|
+
includeRecommended: false
|
|
9067
|
+
});
|
|
9068
|
+
}
|
|
9069
|
+
function environmentProfileForUpdate(profile, selectedModules) {
|
|
9070
|
+
if (!profile)
|
|
9071
|
+
return;
|
|
9072
|
+
const runtimes = profile.build.runtimes ? { ...profile.build.runtimes } : undefined;
|
|
9073
|
+
const runtime = profile.runtime ? { ...profile.runtime } : undefined;
|
|
9074
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
9075
|
+
if (selectedModules.includes(runtimeDistributionModule(kind)))
|
|
9076
|
+
continue;
|
|
9077
|
+
if (runtimes)
|
|
9078
|
+
delete runtimes[kind];
|
|
9079
|
+
if (runtime)
|
|
9080
|
+
delete runtime[kind];
|
|
9081
|
+
}
|
|
9082
|
+
return {
|
|
9083
|
+
...profile,
|
|
9084
|
+
build: { modules: [...selectedModules], ...runtimes ? { runtimes } : {} },
|
|
9085
|
+
...runtime ? { runtime } : {}
|
|
9086
|
+
};
|
|
9087
|
+
}
|
|
9088
|
+
|
|
8765
9089
|
// src/update/artifacts.ts
|
|
8766
9090
|
import { mkdtemp, readFile as readFile15 } from "fs/promises";
|
|
8767
9091
|
import { tmpdir } from "os";
|
|
@@ -8972,7 +9296,6 @@ async function generatePublicArtifactProject(temporaryRoot, label, projectName,
|
|
|
8972
9296
|
"--yes",
|
|
8973
9297
|
"--skip-install",
|
|
8974
9298
|
"--no-git",
|
|
8975
|
-
"--no-optional-modules",
|
|
8976
9299
|
"--license",
|
|
8977
9300
|
provenance.legalLicense
|
|
8978
9301
|
];
|
|
@@ -8981,9 +9304,16 @@ async function generatePublicArtifactProject(temporaryRoot, label, projectName,
|
|
|
8981
9304
|
if (provenance.legalLicense === "MIT") {
|
|
8982
9305
|
args.push("--license-holder", "Windy project owner");
|
|
8983
9306
|
}
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
9307
|
+
if (provenance.environmentProfile) {
|
|
9308
|
+
const path2 = join18(temporaryRoot, `${label}.environment.json`);
|
|
9309
|
+
await writeFile10(path2, JSON.stringify(provenance.environmentProfile));
|
|
9310
|
+
args.push("--environment-profile", path2);
|
|
9311
|
+
} else {
|
|
9312
|
+
args.push("--no-optional-modules");
|
|
9313
|
+
for (const { name } of provenance.modules) {
|
|
9314
|
+
if (!requiredModuleNames.includes(name)) {
|
|
9315
|
+
args.push("--module", name);
|
|
9316
|
+
}
|
|
8987
9317
|
}
|
|
8988
9318
|
}
|
|
8989
9319
|
await assertProcess("bun", args, parent);
|
|
@@ -9094,12 +9424,14 @@ class PublishedArtifactProvider {
|
|
|
9094
9424
|
throw new Error("Project Lock \u4E0E\u6765\u6E90 registry artifact \u7684 template commit \u4E0D\u4E00\u81F4");
|
|
9095
9425
|
}
|
|
9096
9426
|
await generatePublicArtifactProject(temporaryRoot, "base", projectName, baseArtifact.root, provenance);
|
|
9427
|
+
const selectedModules = targetModules ?? provenance.modules.map(({ name }) => name);
|
|
9097
9428
|
await generateProject({
|
|
9098
9429
|
sourceRoot: await resolveTemplateRoot(),
|
|
9099
9430
|
targetDirectory,
|
|
9100
9431
|
projectName,
|
|
9101
|
-
selectedModules
|
|
9102
|
-
|
|
9432
|
+
selectedModules,
|
|
9433
|
+
environmentProfile: environmentProfileForUpdate(provenance.environmentProfile, selectedModules),
|
|
9434
|
+
includeExample: selectedModules.includes("work-order"),
|
|
9103
9435
|
includeOxc: provenance.choices.includeOxc,
|
|
9104
9436
|
projectLicense: provenance.legalLicense,
|
|
9105
9437
|
licenseHolder: provenance.legalLicense === "MIT" ? "Windy project owner" : undefined,
|
|
@@ -9120,660 +9452,262 @@ async function readProjectName2(projectDirectory) {
|
|
|
9120
9452
|
return source.name || basename10(projectDirectory);
|
|
9121
9453
|
}
|
|
9122
9454
|
|
|
9123
|
-
// src/update/
|
|
9124
|
-
import {
|
|
9125
|
-
import { dirname as dirname9, join as join29 } from "path";
|
|
9455
|
+
// src/update/admin-settings-yaml-plan.ts
|
|
9456
|
+
import { join as join25 } from "path";
|
|
9126
9457
|
|
|
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
|
-
});
|
|
9458
|
+
// src/update/planner-snapshots.ts
|
|
9459
|
+
import { readFile as readFile17, stat as stat2 } from "fs/promises";
|
|
9460
|
+
import { join as join24 } from "path";
|
|
9461
|
+
|
|
9462
|
+
// src/update/recipe-admin-api.ts
|
|
9463
|
+
var apiRecipes = [
|
|
9464
|
+
{
|
|
9465
|
+
path: "apps/web/src/services/platform-settings-api.ts",
|
|
9466
|
+
beforeImport: 'import { apiRequest } from "./http";',
|
|
9467
|
+
afterImport: 'import { apiRequest, apiResponse } from "./http";',
|
|
9468
|
+
addedImport: "apiResponse",
|
|
9469
|
+
marker: 'const WATERMARK_YAML_PATH = "/system/settings/watermark/yaml";',
|
|
9470
|
+
symbols: [
|
|
9471
|
+
"WATERMARK_YAML_PATH",
|
|
9472
|
+
"WatermarkYamlPreview",
|
|
9473
|
+
"exportWatermarkYaml",
|
|
9474
|
+
"previewWatermarkYaml",
|
|
9475
|
+
"importWatermarkYaml"
|
|
9476
|
+
]
|
|
9477
|
+
},
|
|
9478
|
+
{
|
|
9479
|
+
path: "apps/web/src/services/diagnostics-api.ts",
|
|
9480
|
+
beforeImport: 'import type { DiagnosticRecord } from "@southwind-ai/shared";',
|
|
9481
|
+
afterImport: 'import type { DiagnosticRecord, PageResult } from "@southwind-ai/shared";',
|
|
9482
|
+
addedImport: "PageResult",
|
|
9483
|
+
marker: "export function listDiagnostics(",
|
|
9484
|
+
symbols: ["listDiagnostics"]
|
|
9160
9485
|
}
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9486
|
+
];
|
|
9487
|
+
var adminApiRecipePaths = apiRecipes.map(({ path: path2 }) => path2);
|
|
9488
|
+
function isAdminApiRecipePath(path2) {
|
|
9489
|
+
return adminApiRecipePaths.includes(path2);
|
|
9490
|
+
}
|
|
9491
|
+
function addAdminApiExports(path2, source, target) {
|
|
9492
|
+
const recipe = apiRecipes.find((item) => item.path === path2);
|
|
9493
|
+
if (!recipe || !target)
|
|
9494
|
+
return { error: "Admin API recipe \u76EE\u6807\u7F3A\u5931" };
|
|
9495
|
+
if (occurrences(target, recipe.marker) !== 1 || occurrences(target, recipe.afterImport) !== 1) {
|
|
9496
|
+
return { error: "Admin API recipe \u76EE\u6807\u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
9497
|
+
}
|
|
9498
|
+
const block = target.slice(target.indexOf(recipe.marker)).trimEnd();
|
|
9499
|
+
if (recipe.symbols.some((symbol) => !block.includes(symbol))) {
|
|
9500
|
+
return { error: "Admin API recipe \u76EE\u6807\u5BFC\u51FA\u4E0D\u5B8C\u6574" };
|
|
9501
|
+
}
|
|
9502
|
+
if (recipe.symbols.some((symbol) => source.includes(symbol))) {
|
|
9503
|
+
const blockIndex = source.indexOf(block);
|
|
9504
|
+
const remainder = blockIndex < 0 ? source : source.slice(0, blockIndex) + source.slice(blockIndex + block.length);
|
|
9505
|
+
if (blockIndex < 0 || occurrences(source, block) !== 1 || occurrences(source, recipe.afterImport) !== 1 || occurrences(source, recipe.beforeImport) !== 0 || recipe.symbols.some((symbol) => remainder.includes(symbol))) {
|
|
9506
|
+
return { error: "Admin API recipe \u5DF2\u6709\u5BFC\u51FA\u4E0D\u5B8C\u6574\u3001\u91CD\u590D\u6216\u5DF2\u88AB\u4FEE\u6539" };
|
|
9180
9507
|
}
|
|
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);
|
|
9508
|
+
return { content: source };
|
|
9186
9509
|
}
|
|
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
|
-
});
|
|
9510
|
+
if (occurrences(source, recipe.beforeImport) !== 1 || occurrences(source, recipe.afterImport) !== 0 || new RegExp(`\\b${recipe.addedImport}\\b`).test(source)) {
|
|
9511
|
+
return { error: "Admin API recipe \u539F\u59CB import \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
9206
9512
|
}
|
|
9513
|
+
return {
|
|
9514
|
+
content: source.replace(recipe.beforeImport, recipe.afterImport) + `${source.endsWith(`
|
|
9515
|
+
`) ? `
|
|
9516
|
+
` : `
|
|
9517
|
+
|
|
9518
|
+
`}${block}
|
|
9519
|
+
`
|
|
9520
|
+
};
|
|
9207
9521
|
}
|
|
9208
|
-
function
|
|
9209
|
-
return
|
|
9522
|
+
function occurrences(source, value) {
|
|
9523
|
+
return source.split(value).length - 1;
|
|
9210
9524
|
}
|
|
9211
9525
|
|
|
9212
|
-
// src/update/
|
|
9213
|
-
import { readFile as
|
|
9526
|
+
// src/update/planner-file.ts
|
|
9527
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
9214
9528
|
import { join as join23 } from "path";
|
|
9215
9529
|
|
|
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));
|
|
9530
|
+
// src/update/planner-file-support.ts
|
|
9531
|
+
function readyPlannedFile(path2, ownership, action, reason, expectedProjectContent, content) {
|
|
9532
|
+
return {
|
|
9533
|
+
path: path2,
|
|
9534
|
+
ownership,
|
|
9535
|
+
action,
|
|
9536
|
+
reason,
|
|
9537
|
+
expectedProjectContent,
|
|
9538
|
+
content
|
|
9539
|
+
};
|
|
9231
9540
|
}
|
|
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;
|
|
9541
|
+
function expectationForSnapshot(content) {
|
|
9542
|
+
return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
|
|
9247
9543
|
}
|
|
9248
|
-
function
|
|
9249
|
-
return
|
|
9544
|
+
function conflict(path2, ownership, reason, expectedProjectContent) {
|
|
9545
|
+
return {
|
|
9546
|
+
path: path2,
|
|
9547
|
+
ownership,
|
|
9548
|
+
action: "preserve",
|
|
9549
|
+
reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
|
|
9550
|
+
expectedProjectContent,
|
|
9551
|
+
conflict: reason
|
|
9552
|
+
};
|
|
9250
9553
|
}
|
|
9554
|
+
// src/update/merge.ts
|
|
9555
|
+
import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile12 } from "fs/promises";
|
|
9556
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
9557
|
+
import { join as join21 } from "path";
|
|
9251
9558
|
|
|
9252
|
-
// src/update/
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9559
|
+
// src/update/merge-convergent-additions.ts
|
|
9560
|
+
async function reconcileConvergentAdditions(input) {
|
|
9561
|
+
const [oursDiff, theirsDiff] = await Promise.all([
|
|
9562
|
+
diff(input.root, input.basePath, input.oursPath),
|
|
9563
|
+
diff(input.root, input.basePath, input.theirsPath)
|
|
9564
|
+
]);
|
|
9565
|
+
if (oursDiff === undefined || theirsDiff === undefined)
|
|
9566
|
+
return;
|
|
9567
|
+
const oursAdditions = pureAdditions(oursDiff);
|
|
9568
|
+
const theirsAdditions = pureAdditions(theirsDiff);
|
|
9569
|
+
const oursByContent = new Map;
|
|
9570
|
+
for (const addition of oursAdditions) {
|
|
9571
|
+
const key = addition.lines.join(`
|
|
9572
|
+
`);
|
|
9573
|
+
oursByContent.set(key, [...oursByContent.get(key) ?? [], addition]);
|
|
9261
9574
|
}
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
const
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9575
|
+
const decode = (content) => new TextDecoder().decode(content);
|
|
9576
|
+
const baseLines = decode(input.base).split(`
|
|
9577
|
+
`);
|
|
9578
|
+
const oursLines = decode(input.ours).split(`
|
|
9579
|
+
`);
|
|
9580
|
+
const theirsLines = decode(input.theirs).split(`
|
|
9581
|
+
`);
|
|
9582
|
+
const mergedLines = input.merged.split(`
|
|
9583
|
+
`);
|
|
9584
|
+
const convergent = theirsAdditions.flatMap((addition) => {
|
|
9585
|
+
if (!isSubstantial(addition.lines) || !isNamedClassMethod(addition.lines)) {
|
|
9586
|
+
return [];
|
|
9270
9587
|
}
|
|
9271
|
-
|
|
9588
|
+
const key = addition.lines.join(`
|
|
9589
|
+
`);
|
|
9590
|
+
const matchingOurs = oursByContent.get(key);
|
|
9591
|
+
if (matchingOurs?.length !== 1)
|
|
9592
|
+
return [];
|
|
9593
|
+
if (theirsAdditions.filter((candidate2) => candidate2.lines.join(`
|
|
9594
|
+
`) === key).length !== 1) {
|
|
9595
|
+
return [];
|
|
9596
|
+
}
|
|
9597
|
+
const oursContainer = enclosingClass(oursLines, matchingOurs[0]);
|
|
9598
|
+
const theirsContainer = enclosingClass(theirsLines, addition);
|
|
9599
|
+
if (!oursContainer || oursContainer !== theirsContainer)
|
|
9600
|
+
return [];
|
|
9601
|
+
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 }] : [];
|
|
9602
|
+
});
|
|
9603
|
+
if (convergent.length !== 1)
|
|
9604
|
+
return;
|
|
9605
|
+
const candidate = convergent[0];
|
|
9606
|
+
if (!candidate)
|
|
9607
|
+
return;
|
|
9608
|
+
const oursWithout = withoutAddition(oursLines, candidate.ours);
|
|
9609
|
+
const theirsWithout = withoutAddition(theirsLines, candidate.theirs);
|
|
9610
|
+
if (!oursWithout || !theirsWithout || !sameLines(oursWithout, theirsWithout)) {
|
|
9611
|
+
return;
|
|
9272
9612
|
}
|
|
9613
|
+
return input.ours;
|
|
9273
9614
|
}
|
|
9274
|
-
function
|
|
9275
|
-
|
|
9615
|
+
async function diff(root, basePath, branchPath) {
|
|
9616
|
+
const result = await captureProcess("git", ["diff", "--no-index", "--unified=0", "--no-color", basePath, branchPath], root);
|
|
9617
|
+
return result.code === 0 || result.code === 1 ? result.stdout : undefined;
|
|
9276
9618
|
}
|
|
9277
|
-
function
|
|
9278
|
-
|
|
9619
|
+
function pureAdditions(diff2) {
|
|
9620
|
+
const lines = diff2.split(`
|
|
9621
|
+
`);
|
|
9622
|
+
const additions = [];
|
|
9623
|
+
for (let index = 0;index < lines.length; index += 1) {
|
|
9624
|
+
const match = /^@@ -\d+(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(lines[index] ?? "");
|
|
9625
|
+
if (!match)
|
|
9626
|
+
continue;
|
|
9627
|
+
const oldCount = match[1] === undefined ? 1 : Number(match[1]);
|
|
9628
|
+
const start = Number(match[2]);
|
|
9629
|
+
const newCount = match[3] === undefined ? 1 : Number(match[3]);
|
|
9630
|
+
if (oldCount !== 0 || newCount === 0)
|
|
9631
|
+
continue;
|
|
9632
|
+
const added = [];
|
|
9633
|
+
for (let cursor = index + 1;cursor < lines.length; cursor += 1) {
|
|
9634
|
+
const line = lines[cursor] ?? "";
|
|
9635
|
+
if (line.startsWith("@@ "))
|
|
9636
|
+
break;
|
|
9637
|
+
if (line.startsWith("+"))
|
|
9638
|
+
added.push(line.slice(1));
|
|
9639
|
+
}
|
|
9640
|
+
if (added.length === newCount)
|
|
9641
|
+
additions.push({ start, lines: added });
|
|
9642
|
+
}
|
|
9643
|
+
return additions;
|
|
9279
9644
|
}
|
|
9280
|
-
function
|
|
9281
|
-
return
|
|
9645
|
+
function isSubstantial(lines) {
|
|
9646
|
+
return lines.filter((line) => line.trim()).length >= 3 && lines.join(`
|
|
9647
|
+
`).length >= 32;
|
|
9282
9648
|
}
|
|
9283
|
-
function
|
|
9284
|
-
|
|
9649
|
+
function isNamedClassMethod(lines) {
|
|
9650
|
+
const first = lines.find((line) => line.trim())?.trim() ?? "";
|
|
9651
|
+
const last = [...lines].reverse().find((line) => line.trim())?.trim() ?? "";
|
|
9652
|
+
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
9653
|
}
|
|
9286
|
-
function
|
|
9287
|
-
|
|
9654
|
+
function enclosingClass(lines, addition) {
|
|
9655
|
+
const memberIndent = leadingWhitespace(addition.lines.find((line) => line.trim()) ?? "");
|
|
9656
|
+
for (let index = addition.start - 2;index >= 0; index -= 1) {
|
|
9657
|
+
const line = lines[index] ?? "";
|
|
9658
|
+
if (!line.trim() || leadingWhitespace(line) >= memberIndent)
|
|
9659
|
+
continue;
|
|
9660
|
+
const match = /^(\s*)(?:(?:export|default|abstract|declare)\s+)*class\s+([A-Za-z_$][\w$]*)\b/.exec(line);
|
|
9661
|
+
if (!match)
|
|
9662
|
+
return;
|
|
9663
|
+
const name = match[2] ?? "";
|
|
9664
|
+
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;
|
|
9665
|
+
return `${name}#${ordinal}`;
|
|
9666
|
+
}
|
|
9288
9667
|
}
|
|
9289
|
-
function
|
|
9290
|
-
return
|
|
9668
|
+
function leadingWhitespace(line) {
|
|
9669
|
+
return /^\s*/.exec(line)?.[0].length ?? 0;
|
|
9291
9670
|
}
|
|
9292
|
-
function
|
|
9293
|
-
return {
|
|
9671
|
+
function escapeRegExp2(value) {
|
|
9672
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9294
9673
|
}
|
|
9295
|
-
function
|
|
9296
|
-
|
|
9674
|
+
function countSequence(lines, sequence) {
|
|
9675
|
+
let count = 0;
|
|
9676
|
+
for (let index = 0;index <= lines.length - sequence.length; index += 1) {
|
|
9677
|
+
if (sameLines(lines.slice(index, index + sequence.length), sequence)) {
|
|
9678
|
+
count += 1;
|
|
9679
|
+
}
|
|
9680
|
+
}
|
|
9681
|
+
return count;
|
|
9297
9682
|
}
|
|
9298
|
-
function
|
|
9299
|
-
|
|
9300
|
-
|
|
9683
|
+
function withoutAddition(lines, addition) {
|
|
9684
|
+
const index = addition.start - 1;
|
|
9685
|
+
if (!sameLines(lines.slice(index, index + addition.lines.length), addition.lines)) {
|
|
9686
|
+
return;
|
|
9687
|
+
}
|
|
9688
|
+
return [
|
|
9689
|
+
...lines.slice(0, index),
|
|
9690
|
+
...lines.slice(index + addition.lines.length)
|
|
9691
|
+
];
|
|
9301
9692
|
}
|
|
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]);
|
|
9693
|
+
function sameLines(left, right) {
|
|
9694
|
+
return left.length === right.length && left.every((line, index) => line === right[index]);
|
|
9761
9695
|
}
|
|
9762
9696
|
|
|
9763
9697
|
// src/update/merge.ts
|
|
9764
9698
|
async function mergeTextFile(base, ours, theirs) {
|
|
9765
|
-
const root = await mkdtemp2(
|
|
9699
|
+
const root = await mkdtemp2(join21(tmpdir2(), "windy-merge-"));
|
|
9766
9700
|
try {
|
|
9767
|
-
const oursPath =
|
|
9768
|
-
const basePath =
|
|
9769
|
-
const theirsPath =
|
|
9701
|
+
const oursPath = join21(root, "ours");
|
|
9702
|
+
const basePath = join21(root, "base");
|
|
9703
|
+
const theirsPath = join21(root, "theirs");
|
|
9770
9704
|
await Promise.all([
|
|
9771
9705
|
writeFile12(oursPath, ours),
|
|
9772
9706
|
writeFile12(basePath, base),
|
|
9773
9707
|
writeFile12(theirsPath, theirs)
|
|
9774
9708
|
]);
|
|
9775
|
-
const
|
|
9776
|
-
if (
|
|
9709
|
+
const result = await captureProcess("git", ["merge-file", "-p", "--diff3", oursPath, basePath, theirsPath], root);
|
|
9710
|
+
if (result.code === 0) {
|
|
9777
9711
|
const reconciledContent = await reconcileConvergentAdditions({
|
|
9778
9712
|
root,
|
|
9779
9713
|
basePath,
|
|
@@ -9782,18 +9716,18 @@ async function mergeTextFile(base, ours, theirs) {
|
|
|
9782
9716
|
base,
|
|
9783
9717
|
ours,
|
|
9784
9718
|
theirs,
|
|
9785
|
-
merged:
|
|
9719
|
+
merged: result.stdout
|
|
9786
9720
|
});
|
|
9787
9721
|
if (reconciledContent !== undefined) {
|
|
9788
9722
|
return { content: reconciledContent };
|
|
9789
9723
|
}
|
|
9790
|
-
return { content: new TextEncoder().encode(
|
|
9724
|
+
return { content: new TextEncoder().encode(result.stdout) };
|
|
9791
9725
|
}
|
|
9792
|
-
if (
|
|
9793
|
-
const resolved = resolveConservativeConflicts(
|
|
9726
|
+
if (result.code > 0 && result.code <= 127) {
|
|
9727
|
+
const resolved = resolveConservativeConflicts(result.stdout);
|
|
9794
9728
|
return resolved ? { content: new TextEncoder().encode(resolved) } : { conflict: "\u4E09\u65B9\u5408\u5E76\u5B58\u5728\u91CD\u53E0\u4FEE\u6539" };
|
|
9795
9729
|
}
|
|
9796
|
-
return { conflict:
|
|
9730
|
+
return { conflict: result.stderr.trim() || "git merge-file \u6267\u884C\u5931\u8D25" };
|
|
9797
9731
|
} finally {
|
|
9798
9732
|
await rm6(root, { recursive: true, force: true });
|
|
9799
9733
|
}
|
|
@@ -10197,7 +10131,7 @@ ${workflowArtifactProperty}`
|
|
|
10197
10131
|
];
|
|
10198
10132
|
let content = source;
|
|
10199
10133
|
for (const replacement of replacements2) {
|
|
10200
|
-
if (
|
|
10134
|
+
if (occurrences2(content, replacement.anchor) !== 1) {
|
|
10201
10135
|
return conflict3(input, `Agent Runtime Composition \u951A\u70B9\u4E0D\u552F\u4E00\uFF1A${replacement.anchor}`);
|
|
10202
10136
|
}
|
|
10203
10137
|
content = content.replace(replacement.anchor, replacement.value);
|
|
@@ -10227,7 +10161,7 @@ function conflict3(input, message) {
|
|
|
10227
10161
|
function decode(content) {
|
|
10228
10162
|
return new TextDecoder().decode(content);
|
|
10229
10163
|
}
|
|
10230
|
-
function
|
|
10164
|
+
function occurrences2(source, value) {
|
|
10231
10165
|
return source.split(value).length - 1;
|
|
10232
10166
|
}
|
|
10233
10167
|
function validateLegacyRuntimeObject(source) {
|
|
@@ -10235,22 +10169,22 @@ function validateLegacyRuntimeObject(source) {
|
|
|
10235
10169
|
...input,`;
|
|
10236
10170
|
const endAnchor = `
|
|
10237
10171
|
});`;
|
|
10238
|
-
if (
|
|
10172
|
+
if (occurrences2(source, startAnchor) !== 1 || occurrences2(source, endAnchor) !== 1) {
|
|
10239
10173
|
return "Agent Runtime register object \u951A\u70B9\u4E0D\u552F\u4E00";
|
|
10240
10174
|
}
|
|
10241
10175
|
const start = source.indexOf(startAnchor);
|
|
10242
10176
|
const end = source.indexOf(endAnchor, start + startAnchor.length);
|
|
10243
10177
|
if (end < 0)
|
|
10244
10178
|
return "Agent Runtime register object \u7ED3\u675F\u951A\u70B9\u7F3A\u5931";
|
|
10245
|
-
const
|
|
10246
|
-
const host =
|
|
10179
|
+
const object2 = source.slice(start, end);
|
|
10180
|
+
const host = object2.indexOf(hostAuthProperty);
|
|
10247
10181
|
if (host < 0)
|
|
10248
10182
|
return "Agent Runtime Host Auth property \u951A\u70B9\u7F3A\u5931";
|
|
10249
|
-
const tail =
|
|
10183
|
+
const tail = object2.slice(host + hostAuthProperty.length);
|
|
10250
10184
|
if (/^\s*\.\.\./m.test(tail)) {
|
|
10251
10185
|
return "Workflow binding \u63D2\u5165\u70B9\u540E\u5B58\u5728\u53EF\u8986\u76D6\u5B83\u7684 spread";
|
|
10252
10186
|
}
|
|
10253
|
-
if (/["']clientAgentWorkflowArtifactBindings["']\s*:/.test(
|
|
10187
|
+
if (/["']clientAgentWorkflowArtifactBindings["']\s*:/.test(object2) || /\[\s*["']clientAgentWorkflowArtifactBindings["']\s*\]/.test(object2)) {
|
|
10254
10188
|
return "Agent Runtime \u5DF2\u5B58\u5728\u52A8\u6001 Workflow binding property";
|
|
10255
10189
|
}
|
|
10256
10190
|
return;
|
|
@@ -10285,266 +10219,451 @@ function addAiRuntimeTrajectoryTestFixture(source) {
|
|
|
10285
10219
|
};
|
|
10286
10220
|
}
|
|
10287
10221
|
|
|
10288
|
-
// src/update/recipe-project-owned.ts
|
|
10289
|
-
var managedPathsByRecipe = {
|
|
10290
|
-
"starter-0.
|
|
10291
|
-
|
|
10292
|
-
"apps/web/src/router/
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
"apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.
|
|
10297
|
-
"apps/web/src/
|
|
10298
|
-
"apps/web/src/router/
|
|
10299
|
-
"apps/web/src/
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10222
|
+
// src/update/recipe-project-owned.ts
|
|
10223
|
+
var managedPathsByRecipe = {
|
|
10224
|
+
"starter-0.9.1-to-0.10.0": adminApiRecipePaths,
|
|
10225
|
+
"starter-0.6.8-to-0.6.9": [
|
|
10226
|
+
"apps/web/src/router/index.ts",
|
|
10227
|
+
"apps/web/src/router/platform-admin-route-bindings.ts"
|
|
10228
|
+
],
|
|
10229
|
+
"starter-0.6.13-to-0.6.14": [
|
|
10230
|
+
"apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.webtest.ts",
|
|
10231
|
+
"apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.vue",
|
|
10232
|
+
"apps/web/src/router/index.ts",
|
|
10233
|
+
"apps/web/src/router/platform-admin-route-bindings.ts",
|
|
10234
|
+
"apps/web/src/services/ai-runtime-api.ts"
|
|
10235
|
+
],
|
|
10236
|
+
"starter-0.6.14-to-0.6.15": [
|
|
10237
|
+
clientWorkflowCompositionPath,
|
|
10238
|
+
clientWorkflowBindingPath
|
|
10239
|
+
]
|
|
10240
|
+
};
|
|
10241
|
+
function recipeManagedProjectOwnedPaths(recipes2) {
|
|
10242
|
+
return new Set(recipes2.flatMap((recipe) => managedPathsByRecipe[recipe] ?? []));
|
|
10243
|
+
}
|
|
10244
|
+
function recipeCanManageMissingProjectOwnedPath(path2) {
|
|
10245
|
+
return path2 === clientWorkflowCompositionPath || path2 === clientWorkflowBindingPath;
|
|
10246
|
+
}
|
|
10247
|
+
async function planRecipeProjectOwned(input) {
|
|
10248
|
+
if (input.path === clientWorkflowCompositionPath || input.path === clientWorkflowBindingPath) {
|
|
10249
|
+
if (!input.target) {
|
|
10250
|
+
return conflict4(input, "\u7248\u672C recipe \u6240\u9700\u7684\u76EE\u6807\u6587\u4EF6\u7F3A\u5931");
|
|
10251
|
+
}
|
|
10252
|
+
return planClientWorkflowProjectOwned({ ...input, target: input.target });
|
|
10253
|
+
}
|
|
10254
|
+
if (!input.ours) {
|
|
10255
|
+
return conflict4(input, "\u7248\u672C recipe \u6240\u9700\u7684\u9879\u76EE\u951A\u70B9\u7F3A\u5931");
|
|
10256
|
+
}
|
|
10257
|
+
const source = new TextDecoder().decode(input.ours);
|
|
10258
|
+
const target = input.target ? new TextDecoder().decode(input.target) : undefined;
|
|
10259
|
+
const transformed = transformProjectOwnedAnchor(input.path, source, target);
|
|
10260
|
+
if ("error" in transformed)
|
|
10261
|
+
return conflict4(input, transformed.error);
|
|
10262
|
+
if (transformed.content === source) {
|
|
10263
|
+
return preserve(input, "\u5DF2\u5305\u542B\u7248\u672C recipe \u76EE\u6807\u5185\u5BB9");
|
|
10264
|
+
}
|
|
10265
|
+
return update(input, new TextEncoder().encode(transformed.content));
|
|
10266
|
+
}
|
|
10267
|
+
function transformProjectOwnedAnchor(path2, source, target) {
|
|
10268
|
+
if (isAdminApiRecipePath(path2))
|
|
10269
|
+
return addAdminApiExports(path2, source, target);
|
|
10270
|
+
if (path2 === "apps/web/src/router/index.ts") {
|
|
10271
|
+
return addComponentPageLoader(source, target);
|
|
10272
|
+
}
|
|
10273
|
+
if (path2 === "apps/web/src/router/platform-admin-route-bindings.ts") {
|
|
10274
|
+
return addComponentRouteBinding(source, target);
|
|
10275
|
+
}
|
|
10276
|
+
if (path2 === "apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.webtest.ts") {
|
|
10277
|
+
return addAiRuntimeTrajectoryTestFixture(source);
|
|
10278
|
+
}
|
|
10279
|
+
if (path2 === "apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.vue") {
|
|
10280
|
+
return addAiRuntimeTrajectoryView(source);
|
|
10281
|
+
}
|
|
10282
|
+
if (path2 === "apps/web/src/services/ai-runtime-api.ts") {
|
|
10283
|
+
return addAiRuntimeTrajectoryContract(source);
|
|
10284
|
+
}
|
|
10285
|
+
return { error: `\u7248\u672C recipe \u672A\u767B\u8BB0\u9879\u76EE\u951A\u70B9\uFF1A${path2}` };
|
|
10286
|
+
}
|
|
10287
|
+
function addAiRuntimeTrajectoryContract(source) {
|
|
10288
|
+
let content = source;
|
|
10289
|
+
const typeField = ' readonly trajectory: RuntimeRunDetail["trajectory"];';
|
|
10290
|
+
if (!content.includes(typeField)) {
|
|
10291
|
+
const anchors = [
|
|
10292
|
+
...content.matchAll(/^(\s*)readonly attemptItems: readonly AiRuntimeAttempt\[\];$/gm)
|
|
10293
|
+
];
|
|
10294
|
+
if (anchors.length !== 1) {
|
|
10295
|
+
return { error: "AiRuntimeRunDetail attemptItems \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10296
|
+
}
|
|
10297
|
+
content = content.replace(anchors[0][0], `${anchors[0][0]}
|
|
10298
|
+
${anchors[0][1]}readonly trajectory: RuntimeRunDetail["trajectory"];`);
|
|
10299
|
+
}
|
|
10300
|
+
const mapperField = " trajectory: value.trajectory,";
|
|
10301
|
+
if (!content.includes(mapperField)) {
|
|
10302
|
+
const anchors = [
|
|
10303
|
+
...content.matchAll(/^(\s*)attemptItems: value\.attempts\.map\(attemptItem\),$/gm)
|
|
10304
|
+
];
|
|
10305
|
+
if (anchors.length !== 1) {
|
|
10306
|
+
return { error: "runDetail attemptItems mapper \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10307
|
+
}
|
|
10308
|
+
content = content.replace(anchors[0][0], `${anchors[0][0]}
|
|
10309
|
+
${anchors[0][1]}trajectory: value.trajectory,`);
|
|
10310
|
+
}
|
|
10311
|
+
return { content };
|
|
10312
|
+
}
|
|
10313
|
+
function addAiRuntimeTrajectoryView(source) {
|
|
10314
|
+
let content = source;
|
|
10315
|
+
const componentImport = 'import AiRuntimeTrajectory from "./AiRuntimeTrajectory.vue";';
|
|
10316
|
+
if (!content.includes(componentImport)) {
|
|
10317
|
+
const anchors = [
|
|
10318
|
+
...content.matchAll(/^} from "\.\.\/\.\.\/ai-runtime-presenter";$/gm)
|
|
10319
|
+
];
|
|
10320
|
+
if (anchors.length !== 1) {
|
|
10321
|
+
return { error: "AI Runtime presenter import \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10322
|
+
}
|
|
10323
|
+
content = content.replace(anchors[0][0], `${anchors[0][0]}
|
|
10324
|
+
${componentImport}`);
|
|
10325
|
+
}
|
|
10326
|
+
const componentUsage = '<AiRuntimeTrajectory :trajectory="detail.trajectory" />';
|
|
10327
|
+
if (!content.includes(componentUsage)) {
|
|
10328
|
+
const providerSections = [
|
|
10329
|
+
...content.matchAll(/^(\s*)<section class="space-y-3">\n\s*<h3 class="text-sm font-medium">Provider Attempts<\/h3>$/gm)
|
|
10330
|
+
];
|
|
10331
|
+
if (providerSections.length !== 1) {
|
|
10332
|
+
return { error: "Provider Attempts section \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10333
|
+
}
|
|
10334
|
+
const providerSection = providerSections[0];
|
|
10335
|
+
content = content.replace(providerSection[0], `${providerSection[1]}${componentUsage}
|
|
10336
|
+
|
|
10337
|
+
${providerSection[0]}`);
|
|
10338
|
+
}
|
|
10339
|
+
return { content };
|
|
10340
|
+
}
|
|
10341
|
+
function addComponentPageLoader(source, target) {
|
|
10342
|
+
const desired = [
|
|
10343
|
+
{
|
|
10344
|
+
key: "ui-components",
|
|
10345
|
+
value: '() => import("@/pages/ui/UiComponentPage.vue")'
|
|
10346
|
+
},
|
|
10347
|
+
...target?.includes('"agent-session": AgentSessionPage') ? [
|
|
10348
|
+
{
|
|
10349
|
+
key: "agent-session",
|
|
10350
|
+
value: '() => import("@/pages/system/AgentSessionPage.vue")'
|
|
10351
|
+
},
|
|
10352
|
+
{
|
|
10353
|
+
key: "agent-workflow",
|
|
10354
|
+
value: '() => import("@/pages/system/AgentWorkflowPage.vue")'
|
|
10355
|
+
}
|
|
10356
|
+
] : []
|
|
10357
|
+
];
|
|
10358
|
+
const missing = desired.filter(({ key }) => !new RegExp(`^\\s*"${key}"\\s*:`, "m").test(source));
|
|
10359
|
+
if (!missing.length)
|
|
10360
|
+
return { content: source };
|
|
10361
|
+
const declaration = source.indexOf("const platformAdminPageComponents");
|
|
10362
|
+
const start = source.indexOf("= {", declaration);
|
|
10363
|
+
const end = source.indexOf(`
|
|
10364
|
+
};`, start);
|
|
10365
|
+
if (declaration < 0 || start < 0 || end < 0) {
|
|
10366
|
+
return { error: "\u627E\u4E0D\u5230 platformAdminPageComponents \u9879\u76EE\u951A\u70B9" };
|
|
10367
|
+
}
|
|
10368
|
+
const block = source.slice(start, end);
|
|
10369
|
+
const profiles = [...block.matchAll(/^(\s*)profile:\s*.*,$/gm)];
|
|
10370
|
+
if (profiles.length !== 1) {
|
|
10371
|
+
return { error: "platformAdminPageComponents profile \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10372
|
+
}
|
|
10373
|
+
const profile = profiles[0];
|
|
10374
|
+
const insertion = [
|
|
10375
|
+
profile[0],
|
|
10376
|
+
...missing.map(({ key, value }) => `${profile[1]}"${key}": ${value},`)
|
|
10377
|
+
].join(`
|
|
10378
|
+
`);
|
|
10379
|
+
return {
|
|
10380
|
+
content: source.slice(0, start) + block.replace(profile[0], insertion) + source.slice(end)
|
|
10381
|
+
};
|
|
10382
|
+
}
|
|
10383
|
+
function addComponentRouteBinding(source, target) {
|
|
10384
|
+
const unionStart = source.indexOf("export type PlatformAdminPageKey =");
|
|
10385
|
+
const interfaceStart = source.indexOf("export interface PlatformAdminRouteBinding", unionStart);
|
|
10386
|
+
if (unionStart < 0 || interfaceStart < 0) {
|
|
10387
|
+
return { error: "\u627E\u4E0D\u5230 PlatformAdminPageKey \u9879\u76EE\u951A\u70B9" };
|
|
10388
|
+
}
|
|
10389
|
+
const desiredPages = [
|
|
10390
|
+
"ui-components",
|
|
10391
|
+
...target?.includes('routeKey: "system.agent-session"') ? ["agent-session", "agent-workflow"] : []
|
|
10392
|
+
];
|
|
10393
|
+
let content = source;
|
|
10394
|
+
const union = content.slice(unionStart, interfaceStart);
|
|
10395
|
+
const missingPages = desiredPages.filter((page) => !union.includes(`"${page}"`));
|
|
10396
|
+
if (missingPages.length) {
|
|
10397
|
+
const semicolon = content.lastIndexOf(";", interfaceStart);
|
|
10398
|
+
if (semicolon < unionStart) {
|
|
10399
|
+
return { error: "PlatformAdminPageKey \u7ED3\u675F\u951A\u70B9\u7F3A\u5931" };
|
|
10400
|
+
}
|
|
10401
|
+
content = `${content.slice(0, semicolon)}
|
|
10402
|
+
${missingPages.map((page) => ` | "${page}"`).join(`
|
|
10403
|
+
`)}${content.slice(semicolon)}`;
|
|
10404
|
+
}
|
|
10405
|
+
const desiredBindings = [
|
|
10406
|
+
{ routeKey: "system.ui-components", page: "ui-components" },
|
|
10407
|
+
...target?.includes('routeKey: "system.agent-session"') ? [
|
|
10408
|
+
{ routeKey: "system.agent-session", page: "agent-session" },
|
|
10409
|
+
{ routeKey: "system.agent-workflow", page: "agent-workflow" }
|
|
10410
|
+
] : []
|
|
10411
|
+
];
|
|
10412
|
+
const missingBindings = desiredBindings.filter(({ routeKey }) => !content.includes(`routeKey: "${routeKey}"`));
|
|
10413
|
+
if (!missingBindings.length)
|
|
10414
|
+
return { content };
|
|
10415
|
+
const features = [
|
|
10416
|
+
...content.matchAll(/^(\s*)\{ routeKey: "system\.feature", page: "resource", resourceKey: "features" \},$/gm)
|
|
10417
|
+
];
|
|
10418
|
+
if (features.length !== 1) {
|
|
10419
|
+
return { error: "system.feature Admin Route \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10420
|
+
}
|
|
10421
|
+
const feature = features[0];
|
|
10422
|
+
return {
|
|
10423
|
+
content: content.replace(feature[0], [
|
|
10424
|
+
feature[0],
|
|
10425
|
+
...missingBindings.map(({ routeKey, page }) => `${feature[1]}{ routeKey: "${routeKey}", page: "${page}" },`)
|
|
10426
|
+
].join(`
|
|
10427
|
+
`))
|
|
10428
|
+
};
|
|
10429
|
+
}
|
|
10430
|
+
function preserve(input, reason) {
|
|
10431
|
+
return {
|
|
10432
|
+
path: input.path,
|
|
10433
|
+
ownership: "project-owned",
|
|
10434
|
+
action: "preserve",
|
|
10435
|
+
reason,
|
|
10436
|
+
expectedProjectContent: input.expected
|
|
10437
|
+
};
|
|
10438
|
+
}
|
|
10439
|
+
function update(input, content) {
|
|
10440
|
+
return {
|
|
10441
|
+
path: input.path,
|
|
10442
|
+
ownership: "project-owned",
|
|
10443
|
+
action: "update",
|
|
10444
|
+
reason: "\u7248\u672C recipe \u66F4\u65B0\u9879\u76EE\u6269\u5C55\u951A\u70B9",
|
|
10445
|
+
expectedProjectContent: input.expected,
|
|
10446
|
+
content
|
|
10447
|
+
};
|
|
10448
|
+
}
|
|
10449
|
+
function conflict4(input, message) {
|
|
10450
|
+
return {
|
|
10451
|
+
path: input.path,
|
|
10452
|
+
ownership: "project-owned",
|
|
10453
|
+
action: "preserve",
|
|
10454
|
+
reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
|
|
10455
|
+
expectedProjectContent: input.expected,
|
|
10456
|
+
conflict: message
|
|
10457
|
+
};
|
|
10458
|
+
}
|
|
10459
|
+
|
|
10460
|
+
// src/update/dsh-platform-recipe.ts
|
|
10461
|
+
import { join as join22 } from "path";
|
|
10462
|
+
var dshPlatformRecipeId = "dsh-platform-v1";
|
|
10463
|
+
var dshPlatformRecipePaths = new Set([
|
|
10464
|
+
"apps/server/src/app/agent-workflow-presets.ts",
|
|
10465
|
+
"apps/server/src/app/workbench-public-origin.ts",
|
|
10466
|
+
"apps/web/src/router/index.ts",
|
|
10467
|
+
"apps/web/src/router/platform-admin-pages.ts",
|
|
10468
|
+
"apps/web/src/router/platform-admin-route-bindings.ts",
|
|
10469
|
+
"apps/web/src/composables/useLoginFlow.ts",
|
|
10470
|
+
"apps/web/src/pages/system/AgentWorkflowPage.vue",
|
|
10471
|
+
"apps/web/src/services/agent-workflow-api.ts",
|
|
10472
|
+
"apps/web/vite.config.ts",
|
|
10473
|
+
"apps/web/server.ts",
|
|
10474
|
+
"apps/web/runtime-server.ts",
|
|
10475
|
+
"apps/web/dev/start.ts"
|
|
10476
|
+
]);
|
|
10477
|
+
function isDshPlatformRecipePath(path2) {
|
|
10478
|
+
return dshPlatformRecipePaths.has(path2) || path2.startsWith("apps/server/src/app/dsh-") && path2.endsWith(".ts");
|
|
10308
10479
|
}
|
|
10309
|
-
function
|
|
10310
|
-
|
|
10480
|
+
async function isDshPlatformTransition(input) {
|
|
10481
|
+
if (!input.sourceModules.includes("system.agent") || !input.targetModules.includes("system.agent"))
|
|
10482
|
+
return false;
|
|
10483
|
+
const path2 = "apps/agent-server/package.json";
|
|
10484
|
+
const [base, target] = await Promise.all([
|
|
10485
|
+
readOptional(join22(input.baseDirectory, path2)),
|
|
10486
|
+
readOptional(join22(input.targetDirectory, path2))
|
|
10487
|
+
]);
|
|
10488
|
+
return hasDsh(target) && !hasDsh(base);
|
|
10311
10489
|
}
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10490
|
+
function planDshPlatformFile(input) {
|
|
10491
|
+
const common2 = {
|
|
10492
|
+
path: input.path,
|
|
10493
|
+
ownership: input.ownership,
|
|
10494
|
+
expectedProjectContent: input.expected
|
|
10495
|
+
};
|
|
10496
|
+
if (input.target && input.ours && hashContent(input.ours) === hashContent(input.target)) {
|
|
10497
|
+
return {
|
|
10498
|
+
...common2,
|
|
10499
|
+
action: "preserve",
|
|
10500
|
+
reason: "\u5DF2\u5305\u542B DSH \u5E73\u53F0\u63A5\u7EBF\u76EE\u6807\u5185\u5BB9"
|
|
10501
|
+
};
|
|
10318
10502
|
}
|
|
10319
|
-
if (!input.ours) {
|
|
10320
|
-
return
|
|
10503
|
+
if (input.target && !input.ours && !input.base) {
|
|
10504
|
+
return {
|
|
10505
|
+
...common2,
|
|
10506
|
+
action: "create",
|
|
10507
|
+
reason: "DSH \u5E73\u53F0\u65B0\u589E\u9879\u76EE\u6269\u5C55\u70B9",
|
|
10508
|
+
content: input.target
|
|
10509
|
+
};
|
|
10321
10510
|
}
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
|
|
10511
|
+
if (input.target && input.base && input.ours && hashContent(input.ours) === hashContent(input.base)) {
|
|
10512
|
+
return {
|
|
10513
|
+
...common2,
|
|
10514
|
+
action: "update",
|
|
10515
|
+
reason: "DSH \u5E73\u53F0\u5347\u7EA7\u7CBE\u786E\u6765\u6E90\u63A5\u7EBF",
|
|
10516
|
+
content: input.target
|
|
10517
|
+
};
|
|
10329
10518
|
}
|
|
10330
|
-
return
|
|
10519
|
+
return {
|
|
10520
|
+
...common2,
|
|
10521
|
+
action: "preserve",
|
|
10522
|
+
reason: "\u4FDD\u7559\u5BA2\u6237 DSH \u63A5\u7EBF",
|
|
10523
|
+
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"
|
|
10524
|
+
};
|
|
10331
10525
|
}
|
|
10332
|
-
function
|
|
10333
|
-
if (
|
|
10334
|
-
return
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
return addComponentRouteBinding(source, target);
|
|
10338
|
-
}
|
|
10339
|
-
if (path2 === "apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.webtest.ts") {
|
|
10340
|
-
return addAiRuntimeTrajectoryTestFixture(source);
|
|
10341
|
-
}
|
|
10342
|
-
if (path2 === "apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.vue") {
|
|
10343
|
-
return addAiRuntimeTrajectoryView(source);
|
|
10344
|
-
}
|
|
10345
|
-
if (path2 === "apps/web/src/services/ai-runtime-api.ts") {
|
|
10346
|
-
return addAiRuntimeTrajectoryContract(source);
|
|
10347
|
-
}
|
|
10348
|
-
return { error: `\u7248\u672C recipe \u672A\u767B\u8BB0\u9879\u76EE\u951A\u70B9\uFF1A${path2}` };
|
|
10526
|
+
function hasDsh(content) {
|
|
10527
|
+
if (!content)
|
|
10528
|
+
return false;
|
|
10529
|
+
const value = JSON.parse(new TextDecoder().decode(content));
|
|
10530
|
+
return typeof value.dependencies?.["@deepseek-ai/dsh"] === "string";
|
|
10349
10531
|
}
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10532
|
+
|
|
10533
|
+
// src/update/planner-file.ts
|
|
10534
|
+
async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride, manageGeneratedProjectOwned = false, forcePlatformBaseline = false, manageRecipeProjectOwned = false, migrateDshPlatform = false) {
|
|
10535
|
+
const [base, theirs] = await Promise.all([
|
|
10536
|
+
readOptional2(join23(baseRoot, path2)),
|
|
10537
|
+
targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional2(join23(targetRoot, path2))
|
|
10538
|
+
]);
|
|
10539
|
+
const ownership = source?.ownership ?? target?.ownership ?? classifyOwnership(path2);
|
|
10540
|
+
const expected = expectationForSnapshot(ours);
|
|
10541
|
+
if (migrateDshPlatform && isDshPlatformRecipePath(path2)) {
|
|
10542
|
+
return planDshPlatformFile({
|
|
10543
|
+
path: path2,
|
|
10544
|
+
ownership,
|
|
10545
|
+
ours,
|
|
10546
|
+
base,
|
|
10547
|
+
target: theirs,
|
|
10548
|
+
expected
|
|
10549
|
+
});
|
|
10550
|
+
}
|
|
10551
|
+
if (ownership === "project-owned") {
|
|
10552
|
+
const hasExistingRecipeSource = source !== undefined && source.state !== "missing" && ours !== undefined;
|
|
10553
|
+
if (manageRecipeProjectOwned && target && (hasExistingRecipeSource || source !== undefined && isAdminApiRecipePath(path2) || recipeCanManageMissingProjectOwnedPath(path2))) {
|
|
10554
|
+
return planRecipeProjectOwned({ path: path2, ours, target: theirs, expected });
|
|
10359
10555
|
}
|
|
10360
|
-
|
|
10361
|
-
|
|
10556
|
+
if (manageGeneratedProjectOwned) {
|
|
10557
|
+
return planGeneratedProjectOwned(path2, source, target, ours, theirs, expected);
|
|
10558
|
+
}
|
|
10559
|
+
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);
|
|
10362
10560
|
}
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
return { error: "runDetail attemptItems mapper \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10561
|
+
if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
|
|
10562
|
+
if (source && !target) {
|
|
10563
|
+
return conflict(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
|
|
10564
|
+
}
|
|
10565
|
+
if (source && target && source.hash !== target.hash) {
|
|
10566
|
+
return conflict(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
|
|
10370
10567
|
}
|
|
10371
|
-
content = content.replace(anchors[0][0], `${anchors[0][0]}
|
|
10372
|
-
${anchors[0][1]}trajectory: value.trajectory,`);
|
|
10373
10568
|
}
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
let content = source;
|
|
10378
|
-
const componentImport = 'import AiRuntimeTrajectory from "./AiRuntimeTrajectory.vue";';
|
|
10379
|
-
if (!content.includes(componentImport)) {
|
|
10380
|
-
const anchors = [
|
|
10381
|
-
...content.matchAll(/^} from "\.\.\/\.\.\/ai-runtime-presenter";$/gm)
|
|
10382
|
-
];
|
|
10383
|
-
if (anchors.length !== 1) {
|
|
10384
|
-
return { error: "AI Runtime presenter import \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10569
|
+
if (!source && target) {
|
|
10570
|
+
if (!ours) {
|
|
10571
|
+
return readyPlannedFile(path2, ownership, "create", "\u76EE\u6807\u7248\u672C\u65B0\u589E", expected, theirs);
|
|
10385
10572
|
}
|
|
10386
|
-
|
|
10387
|
-
${componentImport}`);
|
|
10573
|
+
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);
|
|
10388
10574
|
}
|
|
10389
|
-
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
...content.matchAll(/^(\s*)<section class="space-y-3">\n\s*<h3 class="text-sm font-medium">Provider Attempts<\/h3>$/gm)
|
|
10393
|
-
];
|
|
10394
|
-
if (providerSections.length !== 1) {
|
|
10395
|
-
return { error: "Provider Attempts section \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10575
|
+
if (source && !target) {
|
|
10576
|
+
if (!ours) {
|
|
10577
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
|
|
10396
10578
|
}
|
|
10397
|
-
|
|
10398
|
-
|
|
10399
|
-
|
|
10400
|
-
|
|
10579
|
+
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);
|
|
10580
|
+
}
|
|
10581
|
+
if (source && target && !ours) {
|
|
10582
|
+
return readyPlannedFile(path2, "project-owned", "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
|
|
10583
|
+
}
|
|
10584
|
+
if (!source || !target || !ours || !theirs) {
|
|
10585
|
+
return conflict(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
|
|
10586
|
+
}
|
|
10587
|
+
const oursChanged = hashContent(ours) !== source.hash;
|
|
10588
|
+
const sourceArtifactHash = artifactHashOf(source);
|
|
10589
|
+
const targetChanged = targetChangedSinceBase(sourceArtifactHash, base, theirs);
|
|
10590
|
+
const adoptedProjectDelta = source.artifactHash !== undefined && source.artifactHash !== source.hash;
|
|
10591
|
+
const forceTargetBaseline = !adoptedProjectDelta && shouldForcePlatformBaseline({
|
|
10592
|
+
forcePlatformBaseline,
|
|
10593
|
+
oursChanged,
|
|
10594
|
+
sourceArtifactHash,
|
|
10595
|
+
base
|
|
10596
|
+
});
|
|
10597
|
+
if (forceTargetBaseline && path2.endsWith("package.json") && base) {
|
|
10598
|
+
const merged = mergePackageJson(base, ours, theirs);
|
|
10599
|
+
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);
|
|
10600
|
+
}
|
|
10601
|
+
if (forceTargetBaseline) {
|
|
10602
|
+
return readyPlannedFile(path2, ownership, "update", "\u5F3A\u5236\u91C7\u7528\u76EE\u6807\u5E73\u53F0\u57FA\u7EBF", expected, theirs);
|
|
10603
|
+
}
|
|
10604
|
+
if (!oursChanged && !targetChanged) {
|
|
10605
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u53CC\u65B9\u672A\u4FEE\u6539", expected);
|
|
10401
10606
|
}
|
|
10402
|
-
|
|
10403
|
-
|
|
10404
|
-
|
|
10405
|
-
const desired = [
|
|
10406
|
-
{
|
|
10407
|
-
key: "ui-components",
|
|
10408
|
-
value: '() => import("@/pages/ui/UiComponentPage.vue")'
|
|
10409
|
-
},
|
|
10410
|
-
...target?.includes('"agent-session": AgentSessionPage') ? [
|
|
10411
|
-
{
|
|
10412
|
-
key: "agent-session",
|
|
10413
|
-
value: '() => import("@/pages/system/AgentSessionPage.vue")'
|
|
10414
|
-
},
|
|
10415
|
-
{
|
|
10416
|
-
key: "agent-workflow",
|
|
10417
|
-
value: '() => import("@/pages/system/AgentWorkflowPage.vue")'
|
|
10418
|
-
}
|
|
10419
|
-
] : []
|
|
10420
|
-
];
|
|
10421
|
-
const missing = desired.filter(({ key }) => !new RegExp(`^\\s*"${key}"\\s*:`, "m").test(source));
|
|
10422
|
-
if (!missing.length)
|
|
10423
|
-
return { content: source };
|
|
10424
|
-
const declaration = source.indexOf("const platformAdminPageComponents");
|
|
10425
|
-
const start = source.indexOf("= {", declaration);
|
|
10426
|
-
const end = source.indexOf(`
|
|
10427
|
-
};`, start);
|
|
10428
|
-
if (declaration < 0 || start < 0 || end < 0) {
|
|
10429
|
-
return { error: "\u627E\u4E0D\u5230 platformAdminPageComponents \u9879\u76EE\u951A\u70B9" };
|
|
10607
|
+
if (targetChanged && path2.endsWith("package.json") && base) {
|
|
10608
|
+
const merged = mergePackageJson(base, ours, theirs);
|
|
10609
|
+
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);
|
|
10430
10610
|
}
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
|
|
10434
|
-
return { error: "platformAdminPageComponents profile \u951A\u70B9\u4E0D\u552F\u4E00" };
|
|
10611
|
+
if (!oursChanged && targetChanged && adoptedProjectDelta && base) {
|
|
10612
|
+
const merged = await mergeTextFile(base, ours, theirs);
|
|
10613
|
+
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);
|
|
10435
10614
|
}
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
profile[0],
|
|
10439
|
-
...missing.map(({ key, value }) => `${profile[1]}"${key}": ${value},`)
|
|
10440
|
-
].join(`
|
|
10441
|
-
`);
|
|
10442
|
-
return {
|
|
10443
|
-
content: source.slice(0, start) + block.replace(profile[0], insertion) + source.slice(end)
|
|
10444
|
-
};
|
|
10445
|
-
}
|
|
10446
|
-
function addComponentRouteBinding(source, target) {
|
|
10447
|
-
const unionStart = source.indexOf("export type PlatformAdminPageKey =");
|
|
10448
|
-
const interfaceStart = source.indexOf("export interface PlatformAdminRouteBinding", unionStart);
|
|
10449
|
-
if (unionStart < 0 || interfaceStart < 0) {
|
|
10450
|
-
return { error: "\u627E\u4E0D\u5230 PlatformAdminPageKey \u9879\u76EE\u951A\u70B9" };
|
|
10615
|
+
if (!oursChanged) {
|
|
10616
|
+
return readyPlannedFile(path2, ownership, "update", "\u4EC5 Windy \u4FEE\u6539", expected, theirs);
|
|
10451
10617
|
}
|
|
10452
|
-
|
|
10453
|
-
"
|
|
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)}`;
|
|
10618
|
+
if (!targetChanged) {
|
|
10619
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u5BA2\u6237\u5DF2\u4FEE\u6539", expected);
|
|
10467
10620
|
}
|
|
10468
|
-
|
|
10469
|
-
|
|
10470
|
-
...target?.includes('routeKey: "system.agent-session"') ? [
|
|
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" };
|
|
10621
|
+
if (hashContent(ours) === target.hash) {
|
|
10622
|
+
return readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected);
|
|
10483
10623
|
}
|
|
10484
|
-
|
|
10485
|
-
|
|
10486
|
-
content:
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
].join(`
|
|
10490
|
-
`))
|
|
10491
|
-
};
|
|
10624
|
+
if (base) {
|
|
10625
|
+
const merged = await mergeTextFile(base, ours, theirs);
|
|
10626
|
+
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);
|
|
10627
|
+
}
|
|
10628
|
+
return conflict(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
|
|
10492
10629
|
}
|
|
10493
|
-
function
|
|
10494
|
-
return
|
|
10495
|
-
path: input.path,
|
|
10496
|
-
ownership: "project-owned",
|
|
10497
|
-
action: "preserve",
|
|
10498
|
-
reason,
|
|
10499
|
-
expectedProjectContent: input.expected
|
|
10500
|
-
};
|
|
10630
|
+
function shouldForcePlatformBaseline(input) {
|
|
10631
|
+
return input.forcePlatformBaseline && !input.oursChanged && input.base !== undefined && hashContent(input.base) !== input.sourceArtifactHash;
|
|
10501
10632
|
}
|
|
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
|
-
};
|
|
10633
|
+
function targetChangedSinceBase(sourceHash, base, target) {
|
|
10634
|
+
return base && target ? hashContent(base) !== hashContent(target) : !!target && hashContent(target) !== sourceHash;
|
|
10511
10635
|
}
|
|
10512
|
-
function
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
}
|
|
10636
|
+
async function readOptional2(path2) {
|
|
10637
|
+
try {
|
|
10638
|
+
return await readFile16(path2);
|
|
10639
|
+
} catch (error) {
|
|
10640
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
10641
|
+
return;
|
|
10642
|
+
}
|
|
10643
|
+
throw error;
|
|
10644
|
+
}
|
|
10521
10645
|
}
|
|
10522
10646
|
|
|
10523
|
-
// src/update/dsh-platform-recipe.ts
|
|
10524
|
-
import { join as join26 } from "path";
|
|
10525
|
-
|
|
10526
10647
|
// src/update/planner-snapshots.ts
|
|
10527
|
-
import { readFile as readFile20, stat as stat2 } from "fs/promises";
|
|
10528
|
-
import { join as join25 } from "path";
|
|
10529
10648
|
async function snapshotProjectFiles(project, paths, seed) {
|
|
10530
10649
|
const snapshots = new Map(seed);
|
|
10531
10650
|
await Promise.all([...paths].filter((path2) => !snapshots.has(path2)).map(async (path2) => {
|
|
10532
|
-
snapshots.set(path2, await readOptional(
|
|
10651
|
+
snapshots.set(path2, await readOptional(join24(project, path2)));
|
|
10533
10652
|
}));
|
|
10534
10653
|
return snapshots;
|
|
10535
10654
|
}
|
|
10536
10655
|
async function snapshotProjectModes(project, paths) {
|
|
10537
|
-
return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(
|
|
10656
|
+
return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(join24(project, path2))])));
|
|
10538
10657
|
}
|
|
10539
10658
|
async function assertPlanSnapshots(project, expectations) {
|
|
10540
10659
|
const changed = [];
|
|
10541
10660
|
for (const expectation2 of expectations) {
|
|
10542
|
-
const actual = expectationForSnapshot(await readOptional(
|
|
10661
|
+
const actual = expectationForSnapshot(await readOptional(join24(project, expectation2.path)));
|
|
10543
10662
|
if (JSON.stringify(actual) !== JSON.stringify(expectation2.expected)) {
|
|
10544
10663
|
changed.push(expectation2.path);
|
|
10545
10664
|
continue;
|
|
10546
10665
|
}
|
|
10547
|
-
if ("mode" in expectation2 && await readModeOptional(
|
|
10666
|
+
if ("mode" in expectation2 && await readModeOptional(join24(project, expectation2.path)) !== expectation2.mode) {
|
|
10548
10667
|
changed.push(expectation2.path);
|
|
10549
10668
|
}
|
|
10550
10669
|
}
|
|
@@ -10574,204 +10693,573 @@ async function readSourceParentMode(path2) {
|
|
|
10574
10693
|
throw error;
|
|
10575
10694
|
}
|
|
10576
10695
|
}
|
|
10577
|
-
async function readOptional(path2) {
|
|
10696
|
+
async function readOptional(path2) {
|
|
10697
|
+
try {
|
|
10698
|
+
return await readFile17(path2);
|
|
10699
|
+
} catch (error) {
|
|
10700
|
+
if (isMissing7(error))
|
|
10701
|
+
return;
|
|
10702
|
+
throw error;
|
|
10703
|
+
}
|
|
10704
|
+
}
|
|
10705
|
+
function isMissing7(error) {
|
|
10706
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
10707
|
+
}
|
|
10708
|
+
|
|
10709
|
+
// src/update/admin-settings-yaml-plan.ts
|
|
10710
|
+
var transferPath = "apps/web/src/pages/settings/WatermarkYamlTransfer.vue";
|
|
10711
|
+
var settingsPaths = [
|
|
10712
|
+
"apps/web/src/composables/useWatermarkSettings.ts",
|
|
10713
|
+
"apps/web/src/pages/settings/GlobalSettingsPage.vue",
|
|
10714
|
+
"apps/web/src/pages/settings/WatermarkSettingsSection.vue",
|
|
10715
|
+
"apps/web/src/pages/settings/BrandingSettingsSection.vue"
|
|
10716
|
+
];
|
|
10717
|
+
async function reconcileAdminSettingsYamlPlan(input) {
|
|
10718
|
+
if (input.sourceEntries.has(transferPath) || !input.targetEntries.has(transferPath))
|
|
10719
|
+
return;
|
|
10720
|
+
for (const path2 of settingsPaths) {
|
|
10721
|
+
const plan = input.files.find((file) => file.path === path2);
|
|
10722
|
+
if (!plan || !input.sourceEntries.has(path2))
|
|
10723
|
+
continue;
|
|
10724
|
+
const [base, target] = await Promise.all([
|
|
10725
|
+
readOptional(join25(input.baseDirectory, path2)),
|
|
10726
|
+
readOptional(join25(input.targetDirectory, path2))
|
|
10727
|
+
]);
|
|
10728
|
+
const current = input.projectSnapshots.get(path2);
|
|
10729
|
+
if (current && target && hashContent(current) === hashContent(target))
|
|
10730
|
+
continue;
|
|
10731
|
+
if (!base || !current || !target || hashContent(base) !== hashContent(current)) {
|
|
10732
|
+
plan.conflict = "\u5168\u5C40\u8BBE\u7F6E YAML \u8FC1\u79FB\u9700\u8981\u5408\u5E76\u5DF2\u81EA\u5B9A\u4E49\u7684\u9879\u76EE\u6587\u4EF6";
|
|
10733
|
+
continue;
|
|
10734
|
+
}
|
|
10735
|
+
plan.action = "update";
|
|
10736
|
+
plan.reason = "\u8865\u9F50\u5168\u5C40\u8BBE\u7F6E YAML \u7684\u914D\u5957\u9875\u9762\u4E0E API";
|
|
10737
|
+
plan.content = target;
|
|
10738
|
+
delete plan.conflict;
|
|
10739
|
+
}
|
|
10740
|
+
}
|
|
10741
|
+
|
|
10742
|
+
// src/update/environment-mount-plan.ts
|
|
10743
|
+
var environmentProfile = "windy.environment.yaml";
|
|
10744
|
+
var generatedMount = "./windy.environment.yaml:/app/windy.environment.yaml:ro";
|
|
10745
|
+
function validateEnvironmentMountPlan(files, currentProfile) {
|
|
10746
|
+
const compose = files.find(({ path: path2 }) => path2 === "docker-compose.yml");
|
|
10747
|
+
if (!compose?.content || compose.action !== "create" && compose.action !== "update" || compose.conflict || !new TextDecoder().decode(compose.content).includes(generatedMount))
|
|
10748
|
+
return;
|
|
10749
|
+
const profile = files.find(({ path: path2 }) => path2 === environmentProfile);
|
|
10750
|
+
const available = profile?.action === "create" || profile?.action === "update" ? profile.content !== undefined : profile?.action !== "delete" && currentProfile !== undefined;
|
|
10751
|
+
if (available)
|
|
10752
|
+
return;
|
|
10753
|
+
compose.action = "preserve";
|
|
10754
|
+
delete compose.content;
|
|
10755
|
+
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";
|
|
10756
|
+
}
|
|
10757
|
+
|
|
10758
|
+
// src/update/media-runtime-registry.ts
|
|
10759
|
+
function reconcileMediaRuntimeRegistry(files, current, sourceModules, targetModules) {
|
|
10760
|
+
if (!current || !sourceModules.includes("system.agent") || sourceModules.includes("system.media-runtime") || !targetModules.includes("system.media-runtime"))
|
|
10761
|
+
return;
|
|
10762
|
+
const file = files.find(({ path: path2 }) => path2 === projectModuleRegistryPath);
|
|
10763
|
+
if (!file)
|
|
10764
|
+
throw new Error("\u5A92\u4F53\u8FD0\u884C\u65F6\u8FC1\u79FB\u7F3A\u5C11\u9879\u76EE\u6A21\u5757\u88C5\u914D\u6E05\u5355");
|
|
10765
|
+
const registry = parseProjectModuleRegistry(current);
|
|
10766
|
+
if (registry.modules.some(({ name }) => name === "system.media-runtime"))
|
|
10767
|
+
return;
|
|
10768
|
+
if (!registry.modules.find(({ name }) => name === "system.agent")?.enabled) {
|
|
10769
|
+
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";
|
|
10770
|
+
return;
|
|
10771
|
+
}
|
|
10772
|
+
const orders = new Set(registry.modules.map(({ order: order2 }) => order2));
|
|
10773
|
+
const lastOrder = Math.max(0, ...orders);
|
|
10774
|
+
let order = lastOrder + 100;
|
|
10775
|
+
if (!Number.isSafeInteger(order)) {
|
|
10776
|
+
order = 0;
|
|
10777
|
+
while (orders.has(order))
|
|
10778
|
+
order += 1;
|
|
10779
|
+
}
|
|
10780
|
+
registry.modules.push({
|
|
10781
|
+
name: "system.media-runtime",
|
|
10782
|
+
package: null,
|
|
10783
|
+
enabled: true,
|
|
10784
|
+
order,
|
|
10785
|
+
admin: { visible: true },
|
|
10786
|
+
config: {}
|
|
10787
|
+
});
|
|
10788
|
+
file.action = "update";
|
|
10789
|
+
file.reason = "\u6CE8\u518C\u65E7 Agent \u4EA4\u4ED8\u4E2D\u5DF2\u6709\u7684\u5A92\u4F53\u8FD0\u884C\u65F6";
|
|
10790
|
+
file.content = new TextEncoder().encode(`${JSON.stringify(registry, null, 2)}
|
|
10791
|
+
`);
|
|
10792
|
+
delete file.conflict;
|
|
10793
|
+
}
|
|
10794
|
+
|
|
10795
|
+
// src/update/planner.ts
|
|
10796
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
10797
|
+
import { dirname as dirname9, join as join30 } from "path";
|
|
10798
|
+
|
|
10799
|
+
// src/update/docker-copy-update-plan.ts
|
|
10800
|
+
async function deriveDockerfilePlans(files, snapshots, paths, targetWorkspaceManifests) {
|
|
10801
|
+
const rootPackage = virtualPathContent("package.json", files, snapshots, targetWorkspaceManifests);
|
|
10802
|
+
if (!rootPackage)
|
|
10803
|
+
return;
|
|
10804
|
+
const rootManifest = parsePackage(rootPackage, "package.json");
|
|
10805
|
+
const workspacePatterns = rootManifest.workspaces ?? [];
|
|
10806
|
+
const packages = [];
|
|
10807
|
+
for (const path2 of [
|
|
10808
|
+
...new Set([...paths, ...targetWorkspaceManifests.keys()])
|
|
10809
|
+
].filter((path3) => path3.endsWith("package.json"))) {
|
|
10810
|
+
const directory = path2 === "package.json" ? "." : path2.slice(0, -13);
|
|
10811
|
+
if (directory === ".")
|
|
10812
|
+
continue;
|
|
10813
|
+
if (!workspacePatterns.some((pattern) => matchesWorkspace(pattern, directory))) {
|
|
10814
|
+
continue;
|
|
10815
|
+
}
|
|
10816
|
+
const content = virtualPathContent(path2, files, snapshots, targetWorkspaceManifests);
|
|
10817
|
+
if (!content)
|
|
10818
|
+
continue;
|
|
10819
|
+
const manifest = parsePackage(content, path2);
|
|
10820
|
+
packages.push({
|
|
10821
|
+
name: manifest.name,
|
|
10822
|
+
directory,
|
|
10823
|
+
dependencies: [
|
|
10824
|
+
...Object.keys(manifest.dependencies ?? {}),
|
|
10825
|
+
...Object.keys(manifest.devDependencies ?? {})
|
|
10826
|
+
],
|
|
10827
|
+
workspaceDependencies: Object.entries({
|
|
10828
|
+
...manifest.dependencies,
|
|
10829
|
+
...manifest.devDependencies
|
|
10830
|
+
}).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name)
|
|
10831
|
+
});
|
|
10832
|
+
}
|
|
10833
|
+
packages.sort((left, right) => left.directory.localeCompare(right.directory));
|
|
10834
|
+
for (const target of dockerfileCopyTargets) {
|
|
10835
|
+
const dockerPlan = files.find(({ path: path2 }) => path2 === target.dockerfilePath);
|
|
10836
|
+
if (!dockerPlan || dockerPlan.conflict)
|
|
10837
|
+
continue;
|
|
10838
|
+
const dockerSource = virtualContent(dockerPlan, snapshots);
|
|
10839
|
+
if (!dockerSource)
|
|
10840
|
+
continue;
|
|
10841
|
+
const source = new TextDecoder().decode(dockerSource);
|
|
10842
|
+
if (!hasDockerfileCopyAnchors(source, target)) {
|
|
10843
|
+
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";
|
|
10844
|
+
continue;
|
|
10845
|
+
}
|
|
10846
|
+
let next;
|
|
10847
|
+
try {
|
|
10848
|
+
next = syncDockerfileSource(source, target, packages);
|
|
10849
|
+
} catch (error) {
|
|
10850
|
+
dockerPlan.conflict = error instanceof Error ? error.message : "Docker COPY \u951A\u70B9\u65E0\u6548";
|
|
10851
|
+
continue;
|
|
10852
|
+
}
|
|
10853
|
+
if (next === source)
|
|
10854
|
+
continue;
|
|
10855
|
+
dockerPlan.action = "update";
|
|
10856
|
+
dockerPlan.reason = "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355";
|
|
10857
|
+
dockerPlan.content = new TextEncoder().encode(next);
|
|
10858
|
+
}
|
|
10859
|
+
}
|
|
10860
|
+
function virtualPathContent(path2, files, snapshots, targetWorkspaceManifests) {
|
|
10861
|
+
const plan = files.find((item) => item.path === path2);
|
|
10862
|
+
return plan ? virtualContent(plan, snapshots) : snapshots.get(path2) ?? targetWorkspaceManifests.get(path2);
|
|
10863
|
+
}
|
|
10864
|
+
function virtualContent(plan, snapshots) {
|
|
10865
|
+
if (plan.action === "delete")
|
|
10866
|
+
return;
|
|
10867
|
+
if (plan.action === "create" || plan.action === "update")
|
|
10868
|
+
return plan.content;
|
|
10869
|
+
return snapshots.get(plan.path);
|
|
10870
|
+
}
|
|
10871
|
+
function parsePackage(content, path2) {
|
|
10578
10872
|
try {
|
|
10579
|
-
return
|
|
10873
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
10580
10874
|
} catch (error) {
|
|
10581
|
-
|
|
10582
|
-
|
|
10583
|
-
|
|
10875
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790 Docker workspace \u8F93\u5165\uFF1A${path2}`, {
|
|
10876
|
+
cause: error
|
|
10877
|
+
});
|
|
10584
10878
|
}
|
|
10585
10879
|
}
|
|
10586
|
-
function
|
|
10587
|
-
return
|
|
10880
|
+
function matchesWorkspace(pattern, directory) {
|
|
10881
|
+
return pattern.endsWith("/*") && directory.startsWith(pattern.slice(0, -1));
|
|
10588
10882
|
}
|
|
10589
10883
|
|
|
10590
|
-
// src/update/
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
|
|
10602
|
-
|
|
10603
|
-
|
|
10604
|
-
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
async function isDshPlatformTransition(input) {
|
|
10610
|
-
if (!input.sourceModules.includes("system.agent") || !input.targetModules.includes("system.agent"))
|
|
10611
|
-
return false;
|
|
10612
|
-
const path2 = "apps/agent-server/package.json";
|
|
10613
|
-
const [base, target] = await Promise.all([
|
|
10614
|
-
readOptional(join26(input.baseDirectory, path2)),
|
|
10615
|
-
readOptional(join26(input.targetDirectory, path2))
|
|
10616
|
-
]);
|
|
10617
|
-
return hasDsh(target) && !hasDsh(base);
|
|
10884
|
+
// src/update/migration-reconciler.ts
|
|
10885
|
+
import { readFile as readFile21 } from "fs/promises";
|
|
10886
|
+
import { join as join28 } from "path";
|
|
10887
|
+
|
|
10888
|
+
// src/update/migration-adoption.ts
|
|
10889
|
+
import { readFile as readFile20 } from "fs/promises";
|
|
10890
|
+
import { join as join27 } from "path";
|
|
10891
|
+
|
|
10892
|
+
// src/update/migration-project-file.ts
|
|
10893
|
+
import { readFile as readFile18 } from "fs/promises";
|
|
10894
|
+
import { join as join26 } from "path";
|
|
10895
|
+
async function readProjectJson(input, path2) {
|
|
10896
|
+
const content = await readProjectFile(input, path2);
|
|
10897
|
+
if (!content) {
|
|
10898
|
+
const error = new Error(`\u5F53\u524D\u9879\u76EE\u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
10899
|
+
error.code = "ENOENT";
|
|
10900
|
+
throw error;
|
|
10901
|
+
}
|
|
10902
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
10618
10903
|
}
|
|
10619
|
-
function
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
ownership: input.ownership,
|
|
10623
|
-
expectedProjectContent: input.expected
|
|
10624
|
-
};
|
|
10625
|
-
if (input.target && input.ours && hashContent(input.ours) === hashContent(input.target)) {
|
|
10626
|
-
return {
|
|
10627
|
-
...common2,
|
|
10628
|
-
action: "preserve",
|
|
10629
|
-
reason: "\u5DF2\u5305\u542B DSH \u5E73\u53F0\u63A5\u7EBF\u76EE\u6807\u5185\u5BB9"
|
|
10630
|
-
};
|
|
10904
|
+
async function readProjectFile(input, path2) {
|
|
10905
|
+
if (input.projectSnapshots?.has(path2)) {
|
|
10906
|
+
return input.projectSnapshots.get(path2);
|
|
10631
10907
|
}
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
};
|
|
10908
|
+
let content;
|
|
10909
|
+
try {
|
|
10910
|
+
content = await readFile18(join26(input.projectDirectory, path2));
|
|
10911
|
+
} catch (error) {
|
|
10912
|
+
if (!isMissingFileError(error))
|
|
10913
|
+
throw error;
|
|
10639
10914
|
}
|
|
10640
|
-
if (input.
|
|
10641
|
-
|
|
10642
|
-
...common2,
|
|
10643
|
-
action: "update",
|
|
10644
|
-
reason: "DSH \u5E73\u53F0\u5347\u7EA7\u7CBE\u786E\u6765\u6E90\u63A5\u7EBF",
|
|
10645
|
-
content: input.target
|
|
10646
|
-
};
|
|
10915
|
+
if (input.projectSnapshots) {
|
|
10916
|
+
input.projectSnapshots.set(path2, content);
|
|
10647
10917
|
}
|
|
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
|
-
};
|
|
10918
|
+
return content;
|
|
10654
10919
|
}
|
|
10655
|
-
function
|
|
10656
|
-
|
|
10657
|
-
return false;
|
|
10658
|
-
const value = JSON.parse(new TextDecoder().decode(content));
|
|
10659
|
-
return typeof value.dependencies?.["@deepseek-ai/dsh"] === "string";
|
|
10920
|
+
function isMissingFileError(error) {
|
|
10921
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
10660
10922
|
}
|
|
10661
10923
|
|
|
10662
|
-
// src/update/
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
const
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
return planDshPlatformFile({
|
|
10672
|
-
path: path2,
|
|
10673
|
-
ownership,
|
|
10674
|
-
ours,
|
|
10675
|
-
base,
|
|
10676
|
-
target: theirs,
|
|
10677
|
-
expected
|
|
10678
|
-
});
|
|
10924
|
+
// src/update/migration-history.ts
|
|
10925
|
+
import { readFile as readFile19 } from "fs/promises";
|
|
10926
|
+
var drizzleRoot = "packages/database/drizzle";
|
|
10927
|
+
var journalPath = `${drizzleRoot}/meta/_journal.json`;
|
|
10928
|
+
var migrationPattern = /^(\d{4})_(.+)$/;
|
|
10929
|
+
function snapshotPath(tag) {
|
|
10930
|
+
const match = migrationPattern.exec(tag);
|
|
10931
|
+
if (!match) {
|
|
10932
|
+
throw new Error(`${journalPath}\uFF1Amigration tag \u683C\u5F0F\u65E0\u6548\uFF1A${tag}`);
|
|
10679
10933
|
}
|
|
10680
|
-
|
|
10681
|
-
|
|
10682
|
-
|
|
10683
|
-
|
|
10934
|
+
return `${drizzleRoot}/meta/${match[1]}_snapshot.json`;
|
|
10935
|
+
}
|
|
10936
|
+
function validateUniqueNames(journal, label, conflicts) {
|
|
10937
|
+
const seen = new Set;
|
|
10938
|
+
for (const { tag } of journal.entries) {
|
|
10939
|
+
const name = stableName(tag);
|
|
10940
|
+
if (seen.has(name)) {
|
|
10941
|
+
conflicts.push(`${journalPath}\uFF1A${label}\u5B58\u5728\u91CD\u590D migration \u540D\u79F0 ${name}`);
|
|
10684
10942
|
}
|
|
10685
|
-
|
|
10686
|
-
|
|
10943
|
+
seen.add(name);
|
|
10944
|
+
}
|
|
10945
|
+
}
|
|
10946
|
+
function stableName(tag) {
|
|
10947
|
+
return migrationPattern.exec(tag)?.[2] ?? tag;
|
|
10948
|
+
}
|
|
10949
|
+
function highestPrefix(journal) {
|
|
10950
|
+
return Math.max(-1, ...journal.entries.map(({ tag }) => Number(migrationPattern.exec(tag)?.[1] ?? -1)));
|
|
10951
|
+
}
|
|
10952
|
+
function highestIndex(journal) {
|
|
10953
|
+
return Math.max(-1, ...journal.entries.map(({ idx }) => idx));
|
|
10954
|
+
}
|
|
10955
|
+
function isDrizzleHistoryPath(path2) {
|
|
10956
|
+
return path2 === journalPath || isMigrationArtifact(path2);
|
|
10957
|
+
}
|
|
10958
|
+
function isMigrationArtifact(path2) {
|
|
10959
|
+
return isSqlMigration(path2) || new RegExp(`^${drizzleRoot}/meta/\\d{4}_snapshot\\.json$`).test(path2);
|
|
10960
|
+
}
|
|
10961
|
+
function isSqlMigration(path2) {
|
|
10962
|
+
return new RegExp(`^${drizzleRoot}/\\d{4}_.+\\.sql$`).test(path2);
|
|
10963
|
+
}
|
|
10964
|
+
function managedEntry(path2, content) {
|
|
10965
|
+
return { path: path2, ownership: "windy-managed", hash: hashContent(content) };
|
|
10966
|
+
}
|
|
10967
|
+
function deduplicate(files) {
|
|
10968
|
+
return [...new Map(files.map((entry) => [entry.path, entry])).values()];
|
|
10969
|
+
}
|
|
10970
|
+
function encodeJson(value) {
|
|
10971
|
+
return new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
|
|
10972
|
+
`);
|
|
10973
|
+
}
|
|
10974
|
+
async function readJson(path2) {
|
|
10975
|
+
return JSON.parse(await readFile19(path2, "utf8"));
|
|
10976
|
+
}
|
|
10977
|
+
|
|
10978
|
+
// src/update/snapshot-delta.ts
|
|
10979
|
+
function applySnapshotDelta(before, after, current, path2, conflicts, conflictPath) {
|
|
10980
|
+
if (deepEqual(before, after))
|
|
10981
|
+
return structuredClone(current);
|
|
10982
|
+
if (!isRecord(before) || !isRecord(after) || !isRecord(current)) {
|
|
10983
|
+
if (deepEqual(current, before) || deepEqual(current, after)) {
|
|
10984
|
+
return structuredClone(after);
|
|
10687
10985
|
}
|
|
10688
|
-
|
|
10986
|
+
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u4E0E\u4E1A\u52A1\u540C\u65F6\u4FEE\u6539 snapshot \u8282\u70B9 ${path2.join(".") || "<root>"}`);
|
|
10987
|
+
return structuredClone(current);
|
|
10689
10988
|
}
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
10989
|
+
const merged = structuredClone(current);
|
|
10990
|
+
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
10991
|
+
for (const key of keys) {
|
|
10992
|
+
if (path2.length === 0 && (key === "id" || key === "prevId"))
|
|
10993
|
+
continue;
|
|
10994
|
+
const nextPath = [...path2, key];
|
|
10995
|
+
if (!(key in after)) {
|
|
10996
|
+
if (!(key in current))
|
|
10997
|
+
continue;
|
|
10998
|
+
if (deepEqual(current[key], before[key]))
|
|
10999
|
+
delete merged[key];
|
|
11000
|
+
else
|
|
11001
|
+
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u5220\u9664\u4E86\u4E1A\u52A1\u5DF2\u4FEE\u6539\u7684 snapshot \u8282\u70B9 ${nextPath.join(".")}`);
|
|
11002
|
+
continue;
|
|
10693
11003
|
}
|
|
10694
|
-
if (
|
|
10695
|
-
|
|
11004
|
+
if (!(key in before)) {
|
|
11005
|
+
if (!(key in current) || deepEqual(current[key], after[key])) {
|
|
11006
|
+
merged[key] = structuredClone(after[key]);
|
|
11007
|
+
} else {
|
|
11008
|
+
conflicts.push(`${conflictPath}\uFF1A\u5E73\u53F0\u65B0\u589E\u7684 snapshot \u8282\u70B9\u5DF2\u88AB\u4E1A\u52A1\u5360\u7528 ${nextPath.join(".")}`);
|
|
11009
|
+
}
|
|
11010
|
+
continue;
|
|
10696
11011
|
}
|
|
11012
|
+
merged[key] = applySnapshotDelta(before[key], after[key], current[key], nextPath, conflicts, conflictPath);
|
|
10697
11013
|
}
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
11014
|
+
return merged;
|
|
11015
|
+
}
|
|
11016
|
+
function isRecord(value) {
|
|
11017
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
11018
|
+
}
|
|
11019
|
+
function deepEqual(left, right) {
|
|
11020
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
11021
|
+
}
|
|
11022
|
+
|
|
11023
|
+
// src/update/migration-adoption.ts
|
|
11024
|
+
async function inspectPreexistingMigrationAdoptions(input) {
|
|
11025
|
+
const conflicts = [];
|
|
11026
|
+
const adoptions = [];
|
|
11027
|
+
const projectByName = new Map(input.project.entries.map((entry) => [stableName(entry.tag), entry]));
|
|
11028
|
+
for (const candidate of input.candidates) {
|
|
11029
|
+
const name = stableName(candidate.tag);
|
|
11030
|
+
const projectEntry = projectByName.get(name);
|
|
11031
|
+
if (!projectEntry || input.managedNames.has(name))
|
|
11032
|
+
continue;
|
|
11033
|
+
const targetPosition = input.target.entries.indexOf(candidate);
|
|
11034
|
+
const projectPosition = input.project.entries.indexOf(projectEntry);
|
|
11035
|
+
const previousTarget = input.target.entries[targetPosition - 1];
|
|
11036
|
+
const previousProject = input.project.entries[projectPosition - 1];
|
|
11037
|
+
if (!previousTarget || !previousProject) {
|
|
11038
|
+
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C\u7F3A\u5C11\u524D\u7F6E\u5386\u53F2`);
|
|
11039
|
+
continue;
|
|
11040
|
+
}
|
|
11041
|
+
const projectSqlPath = `${drizzleRoot}/${projectEntry.tag}.sql`;
|
|
11042
|
+
const projectSnapshotPath = snapshotPath(projectEntry.tag);
|
|
11043
|
+
const [
|
|
11044
|
+
targetSql,
|
|
11045
|
+
projectSql,
|
|
11046
|
+
targetBefore,
|
|
11047
|
+
targetAfter,
|
|
11048
|
+
projectBeforeBytes,
|
|
11049
|
+
projectAfterBytes
|
|
11050
|
+
] = await Promise.all([
|
|
11051
|
+
readFile20(join27(input.targetDirectory, `${drizzleRoot}/${candidate.tag}.sql`)),
|
|
11052
|
+
readProjectFile(input, projectSqlPath),
|
|
11053
|
+
readJson(join27(input.targetDirectory, snapshotPath(previousTarget.tag))),
|
|
11054
|
+
readJson(join27(input.targetDirectory, snapshotPath(candidate.tag))),
|
|
11055
|
+
readProjectFile(input, snapshotPath(previousProject.tag)),
|
|
11056
|
+
readProjectFile(input, projectSnapshotPath)
|
|
11057
|
+
]);
|
|
11058
|
+
if (!projectSql || !projectBeforeBytes || !projectAfterBytes) {
|
|
11059
|
+
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C\u9879\u76EE migration \u6587\u4EF6\u4E0D\u5B8C\u6574`);
|
|
11060
|
+
continue;
|
|
10701
11061
|
}
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
11062
|
+
const projectBefore = decodeSnapshot(projectBeforeBytes);
|
|
11063
|
+
const projectAfter = decodeSnapshot(projectAfterBytes);
|
|
11064
|
+
const reason = validateAdoption({
|
|
11065
|
+
targetSql,
|
|
11066
|
+
projectSql,
|
|
11067
|
+
targetBefore,
|
|
11068
|
+
targetAfter,
|
|
11069
|
+
projectBefore,
|
|
11070
|
+
projectAfter
|
|
11071
|
+
});
|
|
11072
|
+
if (reason) {
|
|
11073
|
+
conflicts.push(`${journalPath}\uFF1A\u65E0\u6CD5\u91C7\u7EB3\u73B0\u6709\u5E73\u53F0 migration ${name}\uFF0C${reason}`);
|
|
11074
|
+
continue;
|
|
10707
11075
|
}
|
|
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);
|
|
10715
|
-
}
|
|
10716
|
-
const oursChanged = hashContent(ours) !== source.hash;
|
|
10717
|
-
const sourceArtifactHash = artifactHashOf(source);
|
|
10718
|
-
const targetChanged = targetChangedSinceBase(sourceArtifactHash, base, theirs);
|
|
10719
|
-
const adoptedProjectDelta = source.artifactHash !== undefined && source.artifactHash !== source.hash;
|
|
10720
|
-
const forceTargetBaseline = !adoptedProjectDelta && shouldForcePlatformBaseline({
|
|
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);
|
|
11076
|
+
adoptions.push({
|
|
11077
|
+
sqlPath: projectSqlPath,
|
|
11078
|
+
snapshotPath: projectSnapshotPath,
|
|
11079
|
+
sql: projectSql,
|
|
11080
|
+
snapshot: projectAfterBytes
|
|
11081
|
+
});
|
|
10729
11082
|
}
|
|
10730
|
-
|
|
10731
|
-
|
|
11083
|
+
return { adoptions, conflicts };
|
|
11084
|
+
}
|
|
11085
|
+
function validateAdoption(input) {
|
|
11086
|
+
if (!equalBytes(input.targetSql, input.projectSql)) {
|
|
11087
|
+
return "SQL \u5185\u5BB9\u4E0D\u4E00\u81F4";
|
|
10732
11088
|
}
|
|
10733
|
-
if (
|
|
10734
|
-
return
|
|
11089
|
+
if (input.projectAfter.prevId !== input.projectBefore.id) {
|
|
11090
|
+
return "\u9879\u76EE snapshot lineage \u4E0D\u8FDE\u7EED";
|
|
10735
11091
|
}
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
11092
|
+
const deltaConflicts = [];
|
|
11093
|
+
const expected = applySnapshotDelta(input.targetBefore, input.targetAfter, input.projectBefore, [], deltaConflicts, journalPath);
|
|
11094
|
+
if (deltaConflicts.length || canonicalSnapshot(expected) !== canonicalSnapshot(input.projectAfter)) {
|
|
11095
|
+
return "snapshot delta \u4E0E\u9879\u76EE\u5386\u53F2\u4E0D\u4E00\u81F4";
|
|
10739
11096
|
}
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
11097
|
+
}
|
|
11098
|
+
function decodeSnapshot(content) {
|
|
11099
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
11100
|
+
}
|
|
11101
|
+
function equalBytes(left, right) {
|
|
11102
|
+
return left.byteLength === right.byteLength && left.every((value, index) => value === right[index]);
|
|
11103
|
+
}
|
|
11104
|
+
function canonicalSnapshot(value) {
|
|
11105
|
+
return JSON.stringify(canonicalize(value, true));
|
|
11106
|
+
}
|
|
11107
|
+
function canonicalize(value, root = false) {
|
|
11108
|
+
if (Array.isArray(value))
|
|
11109
|
+
return value.map((item) => canonicalize(item));
|
|
11110
|
+
if (!value || typeof value !== "object")
|
|
11111
|
+
return value;
|
|
11112
|
+
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)]));
|
|
11113
|
+
}
|
|
11114
|
+
|
|
11115
|
+
// src/update/migration-reconciler.ts
|
|
11116
|
+
async function reconcileDrizzleMigrations(input) {
|
|
11117
|
+
const journals = await readJournals(input);
|
|
11118
|
+
if (!journals) {
|
|
11119
|
+
return unchanged(input.targetManifest);
|
|
10743
11120
|
}
|
|
10744
|
-
|
|
10745
|
-
|
|
11121
|
+
const { base, project, target } = journals;
|
|
11122
|
+
const conflicts = [];
|
|
11123
|
+
validateUniqueNames(base, "\u6765\u6E90\u6A21\u677F", conflicts);
|
|
11124
|
+
validateUniqueNames(project, "\u5F53\u524D\u9879\u76EE", conflicts);
|
|
11125
|
+
validateUniqueNames(target, "\u76EE\u6807\u6A21\u677F", conflicts);
|
|
11126
|
+
if (conflicts.length) {
|
|
11127
|
+
return { ...unchanged(input.targetManifest), conflicts };
|
|
10746
11128
|
}
|
|
10747
|
-
|
|
10748
|
-
|
|
11129
|
+
const baseNames = new Set(base.entries.map(({ tag }) => stableName(tag)));
|
|
11130
|
+
const projectNames = new Set(project.entries.map(({ tag }) => stableName(tag)));
|
|
11131
|
+
const managedNames = new Set(input.sourceManifest.files.filter(({ path: path2 }) => isSqlMigration(path2)).map(({ path: path2 }) => stableName(path2.slice(drizzleRoot.length + 1, -4))));
|
|
11132
|
+
const candidates = target.entries.filter(({ tag }) => !baseNames.has(stableName(tag)));
|
|
11133
|
+
const adoption = await inspectPreexistingMigrationAdoptions({
|
|
11134
|
+
...input,
|
|
11135
|
+
project,
|
|
11136
|
+
target,
|
|
11137
|
+
candidates,
|
|
11138
|
+
managedNames
|
|
11139
|
+
});
|
|
11140
|
+
conflicts.push(...adoption.conflicts);
|
|
11141
|
+
const additions = candidates.filter(({ tag }) => !projectNames.has(stableName(tag)));
|
|
11142
|
+
const contentOverrides = new Map;
|
|
11143
|
+
const files = await preservePublishedHistory(input.sourceManifest, input, contentOverrides);
|
|
11144
|
+
const publishedPaths = new Set(files.map(({ path: path2 }) => path2));
|
|
11145
|
+
for (const adopted of adoption.adoptions) {
|
|
11146
|
+
contentOverrides.set(adopted.sqlPath, adopted.sql);
|
|
11147
|
+
contentOverrides.set(adopted.snapshotPath, adopted.snapshot);
|
|
11148
|
+
files.push(managedEntry(adopted.sqlPath, adopted.sql), managedEntry(adopted.snapshotPath, adopted.snapshot));
|
|
11149
|
+
publishedPaths.add(adopted.sqlPath);
|
|
11150
|
+
publishedPaths.add(adopted.snapshotPath);
|
|
10749
11151
|
}
|
|
10750
|
-
|
|
10751
|
-
|
|
11152
|
+
files.push(...input.targetManifest.files.filter(({ path: path2 }) => !isDrizzleHistoryPath(path2)));
|
|
11153
|
+
if (!additions.length) {
|
|
11154
|
+
const journalContent2 = encodeJson(project);
|
|
11155
|
+
contentOverrides.set(journalPath, journalContent2);
|
|
11156
|
+
files.push(managedEntry(journalPath, journalContent2));
|
|
11157
|
+
return result(input.targetManifest, files, contentOverrides, publishedPaths, conflicts);
|
|
10752
11158
|
}
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
11159
|
+
let nextPrefix = highestPrefix(project) + 1;
|
|
11160
|
+
let nextIndex = highestIndex(project) + 1;
|
|
11161
|
+
let previousWhen = project.entries.at(-1)?.when ?? 0;
|
|
11162
|
+
let currentSnapshot = await readLatestSnapshot(input, project);
|
|
11163
|
+
const mergedJournal = structuredClone(project);
|
|
11164
|
+
for (const addition of additions) {
|
|
11165
|
+
const targetPosition = target.entries.indexOf(addition);
|
|
11166
|
+
const previousTarget = target.entries[targetPosition - 1];
|
|
11167
|
+
if (!previousTarget) {
|
|
11168
|
+
conflicts.push(`${journalPath}\uFF1A\u76EE\u6807 migration \u7F3A\u5C11\u524D\u7F6E\u5FEB\u7167`);
|
|
11169
|
+
break;
|
|
11170
|
+
}
|
|
11171
|
+
const targetBefore = await readSnapshot(input.targetDirectory, previousTarget.tag);
|
|
11172
|
+
const targetAfter = await readSnapshot(input.targetDirectory, addition.tag);
|
|
11173
|
+
const merged = applySnapshotDelta(targetBefore, targetAfter, currentSnapshot, [], conflicts, journalPath);
|
|
11174
|
+
if (conflicts.length)
|
|
11175
|
+
break;
|
|
11176
|
+
const prefix = String(nextPrefix).padStart(4, "0");
|
|
11177
|
+
const name = stableName(addition.tag);
|
|
11178
|
+
const tag = `${prefix}_${name}`;
|
|
11179
|
+
const sqlPath = `${drizzleRoot}/${tag}.sql`;
|
|
11180
|
+
const snapshotPath2 = `${drizzleRoot}/meta/${prefix}_snapshot.json`;
|
|
11181
|
+
const sql = await readFile21(join28(input.targetDirectory, `${drizzleRoot}/${addition.tag}.sql`));
|
|
11182
|
+
merged.id = targetAfter.id;
|
|
11183
|
+
merged.prevId = currentSnapshot.id;
|
|
11184
|
+
const snapshot2 = encodeJson(merged);
|
|
11185
|
+
contentOverrides.set(sqlPath, sql);
|
|
11186
|
+
contentOverrides.set(snapshotPath2, snapshot2);
|
|
11187
|
+
files.push(managedEntry(sqlPath, sql), managedEntry(snapshotPath2, snapshot2));
|
|
11188
|
+
previousWhen = Math.max(previousWhen + 1, addition.when);
|
|
11189
|
+
mergedJournal.entries.push({
|
|
11190
|
+
...addition,
|
|
11191
|
+
idx: nextIndex,
|
|
11192
|
+
when: previousWhen,
|
|
11193
|
+
tag
|
|
11194
|
+
});
|
|
11195
|
+
currentSnapshot = merged;
|
|
11196
|
+
nextPrefix += 1;
|
|
11197
|
+
nextIndex += 1;
|
|
10756
11198
|
}
|
|
10757
|
-
|
|
11199
|
+
const journalContent = encodeJson(mergedJournal);
|
|
11200
|
+
contentOverrides.set(journalPath, journalContent);
|
|
11201
|
+
files.push(managedEntry(journalPath, journalContent));
|
|
11202
|
+
return result(input.targetManifest, files, contentOverrides, publishedPaths, conflicts);
|
|
10758
11203
|
}
|
|
10759
|
-
function
|
|
10760
|
-
return
|
|
11204
|
+
function result(targetManifest, files, contentOverrides, forcePreserves, conflicts) {
|
|
11205
|
+
return {
|
|
11206
|
+
targetManifest: {
|
|
11207
|
+
...targetManifest,
|
|
11208
|
+
files: deduplicate(files).sort((left, right) => left.path.localeCompare(right.path))
|
|
11209
|
+
},
|
|
11210
|
+
contentOverrides,
|
|
11211
|
+
forceUpdates: new Set([journalPath]),
|
|
11212
|
+
forcePreserves,
|
|
11213
|
+
conflicts
|
|
11214
|
+
};
|
|
10761
11215
|
}
|
|
10762
|
-
function
|
|
10763
|
-
return
|
|
11216
|
+
function unchanged(targetManifest) {
|
|
11217
|
+
return {
|
|
11218
|
+
targetManifest,
|
|
11219
|
+
contentOverrides: new Map,
|
|
11220
|
+
forceUpdates: new Set,
|
|
11221
|
+
forcePreserves: new Set,
|
|
11222
|
+
conflicts: []
|
|
11223
|
+
};
|
|
10764
11224
|
}
|
|
10765
|
-
async function
|
|
11225
|
+
async function readJournals(input) {
|
|
10766
11226
|
try {
|
|
10767
|
-
|
|
11227
|
+
const [base, project, target] = await Promise.all([
|
|
11228
|
+
readJson(join28(input.baseDirectory, journalPath)),
|
|
11229
|
+
readProjectJson(input, journalPath),
|
|
11230
|
+
readJson(join28(input.targetDirectory, journalPath))
|
|
11231
|
+
]);
|
|
11232
|
+
return { base, project, target };
|
|
10768
11233
|
} catch (error) {
|
|
10769
|
-
if (error
|
|
11234
|
+
if (isMissingFileError(error))
|
|
10770
11235
|
return;
|
|
10771
|
-
}
|
|
10772
11236
|
throw error;
|
|
10773
11237
|
}
|
|
10774
11238
|
}
|
|
11239
|
+
async function preservePublishedHistory(manifest, input, overrides) {
|
|
11240
|
+
const entries = manifest.files.filter(({ path: path2 }) => isMigrationArtifact(path2) && path2 !== journalPath);
|
|
11241
|
+
await Promise.all(entries.map(async ({ path: path2 }) => {
|
|
11242
|
+
const content = await readProjectFile(input, path2);
|
|
11243
|
+
if (!content)
|
|
11244
|
+
throw new Error(`\u5F53\u524D\u9879\u76EE migration \u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
11245
|
+
overrides.set(path2, content);
|
|
11246
|
+
}));
|
|
11247
|
+
return entries;
|
|
11248
|
+
}
|
|
11249
|
+
async function readLatestSnapshot(input, journal) {
|
|
11250
|
+
const latest = journal.entries.at(-1);
|
|
11251
|
+
if (!latest)
|
|
11252
|
+
throw new Error(`${journalPath}\uFF1A\u5F53\u524D\u9879\u76EE\u6CA1\u6709 migration`);
|
|
11253
|
+
const path2 = snapshotPath(latest.tag);
|
|
11254
|
+
const content = await readProjectFile(input, path2);
|
|
11255
|
+
if (!content) {
|
|
11256
|
+
throw new Error(`\u5F53\u524D\u9879\u76EE migration \u6587\u4EF6\u7F3A\u5931\uFF1A${path2}`);
|
|
11257
|
+
}
|
|
11258
|
+
return JSON.parse(new TextDecoder().decode(content));
|
|
11259
|
+
}
|
|
11260
|
+
async function readSnapshot(root, tag) {
|
|
11261
|
+
return await readJson(join28(root, snapshotPath(tag)));
|
|
11262
|
+
}
|
|
10775
11263
|
|
|
10776
11264
|
// src/update/planner-files.ts
|
|
10777
11265
|
var metadataPaths = new Set([
|
|
@@ -10852,17 +11340,9 @@ async function assertNoPendingUpdate(projectDirectory) {
|
|
|
10852
11340
|
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
11341
|
}
|
|
10854
11342
|
|
|
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
11343
|
// src/update/legacy-python-agent-retirement.ts
|
|
10864
11344
|
import { lstat as lstat8, readFile as readFile22 } from "fs/promises";
|
|
10865
|
-
import { join as
|
|
11345
|
+
import { join as join29 } from "path";
|
|
10866
11346
|
var retiredKeys = [
|
|
10867
11347
|
"AGENT_DATABASE_URL",
|
|
10868
11348
|
"AGENT_RUN_STORE_PATH",
|
|
@@ -10873,7 +11353,7 @@ var retiredKeys = [
|
|
|
10873
11353
|
"OTEL_EXPORTER_OTLP_HEADERS"
|
|
10874
11354
|
];
|
|
10875
11355
|
async function inspectPythonAgentRetirement(projectDirectory) {
|
|
10876
|
-
const path2 =
|
|
11356
|
+
const path2 = join29(projectDirectory, ".env");
|
|
10877
11357
|
try {
|
|
10878
11358
|
const stat3 = await lstat8(path2);
|
|
10879
11359
|
if (stat3.isSymbolicLink() || !stat3.isFile())
|
|
@@ -10906,7 +11386,7 @@ var oxcManagedPaths = new Set([
|
|
|
10906
11386
|
]);
|
|
10907
11387
|
async function createUpdatePlan(request, artifacts, dependencies = {}) {
|
|
10908
11388
|
await assertProjectReadyForUpdate(request.projectDirectory);
|
|
10909
|
-
const manifestPath =
|
|
11389
|
+
const manifestPath = join30(request.projectDirectory, ".windy/files.json");
|
|
10910
11390
|
const expectedManifestHash = hashContent(await readFile23(manifestPath));
|
|
10911
11391
|
const generationSnapshot = await readGenerationProvenanceSnapshot(request.projectDirectory);
|
|
10912
11392
|
const provenance = generationSnapshot.provenance;
|
|
@@ -10964,10 +11444,10 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
|
|
|
10964
11444
|
const paths = new Set([...sourceEntries.keys(), ...targetEntries.keys()]);
|
|
10965
11445
|
for (const path2 of paths) {
|
|
10966
11446
|
if (!projectSnapshots.has(path2)) {
|
|
10967
|
-
projectSnapshots.set(path2, await readOptional(
|
|
11447
|
+
projectSnapshots.set(path2, await readOptional(join30(request.projectDirectory, path2)));
|
|
10968
11448
|
}
|
|
10969
11449
|
if (!projectModes.has(path2)) {
|
|
10970
|
-
projectModes.set(path2, await readModeOptional(
|
|
11450
|
+
projectModes.set(path2, await readModeOptional(join30(request.projectDirectory, path2)));
|
|
10971
11451
|
}
|
|
10972
11452
|
}
|
|
10973
11453
|
const files = await planFiles({
|
|
@@ -10983,19 +11463,31 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
|
|
|
10983
11463
|
recipeProjectOwnedPaths,
|
|
10984
11464
|
migrateDshPlatform
|
|
10985
11465
|
});
|
|
11466
|
+
if (!request.lifecycle) {
|
|
11467
|
+
reconcileMediaRuntimeRegistry(files, projectSnapshots.get(projectModuleRegistryPath), provenance.modules.map(({ name }) => name), targetProvenance.modules.map(({ name }) => name));
|
|
11468
|
+
}
|
|
11469
|
+
await reconcileAdminSettingsYamlPlan({
|
|
11470
|
+
files,
|
|
11471
|
+
sourceEntries,
|
|
11472
|
+
targetEntries,
|
|
11473
|
+
projectSnapshots,
|
|
11474
|
+
baseDirectory: artifactSet.baseDirectory,
|
|
11475
|
+
targetDirectory: artifactSet.targetDirectory
|
|
11476
|
+
});
|
|
10986
11477
|
preserveTestsForExistingProjectOwnedSources(files, sourceEntries);
|
|
10987
11478
|
await deriveDockerfilePlans(files, projectSnapshots, new Set([
|
|
10988
11479
|
...paths,
|
|
10989
11480
|
...workspaceSnapshot.manifests.keys(),
|
|
10990
11481
|
...targetWorkspaceSnapshot.manifests.keys()
|
|
10991
11482
|
]), targetWorkspaceSnapshot.manifests);
|
|
11483
|
+
validateEnvironmentMountPlan(files, projectSnapshots.get("windy.environment.yaml"));
|
|
10992
11484
|
for (const file of files) {
|
|
10993
11485
|
file.expectedProjectMode = projectModes.get(file.path);
|
|
10994
11486
|
if (file.action === "create" || file.action === "update") {
|
|
10995
|
-
file.mode = file.expectedProjectMode ?? await readModeOptional(
|
|
11487
|
+
file.mode = file.expectedProjectMode ?? await readModeOptional(join30(artifactSet.targetDirectory, file.path));
|
|
10996
11488
|
}
|
|
10997
11489
|
if (file.action === "create") {
|
|
10998
|
-
file.parentMode = await readSourceParentMode(
|
|
11490
|
+
file.parentMode = await readSourceParentMode(join30(artifactSet.targetDirectory, dirname9(file.path)));
|
|
10999
11491
|
}
|
|
11000
11492
|
}
|
|
11001
11493
|
const plannedPaths = new Set(files.map(({ path: path2 }) => path2));
|
|
@@ -11129,7 +11621,7 @@ function frozenManifestHash(file, finalizedHashes) {
|
|
|
11129
11621
|
// src/update/format-stabilizer.ts
|
|
11130
11622
|
import { mkdir as mkdir8, mkdtemp as mkdtemp3, readFile as readFile24, rm as rm7, writeFile as writeFile13 } from "fs/promises";
|
|
11131
11623
|
import { tmpdir as tmpdir3 } from "os";
|
|
11132
|
-
import { dirname as dirname10, extname as extname4, join as
|
|
11624
|
+
import { dirname as dirname10, extname as extname4, join as join31, resolve as resolve6, sep as sep5 } from "path";
|
|
11133
11625
|
var formattedExtensions = new Set([
|
|
11134
11626
|
".cjs",
|
|
11135
11627
|
".css",
|
|
@@ -11168,7 +11660,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
11168
11660
|
}
|
|
11169
11661
|
}
|
|
11170
11662
|
inputs.set(".windy/generation.json", new TextEncoder().encode(generationContent));
|
|
11171
|
-
const temporaryRoot = await mkdtemp3(
|
|
11663
|
+
const temporaryRoot = await mkdtemp3(join31(tmpdir3(), "windy-update-format-"));
|
|
11172
11664
|
try {
|
|
11173
11665
|
const stagedPaths = await stageInputs(temporaryRoot, inputs);
|
|
11174
11666
|
for (let offset = 0;offset < stagedPaths.length; offset += 80) {
|
|
@@ -11176,7 +11668,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
11176
11668
|
"x",
|
|
11177
11669
|
"oxfmt",
|
|
11178
11670
|
"--write",
|
|
11179
|
-
`--config=${
|
|
11671
|
+
`--config=${join31(result2.plan.projectDirectory, ".oxfmtrc.json")}`,
|
|
11180
11672
|
...stagedPaths.slice(offset, offset + 80)
|
|
11181
11673
|
], result2.plan.projectDirectory);
|
|
11182
11674
|
}
|
|
@@ -11225,7 +11717,7 @@ function safeTemporaryPath(root, path2) {
|
|
|
11225
11717
|
|
|
11226
11718
|
// src/update/project-quality-verification.ts
|
|
11227
11719
|
import { readFile as readFile25 } from "fs/promises";
|
|
11228
|
-
import { join as
|
|
11720
|
+
import { join as join32 } from "path";
|
|
11229
11721
|
var qualityScriptNames = ["lint", "typecheck", "test", "build"];
|
|
11230
11722
|
function skippedProjectQualityVerification() {
|
|
11231
11723
|
return {
|
|
@@ -11239,7 +11731,7 @@ function skippedProjectQualityVerification() {
|
|
|
11239
11731
|
};
|
|
11240
11732
|
}
|
|
11241
11733
|
async function runProjectQualityVerification(projectDirectory, execute) {
|
|
11242
|
-
const packageJson = JSON.parse(await readFile25(
|
|
11734
|
+
const packageJson = JSON.parse(await readFile25(join32(projectDirectory, "package.json"), "utf8"));
|
|
11243
11735
|
const steps = [];
|
|
11244
11736
|
for (const name of qualityScriptNames) {
|
|
11245
11737
|
const stepName = `bun run ${name}`;
|
|
@@ -12322,7 +12814,7 @@ import {
|
|
|
12322
12814
|
rm as rm11,
|
|
12323
12815
|
writeFile as writeFile14
|
|
12324
12816
|
} from "fs/promises";
|
|
12325
|
-
import { dirname as dirname11, join as
|
|
12817
|
+
import { dirname as dirname11, join as join33, relative as relative7 } from "path";
|
|
12326
12818
|
|
|
12327
12819
|
// src/module-schema/config.ts
|
|
12328
12820
|
import { readFile as readFile26 } from "fs/promises";
|
|
@@ -12463,17 +12955,17 @@ async function handoffModuleSchemaLineages(options) {
|
|
|
12463
12955
|
async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
12464
12956
|
const outputs = [];
|
|
12465
12957
|
for (const [index, module2] of config.modules.entries()) {
|
|
12466
|
-
const output =
|
|
12958
|
+
const output = join33(temporaryRoot, `module-${index}`);
|
|
12467
12959
|
await mkdir9(output, { recursive: true });
|
|
12468
|
-
const generatedConfig =
|
|
12960
|
+
const generatedConfig = join33(temporaryRoot, `module-${index}.config.ts`);
|
|
12469
12961
|
await writeDrizzleConfig(generatedConfig, project, module2.schema, relative7(temporaryRoot, output));
|
|
12470
12962
|
await execute(generatedConfig, temporaryRoot);
|
|
12471
12963
|
const sqlFiles = await listSqlFiles(output);
|
|
12472
12964
|
if (sqlFiles.length !== 1) {
|
|
12473
12965
|
throw new Error(`${module2.key} baseline \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration`);
|
|
12474
12966
|
}
|
|
12475
|
-
await writeFile14(
|
|
12476
|
-
await writeFile14(
|
|
12967
|
+
await writeFile14(join33(output, sqlFiles[0]), metadataOnlySql("module"));
|
|
12968
|
+
await writeFile14(join33(output, "lineage.json"), `${JSON.stringify({
|
|
12477
12969
|
schemaVersion: 1,
|
|
12478
12970
|
moduleKey: module2.key,
|
|
12479
12971
|
schema: module2.schema,
|
|
@@ -12487,17 +12979,17 @@ async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
|
12487
12979
|
}
|
|
12488
12980
|
async function stagePlatformLineage(project, temporaryRoot, config, execute) {
|
|
12489
12981
|
const source = resolveProjectPath(project, config.platform.out);
|
|
12490
|
-
const output =
|
|
12982
|
+
const output = join33(temporaryRoot, "platform");
|
|
12491
12983
|
await cp(source, output, { recursive: true });
|
|
12492
12984
|
const before = new Set(await listSqlFiles(output));
|
|
12493
|
-
const generatedConfig =
|
|
12985
|
+
const generatedConfig = join33(temporaryRoot, "platform.config.ts");
|
|
12494
12986
|
await writeDrizzleConfig(generatedConfig, project, config.platform.schema, relative7(temporaryRoot, output));
|
|
12495
12987
|
await execute(generatedConfig, temporaryRoot);
|
|
12496
12988
|
const created = (await listSqlFiles(output)).filter((path2) => !before.has(path2));
|
|
12497
12989
|
if (created.length !== 1) {
|
|
12498
12990
|
throw new Error("\u5E73\u53F0 lineage handoff \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration");
|
|
12499
12991
|
}
|
|
12500
|
-
const sqlPath =
|
|
12992
|
+
const sqlPath = join33(output, created[0]);
|
|
12501
12993
|
const allowed = config.modules.flatMap(({ legacyPlatformTables }) => legacyPlatformTables);
|
|
12502
12994
|
validatePlatformHandoffSql(await readFile27(sqlPath, "utf8"), allowed);
|
|
12503
12995
|
await writeFile14(sqlPath, metadataOnlySql("platform"));
|
|
@@ -12505,7 +12997,7 @@ async function stagePlatformLineage(project, temporaryRoot, config, execute) {
|
|
|
12505
12997
|
}
|
|
12506
12998
|
async function installStagedLineages(project, temporaryRoot, config, stagedModules, stagedPlatform) {
|
|
12507
12999
|
const platform = resolveProjectPath(project, config.platform.out);
|
|
12508
|
-
const backup =
|
|
13000
|
+
const backup = join33(temporaryRoot, "platform-backup");
|
|
12509
13001
|
const installed = [];
|
|
12510
13002
|
await rename2(platform, backup);
|
|
12511
13003
|
try {
|
|
@@ -12552,9 +13044,9 @@ async function validateSchemaSources(project, config) {
|
|
|
12552
13044
|
}
|
|
12553
13045
|
}
|
|
12554
13046
|
async function createTemporaryRoot(project) {
|
|
12555
|
-
const windy =
|
|
13047
|
+
const windy = join33(project, ".windy");
|
|
12556
13048
|
await mkdir9(windy, { recursive: true });
|
|
12557
|
-
return await mkdtemp4(
|
|
13049
|
+
return await mkdtemp4(join33(windy, "module-schema-handoff-"));
|
|
12558
13050
|
}
|
|
12559
13051
|
async function listSqlFiles(root) {
|
|
12560
13052
|
return (await readdir9(root)).filter((path2) => path2.endsWith(".sql")).sort();
|
|
@@ -12645,7 +13137,7 @@ async function readPackageConfiguration(projectDirectory) {
|
|
|
12645
13137
|
}
|
|
12646
13138
|
}
|
|
12647
13139
|
function parsePackageConfiguration(value) {
|
|
12648
|
-
const root =
|
|
13140
|
+
const root = object2(value, "windy.build.json");
|
|
12649
13141
|
rejectUnknown(root, ["schemaVersion", "product", "platforms", "profiles"], "windy.build.json");
|
|
12650
13142
|
if (root.schemaVersion !== 1)
|
|
12651
13143
|
throw new Error("windy.build.json \u53EA\u652F\u6301 schemaVersion: 1");
|
|
@@ -12671,7 +13163,7 @@ function parsePackageConfiguration(value) {
|
|
|
12671
13163
|
};
|
|
12672
13164
|
}
|
|
12673
13165
|
function parseProfile(value) {
|
|
12674
|
-
const profile =
|
|
13166
|
+
const profile = object2(value, "profile");
|
|
12675
13167
|
rejectUnknown(profile, [
|
|
12676
13168
|
"key",
|
|
12677
13169
|
"label",
|
|
@@ -12684,7 +13176,7 @@ function parseProfile(value) {
|
|
|
12684
13176
|
const key = identifier(profile.key, "profile key");
|
|
12685
13177
|
const inputs = array(profile.inputs, `profile ${key}.inputs`).map((item) => parseInput(item, key));
|
|
12686
13178
|
unique2(inputs.map(({ key: inputKey }) => inputKey), `profile ${key} input key`);
|
|
12687
|
-
const command =
|
|
13179
|
+
const command = object2(profile.command, `profile ${key}.command`);
|
|
12688
13180
|
rejectUnknown(command, ["executable", "arguments"], `profile ${key}.command`);
|
|
12689
13181
|
const executable = string(command.executable, `profile ${key}.command.executable`);
|
|
12690
13182
|
if (shellExecutables.has(executable.toLowerCase()) || shellCharacters.test(executable) || !/^[a-zA-Z0-9._-]+$/u.test(executable)) {
|
|
@@ -12698,7 +13190,7 @@ function parseProfile(value) {
|
|
|
12698
13190
|
}
|
|
12699
13191
|
return argument;
|
|
12700
13192
|
});
|
|
12701
|
-
const output =
|
|
13193
|
+
const output = object2(profile.output, `profile ${key}.output`);
|
|
12702
13194
|
rejectUnknown(output, ["directory", "artifactSuffix"], `profile ${key}.output`);
|
|
12703
13195
|
const directory = string(output.directory, `profile ${key}.output.directory`);
|
|
12704
13196
|
if (!isSafeRelativePath(directory) || !/^[a-zA-Z0-9._/-]+$/u.test(directory))
|
|
@@ -12707,7 +13199,7 @@ function parseProfile(value) {
|
|
|
12707
13199
|
if (!artifactSuffix.startsWith(".") || shellCharacters.test(artifactSuffix) || !/^\.[a-zA-Z0-9._-]+$/u.test(artifactSuffix)) {
|
|
12708
13200
|
throw new Error(`profile ${key} \u7684 output.artifactSuffix \u975E\u6CD5`);
|
|
12709
13201
|
}
|
|
12710
|
-
const requirements =
|
|
13202
|
+
const requirements = object2(profile.requirements, `profile ${key}.requirements`);
|
|
12711
13203
|
rejectUnknown(requirements, ["docker", "buildx"], `profile ${key}.requirements`);
|
|
12712
13204
|
const docker = boolean(requirements.docker, `profile ${key}.requirements.docker`);
|
|
12713
13205
|
const buildx = boolean(requirements.buildx, `profile ${key}.requirements.buildx`);
|
|
@@ -12724,7 +13216,7 @@ function parseProfile(value) {
|
|
|
12724
13216
|
};
|
|
12725
13217
|
}
|
|
12726
13218
|
function parseInput(value, profile) {
|
|
12727
|
-
const input =
|
|
13219
|
+
const input = object2(value, `profile ${profile}.input`);
|
|
12728
13220
|
rejectUnknown(input, ["key", "label", "required", "pattern"], `profile ${profile}.input`);
|
|
12729
13221
|
const key = identifier(input.key, `profile ${profile}.input.key`);
|
|
12730
13222
|
if (secretName.test(key))
|
|
@@ -12755,7 +13247,7 @@ function validatePlaceholders(value, inputs, profile) {
|
|
|
12755
13247
|
if (value.replace(placeholder, "").includes("${"))
|
|
12756
13248
|
throw new Error(`profile ${profile} \u5305\u542B\u672A\u58F0\u660E\u5360\u4F4D\u7B26`);
|
|
12757
13249
|
}
|
|
12758
|
-
function
|
|
13250
|
+
function object2(value, label) {
|
|
12759
13251
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
12760
13252
|
throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
|
|
12761
13253
|
return value;
|