create-windy 0.6.14 → 0.6.16

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.
Files changed (162) hide show
  1. package/dist/cli.js +1008 -61
  2. package/package.json +1 -1
  3. package/template/.agents/skills/windy-business-module/SKILL.md +58 -8
  4. package/template/.windy-template.json +2 -2
  5. package/template/apps/server/src/agent/client-session/attempt-authority.test.ts +162 -0
  6. package/template/apps/server/src/agent/client-session/attempt-authority.ts +191 -0
  7. package/template/apps/server/src/agent/client-session/bootstrap.ts +27 -11
  8. package/template/apps/server/src/agent/client-session/completion.ts +75 -24
  9. package/template/apps/server/src/agent/client-session/contracts.ts +23 -0
  10. package/template/apps/server/src/agent/client-session/creation.ts +103 -0
  11. package/template/apps/server/src/agent/client-session/digest.ts +11 -1
  12. package/template/apps/server/src/agent/client-session/drizzle-records.ts +150 -0
  13. package/template/apps/server/src/agent/client-session/drizzle-repository.integration.test.ts +30 -3
  14. package/template/apps/server/src/agent/client-session/drizzle-repository.ts +23 -132
  15. package/template/apps/server/src/agent/client-session/finalization.ts +99 -0
  16. package/template/apps/server/src/agent/client-session/host-auth.ts +22 -10
  17. package/template/apps/server/src/agent/client-session/host-revocation-composition.test.ts +77 -0
  18. package/template/apps/server/src/agent/client-session/host-revocation-composition.ts +28 -0
  19. package/template/apps/server/src/agent/client-session/launch-authority.contract.test.ts +21 -0
  20. package/template/apps/server/src/agent/client-session/manifest-admission.ts +11 -0
  21. package/template/apps/server/src/agent/client-session/service.test-support.ts +22 -0
  22. package/template/apps/server/src/agent/client-session/service.ts +104 -134
  23. package/template/apps/server/src/agent/client-session/terminal-digest.test.ts +23 -0
  24. package/template/apps/server/src/agent/client-workflow-artifact/active-blob-references.ts +8 -0
  25. package/template/apps/server/src/agent/client-workflow-artifact/artifact-builder.ts +60 -0
  26. package/template/apps/server/src/agent/client-workflow-artifact/authority-current.ts +59 -0
  27. package/template/apps/server/src/agent/client-workflow-artifact/binding-registry.test.ts +189 -0
  28. package/template/apps/server/src/agent/client-workflow-artifact/binding-registry.ts +153 -0
  29. package/template/apps/server/src/agent/client-workflow-artifact/bootstrap.ts +77 -0
  30. package/template/apps/server/src/agent/client-workflow-artifact/cancellation.ts +47 -0
  31. package/template/apps/server/src/agent/client-workflow-artifact/completed-recovery.ts +31 -0
  32. package/template/apps/server/src/agent/client-workflow-artifact/contracts.ts +104 -0
  33. package/template/apps/server/src/agent/client-workflow-artifact/drizzle-locks.ts +30 -0
  34. package/template/apps/server/src/agent/client-workflow-artifact/drizzle-mapper.ts +138 -0
  35. package/template/apps/server/src/agent/client-workflow-artifact/drizzle-repository.ts +346 -0
  36. package/template/apps/server/src/agent/client-workflow-artifact/error.ts +21 -0
  37. package/template/apps/server/src/agent/client-workflow-artifact/handler.ts +167 -0
  38. package/template/apps/server/src/agent/client-workflow-artifact/host-revocation.ts +29 -0
  39. package/template/apps/server/src/agent/client-workflow-artifact/in-memory-repository.ts +232 -0
  40. package/template/apps/server/src/agent/client-workflow-artifact/job-port.ts +101 -0
  41. package/template/apps/server/src/agent/client-workflow-artifact/presentation.ts +41 -0
  42. package/template/apps/server/src/agent/client-workflow-artifact/recovery.contract.test.ts +253 -0
  43. package/template/apps/server/src/agent/client-workflow-artifact/release-binding.ts +85 -0
  44. package/template/apps/server/src/agent/client-workflow-artifact/repository.test.ts +204 -0
  45. package/template/apps/server/src/agent/client-workflow-artifact/repository.ts +97 -0
  46. package/template/apps/server/src/agent/client-workflow-artifact/routes-handler.contract.test.ts +201 -0
  47. package/template/apps/server/src/agent/client-workflow-artifact/routes.ts +161 -0
  48. package/template/apps/server/src/agent/client-workflow-artifact/runtime-composition.ts +101 -0
  49. package/template/apps/server/src/agent/client-workflow-artifact/scope-authority.ts +39 -0
  50. package/template/apps/server/src/agent/client-workflow-artifact/service-authorization.ts +117 -0
  51. package/template/apps/server/src/agent/client-workflow-artifact/service-support.ts +28 -0
  52. package/template/apps/server/src/agent/client-workflow-artifact/service.contract.test.ts +345 -0
  53. package/template/apps/server/src/agent/client-workflow-artifact/service.ts +350 -0
  54. package/template/apps/server/src/agent/client-workflow-artifact/session-boundary.ts +39 -0
  55. package/template/apps/server/src/agent/client-workflow-artifact/source-access.contract.test.ts +98 -0
  56. package/template/apps/server/src/agent/client-workflow-artifact/source-access.ts +80 -0
  57. package/template/apps/server/src/agent/client-workflow-artifact/takeover.ts +122 -0
  58. package/template/apps/server/src/agent/client-workflow-artifact/task-authority.contract.test.ts +97 -0
  59. package/template/apps/server/src/agent/client-workflow-artifact/task-authority.ts +147 -0
  60. package/template/apps/server/src/agent/client-workflow-artifact/terminal-authority.contract.test.ts +100 -0
  61. package/template/apps/server/src/agent/client-workflow-artifact/terminal-replay.ts +31 -0
  62. package/template/apps/server/src/agent/client-workflow-artifact/terminal-seal.ts +211 -0
  63. package/template/apps/server/src/agent/client-workflow-artifact/workflow-artifact.test-support.ts +173 -0
  64. package/template/apps/server/src/agent/client-workflow-artifact/workflow-loader.contract.test.ts +254 -0
  65. package/template/apps/server/src/agent/client-workflow-artifact/workflow-loader.ts +285 -0
  66. package/template/apps/server/src/agent/run-facade.test-support.ts +17 -4
  67. package/template/apps/server/src/agent/run-facade.test.ts +16 -0
  68. package/template/apps/server/src/agent/run-session-authorization.ts +12 -10
  69. package/template/apps/server/src/agent/runtime-bootstrap-input.ts +5 -1
  70. package/template/apps/server/src/agent/runtime-bootstrap.ts +33 -33
  71. package/template/apps/server/src/agent/runtime-public-ports.ts +40 -0
  72. package/template/apps/server/src/agent/session-invalidation/contracts.ts +25 -26
  73. package/template/apps/server/src/agent/session-projection-access.ts +31 -19
  74. package/template/apps/server/src/agent/unavailable-routes.ts +21 -0
  75. package/template/apps/server/src/agent/workflow-runtime-bootstrap.ts +2 -0
  76. package/template/apps/server/src/agent-workflow/artifact-source-authorization.ts +12 -6
  77. package/template/apps/server/src/agent-workflow/command-facade.ts +70 -11
  78. package/template/apps/server/src/agent-workflow/drizzle-artifact-port.ts +9 -9
  79. package/template/apps/server/src/agent-workflow/drizzle-delegation-completion.ts +1 -1
  80. package/template/apps/server/src/agent-workflow/platform-node-adapters.ts +14 -6
  81. package/template/apps/server/src/agent-workflow/project-launch-authority.contract.test.ts +53 -0
  82. package/template/apps/server/src/agent-workflow/project-launch-authority.ts +92 -0
  83. package/template/apps/server/src/agent-workflow/runtime-composition.ts +30 -14
  84. package/template/apps/server/src/app/agent-runtime-composition.ts +6 -1
  85. package/template/apps/server/src/app/client-agent-workflow-artifact-binding.ts +14 -0
  86. package/template/apps/server/src/application-services.ts +6 -0
  87. package/template/apps/server/src/data-access/scope-containment.test.ts +31 -0
  88. package/template/apps/server/src/data-access/scope-containment.ts +48 -0
  89. package/template/apps/server/src/jobs/artifact-publication.test.ts +192 -0
  90. package/template/apps/server/src/jobs/artifact-publication.ts +56 -0
  91. package/template/apps/server/src/jobs/artifact-publisher.ts +101 -0
  92. package/template/apps/server/src/jobs/drizzle-artifact.ts +73 -1
  93. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +14 -1
  94. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +65 -0
  95. package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +1 -0
  96. package/template/apps/server/src/jobs/execution-repository.ts +28 -0
  97. package/template/apps/server/src/jobs/execution.test.ts +3 -1
  98. package/template/apps/server/src/jobs/in-memory-execution.ts +16 -0
  99. package/template/apps/server/src/jobs/in-memory-lease.ts +45 -1
  100. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +2 -0
  101. package/template/apps/server/src/jobs/postgres-cleanup-contract.test.ts +58 -0
  102. package/template/apps/server/src/jobs/worker.ts +8 -14
  103. package/template/apps/server/src/module-host/background-ai-unavailable.ts +18 -0
  104. package/template/apps/server/src/module-host/durable-context.ts +19 -22
  105. package/template/apps/server/src/module-host/implementation-completeness.test.ts +80 -1
  106. package/template/apps/server/src/module-host/implementation-completeness.ts +28 -1
  107. package/template/apps/server/src/module-host/request-context.ts +32 -8
  108. package/template/apps/server/src/module-host/storage-port.ts +3 -0
  109. package/template/apps/server/src/module-host/workflow-input-artifact-port.test.ts +104 -0
  110. package/template/apps/server/src/module-host/workflow-input-artifact-port.ts +229 -0
  111. package/template/apps/server/src/module-host/workflow-input-materialization.test.ts +163 -0
  112. package/template/apps/server/src/module-host/workflow-input-materialization.ts +161 -0
  113. package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +1 -0
  114. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeFilters.vue +2 -1
  115. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeFilters.webtest.ts +16 -0
  116. package/template/docs/architecture/agent-workflow.md +13 -2
  117. package/template/docs/architecture/durable-jobs.md +7 -0
  118. package/template/docs/operations/agent-session-memory.md +2 -1
  119. package/template/docs/operations/agent-session-troubleshooting.md +87 -2
  120. package/template/docs/operations/agent-workflow-recovery.md +25 -14
  121. package/template/docs/platform/client-agent-session.md +148 -2
  122. package/template/packages/ai-client/package.json +2 -1
  123. package/template/packages/ai-client/src/client-agent/index.ts +1 -0
  124. package/template/packages/ai-client/src/client-agent/workflow-artifact/contracts.ts +85 -0
  125. package/template/packages/ai-client/src/client-agent/workflow-artifact/http.test.ts +49 -0
  126. package/template/packages/ai-client/src/client-agent/workflow-artifact/http.ts +82 -0
  127. package/template/packages/ai-client/src/client-agent/workflow-artifact/index.ts +3 -0
  128. package/template/packages/ai-client/src/client-agent/workflow-artifact/validation.test.ts +154 -0
  129. package/template/packages/ai-client/src/client-agent/workflow-artifact/validation.ts +332 -0
  130. package/template/packages/database/drizzle/0062_client_agent_workflow_artifact.sql +63 -0
  131. package/template/packages/database/drizzle/meta/0062_snapshot.json +14839 -0
  132. package/template/packages/database/drizzle/meta/_journal.json +7 -0
  133. package/template/packages/database/package.json +1 -1
  134. package/template/packages/database/src/agent-runtime-schema.test.ts +177 -0
  135. package/template/packages/database/src/schema/client-agent-workflow-artifact.ts +158 -0
  136. package/template/packages/database/src/schema/index.ts +1 -0
  137. package/template/packages/jobs/package.json +1 -1
  138. package/template/packages/jobs/src/handlers.test.ts +10 -0
  139. package/template/packages/jobs/src/handlers.ts +28 -11
  140. package/template/packages/modules/package.json +1 -1
  141. package/template/packages/modules/src/ai-client-execution-policy.ts +6 -0
  142. package/template/packages/modules/src/manifest.ts +2 -0
  143. package/template/packages/modules/src/system-agent-audit-actions.ts +3 -0
  144. package/template/packages/modules/src/system-ai-api-bindings.ts +15 -0
  145. package/template/packages/modules/src/system-audit-actions.ts +15 -0
  146. package/template/packages/server-sdk/index.ts +52 -0
  147. package/template/packages/server-sdk/package.json +5 -1
  148. package/template/packages/server-sdk/src/client-agent-session.ts +13 -1
  149. package/template/packages/server-sdk/src/client-agent-workflow-artifact.contract.test.ts +113 -0
  150. package/template/packages/server-sdk/src/client-agent-workflow-artifact.ts +183 -0
  151. package/template/packages/server-sdk/src/durable-handler.ts +7 -0
  152. package/template/packages/server-sdk/src/request-context.ts +7 -0
  153. package/template/packages/server-sdk/src/workflow-input-artifact-port.ts +104 -0
  154. package/template/packages/server-sdk/src/workflow-input-artifact-validation.contract.test.ts +124 -0
  155. package/template/packages/server-sdk/src/workflow-input-artifact-validation.ts +347 -0
  156. package/template/packages/server-sdk/src/workflow-input-materialization-handler.ts +43 -0
  157. package/template/packages/storage/package.json +1 -1
  158. package/template/packages/storage/src/blob-store-put-once.test.ts +70 -0
  159. package/template/packages/storage/src/blob-store.ts +9 -0
  160. package/template/packages/storage/src/local-file-blob-put-once.ts +120 -0
  161. package/template/packages/storage/src/local-file-blob-store.ts +53 -1
  162. package/template/packages/storage/src/memory-blob-store.ts +73 -33
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/cli-width/index.js
36
+ // ../../node_modules/.bun/cli-width@4.1.0/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/mute-stream/lib/index.js
76
+ // ../../node_modules/.bun/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js
77
77
  var require_lib = __commonJS((exports, module2) => {
78
78
  var Stream = __require("stream");
79
79
 
@@ -304,6 +304,7 @@ var agentOptionalModule = {
304
304
  "apps/server/src/app/ai-screenshot-intake-binding.ts",
305
305
  "apps/server/src/app/agent-runtime-composition.ts",
306
306
  "apps/server/src/app/client-agent-host-auth-binding.ts",
307
+ "apps/server/src/app/client-agent-workflow-artifact-binding.ts",
307
308
  "apps/server/src/app/document-output-artifact-bindings.ts",
308
309
  "apps/server/src/app/speech-output-artifact-bindings.ts",
309
310
  "apps/server/src/ai-artifact",
@@ -316,6 +317,10 @@ var agentOptionalModule = {
316
317
  "apps/server/src/module-host/ai-operation-port.test.ts",
317
318
  "apps/server/src/module-host/agent-session-memory-port.ts",
318
319
  "apps/server/src/module-host/agent-source-invalidation-port.ts",
320
+ "apps/server/src/module-host/workflow-input-artifact-port.ts",
321
+ "apps/server/src/module-host/workflow-input-artifact-port.test.ts",
322
+ "apps/server/src/module-host/workflow-input-materialization.ts",
323
+ "apps/server/src/module-host/workflow-input-materialization.test.ts",
319
324
  "apps/server/src/module-host/tool-handlers.ts",
320
325
  "apps/server/src/module-host/tool-handlers.test.ts",
321
326
  "apps/server/src/module-host/module-secret-tool-boundary.test.ts",
@@ -346,6 +351,12 @@ var agentOptionalModule = {
346
351
  "packages/modules/src/system-ai-api-bindings.ts",
347
352
  "packages/server-sdk/src/system-agent-supervisor.ts",
348
353
  "packages/server-sdk/src/system-agent-supervisor.test.ts",
354
+ "packages/server-sdk/src/client-agent-workflow-artifact.ts",
355
+ "packages/server-sdk/src/client-agent-workflow-artifact.contract.test.ts",
356
+ "packages/server-sdk/src/workflow-input-artifact-port.ts",
357
+ "packages/server-sdk/src/workflow-input-artifact-validation.ts",
358
+ "packages/server-sdk/src/workflow-input-artifact-validation.contract.test.ts",
359
+ "packages/server-sdk/src/workflow-input-materialization-handler.ts",
349
360
  "packages/database/src/agent-runtime-schema.test.ts",
350
361
  "packages/database/src/ai-output-artifacts.test.ts",
351
362
  "packages/shared/src/agent-workflow-definition.ts",
@@ -362,6 +373,7 @@ var agentOptionalModule = {
362
373
  "docs/adr/0003-agent-session-event-source.md",
363
374
  "docs/architecture/agent-harness.md",
364
375
  "docs/architecture/agent-workflow.md",
376
+ "docs/architecture/durable-jobs.md",
365
377
  "docs/architecture/ai-egress.md",
366
378
  "docs/architecture/ai-runtime-readiness.md",
367
379
  "docs/architecture/ai-runtime.md",
@@ -396,6 +408,7 @@ var agentOptionalModule = {
396
408
  "packages/database/src/schema/agent-workflow-effects.ts",
397
409
  "packages/database/src/schema/agent-workflow-evaluation.ts",
398
410
  "packages/database/src/schema/client-agent.ts",
411
+ "packages/database/src/schema/client-agent-workflow-artifact.ts",
399
412
  "packages/database/src/schema/embedding-runtime.ts",
400
413
  "packages/database/src/schema/ai-output-artifacts.ts"
401
414
  ],
@@ -410,6 +423,7 @@ var agentOptionalModule = {
410
423
  "agent_runtime_report_attempts",
411
424
  "client_agent_sessions",
412
425
  "client_agent_receipts",
426
+ "client_agent_workflow_artifacts",
413
427
  "embedding_run_bindings",
414
428
  "ai_output_artifact_scopes",
415
429
  "ai_output_artifacts",
@@ -439,7 +453,8 @@ var agentOptionalModule = {
439
453
  "idx_agent_context_sources_origin",
440
454
  "idx_agent_memory_sources_origin",
441
455
  "uk_agent_source_invalidations_sequence",
442
- "agent_workflow_"
456
+ "agent_workflow_",
457
+ "client_agent_workflow_"
443
458
  ]
444
459
  };
445
460
 
@@ -4651,7 +4666,7 @@ function isMissing6(error) {
4651
4666
  import { createInterface as createInterface2 } from "readline/promises";
4652
4667
  import { stdin, stdout } from "process";
4653
4668
 
4654
- // ../../node_modules/@inquirer/core/dist/lib/key.js
4669
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/key.js
4655
4670
  var keybindings = ["emacs", "vim"];
4656
4671
  var keybindingLookup = new Set(keybindings);
4657
4672
  function isKeybinding(value) {
@@ -4668,7 +4683,7 @@ var isDownKey = (key, keybindings2 = []) => key.name === "down" || keybindings2.
4668
4683
  var isSpaceKey = (key) => key.name === "space";
4669
4684
  var isNumberKey = (key) => "1234567890".includes(key.name);
4670
4685
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
4671
- // ../../node_modules/@inquirer/core/dist/lib/errors.js
4686
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/errors.js
4672
4687
  class AbortPromptError extends Error {
4673
4688
  name = "AbortPromptError";
4674
4689
  message = "Prompt was aborted";
@@ -4694,10 +4709,10 @@ class HookError extends Error {
4694
4709
  class ValidationError extends Error {
4695
4710
  name = "ValidationError";
4696
4711
  }
4697
- // ../../node_modules/@inquirer/core/dist/lib/use-state.js
4712
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-state.js
4698
4713
  import { AsyncResource as AsyncResource2 } from "async_hooks";
4699
4714
 
4700
- // ../../node_modules/@inquirer/core/dist/lib/hook-engine.js
4715
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/hook-engine.js
4701
4716
  import { AsyncLocalStorage, AsyncResource } from "async_hooks";
4702
4717
  var hookStorage = new AsyncLocalStorage;
4703
4718
  function createStore(rl) {
@@ -4802,7 +4817,7 @@ var effectScheduler = {
4802
4817
  }
4803
4818
  };
4804
4819
 
4805
- // ../../node_modules/@inquirer/core/dist/lib/use-state.js
4820
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-state.js
4806
4821
  function isFactory(value) {
4807
4822
  return typeof value === "function";
4808
4823
  }
@@ -4823,7 +4838,7 @@ function useState(defaultValue) {
4823
4838
  });
4824
4839
  }
4825
4840
 
4826
- // ../../node_modules/@inquirer/core/dist/lib/use-effect.js
4841
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-effect.js
4827
4842
  function useEffect(cb, depArray) {
4828
4843
  withPointer((pointer) => {
4829
4844
  const oldDeps = pointer.get();
@@ -4835,10 +4850,10 @@ function useEffect(cb, depArray) {
4835
4850
  });
4836
4851
  }
4837
4852
 
4838
- // ../../node_modules/@inquirer/core/dist/lib/theme.js
4853
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/theme.js
4839
4854
  import { styleText } from "util";
4840
4855
 
4841
- // ../../node_modules/@inquirer/figures/dist/index.js
4856
+ // ../../node_modules/.bun/@inquirer+figures@2.0.7/node_modules/@inquirer/figures/dist/index.js
4842
4857
  import process2 from "process";
4843
4858
  function isUnicodeSupported() {
4844
4859
  if (!process2.platform.startsWith("win")) {
@@ -5127,7 +5142,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
5127
5142
  var dist_default = figures;
5128
5143
  var replacements = Object.entries(specialMainSymbols);
5129
5144
 
5130
- // ../../node_modules/@inquirer/core/dist/lib/theme.js
5145
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/theme.js
5131
5146
  var defaultTheme = {
5132
5147
  prefix: {
5133
5148
  idle: styleText("blue", "?"),
@@ -5155,7 +5170,7 @@ function getDefaultTheme() {
5155
5170
  };
5156
5171
  }
5157
5172
 
5158
- // ../../node_modules/@inquirer/core/dist/lib/make-theme.js
5173
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/make-theme.js
5159
5174
  function isPlainObject(value) {
5160
5175
  if (typeof value !== "object" || value === null)
5161
5176
  return false;
@@ -5183,7 +5198,7 @@ function makeTheme(...themes) {
5183
5198
  return deepMerge(...themesToMerge);
5184
5199
  }
5185
5200
 
5186
- // ../../node_modules/@inquirer/core/dist/lib/use-prefix.js
5201
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-prefix.js
5187
5202
  function usePrefix({ status = "idle", theme }) {
5188
5203
  const [showLoader, setShowLoader] = useState(false);
5189
5204
  const [tick, setTick] = useState(0);
@@ -5213,7 +5228,7 @@ function usePrefix({ status = "idle", theme }) {
5213
5228
  const iconName = status === "loading" ? "idle" : status;
5214
5229
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
5215
5230
  }
5216
- // ../../node_modules/@inquirer/core/dist/lib/use-memo.js
5231
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-memo.js
5217
5232
  function useMemo(fn, dependencies) {
5218
5233
  return withPointer((pointer) => {
5219
5234
  const prev = pointer.get();
@@ -5225,12 +5240,12 @@ function useMemo(fn, dependencies) {
5225
5240
  return prev.value;
5226
5241
  });
5227
5242
  }
5228
- // ../../node_modules/@inquirer/core/dist/lib/use-ref.js
5243
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-ref.js
5229
5244
  function useRef(val) {
5230
5245
  return useState({ current: val })[0];
5231
5246
  }
5232
5247
 
5233
- // ../../node_modules/@inquirer/core/dist/lib/use-keypress.js
5248
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-keypress.js
5234
5249
  function useKeypress(userHandler) {
5235
5250
  const signal = useRef(userHandler);
5236
5251
  signal.current = userHandler;
@@ -5248,10 +5263,10 @@ function useKeypress(userHandler) {
5248
5263
  };
5249
5264
  }, []);
5250
5265
  }
5251
- // ../../node_modules/@inquirer/core/dist/lib/utils.js
5266
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/utils.js
5252
5267
  var import_cli_width = __toESM(require_cli_width(), 1);
5253
5268
 
5254
- // ../../node_modules/fast-string-truncated-width/dist/utils.js
5269
+ // ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
5255
5270
  var getCodePointsLength = (() => {
5256
5271
  const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
5257
5272
  return (input) => {
@@ -5270,7 +5285,7 @@ var isWideNotCJKTNotEmoji = (x) => {
5270
5285
  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;
5271
5286
  };
5272
5287
 
5273
- // ../../node_modules/fast-string-truncated-width/dist/index.js
5288
+ // ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
5274
5289
  var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
5275
5290
  var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
5276
5291
  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;
@@ -5369,7 +5384,7 @@ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {})
5369
5384
  };
5370
5385
  var dist_default2 = getStringTruncatedWidth;
5371
5386
 
5372
- // ../../node_modules/fast-string-width/dist/index.js
5387
+ // ../../node_modules/.bun/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
5373
5388
  var NO_TRUNCATION2 = {
5374
5389
  limit: Infinity,
5375
5390
  ellipsis: "",
@@ -5380,7 +5395,7 @@ var fastStringWidth = (input, options = {}) => {
5380
5395
  };
5381
5396
  var dist_default3 = fastStringWidth;
5382
5397
 
5383
- // ../../node_modules/fast-wrap-ansi/lib/main.js
5398
+ // ../../node_modules/.bun/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
5384
5399
  var ESC = "\x1B";
5385
5400
  var CSI = "\x9B";
5386
5401
  var END_CODE = 39;
@@ -5592,7 +5607,7 @@ function wrapAnsi(string, columns, options) {
5592
5607
  `);
5593
5608
  }
5594
5609
 
5595
- // ../../node_modules/@inquirer/core/dist/lib/utils.js
5610
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/utils.js
5596
5611
  function breakLines(content, width) {
5597
5612
  return content.split(`
5598
5613
  `).flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split(`
@@ -5603,7 +5618,7 @@ function readlineWidth() {
5603
5618
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
5604
5619
  }
5605
5620
 
5606
- // ../../node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
5621
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
5607
5622
  function usePointerPosition({ active, renderedItems, pageSize, loop }) {
5608
5623
  const state = useRef({
5609
5624
  lastPointer: active,
@@ -5669,12 +5684,12 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
5669
5684
  return pageBuffer.filter((line) => typeof line === "string").join(`
5670
5685
  `);
5671
5686
  }
5672
- // ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
5687
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
5673
5688
  var import_mute_stream = __toESM(require_lib(), 1);
5674
5689
  import * as readline2 from "readline";
5675
5690
  import { AsyncResource as AsyncResource3 } from "async_hooks";
5676
5691
 
5677
- // ../../node_modules/signal-exit/dist/mjs/signals.js
5692
+ // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
5678
5693
  var signals = [];
5679
5694
  signals.push("SIGHUP", "SIGINT", "SIGTERM");
5680
5695
  if (process.platform !== "win32") {
@@ -5684,7 +5699,7 @@ if (process.platform === "linux") {
5684
5699
  signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
5685
5700
  }
5686
5701
 
5687
- // ../../node_modules/signal-exit/dist/mjs/index.js
5702
+ // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
5688
5703
  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";
5689
5704
  var kExitEmitter = Symbol.for("signal-exit emitter");
5690
5705
  var global = globalThis;
@@ -5882,10 +5897,10 @@ var {
5882
5897
  unload
5883
5898
  } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
5884
5899
 
5885
- // ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
5900
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/screen-manager.js
5886
5901
  import { stripVTControlCharacters } from "util";
5887
5902
 
5888
- // ../../node_modules/@inquirer/ansi/dist/index.js
5903
+ // ../../node_modules/.bun/@inquirer+ansi@2.0.7/node_modules/@inquirer/ansi/dist/index.js
5889
5904
  var ESC2 = "\x1B[";
5890
5905
  var cursorLeft = ESC2 + "G";
5891
5906
  var cursorHide = ESC2 + "?25l";
@@ -5901,7 +5916,7 @@ var cursorTo = (x, y) => {
5901
5916
  var eraseLine = ESC2 + "2K";
5902
5917
  var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
5903
5918
 
5904
- // ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
5919
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/screen-manager.js
5905
5920
  var height = (content) => content.split(`
5906
5921
  `).length;
5907
5922
  var lastLine = (content) => content.split(`
@@ -5967,7 +5982,7 @@ class ScreenManager {
5967
5982
  }
5968
5983
  }
5969
5984
 
5970
- // ../../node_modules/@inquirer/core/dist/lib/promise-polyfill.js
5985
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/promise-polyfill.js
5971
5986
  class PromisePolyfill extends Promise {
5972
5987
  static withResolver() {
5973
5988
  let resolve6;
@@ -5980,7 +5995,7 @@ class PromisePolyfill extends Promise {
5980
5995
  }
5981
5996
  }
5982
5997
 
5983
- // ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
5998
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
5984
5999
  import path from "path";
5985
6000
  var nativeSetImmediate = globalThis.setImmediate;
5986
6001
  function getCallSites() {
@@ -6091,7 +6106,7 @@ function createPrompt(view) {
6091
6106
  };
6092
6107
  return prompt;
6093
6108
  }
6094
- // ../../node_modules/@inquirer/core/dist/lib/Separator.js
6109
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/Separator.js
6095
6110
  import { styleText as styleText2 } from "util";
6096
6111
  class Separator {
6097
6112
  separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
@@ -6105,7 +6120,7 @@ class Separator {
6105
6120
  return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
6106
6121
  }
6107
6122
  }
6108
- // ../../node_modules/@inquirer/checkbox/dist/index.js
6123
+ // ../../node_modules/.bun/@inquirer+checkbox@5.2.1+7cb241fc07b679d9/node_modules/@inquirer/checkbox/dist/index.js
6109
6124
  import { styleText as styleText3 } from "util";
6110
6125
  var checkboxTheme = {
6111
6126
  icon: {
@@ -7458,11 +7473,14 @@ async function retainTransactionConflicts(root, paths, conflictArtifacts = []) {
7458
7473
  const current = await readTransactionState(root);
7459
7474
  if (!current)
7460
7475
  throw new Error("\u7F3A\u5C11\u53EF\u4FDD\u7559\u7684\u66F4\u65B0\u4E8B\u52A1\u72B6\u6001");
7476
+ const preservePaths = [
7477
+ ...new Set([...current.preservePaths ?? [], ...paths])
7478
+ ].filter((path2) => path2 !== updateStatePath);
7461
7479
  const next = {
7462
7480
  ...current,
7463
- preservePaths: [...new Set([...current.preservePaths ?? [], ...paths])],
7481
+ preservePaths: preservePaths.length ? preservePaths : undefined,
7464
7482
  conflictArtifacts: [
7465
- ...new Map([...current.conflictArtifacts ?? [], ...conflictArtifacts].map((artifact) => [artifact.artifactPath, artifact])).values()
7483
+ ...new Map([...current.conflictArtifacts ?? [], ...conflictArtifacts].filter((artifact) => artifact.path !== updateStatePath).map((artifact) => [artifact.artifactPath, artifact])).values()
7466
7484
  ]
7467
7485
  };
7468
7486
  await publishTransactionState(root, current, next);
@@ -7714,6 +7732,8 @@ async function assertRestoredEntries(root, state, backups) {
7714
7732
  async function unresolvedPreservePaths(root, backupPath, state) {
7715
7733
  const unresolved = [];
7716
7734
  for (const path2 of state.preservePaths ?? []) {
7735
+ if (path2 === updateStatePath)
7736
+ continue;
7717
7737
  const entry = state.entries.find((candidate) => candidate.path === path2);
7718
7738
  if (!entry) {
7719
7739
  unresolved.push(path2);
@@ -8452,6 +8472,16 @@ var recipes = [
8452
8472
  id: "starter-0.6.13-to-0.6.14",
8453
8473
  from: "0.6.13",
8454
8474
  to: "0.6.14"
8475
+ },
8476
+ {
8477
+ id: "starter-0.6.14-to-0.6.15",
8478
+ from: "0.6.14",
8479
+ to: "0.6.15"
8480
+ },
8481
+ {
8482
+ id: "starter-0.6.15-to-0.6.16",
8483
+ from: "0.6.15",
8484
+ to: "0.6.16"
8455
8485
  }
8456
8486
  ];
8457
8487
  function resolveRecipeChain(sourceVersion, targetVersion) {
@@ -9813,6 +9843,163 @@ function conflict(path2, reason, expectedProjectContent) {
9813
9843
  };
9814
9844
  }
9815
9845
 
9846
+ // src/update/recipe-project-owned-client-workflow.ts
9847
+ var clientWorkflowCompositionPath = "apps/server/src/app/agent-runtime-composition.ts";
9848
+ var clientWorkflowBindingPath = "apps/server/src/app/client-agent-workflow-artifact-binding.ts";
9849
+ var legacyDefaultBinding = `import type { ModuleClientAgentWorkflowArtifactProjectBinding } from "@southwind-ai/server-sdk";
9850
+
9851
+ /**
9852
+ * Project-owned Workflow -> PageAgent \u7ED1\u5B9A\u3002Starter \u9ED8\u8BA4\u7A7A\u6570\u7EC4\u5E76 fail closed\uFF1B
9853
+ * \u4EA7\u54C1\u53EA\u4E3A\u5DF2\u5BA1\u6838\u3001\u5DF2\u53D1\u5E03\u7684\u56FA\u5B9A Workflow Job node \u589E\u52A0\u9759\u6001\u7ED1\u5B9A\u3002
9854
+ */
9855
+ export const projectClientAgentWorkflowArtifactBindings: readonly ModuleClientAgentWorkflowArtifactProjectBinding[] =
9856
+ [];
9857
+ `;
9858
+ var immutableReleaseDefaultBinding = `import type { ModuleClientAgentWorkflowArtifactProjectBinding } from "@southwind-ai/server-sdk";
9859
+
9860
+ /**
9861
+ * Project-owned Workflow -> PageAgent \u7ED1\u5B9A\u3002Starter \u9ED8\u8BA4\u7A7A\u6570\u7EC4\u5E76 fail closed\uFF1B
9862
+ * \u4EA7\u54C1\u53EA\u4E3A\u5DF2\u5BA1\u6838\u3001\u5DF2\u53D1\u5E03\u7684\u56FA\u5B9A Workflow Job node \u589E\u52A0\u9759\u6001\u7ED1\u5B9A\u3002Operation \u5FC5\u987B\u58F0\u660E
9863
+ * \`clientExecution.launchAuthority="workflow-artifact"\`\uFF1Bbinding \u5FC5\u987B\u767B\u8BB0 Immutable
9864
+ * canonical \`releaseDigest\`\u3001scope containment contract v1\uFF0C\u4EE5\u53CA project launch\u3001client task\u3001terminal
9865
+ * authority version/digest\u3002launch authority \u4ECE Host \u5F53\u524D scope \u663E\u5F0F\u6536\u7A84\uFF1Bterminal authority
9866
+ * \u540C\u65F6\u590D\u9A8C Host \u91CD\u6388\u6743\u5E76\u6253\u5F00\u7684 canonical input artifacts\u3002project preset \u4F7F\u7528
9867
+ * runtime.agentWorkflowProjects\uFF1B\u666E\u901A routes \u6C38\u8FDC\u4E0D\u80FD\u53D1\u5E03/\u542F\u52A8\u53D7\u4FDD\u62A4 Workflow\u3002
9868
+ * \u53D1\u5E03 Release \u6216 authority contract \u540E\u5FC5\u987B\u91CD\u65B0\u5BA1\u6838\u5E76\u663E\u5F0F\u66F4\u65B0\u3002
9869
+ */
9870
+ export const projectClientAgentWorkflowArtifactBindings: readonly ModuleClientAgentWorkflowArtifactProjectBinding[] =
9871
+ [];
9872
+ `;
9873
+ var immutableReleaseCompositionHash = "98c23266799311cf26c160374aad738456888f3c04f40f3667122e28b3e8e188";
9874
+ var hostAuthImport = 'import { projectClientAgentHostAuthAdapter } from "./client-agent-host-auth-binding.js";';
9875
+ var workflowArtifactImport = 'import { projectClientAgentWorkflowArtifactBindings } from "./client-agent-workflow-artifact-binding.js";';
9876
+ var oldOmit = ' "clientAgentHostAuth" | "screenshotPageRegistry"';
9877
+ var newOmit = ` | "clientAgentHostAuth"
9878
+ | "clientAgentWorkflowArtifactBindings"
9879
+ | "screenshotPageRegistry"`;
9880
+ var hostAuthProperty = " clientAgentHostAuth: projectClientAgentHostAuthAdapter,";
9881
+ var workflowArtifactProperty = ` clientAgentWorkflowArtifactBindings:
9882
+ projectClientAgentWorkflowArtifactBindings,`;
9883
+ function planClientWorkflowProjectOwned(input) {
9884
+ return input.path === clientWorkflowBindingPath ? planBinding(input) : planComposition(input);
9885
+ }
9886
+ function planBinding(input) {
9887
+ if (!input.target)
9888
+ return conflict2(input, "\u76EE\u6807\u7248\u672C\u7F3A\u5C11 Workflow binding seam");
9889
+ const target = decode(input.target);
9890
+ if (target !== immutableReleaseDefaultBinding) {
9891
+ return conflict2(input, "\u76EE\u6807\u7248\u672C Workflow binding seam \u5951\u7EA6\u65E0\u6548");
9892
+ }
9893
+ if (!input.ours) {
9894
+ return ready2(input, "create", "\u65B0\u589E\u9ED8\u8BA4\u5173\u95ED\u7684 Workflow binding seam", input.target);
9895
+ }
9896
+ const source = decode(input.ours);
9897
+ if (source === target) {
9898
+ return ready2(input, "preserve", "\u5DF2\u5305\u542B immutable release binding seam");
9899
+ }
9900
+ if (source !== legacyDefaultBinding) {
9901
+ return conflict2(input, "Workflow binding seam \u4E0D\u662F 0.6.14 \u9ED8\u8BA4\u7A7A\u7248\u672C");
9902
+ }
9903
+ return ready2(input, "update", "\u5347\u7EA7\u9ED8\u8BA4\u7A7A Workflow binding seam", input.target);
9904
+ }
9905
+ function planComposition(input) {
9906
+ if (!input.target) {
9907
+ return conflict2(input, "\u76EE\u6807\u7248\u672C\u7F3A\u5C11 Agent Runtime Composition");
9908
+ }
9909
+ const target = decode(input.target);
9910
+ if (hashContent(target) !== immutableReleaseCompositionHash) {
9911
+ return conflict2(input, "\u76EE\u6807\u7248\u672C Agent Runtime Composition \u5951\u7EA6\u65E0\u6548");
9912
+ }
9913
+ if (!input.ours) {
9914
+ return ready2(input, "create", "\u65B0\u589E Agent Runtime Composition", input.target);
9915
+ }
9916
+ const source = decode(input.ours);
9917
+ if (source === target) {
9918
+ return ready2(input, "preserve", "\u5DF2\u88C5\u914D Workflow Artifact binding");
9919
+ }
9920
+ if ([workflowArtifactImport, newOmit, workflowArtifactProperty].some((value) => source.includes(value))) {
9921
+ return conflict2(input, "Agent Runtime Composition \u53EA\u5305\u542B\u90E8\u5206\u76EE\u6807\u88C5\u914D");
9922
+ }
9923
+ const runtimeConflict = validateLegacyRuntimeObject(source);
9924
+ if (runtimeConflict)
9925
+ return conflict2(input, runtimeConflict);
9926
+ const replacements2 = [
9927
+ {
9928
+ anchor: hostAuthImport,
9929
+ value: `${hostAuthImport}
9930
+ ${workflowArtifactImport}`
9931
+ },
9932
+ {
9933
+ anchor: oldOmit,
9934
+ value: newOmit
9935
+ },
9936
+ {
9937
+ anchor: hostAuthProperty,
9938
+ value: `${hostAuthProperty}
9939
+ ${workflowArtifactProperty}`
9940
+ }
9941
+ ];
9942
+ let content = source;
9943
+ for (const replacement of replacements2) {
9944
+ if (occurrences(content, replacement.anchor) !== 1) {
9945
+ return conflict2(input, `Agent Runtime Composition \u951A\u70B9\u4E0D\u552F\u4E00\uFF1A${replacement.anchor}`);
9946
+ }
9947
+ content = content.replace(replacement.anchor, replacement.value);
9948
+ }
9949
+ return ready2(input, "update", "\u88C5\u914D Workflow Artifact project binding", new TextEncoder().encode(content));
9950
+ }
9951
+ function ready2(input, action, reason, content) {
9952
+ return {
9953
+ path: input.path,
9954
+ ownership: "project-owned",
9955
+ action,
9956
+ reason,
9957
+ expectedProjectContent: input.expected,
9958
+ content
9959
+ };
9960
+ }
9961
+ function conflict2(input, message) {
9962
+ return {
9963
+ path: input.path,
9964
+ ownership: "project-owned",
9965
+ action: "preserve",
9966
+ reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
9967
+ expectedProjectContent: input.expected,
9968
+ conflict: message
9969
+ };
9970
+ }
9971
+ function decode(content) {
9972
+ return new TextDecoder().decode(content);
9973
+ }
9974
+ function occurrences(source, value) {
9975
+ return source.split(value).length - 1;
9976
+ }
9977
+ function validateLegacyRuntimeObject(source) {
9978
+ const startAnchor = ` const runtime = registerAgentPlatformRuntime({
9979
+ ...input,`;
9980
+ const endAnchor = `
9981
+ });`;
9982
+ if (occurrences(source, startAnchor) !== 1 || occurrences(source, endAnchor) !== 1) {
9983
+ return "Agent Runtime register object \u951A\u70B9\u4E0D\u552F\u4E00";
9984
+ }
9985
+ const start = source.indexOf(startAnchor);
9986
+ const end = source.indexOf(endAnchor, start + startAnchor.length);
9987
+ if (end < 0)
9988
+ return "Agent Runtime register object \u7ED3\u675F\u951A\u70B9\u7F3A\u5931";
9989
+ const object = source.slice(start, end);
9990
+ const host = object.indexOf(hostAuthProperty);
9991
+ if (host < 0)
9992
+ return "Agent Runtime Host Auth property \u951A\u70B9\u7F3A\u5931";
9993
+ const tail = object.slice(host + hostAuthProperty.length);
9994
+ if (/^\s*\.\.\./m.test(tail)) {
9995
+ return "Workflow binding \u63D2\u5165\u70B9\u540E\u5B58\u5728\u53EF\u8986\u76D6\u5B83\u7684 spread";
9996
+ }
9997
+ if (/["']clientAgentWorkflowArtifactBindings["']\s*:/.test(object) || /\[\s*["']clientAgentWorkflowArtifactBindings["']\s*\]/.test(object)) {
9998
+ return "Agent Runtime \u5DF2\u5B58\u5728\u52A8\u6001 Workflow binding property";
9999
+ }
10000
+ return;
10001
+ }
10002
+
9816
10003
  // src/update/recipe-project-owned-trajectory-test.ts
9817
10004
  var legacyAnchor = /^(\s*)traceId: "trace_1",\n\1attemptItems: \[$/gm;
9818
10005
  var migratedAnchor = /^(\s*)traceId: "trace_1",\n\1trajectory: \{\n\1 {2}available: true,\n\1 {2}events: \[\],\n\1\},\n\1attemptItems: \[$/gm;
@@ -9854,20 +10041,33 @@ var managedPathsByRecipe = {
9854
10041
  "apps/web/src/router/index.ts",
9855
10042
  "apps/web/src/router/platform-admin-route-bindings.ts",
9856
10043
  "apps/web/src/services/ai-runtime-api.ts"
10044
+ ],
10045
+ "starter-0.6.14-to-0.6.15": [
10046
+ clientWorkflowCompositionPath,
10047
+ clientWorkflowBindingPath
9857
10048
  ]
9858
10049
  };
9859
10050
  function recipeManagedProjectOwnedPaths(recipes2) {
9860
10051
  return new Set(recipes2.flatMap((recipe) => managedPathsByRecipe[recipe] ?? []));
9861
10052
  }
10053
+ function recipeCanManageMissingProjectOwnedPath(path2) {
10054
+ return path2 === clientWorkflowCompositionPath || path2 === clientWorkflowBindingPath;
10055
+ }
9862
10056
  async function planRecipeProjectOwned(input) {
10057
+ if (input.path === clientWorkflowCompositionPath || input.path === clientWorkflowBindingPath) {
10058
+ if (!input.target) {
10059
+ return conflict3(input, "\u7248\u672C recipe \u6240\u9700\u7684\u76EE\u6807\u6587\u4EF6\u7F3A\u5931");
10060
+ }
10061
+ return planClientWorkflowProjectOwned({ ...input, target: input.target });
10062
+ }
9863
10063
  if (!input.ours) {
9864
- return conflict2(input, "\u7248\u672C recipe \u6240\u9700\u7684\u9879\u76EE\u951A\u70B9\u7F3A\u5931");
10064
+ return conflict3(input, "\u7248\u672C recipe \u6240\u9700\u7684\u9879\u76EE\u951A\u70B9\u7F3A\u5931");
9865
10065
  }
9866
10066
  const source = new TextDecoder().decode(input.ours);
9867
10067
  const target = input.target ? new TextDecoder().decode(input.target) : undefined;
9868
10068
  const transformed = transformProjectOwnedAnchor(input.path, source, target);
9869
10069
  if ("error" in transformed)
9870
- return conflict2(input, transformed.error);
10070
+ return conflict3(input, transformed.error);
9871
10071
  if (transformed.content === source) {
9872
10072
  return preserve(input, "\u5DF2\u5305\u542B\u7248\u672C recipe \u76EE\u6807\u5185\u5BB9");
9873
10073
  }
@@ -10053,7 +10253,7 @@ function update(input, content) {
10053
10253
  content
10054
10254
  };
10055
10255
  }
10056
- function conflict2(input, message) {
10256
+ function conflict3(input, message) {
10057
10257
  return {
10058
10258
  path: input.path,
10059
10259
  ownership: "project-owned",
@@ -10073,7 +10273,8 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10073
10273
  const ownership = source?.ownership ?? target?.ownership ?? classifyOwnership(path2);
10074
10274
  const expected = expectationForSnapshot(ours);
10075
10275
  if (ownership === "project-owned") {
10076
- if (manageRecipeProjectOwned && source) {
10276
+ const hasExistingRecipeSource = source !== undefined && source.state !== "missing" && ours !== undefined;
10277
+ if (manageRecipeProjectOwned && target && (hasExistingRecipeSource || recipeCanManageMissingProjectOwnedPath(path2))) {
10077
10278
  return planRecipeProjectOwned({ path: path2, ours, target: theirs, expected });
10078
10279
  }
10079
10280
  if (manageGeneratedProjectOwned) {
@@ -10083,29 +10284,29 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10083
10284
  }
10084
10285
  if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
10085
10286
  if (source && !target) {
10086
- return conflict3(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
10287
+ return conflict4(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
10087
10288
  }
10088
10289
  if (source && target && source.hash !== target.hash) {
10089
- return conflict3(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
10290
+ return conflict4(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
10090
10291
  }
10091
10292
  }
10092
10293
  if (!source && target) {
10093
10294
  if (!ours) {
10094
10295
  return readyPlannedFile(path2, ownership, "create", "\u76EE\u6807\u7248\u672C\u65B0\u589E", expected, theirs);
10095
10296
  }
10096
- return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict3(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
10297
+ return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict4(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
10097
10298
  }
10098
10299
  if (source && !target) {
10099
10300
  if (!ours) {
10100
10301
  return readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
10101
10302
  }
10102
- return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict3(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
10303
+ return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict4(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
10103
10304
  }
10104
10305
  if (source && target && !ours) {
10105
10306
  return readyPlannedFile(path2, "project-owned", "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
10106
10307
  }
10107
10308
  if (!source || !target || !ours || !theirs) {
10108
- return conflict3(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
10309
+ return conflict4(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
10109
10310
  }
10110
10311
  const oursChanged = hashContent(ours) !== source.hash;
10111
10312
  const sourceArtifactHash = artifactHashOf(source);
@@ -10119,7 +10320,7 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10119
10320
  });
10120
10321
  if (forceTargetBaseline && path2.endsWith("package.json") && base) {
10121
10322
  const merged = mergePackageJson(base, ours, theirs);
10122
- return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10323
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict4(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10123
10324
  }
10124
10325
  if (forceTargetBaseline) {
10125
10326
  return readyPlannedFile(path2, ownership, "update", "\u5F3A\u5236\u91C7\u7528\u76EE\u6807\u5E73\u53F0\u57FA\u7EBF", expected, theirs);
@@ -10129,11 +10330,11 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10129
10330
  }
10130
10331
  if (targetChanged && path2.endsWith("package.json") && base) {
10131
10332
  const merged = mergePackageJson(base, ours, theirs);
10132
- return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10333
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict4(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10133
10334
  }
10134
10335
  if (!oursChanged && targetChanged && adoptedProjectDelta && base) {
10135
10336
  const merged = await mergeTextFile(base, ours, theirs);
10136
- return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict3(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10337
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict4(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10137
10338
  }
10138
10339
  if (!oursChanged) {
10139
10340
  return readyPlannedFile(path2, ownership, "update", "\u4EC5 Windy \u4FEE\u6539", expected, theirs);
@@ -10146,9 +10347,9 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10146
10347
  }
10147
10348
  if (base) {
10148
10349
  const merged = await mergeTextFile(base, ours, theirs);
10149
- return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10350
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict4(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10150
10351
  }
10151
- return conflict3(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
10352
+ return conflict4(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
10152
10353
  }
10153
10354
  function shouldForcePlatformBaseline(input) {
10154
10355
  return input.forcePlatformBaseline && !input.oursChanged && input.base !== undefined && hashContent(input.base) !== input.sourceArtifactHash;
@@ -10169,7 +10370,7 @@ function readyPlannedFile(path2, ownership, action, reason, expectedProjectConte
10169
10370
  function expectationForSnapshot(content) {
10170
10371
  return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
10171
10372
  }
10172
- function conflict3(path2, ownership, reason, expectedProjectContent) {
10373
+ function conflict4(path2, ownership, reason, expectedProjectContent) {
10173
10374
  return {
10174
10375
  path: path2,
10175
10376
  ownership,
@@ -11000,9 +11201,9 @@ function assertEnabledConflicts(target, catalog) {
11000
11201
  for (const [name, enabled] of target) {
11001
11202
  if (!enabled)
11002
11203
  continue;
11003
- const conflict4 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
11004
- if (conflict4)
11005
- throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict4}`);
11204
+ const conflict5 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
11205
+ if (conflict5)
11206
+ throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict5}`);
11006
11207
  }
11007
11208
  }
11008
11209
  function assertCompatible(version, range, name) {
@@ -11017,7 +11218,7 @@ function reconcileProjectModuleRegistryPlan(plan, current, lifecycle) {
11017
11218
  if (!registryFile) {
11018
11219
  throw new Error("\u6A21\u5757\u751F\u547D\u5468\u671F\u8BA1\u5212\u7F3A\u5C11 project-owned \u88C5\u914D\u9009\u62E9");
11019
11220
  }
11020
- plan.conflicts = plan.conflicts.filter((conflict4) => !conflict4.startsWith(`${projectModuleRegistryPath}\uFF1A`));
11221
+ plan.conflicts = plan.conflicts.filter((conflict5) => !conflict5.startsWith(`${projectModuleRegistryPath}\uFF1A`));
11021
11222
  delete registryFile.conflict;
11022
11223
  if (lifecycle.action === "update") {
11023
11224
  registryFile.action = "preserve";
@@ -11270,7 +11471,7 @@ function assertKnownModuleArguments(args) {
11270
11471
 
11271
11472
  // src/module-lifecycle-confirmation.ts
11272
11473
  import { createInterface as createInterface3 } from "readline/promises";
11273
- async function confirmModuleMutation(args, dependencies, log) {
11474
+ async function confirmModuleMutation(args, dependencies, log, message = "\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u6A21\u5757\u8BA1\u5212\uFF1F") {
11274
11475
  if (args.includes("--yes"))
11275
11476
  return true;
11276
11477
  const isTTY = dependencies.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
@@ -11278,7 +11479,7 @@ async function confirmModuleMutation(args, dependencies, log) {
11278
11479
  throw new Error("\u975E\u4EA4\u4E92\u73AF\u5883\u6B63\u5F0F\u53D8\u66F4\u5FC5\u987B\u4F20\u5165 --yes");
11279
11480
  }
11280
11481
  const confirm = dependencies.confirm ?? promptForConfirmation;
11281
- const accepted = await confirm("\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u6A21\u5757\u8BA1\u5212\uFF1F");
11482
+ const accepted = await confirm(message);
11282
11483
  if (!accepted)
11283
11484
  log("\u5DF2\u53D6\u6D88\uFF1A\u9879\u76EE\u672A\u88AB\u4FEE\u6539");
11284
11485
  return accepted;
@@ -11447,8 +11648,8 @@ function printModulePlan(plan, log) {
11447
11648
  for (const file of changed) {
11448
11649
  log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
11449
11650
  }
11450
- for (const conflict4 of plan.conflicts)
11451
- log(` conflict ${conflict4}`);
11651
+ for (const conflict5 of plan.conflicts)
11652
+ log(` conflict ${conflict5}`);
11452
11653
  }
11453
11654
  function hasChanges(lifecycle) {
11454
11655
  return lifecycle.addedModules.length > 0 || lifecycle.updatedModules.length > 0 || lifecycle.removedModules.length > 0;
@@ -11620,8 +11821,8 @@ function printPlan(plan) {
11620
11821
  console.log(`\u8BA1\u5212\u6539\u52A8\uFF1A${changed.length} \u4E2A\u6587\u4EF6\uFF1B\u51B2\u7A81\uFF1A${plan.conflicts.length}`);
11621
11822
  for (const file of changed)
11622
11823
  console.log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
11623
- for (const conflict4 of plan.conflicts)
11624
- console.log(` conflict ${conflict4}`);
11824
+ for (const conflict5 of plan.conflicts)
11825
+ console.log(` conflict ${conflict5}`);
11625
11826
  for (const finding of plan.manualCleanup ?? []) {
11626
11827
  console.log(` manual ${finding.message}`);
11627
11828
  }
@@ -11989,6 +12190,750 @@ function readValue4(args, flag) {
11989
12190
  return index >= 0 ? args[index + 1] : undefined;
11990
12191
  }
11991
12192
 
12193
+ // src/package-command.ts
12194
+ import { resolve as resolve14 } from "path";
12195
+
12196
+ // src/package-configuration.ts
12197
+ import { createHash as createHash5 } from "crypto";
12198
+ import { readFile as readFile27 } from "fs/promises";
12199
+ import { isAbsolute as isAbsolute3, normalize, relative as relative8, resolve as resolve11, sep as sep6 } from "path";
12200
+
12201
+ // src/package-types.ts
12202
+ var packagePlatforms = ["linux/amd64", "linux/arm64"];
12203
+
12204
+ // src/package-configuration.ts
12205
+ var configurationFile = "windy.build.json";
12206
+ var shellCharacters = /[;&|`><\r\n$()'"]/u;
12207
+ var placeholder = /\$\{(platform|output\.directory|input\.([a-z][a-z0-9-]*))\}/gu;
12208
+ var secretName = /secret|token|password|credential|private[-_]?key|api[-_]?key/iu;
12209
+ var shellExecutables = new Set([
12210
+ "sh",
12211
+ "bash",
12212
+ "zsh",
12213
+ "fish",
12214
+ "cmd",
12215
+ "powershell",
12216
+ "pwsh"
12217
+ ]);
12218
+ async function readPackageConfiguration(projectDirectory) {
12219
+ const path2 = resolve11(projectDirectory, configurationFile);
12220
+ let source;
12221
+ try {
12222
+ source = await readFile27(path2, "utf8");
12223
+ } catch (error) {
12224
+ if (error.code === "ENOENT") {
12225
+ throw new Error("\u672A\u58F0\u660E\u6253\u5305\u9002\u914D\u5668\uFF1A\u9879\u76EE\u6839\u76EE\u5F55\u7F3A\u5C11 windy.build.json", {
12226
+ cause: error
12227
+ });
12228
+ }
12229
+ throw error;
12230
+ }
12231
+ try {
12232
+ const configuration = parsePackageConfiguration(JSON.parse(source));
12233
+ return { configuration, digest: sha256(canonicalJson(configuration)) };
12234
+ } catch (error) {
12235
+ if (error instanceof SyntaxError)
12236
+ throw new Error("windy.build.json \u4E0D\u662F\u6709\u6548 JSON", { cause: error });
12237
+ throw error;
12238
+ }
12239
+ }
12240
+ function parsePackageConfiguration(value) {
12241
+ const root = object(value, "windy.build.json");
12242
+ rejectUnknown(root, ["schemaVersion", "product", "platforms", "profiles"], "windy.build.json");
12243
+ if (root.schemaVersion !== 1)
12244
+ throw new Error("windy.build.json \u53EA\u652F\u6301 schemaVersion: 1");
12245
+ const platforms = array(root.platforms, "platforms").map((item) => {
12246
+ const platform = string(item, "platforms[]");
12247
+ if (!packagePlatforms.includes(platform)) {
12248
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u76EE\u6807\u5E73\u53F0\uFF1A${platform}`);
12249
+ }
12250
+ return platform;
12251
+ });
12252
+ unique2(platforms, "platforms");
12253
+ if (!platforms.length)
12254
+ throw new Error("platforms \u4E0D\u80FD\u4E3A\u7A7A");
12255
+ const profiles = array(root.profiles, "profiles").map(parseProfile);
12256
+ unique2(profiles.map(({ key }) => key), "profile key");
12257
+ if (!profiles.length)
12258
+ throw new Error("profiles \u4E0D\u80FD\u4E3A\u7A7A");
12259
+ return {
12260
+ schemaVersion: 1,
12261
+ product: string(root.product, "product"),
12262
+ platforms,
12263
+ profiles
12264
+ };
12265
+ }
12266
+ function parseProfile(value) {
12267
+ const profile = object(value, "profile");
12268
+ rejectUnknown(profile, [
12269
+ "key",
12270
+ "label",
12271
+ "description",
12272
+ "inputs",
12273
+ "command",
12274
+ "output",
12275
+ "requirements"
12276
+ ], "profile");
12277
+ const key = identifier(profile.key, "profile key");
12278
+ const inputs = array(profile.inputs, `profile ${key}.inputs`).map((item) => parseInput(item, key));
12279
+ unique2(inputs.map(({ key: inputKey }) => inputKey), `profile ${key} input key`);
12280
+ const command = object(profile.command, `profile ${key}.command`);
12281
+ rejectUnknown(command, ["executable", "arguments"], `profile ${key}.command`);
12282
+ const executable = string(command.executable, `profile ${key}.command.executable`);
12283
+ if (shellExecutables.has(executable.toLowerCase()) || shellCharacters.test(executable) || !/^[a-zA-Z0-9._-]+$/u.test(executable)) {
12284
+ throw new Error(`profile ${key} \u7684 command.executable \u5FC5\u987B\u662F PATH \u4E2D\u7684\u5B89\u5168\u7A0B\u5E8F\u540D`);
12285
+ }
12286
+ const commandArguments = array(command.arguments, `profile ${key}.command.arguments`).map((item) => {
12287
+ const argument = string(item, `profile ${key}.command.arguments[]`);
12288
+ validatePlaceholders(argument, inputs, key);
12289
+ if (shellCharacters.test(argument.replace(placeholder, ""))) {
12290
+ throw new Error(`profile ${key} \u7684 command.arguments \u4E0D\u5141\u8BB8 Shell \u5B57\u7B26\u4E32`);
12291
+ }
12292
+ return argument;
12293
+ });
12294
+ const output = object(profile.output, `profile ${key}.output`);
12295
+ rejectUnknown(output, ["directory", "artifactSuffix"], `profile ${key}.output`);
12296
+ const directory = string(output.directory, `profile ${key}.output.directory`);
12297
+ if (!isSafeRelativePath(directory) || !/^[a-zA-Z0-9._/-]+$/u.test(directory))
12298
+ throw new Error(`profile ${key} \u7684 output.directory \u8D8A\u51FA\u9879\u76EE\u8FB9\u754C`);
12299
+ const artifactSuffix = string(output.artifactSuffix, `profile ${key}.output.artifactSuffix`);
12300
+ if (!artifactSuffix.startsWith(".") || shellCharacters.test(artifactSuffix) || !/^\.[a-zA-Z0-9._-]+$/u.test(artifactSuffix)) {
12301
+ throw new Error(`profile ${key} \u7684 output.artifactSuffix \u975E\u6CD5`);
12302
+ }
12303
+ const requirements = object(profile.requirements, `profile ${key}.requirements`);
12304
+ rejectUnknown(requirements, ["docker", "buildx"], `profile ${key}.requirements`);
12305
+ const docker = boolean(requirements.docker, `profile ${key}.requirements.docker`);
12306
+ const buildx = boolean(requirements.buildx, `profile ${key}.requirements.buildx`);
12307
+ if (buildx && !docker)
12308
+ throw new Error(`profile ${key} \u7684 buildx \u9700\u8981 docker`);
12309
+ return {
12310
+ key,
12311
+ label: string(profile.label, `profile ${key}.label`),
12312
+ description: string(profile.description, `profile ${key}.description`),
12313
+ inputs,
12314
+ command: { executable, arguments: commandArguments },
12315
+ output: { directory, artifactSuffix },
12316
+ requirements: { docker, buildx }
12317
+ };
12318
+ }
12319
+ function parseInput(value, profile) {
12320
+ const input = object(value, `profile ${profile}.input`);
12321
+ rejectUnknown(input, ["key", "label", "required", "pattern"], `profile ${profile}.input`);
12322
+ const key = identifier(input.key, `profile ${profile}.input.key`);
12323
+ if (secretName.test(key))
12324
+ throw new Error(`profile ${profile} \u4E0D\u5141\u8BB8 secret \u8F93\u5165\uFF1A${key}`);
12325
+ const pattern = input.pattern === undefined ? undefined : string(input.pattern, `profile ${profile}.input.pattern`);
12326
+ if (pattern) {
12327
+ try {
12328
+ new RegExp(pattern, "u");
12329
+ } catch {
12330
+ throw new Error(`profile ${profile} \u7684\u8F93\u5165 pattern \u975E\u6CD5`);
12331
+ }
12332
+ }
12333
+ return {
12334
+ key,
12335
+ label: string(input.label, `profile ${profile}.input.label`),
12336
+ required: boolean(input.required, `profile ${profile}.input.required`),
12337
+ pattern
12338
+ };
12339
+ }
12340
+ function validatePlaceholders(value, inputs, profile) {
12341
+ const tokens = [...value.matchAll(placeholder)];
12342
+ for (const token of tokens) {
12343
+ const inputKey = token[2];
12344
+ if (inputKey && !inputs.some(({ key }) => key === inputKey)) {
12345
+ throw new Error(`profile ${profile} \u4F7F\u7528\u672A\u58F0\u660E\u5360\u4F4D\u7B26\uFF1Ainput.${inputKey}`);
12346
+ }
12347
+ }
12348
+ if (value.replace(placeholder, "").includes("${"))
12349
+ throw new Error(`profile ${profile} \u5305\u542B\u672A\u58F0\u660E\u5360\u4F4D\u7B26`);
12350
+ }
12351
+ function object(value, label) {
12352
+ if (!value || typeof value !== "object" || Array.isArray(value))
12353
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
12354
+ return value;
12355
+ }
12356
+ function array(value, label) {
12357
+ if (!Array.isArray(value))
12358
+ throw new Error(`${label} \u5FC5\u987B\u662F\u6570\u7EC4`);
12359
+ return value;
12360
+ }
12361
+ function string(value, label) {
12362
+ if (typeof value !== "string" || !value.trim())
12363
+ throw new Error(`${label} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
12364
+ return value;
12365
+ }
12366
+ function boolean(value, label) {
12367
+ if (typeof value !== "boolean")
12368
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
12369
+ return value;
12370
+ }
12371
+ function identifier(value, label) {
12372
+ const result2 = string(value, label);
12373
+ if (!/^[a-z][a-z0-9-]*$/u.test(result2))
12374
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5C0F\u5199 kebab-case`);
12375
+ return result2;
12376
+ }
12377
+ function unique2(values, label) {
12378
+ if (new Set(values).size !== values.length)
12379
+ throw new Error(`${label} \u4E0D\u80FD\u91CD\u590D`);
12380
+ }
12381
+ function rejectUnknown(source, allowed, label) {
12382
+ for (const key of Object.keys(source))
12383
+ if (!allowed.includes(key))
12384
+ throw new Error(`${label} \u5305\u542B\u672A\u77E5\u5B57\u6BB5\uFF1A${key}`);
12385
+ }
12386
+ function isSafeRelativePath(value) {
12387
+ return Boolean(value) && normalize(value) !== "." && !isAbsolute3(value) && !value.includes("\\") && !relative8(".", resolve11(".", value)).split(sep6).includes("..") && !normalize(value).startsWith("..");
12388
+ }
12389
+ function canonicalJson(value) {
12390
+ if (Array.isArray(value))
12391
+ return `[${value.map(canonicalJson).join(",")}]`;
12392
+ if (value && typeof value === "object")
12393
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
12394
+ return JSON.stringify(value);
12395
+ }
12396
+ function sha256(value) {
12397
+ return createHash5("sha256").update(value).digest("hex");
12398
+ }
12399
+
12400
+ // src/package-execution.ts
12401
+ import { createHash as createHash6 } from "crypto";
12402
+ import { readdir as readdir10, realpath as realpath2, stat as stat3 } from "fs/promises";
12403
+ import { relative as relative9, resolve as resolve12 } from "path";
12404
+ var bunPackageProcess = {
12405
+ async run(command, args, cwd) {
12406
+ const child = Bun.spawn([command, ...args], {
12407
+ cwd,
12408
+ env: withoutParentGitRepository(process.env),
12409
+ stdin: "inherit",
12410
+ stdout: "pipe",
12411
+ stderr: "pipe"
12412
+ });
12413
+ const [stdout2, stderr, code] = await Promise.all([
12414
+ new Response(child.stdout).text(),
12415
+ new Response(child.stderr).text(),
12416
+ child.exited
12417
+ ]);
12418
+ return { code, stdout: stdout2, stderr };
12419
+ }
12420
+ };
12421
+ async function readPackageSource(projectDirectory, process4 = bunPackageProcess, ignoredPaths = []) {
12422
+ const revision = await currentGitRevision(projectDirectory, process4);
12423
+ const status = await assertCommand(process4, "git", ["status", "--porcelain"], projectDirectory, "\u65E0\u6CD5\u8BFB\u53D6 Git \u5DE5\u4F5C\u533A\u72B6\u6001");
12424
+ const root = await realpath2(projectDirectory);
12425
+ const ignored = new Set(ignoredPaths.map((path2) => relative9(root, path2)));
12426
+ const dirty = status.stdout.trim().split(`
12427
+ `).filter(Boolean).filter((line) => !ignored.has(line.slice(3)));
12428
+ if (dirty.length)
12429
+ throw new Error("Git \u5DE5\u4F5C\u533A\u5FC5\u987B\u5E72\u51C0\u624D\u80FD\u51BB\u7ED3\u6216\u6267\u884C\u6253\u5305\u8BA1\u5212");
12430
+ return revision;
12431
+ }
12432
+ async function currentGitRevision(projectDirectory, process4 = bunPackageProcess) {
12433
+ const revision = await assertCommand(process4, "git", ["rev-parse", "HEAD"], projectDirectory, "\u65E0\u6CD5\u8BFB\u53D6 Git SHA");
12434
+ return revision.stdout.trim();
12435
+ }
12436
+ async function preflightPackage(plan, projectDirectory, process4 = bunPackageProcess, ignoredPaths = []) {
12437
+ const sourceRevision = await readPackageSource(projectDirectory, process4, ignoredPaths);
12438
+ if (sourceRevision !== plan.source.revision)
12439
+ throw new Error("\u6267\u884C\u524D\u6E90\u7801 SHA \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C");
12440
+ await assertCommand(process4, "bun", ["--version"], projectDirectory, "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Bun");
12441
+ if (!plan.requirements.docker)
12442
+ return;
12443
+ await assertCommand(process4, "docker", ["version", "--format", "{{.Server.Version}}"], projectDirectory, "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Docker Server");
12444
+ if (!plan.requirements.buildx)
12445
+ return;
12446
+ const buildx = await assertCommand(process4, "docker", ["buildx", "inspect"], projectDirectory, "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Docker Buildx builder");
12447
+ if (!buildx.stdout.includes(plan.platform) && !buildx.stderr.includes(plan.platform)) {
12448
+ throw new Error(`\u5F53\u524D Buildx builder \u4E0D\u652F\u6301 ${plan.platform}`);
12449
+ }
12450
+ }
12451
+ async function executePackagePlan(plan, projectDirectory, process4 = bunPackageProcess, ignoredPaths = []) {
12452
+ const beforeRevision = await readPackageSource(projectDirectory, process4, ignoredPaths);
12453
+ if (beforeRevision !== plan.source.revision)
12454
+ throw new Error("\u6267\u884C\u524D\u6E90\u7801 SHA \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C");
12455
+ const projectRoot = await realpath2(projectDirectory);
12456
+ const outputDirectory = await guardedOutputDirectory(projectDirectory, plan.output.directory, false);
12457
+ const before = new Map((await artifacts(outputDirectory, plan.output.artifactSuffix, projectRoot)).map(({ path: path2, sha256: sha2562 }) => [path2, sha2562]));
12458
+ const command = await process4.run(plan.command.executable, plan.command.arguments, projectDirectory);
12459
+ if (command.code !== 0)
12460
+ return failed(beforeRevision, `\u6784\u5EFA\u547D\u4EE4\u9000\u51FA\u7801 ${command.code}\uFF1A${details(command)}`);
12461
+ const afterRevision = await currentGitRevision(projectDirectory, process4);
12462
+ if (afterRevision !== beforeRevision)
12463
+ return failed(afterRevision, "\u6784\u5EFA\u671F\u95F4\u6E90\u7801 SHA \u53D1\u751F\u6F02\u79FB");
12464
+ const finalOutput = await guardedOutputDirectory(projectDirectory, plan.output.directory, true);
12465
+ const after = await artifacts(finalOutput, plan.output.artifactSuffix, projectRoot);
12466
+ const changed = after.filter((artifact) => before.get(artifact.path) !== artifact.sha256);
12467
+ const sourceDrift = await sourceDriftAfterBuild(process4, projectDirectory, ignoredPaths, changed.map(({ path: path2 }) => path2));
12468
+ if (sourceDrift)
12469
+ return failed(afterRevision, sourceDrift, changed);
12470
+ if (changed.length !== 1)
12471
+ return failed(afterRevision, `\u9884\u671F\u6070\u597D\u4E00\u4E2A\u65B0\u589E\u6216\u53D8\u66F4\u4EA7\u7269\uFF0C\u5B9E\u9645\u53D1\u73B0 ${changed.length} \u4E2A`, changed);
12472
+ return {
12473
+ status: "succeeded",
12474
+ completedAt: new Date().toISOString(),
12475
+ sourceRevision: afterRevision,
12476
+ artifacts: changed
12477
+ };
12478
+ }
12479
+ async function assertCommand(process4, command, args, cwd, message) {
12480
+ const result2 = await process4.run(command, args, cwd);
12481
+ if (result2.code !== 0)
12482
+ throw new Error(`${message}\uFF1A${details(result2)}`);
12483
+ return result2;
12484
+ }
12485
+ async function guardedOutputDirectory(projectDirectory, directory, mustExist) {
12486
+ const root = await realpath2(projectDirectory);
12487
+ const output = resolve12(root, directory);
12488
+ if (!within(root, output))
12489
+ throw new Error("\u8F93\u51FA\u76EE\u5F55\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12490
+ try {
12491
+ const actual = await realpath2(output);
12492
+ if (!within(root, actual))
12493
+ throw new Error("\u8F93\u51FA\u76EE\u5F55\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12494
+ return actual;
12495
+ } catch (error) {
12496
+ if (error instanceof Error && error.message === "\u8F93\u51FA\u76EE\u5F55\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C")
12497
+ throw error;
12498
+ if (mustExist)
12499
+ throw new Error("\u6784\u5EFA\u6CA1\u6709\u4EA7\u751F\u58F0\u660E\u7684\u8F93\u51FA\u76EE\u5F55", { cause: error });
12500
+ return output;
12501
+ }
12502
+ }
12503
+ async function artifacts(directory, suffix, projectDirectory) {
12504
+ try {
12505
+ await stat3(directory);
12506
+ } catch {
12507
+ return [];
12508
+ }
12509
+ const entries = await readdir10(directory, {
12510
+ recursive: true,
12511
+ withFileTypes: true
12512
+ });
12513
+ return await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(suffix)).map(async (entry) => {
12514
+ const path2 = resolve12(directory, entry.parentPath, entry.name);
12515
+ return {
12516
+ path: relative9(projectDirectory, path2),
12517
+ sha256: createHash6("sha256").update(Buffer.from(await Bun.file(path2).arrayBuffer())).digest("hex")
12518
+ };
12519
+ }));
12520
+ }
12521
+ async function sourceDriftAfterBuild(process4, projectDirectory, ignoredPaths, generatedArtifacts) {
12522
+ const status = await process4.run("git", ["status", "--porcelain"], projectDirectory);
12523
+ if (status.code !== 0)
12524
+ return `\u65E0\u6CD5\u68C0\u67E5\u6784\u5EFA\u540E\u7684\u6E90\u7801\u6F02\u79FB\uFF1A${details(status)}`;
12525
+ const root = await realpath2(projectDirectory);
12526
+ const ignored = new Set(ignoredPaths.map((path2) => relative9(root, path2)));
12527
+ const generated = new Set(generatedArtifacts);
12528
+ const drift = status.stdout.trim().split(`
12529
+ `).filter(Boolean).filter((line) => {
12530
+ const path2 = line.slice(3);
12531
+ return !ignored.has(path2) && !(line.startsWith("?? ") && generated.has(path2));
12532
+ });
12533
+ return drift.length ? "\u6784\u5EFA\u671F\u95F4\u6E90\u7801\u5DE5\u4F5C\u533A\u53D1\u751F\u6F02\u79FB" : undefined;
12534
+ }
12535
+ function within(root, path2) {
12536
+ const result2 = relative9(root, path2);
12537
+ return Boolean(result2) && !result2.startsWith("..") && result2 !== "..";
12538
+ }
12539
+ function details(result2) {
12540
+ return (result2.stderr || result2.stdout).trim() || "\u672A\u63D0\u4F9B\u8BCA\u65AD\u4FE1\u606F";
12541
+ }
12542
+ function failed(sourceRevision, diagnostic, artifacts2 = []) {
12543
+ return {
12544
+ status: "failed",
12545
+ completedAt: new Date().toISOString(),
12546
+ sourceRevision,
12547
+ artifacts: artifacts2,
12548
+ diagnostic
12549
+ };
12550
+ }
12551
+
12552
+ // src/package-plan.ts
12553
+ import { readFile as readFile28, realpath as realpath3, writeFile as writeFile15 } from "fs/promises";
12554
+ import { dirname as dirname12, relative as relative10, resolve as resolve13 } from "path";
12555
+ function resolvePackageProfile(configuration, profileKey) {
12556
+ const profile = configuration.profiles.find(({ key }) => key === profileKey);
12557
+ if (!profile)
12558
+ throw new Error(`\u672A\u58F0\u660E\u7684\u6253\u5305 profile\uFF1A${profileKey}`);
12559
+ return profile;
12560
+ }
12561
+ function validatePackageInputs(profile, supplied) {
12562
+ for (const key of Object.keys(supplied)) {
12563
+ if (!profile.inputs.some((input) => input.key === key)) {
12564
+ throw new Error(`profile ${profile.key} \u4E0D\u63A5\u53D7\u8F93\u5165\uFF1A${key}`);
12565
+ }
12566
+ }
12567
+ const validated = {};
12568
+ for (const input of profile.inputs) {
12569
+ const value = supplied[input.key];
12570
+ if (input.required && !value)
12571
+ throw new Error(`profile ${profile.key} \u7F3A\u5C11\u5FC5\u586B\u8F93\u5165\uFF1A${input.key}`);
12572
+ if (value === undefined)
12573
+ continue;
12574
+ if (input.pattern && !new RegExp(input.pattern, "u").test(value)) {
12575
+ throw new Error(`\u8F93\u5165 ${input.key} \u4E0D\u7B26\u5408\u58F0\u660E\u7684\u683C\u5F0F`);
12576
+ }
12577
+ validated[input.key] = value;
12578
+ }
12579
+ return validated;
12580
+ }
12581
+ function createFrozenPackagePlan(input) {
12582
+ const {
12583
+ configuration,
12584
+ configDigest,
12585
+ sourceRevision,
12586
+ profile,
12587
+ platform,
12588
+ inputs
12589
+ } = input;
12590
+ return {
12591
+ schemaVersion: 1,
12592
+ product: configuration.product,
12593
+ configDigest,
12594
+ source: { revision: sourceRevision, clean: true },
12595
+ profile: profile.key,
12596
+ platform,
12597
+ inputs,
12598
+ command: {
12599
+ executable: profile.command.executable,
12600
+ arguments: profile.command.arguments.map((argument) => expand(argument, platform, profile.output.directory, inputs))
12601
+ },
12602
+ output: profile.output,
12603
+ requirements: profile.requirements,
12604
+ createdAt: new Date().toISOString()
12605
+ };
12606
+ }
12607
+ function assertFrozenPlanCurrent(input) {
12608
+ const { plan, configuration, configDigest, sourceRevision } = input;
12609
+ if (plan.product !== configuration.product)
12610
+ throw new Error("\u51BB\u7ED3\u8BA1\u5212\u7684\u4EA7\u54C1\u6807\u8BC6\u4E0E\u5F53\u524D\u9879\u76EE\u4E0D\u4E00\u81F4");
12611
+ if (plan.configDigest !== configDigest)
12612
+ throw new Error("windy.build.json \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C\u51BB\u7ED3\u8BA1\u5212");
12613
+ if (plan.source.revision !== sourceRevision)
12614
+ throw new Error("\u6E90\u7801 SHA \u5DF2\u6F02\u79FB\uFF0C\u62D2\u7EDD\u6267\u884C\u51BB\u7ED3\u8BA1\u5212");
12615
+ if (!configuration.platforms.includes(plan.platform))
12616
+ throw new Error("\u51BB\u7ED3\u8BA1\u5212\u7684\u76EE\u6807\u5E73\u53F0\u5DF2\u4E0D\u88AB\u5F53\u524D\u914D\u7F6E\u652F\u6301");
12617
+ const profile = resolvePackageProfile(configuration, plan.profile);
12618
+ const inputs = validatePackageInputs(profile, plan.inputs);
12619
+ const expected = createFrozenPackagePlan({
12620
+ configuration,
12621
+ configDigest,
12622
+ sourceRevision,
12623
+ profile,
12624
+ platform: plan.platform,
12625
+ inputs
12626
+ });
12627
+ if (canonicalJson(withoutCreatedAt(expected)) !== canonicalJson(withoutCreatedAt(plan))) {
12628
+ throw new Error("\u51BB\u7ED3\u8BA1\u5212\u4E0E\u5F53\u524D\u6784\u5EFA\u914D\u7F6E\u4E0D\u4E00\u81F4\uFF0C\u62D2\u7EDD\u6267\u884C");
12629
+ }
12630
+ }
12631
+ async function readFrozenPackagePlan(path2) {
12632
+ try {
12633
+ return parseFrozenPackagePlan(JSON.parse(await readFile28(path2, "utf8")));
12634
+ } catch (error) {
12635
+ if (error instanceof Error && error.message.startsWith("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212"))
12636
+ throw error;
12637
+ throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u6709\u6548\u7684\u51BB\u7ED3\u6253\u5305\u8BA1\u5212", { cause: error });
12638
+ }
12639
+ }
12640
+ async function writeFrozenPackagePlan(path2, plan) {
12641
+ await writeFile15(path2, `${JSON.stringify(plan, null, 2)}
12642
+ `, "utf8");
12643
+ }
12644
+ async function resolvePackagePlanPath(projectDirectory, requested) {
12645
+ if (!isSafeRelativePath(requested) || !/^[a-zA-Z0-9._/-]+$/u.test(requested))
12646
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12647
+ const root = await realpath3(projectDirectory);
12648
+ const path2 = resolve13(root, requested);
12649
+ if (relative10(root, path2).startsWith(".."))
12650
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12651
+ let parent;
12652
+ try {
12653
+ parent = await realpath3(dirname12(path2));
12654
+ } catch {
12655
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u7236\u76EE\u5F55\u5FC5\u987B\u5DF2\u5B58\u5728\u4E14\u4F4D\u4E8E\u9879\u76EE\u8FB9\u754C\u5185");
12656
+ }
12657
+ if (!withinOrEqual(root, parent))
12658
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12659
+ try {
12660
+ if (!withinOrEqual(root, await realpath3(path2))) {
12661
+ throw new Error("\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C");
12662
+ }
12663
+ } catch (error) {
12664
+ if (error instanceof Error && error.message === "\u8BA1\u5212\u6587\u4EF6\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u8FB9\u754C")
12665
+ throw error;
12666
+ }
12667
+ return path2;
12668
+ }
12669
+ function expand(value, platform, outputDirectory, inputs) {
12670
+ return value.replace(/\$\{(platform|output\.directory|input\.([a-z][a-z0-9-]*))\}/gu, (_, token, inputKey) => {
12671
+ if (token === "platform")
12672
+ return platform;
12673
+ if (token === "output.directory")
12674
+ return outputDirectory;
12675
+ return inputs[inputKey] ?? "";
12676
+ });
12677
+ }
12678
+ function withoutCreatedAt(plan) {
12679
+ const { createdAt: _createdAt, ...rest } = plan;
12680
+ return rest;
12681
+ }
12682
+ function withinOrEqual(root, path2) {
12683
+ const result2 = relative10(root, path2);
12684
+ return !result2 || !result2.startsWith("..") && result2 !== "..";
12685
+ }
12686
+ function parseFrozenPackagePlan(value) {
12687
+ const plan = record(value, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212");
12688
+ rejectUnknown2(plan, [
12689
+ "schemaVersion",
12690
+ "product",
12691
+ "configDigest",
12692
+ "source",
12693
+ "profile",
12694
+ "platform",
12695
+ "inputs",
12696
+ "command",
12697
+ "output",
12698
+ "requirements",
12699
+ "createdAt",
12700
+ "result"
12701
+ ], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212");
12702
+ if (plan.result !== undefined)
12703
+ throw new Error("\u5DF2\u5B8C\u6210\u7684\u6253\u5305\u8BA1\u5212\u4E0D\u80FD\u518D\u6B21\u6267\u884C");
12704
+ const source = record(plan.source, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 source");
12705
+ rejectUnknown2(source, ["revision", "clean"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 source");
12706
+ const command = record(plan.command, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command");
12707
+ rejectUnknown2(command, ["executable", "arguments"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command");
12708
+ const output = record(plan.output, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 output");
12709
+ rejectUnknown2(output, ["directory", "artifactSuffix"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 output");
12710
+ const requirements = record(plan.requirements, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 requirements");
12711
+ rejectUnknown2(requirements, ["docker", "buildx"], "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 requirements");
12712
+ const inputs = record(plan.inputs, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 inputs");
12713
+ for (const [key, input] of Object.entries(inputs)) {
12714
+ if (!/^[a-z][a-z0-9-]*$/u.test(key) || typeof input !== "string") {
12715
+ throw new Error("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 inputs \u975E\u6CD5");
12716
+ }
12717
+ }
12718
+ const arguments_ = array2(command.arguments, "\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command.arguments");
12719
+ if (!arguments_.every((argument) => typeof argument === "string")) {
12720
+ throw new Error("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212 command.arguments \u975E\u6CD5");
12721
+ }
12722
+ if (plan.schemaVersion !== 1 || !nonEmptyString(plan.product) || !nonEmptyString(plan.configDigest) || !nonEmptyString(plan.profile) || !nonEmptyString(plan.platform) || !nonEmptyString(plan.createdAt) || !nonEmptyString(source.revision) || source.clean !== true || !nonEmptyString(command.executable) || !nonEmptyString(output.directory) || !nonEmptyString(output.artifactSuffix) || typeof requirements.docker !== "boolean" || typeof requirements.buildx !== "boolean") {
12723
+ throw new Error("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212\u7F3A\u5C11\u5FC5\u8981\u5B57\u6BB5");
12724
+ }
12725
+ return {
12726
+ schemaVersion: 1,
12727
+ product: plan.product,
12728
+ configDigest: plan.configDigest,
12729
+ source: { revision: source.revision, clean: true },
12730
+ profile: plan.profile,
12731
+ platform: plan.platform,
12732
+ inputs,
12733
+ command: { executable: command.executable, arguments: arguments_ },
12734
+ output: {
12735
+ directory: output.directory,
12736
+ artifactSuffix: output.artifactSuffix
12737
+ },
12738
+ requirements: { docker: requirements.docker, buildx: requirements.buildx },
12739
+ createdAt: plan.createdAt
12740
+ };
12741
+ }
12742
+ function record(value, label) {
12743
+ if (!value || typeof value !== "object" || Array.isArray(value))
12744
+ throw new Error(`${label} \u5FC5\u987B\u662F\u5BF9\u8C61`);
12745
+ return value;
12746
+ }
12747
+ function array2(value, label) {
12748
+ if (!Array.isArray(value))
12749
+ throw new Error(`${label} \u5FC5\u987B\u662F\u6570\u7EC4`);
12750
+ return value;
12751
+ }
12752
+ function rejectUnknown2(source, allowed, label) {
12753
+ for (const key of Object.keys(source)) {
12754
+ if (!allowed.includes(key))
12755
+ throw new Error(`${label} \u5305\u542B\u672A\u77E5\u5B57\u6BB5\uFF1A${key}`);
12756
+ }
12757
+ }
12758
+ function nonEmptyString(value) {
12759
+ return typeof value === "string" && Boolean(value.trim());
12760
+ }
12761
+
12762
+ // src/package-command.ts
12763
+ async function runPackageCommand(args, dependencies = {}) {
12764
+ if (args[0] !== "package")
12765
+ return false;
12766
+ const log = dependencies.log ?? console.log;
12767
+ if (args.includes("--help") || args.includes("-h")) {
12768
+ log(packageHelpText);
12769
+ return true;
12770
+ }
12771
+ const options = await parsePackageArguments(args.slice(1), dependencies.cwd ?? process.cwd());
12772
+ const planPath = options.fromPlan ?? options.plan;
12773
+ const config = await readPackageConfiguration(options.projectDirectory);
12774
+ const sourceRevision = await readPackageSource(options.projectDirectory, dependencies.process, planPath ? [planPath] : []);
12775
+ let plan;
12776
+ if (options.fromPlan) {
12777
+ plan = await readFrozenPackagePlan(options.fromPlan);
12778
+ assertFrozenPlanCurrent({
12779
+ plan,
12780
+ configuration: config.configuration,
12781
+ configDigest: config.digest,
12782
+ sourceRevision
12783
+ });
12784
+ } else {
12785
+ const profile = resolvePackageProfile(config.configuration, options.profile);
12786
+ if (!config.configuration.platforms.includes(options.platform))
12787
+ throw new Error(`profile ${profile.key} \u4E0D\u652F\u6301\u76EE\u6807\u5E73\u53F0\uFF1A${options.platform}`);
12788
+ const inputs = validatePackageInputs(profile, options.inputs);
12789
+ plan = createFrozenPackagePlan({
12790
+ configuration: config.configuration,
12791
+ configDigest: config.digest,
12792
+ sourceRevision,
12793
+ profile,
12794
+ platform: options.platform,
12795
+ inputs
12796
+ });
12797
+ if (options.plan)
12798
+ await writeFrozenPackagePlan(options.plan, plan);
12799
+ }
12800
+ printPlan2(plan, log);
12801
+ if (!options.execute)
12802
+ return true;
12803
+ if (!planPath)
12804
+ throw new Error("\u6267\u884C\u6253\u5305\u5FC5\u987B\u63D0\u4F9B --plan <\u6587\u4EF6> \u6216 --from-plan <\u6587\u4EF6>\uFF0C\u7528\u4E8E\u5199\u56DE\u7ED3\u679C");
12805
+ let persisted = false;
12806
+ try {
12807
+ await preflightPackage(plan, options.projectDirectory, dependencies.process, [planPath]);
12808
+ const current = await readPackageConfiguration(options.projectDirectory);
12809
+ const currentSource = await readPackageSource(options.projectDirectory, dependencies.process, [planPath]);
12810
+ assertFrozenPlanCurrent({
12811
+ plan,
12812
+ configuration: current.configuration,
12813
+ configDigest: current.digest,
12814
+ sourceRevision: currentSource
12815
+ });
12816
+ const accepted = await confirmModuleMutation(args, dependencies, log, "\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u51BB\u7ED3\u6253\u5305\u8BA1\u5212\uFF1F");
12817
+ if (!accepted)
12818
+ return true;
12819
+ const result2 = await executePackagePlan(plan, options.projectDirectory, dependencies.process, [planPath]);
12820
+ await persistPackageResult(planPath, plan, result2);
12821
+ persisted = true;
12822
+ logResult(result2, log);
12823
+ if (result2.status === "failed")
12824
+ throw new Error(result2.diagnostic);
12825
+ } catch (error) {
12826
+ if (!persisted) {
12827
+ const result2 = failedResult(plan, error);
12828
+ await persistPackageResult(planPath, plan, result2);
12829
+ logResult(result2, log);
12830
+ }
12831
+ throw error;
12832
+ }
12833
+ return true;
12834
+ }
12835
+ async function persistPackageResult(planPath, plan, result2) {
12836
+ await writeFrozenPackagePlan(planPath, { ...plan, result: result2 });
12837
+ }
12838
+ function failedResult(plan, error) {
12839
+ return {
12840
+ status: "failed",
12841
+ completedAt: new Date().toISOString(),
12842
+ sourceRevision: plan.source.revision,
12843
+ artifacts: [],
12844
+ diagnostic: error instanceof Error ? error.message : String(error)
12845
+ };
12846
+ }
12847
+ function logResult(result2, log) {
12848
+ log(result2.status === "succeeded" ? `\u6253\u5305\u5B8C\u6210\uFF1A${result2.artifacts.map(({ path: path2, sha256: sha2562 }) => `${path2} sha256:${sha2562}`).join("\uFF0C")}` : `\u6253\u5305\u5931\u8D25\uFF1A${result2.diagnostic}`);
12849
+ }
12850
+ async function parsePackageArguments(args, workingDirectory) {
12851
+ const allowed = new Set([
12852
+ "--profile",
12853
+ "--platform",
12854
+ "--input",
12855
+ "--plan",
12856
+ "--from-plan",
12857
+ "--execute",
12858
+ "--yes",
12859
+ "--cwd"
12860
+ ]);
12861
+ const values = new Map;
12862
+ for (let index = 0;index < args.length; index += 1) {
12863
+ const argument = args[index];
12864
+ if (!allowed.has(argument))
12865
+ throw new Error(`\u672A\u77E5 package \u53C2\u6570\uFF1A${argument}`);
12866
+ if (argument === "--execute" || argument === "--yes")
12867
+ continue;
12868
+ const value = args[index + 1];
12869
+ if (!value || value.startsWith("--"))
12870
+ throw new Error(`${argument} \u9700\u8981\u4E00\u4E2A\u503C`);
12871
+ values.set(argument, [...values.get(argument) ?? [], value]);
12872
+ index += 1;
12873
+ }
12874
+ const single = (name) => {
12875
+ const entries = values.get(name) ?? [];
12876
+ if (entries.length > 1)
12877
+ throw new Error(`${name} \u4E0D\u80FD\u91CD\u590D`);
12878
+ return entries[0];
12879
+ };
12880
+ const plan = single("--plan");
12881
+ const fromPlan = single("--from-plan");
12882
+ if (plan && fromPlan)
12883
+ throw new Error("--plan \u4E0D\u80FD\u4E0E --from-plan \u540C\u65F6\u4F7F\u7528");
12884
+ const projectDirectory = resolve14(workingDirectory, single("--cwd") ?? ".");
12885
+ const inputEntries = values.get("--input") ?? [];
12886
+ const inputs = {};
12887
+ for (const entry of inputEntries) {
12888
+ const match = /^([a-z][a-z0-9-]*)=(.*)$/u.exec(entry);
12889
+ if (!match)
12890
+ throw new Error("--input \u5FC5\u987B\u4E3A key=value\uFF0C\u4E14 key \u4F7F\u7528\u5C0F\u5199 kebab-case");
12891
+ const [, key, value] = match;
12892
+ if (inputs[key] !== undefined)
12893
+ throw new Error(`--input ${key} \u4E0D\u80FD\u91CD\u590D`);
12894
+ inputs[key] = value;
12895
+ }
12896
+ const profile = single("--profile");
12897
+ const platform = single("--platform");
12898
+ if (fromPlan && (profile || platform || inputEntries.length))
12899
+ throw new Error("--from-plan \u4E0D\u63A5\u53D7 --profile\u3001--platform \u6216 --input");
12900
+ if (!fromPlan && (!profile || !platform))
12901
+ throw new Error("\u65B0\u5EFA\u51BB\u7ED3\u8BA1\u5212\u5FC5\u987B\u540C\u65F6\u63D0\u4F9B --profile \u548C --platform");
12902
+ if (platform && !packagePlatforms.includes(platform))
12903
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u76EE\u6807\u5E73\u53F0\uFF1A${platform}`);
12904
+ return {
12905
+ projectDirectory,
12906
+ profile,
12907
+ platform,
12908
+ inputs,
12909
+ plan: plan ? await resolvePackagePlanPath(projectDirectory, plan) : undefined,
12910
+ fromPlan: fromPlan ? await resolvePackagePlanPath(projectDirectory, fromPlan) : undefined,
12911
+ execute: args.includes("--execute")
12912
+ };
12913
+ }
12914
+ function printPlan2(plan, log) {
12915
+ log("\u51BB\u7ED3\u6253\u5305\u8BA1\u5212\uFF1A");
12916
+ log(` \u4EA7\u54C1\uFF1A${plan.product}`);
12917
+ log(` profile\uFF1A${plan.profile}`);
12918
+ log(` \u5E73\u53F0\uFF1A${plan.platform}`);
12919
+ log(` \u6E90\u7801\uFF1A${plan.source.revision}`);
12920
+ log(` \u547D\u4EE4\uFF1A${[plan.command.executable, ...plan.command.arguments].join(" ")}`);
12921
+ log(` \u8F93\u51FA\uFF1A${plan.output.directory}/*${plan.output.artifactSuffix}`);
12922
+ }
12923
+ var packageHelpText = `\u7528\u6CD5\uFF1Acreate-windy package [\u9009\u9879]
12924
+
12925
+ --profile <key> \u58F0\u660E\u7684\u6253\u5305 profile
12926
+ --platform <platform> linux/amd64 \u6216 linux/arm64
12927
+ --input key=value \u4E3A\u58F0\u660E\u7684\u975E secret \u8F93\u5165\u8D4B\u503C\uFF0C\u53EF\u91CD\u590D\u4F7F\u7528
12928
+ --plan <\u6587\u4EF6> \u4FDD\u5B58\u65B0\u5EFA\u51BB\u7ED3\u8BA1\u5212\uFF08\u9879\u76EE\u76EE\u5F55\u5185\uFF09
12929
+ --from-plan <\u6587\u4EF6> \u8BFB\u53D6\u51BB\u7ED3\u8BA1\u5212\uFF08\u9879\u76EE\u76EE\u5F55\u5185\uFF09
12930
+ --execute \u901A\u8FC7\u9884\u68C0\u5E76\u786E\u8BA4\u540E\u6267\u884C
12931
+ --yes \u975E\u4EA4\u4E92\u6267\u884C\u65F6\u786E\u8BA4\u8BA1\u5212
12932
+ --cwd <\u76EE\u5F55> \u6307\u5B9A\u9879\u76EE\u76EE\u5F55
12933
+
12934
+ \u6253\u5305\u9002\u914D\u5668\u5FC5\u987B\u7531\u9879\u76EE\u6839\u76EE\u5F55\u7684 windy.build.json \u660E\u786E\u58F0\u660E\u3002\u6267\u884C\u5FC5\u987B\u4F7F\u7528 --plan \u6216
12935
+ --from-plan\uFF0C\u4EE5\u4FBF\u628A\u4EA7\u7269 SHA-256 \u4E0E\u6E90\u7801\u6F02\u79FB\u7ED3\u679C\u5199\u56DE\u51BB\u7ED3\u8BA1\u5212\u3002`;
12936
+
11992
12937
  // src/cli.ts
11993
12938
  async function main() {
11994
12939
  const args = process.argv.slice(2);
@@ -11996,6 +12941,8 @@ async function main() {
11996
12941
  return;
11997
12942
  if (await runLifecycleCommand(args))
11998
12943
  return;
12944
+ if (await runPackageCommand(args))
12945
+ return;
11999
12946
  const options = parseArguments(args);
12000
12947
  if (options === "help") {
12001
12948
  console.log(helpText);