@alipay/alipay-aipay 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +30 -0
  2. package/dist/commands/install-current.js +15 -7
  3. package/dist/commands/install.js +20 -16
  4. package/dist/commands/uninstall.js +8 -3
  5. package/dist/commands/update.js +34 -16
  6. package/dist/index.js +10 -4
  7. package/dist/utils/channels.js +67 -0
  8. package/dist/utils/config.js +15 -11
  9. package/dist/utils/file.js +23 -10
  10. package/dist/utils/npm.js +19 -33
  11. package/package.json +8 -3
  12. package/skill/SKILL.md +2 -0
  13. package/skill/references/normal/json/release-channel.json +1 -0
  14. package/skill/references/normal/scripts/self_update.mjs +62 -17
  15. package/skill/references/normal/self-update.md +3 -1
  16. package/skill-pre/SKILL.md +65 -0
  17. package/skill-pre/VERSION +1 -0
  18. package/skill-pre/references/integration/flow.md +602 -0
  19. package/skill-pre/references/integration/modules/alipay-sdk-reminder.md +281 -0
  20. package/skill-pre/references/integration/modules/checklist.md +154 -0
  21. package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +199 -0
  22. package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +68 -0
  23. package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +83 -0
  24. package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +80 -0
  25. package/skill-pre/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +73 -0
  26. package/skill-pre/references/integration/modules/code-examples/csharp/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +62 -0
  27. package/skill-pre/references/integration/modules/code-examples/csharp/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +132 -0
  28. package/skill-pre/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +640 -0
  29. package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +184 -0
  30. package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +72 -0
  31. package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +96 -0
  32. package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +81 -0
  33. package/skill-pre/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
  34. package/skill-pre/references/integration/modules/code-examples/java/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +69 -0
  35. package/skill-pre/references/integration/modules/code-examples/java/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +138 -0
  36. package/skill-pre/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +623 -0
  37. package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +135 -0
  38. package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +51 -0
  39. package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +63 -0
  40. package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
  41. package/skill-pre/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +54 -0
  42. package/skill-pre/references/integration/modules/code-examples/nodejs/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +84 -0
  43. package/skill-pre/references/integration/modules/code-examples/nodejs/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +71 -0
  44. package/skill-pre/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +498 -0
  45. package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +157 -0
  46. package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
  47. package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +73 -0
  48. package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +69 -0
  49. package/skill-pre/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
  50. package/skill-pre/references/integration/modules/code-examples/php/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
  51. package/skill-pre/references/integration/modules/code-examples/php/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +110 -0
  52. package/skill-pre/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +806 -0
  53. package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//345/274/202/346/255/245/351/200/232/347/237/245/345/244/204/347/220/206/344/273/243/347/240/201/347/244/272/344/276/213.md +128 -0
  54. package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +57 -0
  55. package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +70 -0
  56. package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
  57. package/skill-pre/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +62 -0
  58. package/skill-pre/references/integration/modules/code-examples/python/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +51 -0
  59. package/skill-pre/references/integration/modules/code-examples/python/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +47 -0
  60. package/skill-pre/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +541 -0
  61. package/skill-pre/references/integration/modules/interface-contract/aipay-interface-contract.md +52 -0
  62. package/skill-pre/references/integration/modules/interface-contract/apppay-interface-contract.md +45 -0
  63. package/skill-pre/references/integration/modules/interface-contract/common-trade-contract.md +42 -0
  64. package/skill-pre/references/integration/modules/interface-contract/notify-url-contract.md +68 -0
  65. package/skill-pre/references/integration/modules/interface-contract/webpay-interface-contract.md +44 -0
  66. package/skill-pre/references/integration/modules/interface-guide.md +61 -0
  67. package/skill-pre/references/integration/modules/product-decision.md +73 -0
  68. package/skill-pre/references/integration/modules/sandbox/a2m-sandbox-test.md +235 -0
  69. package/skill-pre/references/integration/modules/sandbox/alipay-sandbox-tool.md +142 -0
  70. package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +239 -0
  71. package/skill-pre/references/integration/modules/scripts/local_402_sandbox_pay.py +900 -0
  72. package/skill-pre/references/integration/modules/scripts/sandbox_config.sh +347 -0
  73. package/skill-pre/references/integration/modules/troubleshooting-flow.md +28 -0
  74. package/skill-pre/references/normal/alipay-cli-env.md +169 -0
  75. package/skill-pre/references/normal/conversation-telemetry.md +101 -0
  76. package/skill-pre/references/normal/full-process-routing.md +92 -0
  77. package/skill-pre/references/normal/integration-worker.md +90 -0
  78. package/skill-pre/references/normal/json/customer-messages.json +1 -0
  79. package/skill-pre/references/normal/json/managed-jq-assets.json +1 -0
  80. package/skill-pre/references/normal/json/policy-rules.json +1 -0
  81. package/skill-pre/references/normal/json/release-channel.json +1 -0
  82. package/skill-pre/references/normal/rejection-guide.md +41 -0
  83. package/skill-pre/references/normal/scripts/agent_platform.mjs +43 -0
  84. package/skill-pre/references/normal/scripts/alipay_cli_env.mjs +34 -0
  85. package/skill-pre/references/normal/scripts/alipay_cli_env.sh +55 -0
  86. package/skill-pre/references/normal/scripts/alipay_cli_refresh.mjs +129 -0
  87. package/skill-pre/references/normal/scripts/auth_runtime_runner.mjs +60 -0
  88. package/skill-pre/references/normal/scripts/checklist_sections.mjs +43 -0
  89. package/skill-pre/references/normal/scripts/common.sh +365 -0
  90. package/skill-pre/references/normal/scripts/conversation_telemetry.mjs +105 -0
  91. package/skill-pre/references/normal/scripts/detect_dev_tool.sh +79 -0
  92. package/skill-pre/references/normal/scripts/flow_loader.mjs +237 -0
  93. package/skill-pre/references/normal/scripts/integration_context_runner.mjs +151 -0
  94. package/skill-pre/references/normal/scripts/integration_message_runner.mjs +1456 -0
  95. package/skill-pre/references/normal/scripts/interaction_reply.mjs +140 -0
  96. package/skill-pre/references/normal/scripts/managed_jq.mjs +215 -0
  97. package/skill-pre/references/normal/scripts/onboarding_discovery_runner.mjs +387 -0
  98. package/skill-pre/references/normal/scripts/onboarding_message_runner.mjs +1425 -0
  99. package/skill-pre/references/normal/scripts/onboarding_recovery_runner.mjs +100 -0
  100. package/skill-pre/references/normal/scripts/open_official_url.sh +205 -0
  101. package/skill-pre/references/normal/scripts/platform_compat.mjs +42 -0
  102. package/skill-pre/references/normal/scripts/preview_runtime.mjs +151 -0
  103. package/skill-pre/references/normal/scripts/project_route_inspector.sh +132 -0
  104. package/skill-pre/references/normal/scripts/python_script_runner.mjs +58 -0
  105. package/skill-pre/references/normal/scripts/render_customer_message.mjs +1792 -0
  106. package/skill-pre/references/normal/scripts/runtime.mjs +271 -0
  107. package/skill-pre/references/normal/scripts/self_update.mjs +376 -0
  108. package/skill-pre/references/normal/scripts/telemetry.mjs +2102 -0
  109. package/skill-pre/references/normal/self-update.md +7 -0
  110. package/skill-pre/references/normal/telemetry.md +70 -0
  111. package/skill-pre/references/onboarding/assets/keygen.html +926 -0
  112. package/skill-pre/references/onboarding/flow.md +595 -0
  113. package/skill-pre/references/onboarding/modules/app-release.md +90 -0
  114. package/skill-pre/references/onboarding/modules/authorization.md +43 -0
  115. package/skill-pre/references/onboarding/modules/error-handling.md +62 -0
  116. package/skill-pre/references/onboarding/modules/product-sign.md +49 -0
  117. package/skill-pre/references/onboarding/modules/scripts/app.sh +1485 -0
  118. package/skill-pre/references/onboarding/modules/scripts/ar_sign_apply.sh +331 -0
  119. package/skill-pre/references/onboarding/modules/scripts/auth.sh +1040 -0
  120. package/skill-pre/references/onboarding/modules/scripts/download_key_tool.sh +4 -0
  121. package/skill-pre/references/onboarding/modules/scripts/error_handler.sh +841 -0
  122. package/skill-pre/references/onboarding/modules/scripts/mcc.sh +1085 -0
  123. package/skill-pre/references/onboarding/modules/scripts/network_retry.sh +135 -0
  124. package/skill-pre/references/onboarding/modules/scripts/query_sign_status.sh +105 -0
  125. package/skill-pre/references/onboarding/modules/scripts/service.sh +528 -0
  126. package/skill-pre/references/onboarding/modules/scripts/sign_status_parser.sh +58 -0
  127. package/skill-pre/references/onboarding/modules/scripts/upload_screenshots.sh +208 -0
  128. package/skill-pre/references/onboarding/modules/scripts/upload_special_license.sh +195 -0
  129. package/skill-pre/references/onboarding/modules/service-registration.md +40 -0
  130. package/skill-pre/references/runtime-entry.md +97 -0
  131. package/dist/commands/install-current.d.ts +0 -4
  132. package/dist/commands/install-current.d.ts.map +0 -1
  133. package/dist/commands/install-current.js.map +0 -1
  134. package/dist/commands/install.d.ts +0 -10
  135. package/dist/commands/install.d.ts.map +0 -1
  136. package/dist/commands/install.js.map +0 -1
  137. package/dist/commands/prepare-tools.d.ts +0 -5
  138. package/dist/commands/prepare-tools.d.ts.map +0 -1
  139. package/dist/commands/prepare-tools.js.map +0 -1
  140. package/dist/commands/uninstall.d.ts +0 -10
  141. package/dist/commands/uninstall.d.ts.map +0 -1
  142. package/dist/commands/uninstall.js.map +0 -1
  143. package/dist/commands/update.d.ts +0 -10
  144. package/dist/commands/update.d.ts.map +0 -1
  145. package/dist/commands/update.js.map +0 -1
  146. package/dist/index.d.ts +0 -2
  147. package/dist/index.d.ts.map +0 -1
  148. package/dist/index.js.map +0 -1
  149. package/dist/types.d.ts +0 -42
  150. package/dist/types.d.ts.map +0 -1
  151. package/dist/types.js.map +0 -1
  152. package/dist/utils/alipay-cli.d.ts +0 -20
  153. package/dist/utils/alipay-cli.d.ts.map +0 -1
  154. package/dist/utils/alipay-cli.js.map +0 -1
  155. package/dist/utils/config.d.ts +0 -52
  156. package/dist/utils/config.d.ts.map +0 -1
  157. package/dist/utils/config.js.map +0 -1
  158. package/dist/utils/file.d.ts +0 -77
  159. package/dist/utils/file.d.ts.map +0 -1
  160. package/dist/utils/file.js.map +0 -1
  161. package/dist/utils/jq.d.ts +0 -17
  162. package/dist/utils/jq.d.ts.map +0 -1
  163. package/dist/utils/jq.js.map +0 -1
  164. package/dist/utils/npm.d.ts +0 -17
  165. package/dist/utils/npm.d.ts.map +0 -1
  166. package/dist/utils/npm.js.map +0 -1
  167. package/dist/utils/shell.d.ts +0 -24
  168. package/dist/utils/shell.d.ts.map +0 -1
  169. package/dist/utils/shell.js.map +0 -1
package/README.md CHANGED
@@ -3,3 +3,33 @@
3
3
  支持 AI 按量付费、AI 网页应用收款、AI 移动应用收款的代码开发与产品开通。
4
4
 
5
5
  支付宝 AI 付站点:https://aipay.alipay.com/?from=alipay-aipay-skill
6
+
7
+ ## 安装渠道
8
+
9
+ ```bash
10
+ # 正式版(默认)
11
+ npx -y @alipay/alipay-aipay@latest install
12
+
13
+ # 预发版
14
+ npx -y @alipay/alipay-aipay@latest install --channel pre
15
+ ```
16
+
17
+ 两份 Skill 可并存:正式版安装到 Agent 的 `skills/alipay-aipay/`,预发版安装到 `skills/alipay-aipay-pre/`。预发版使用独立名称 `alipay-aipay-pre`,在对话中明确点名或选择预发版使用。`--target` 的 Agent 目标选择规则不变。
18
+
19
+ ```bash
20
+ # 只更新或卸载预发版;省略 --channel pre 则只操作正式版
21
+ npx -y @alipay/alipay-aipay@latest update --channel pre
22
+ npx -y @alipay/alipay-aipay@latest uninstall --channel pre
23
+ ```
24
+
25
+ 安装记录、自更新和卸载按渠道隔离;`--target all` 也只操作所选渠道。两份 Skill 共用系统环境中的 alipay-cli 和 jq,卸载 Skill 不卸载这些工具。
26
+
27
+ ## 维护与发布
28
+
29
+ - `skill/` 是正式版源目录,`skill-pre/` 是可独立修改的预发版源目录,构建不会互相覆盖。
30
+ - `package.json.version` 是 npm 分发包版本;`alipayAipayChannels.stable/pre` 分别对应两份 Skill 的 `VERSION`。安装器保留所选 Skill 的版本,不用包版本覆盖。
31
+ - 每次发布提升 npm 包版本;只修改预发内容时,只提升预发 Skill 版本和相应元数据。正式版自更新发现自身版本未变时不下载安装。
32
+ - 两份常规 Skill 自更新器都查询 npm `latest`,只比较自己的渠道版本,并从查询所得精确 npm 包版本中安装对应目录。元数据缺失、非法或为测试版本时保留本地,不切换渠道。
33
+ - 正式版版本从 `1.7.0` 按 `1.7.1`、`1.7.2` 递增;预发版从 `1.7.0-pre` 按 `1.7.1-pre`、`1.7.2-pre` 递增。npm 包版本自此次拆分起独立维护。
34
+ - 旧版 updater 首次升级前仍按 npm 包版本触发一次正式版迁移。正式版 VERSION 可保持 `1.7.0`;旧更新器可能在文件已迁移后返回内部 `VERIFY_FAILED`,启动器会继续读取当前可用入口,不阻塞业务。后续使用新渠道规则。
35
+ - 本次预发版先复制正式版业务能力,后续定制直接修改 `skill-pre/`。对客消息、业务契约和发布校验仍遵循 `AGENTS.md`。
@@ -1,7 +1,8 @@
1
1
  import fs from 'fs/promises';
2
+ import { getChannelConfig, getSkillVersion, readInstalledChannel, readInstalledVersion, skillVersionKind } from '../utils/channels.js';
2
3
  import path from 'path';
3
4
  import process from 'process';
4
- import { getCommandContextForTargetDir, getPackageVersion, PACKAGE_ROOT, SKILL_NAME, } from '../utils/config.js';
5
+ import { getCommandContextForTargetDir, PACKAGE_ROOT, } from '../utils/config.js';
5
6
  import { installSkillFilesAtPath, readVersionRecord, writeVersionRecordWithFallback, } from '../utils/file.js';
6
7
  export const SELF_UPDATE_TARGET_ENV = 'ALIPAY_AIPAY_SELF_UPDATE_TARGET';
7
8
  export const SELF_UPDATE_TRANSACTION_ENV = 'ALIPAY_AIPAY_SELF_UPDATE_TRANSACTION';
@@ -28,28 +29,35 @@ async function requireCurrentSkillRoot(skillDir) {
28
29
  /**
29
30
  * 仅供 Skill 自更新调用:精确覆盖当前目录,不扫描任何 Agent 安装目标。
30
31
  */
31
- async function installBoundCurrentSkill(target, transactionId) {
32
+ async function installBoundCurrentSkill(target, transactionId, channel) {
32
33
  const skillDir = await requireCurrentSkillRoot(target);
34
+ if (readInstalledChannel(skillDir) !== channel)
35
+ throw new Error('自更新渠道与目标不一致');
36
+ if (skillVersionKind(readInstalledVersion(skillDir), channel) === 'beta')
37
+ throw new Error('beta 版本只允许手动 install 换版');
38
+ if (skillVersionKind(getSkillVersion(PACKAGE_ROOT, channel), channel) !== 'release')
39
+ throw new Error('自更新禁止安装 beta');
40
+ const SKILL_NAME = getChannelConfig(channel).skillName;
33
41
  const canonicalInstall = path.basename(skillDir) === SKILL_NAME;
34
42
  const context = canonicalInstall
35
- ? getCommandContextForTargetDir(path.dirname(skillDir))
43
+ ? getCommandContextForTargetDir(path.dirname(skillDir), channel)
36
44
  : null;
37
45
  const previousRecord = context ? await readVersionRecord(context) : null;
38
- await installSkillFilesAtPath(PACKAGE_ROOT, skillDir, { transactionId });
46
+ await installSkillFilesAtPath(PACKAGE_ROOT, skillDir, { transactionId, channel });
39
47
  if (context && previousRecord) {
40
48
  await writeVersionRecordWithFallback(context, {
41
49
  ...previousRecord,
42
- version: getPackageVersion(),
50
+ version: getSkillVersion(PACKAGE_ROOT, channel),
43
51
  installedAt: new Date().toISOString(),
44
52
  });
45
53
  }
46
54
  }
47
- export async function installCurrentSkillCommand() {
55
+ export async function installCurrentSkillCommand(channel = 'stable') {
48
56
  const target = process.env[SELF_UPDATE_TARGET_ENV] || '';
49
57
  const transactionId = process.env[SELF_UPDATE_TRANSACTION_ENV] || '';
50
58
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(transactionId)) {
51
59
  throw new Error('缺少合法的自更新事务 ID');
52
60
  }
53
- await installBoundCurrentSkill(target, transactionId);
61
+ await installBoundCurrentSkill(target, transactionId, channel);
54
62
  }
55
63
  //# sourceMappingURL=install-current.js.map
@@ -1,21 +1,22 @@
1
1
  import chalk from 'chalk';
2
+ import { getChannelConfig, getSkillVersion } from '../utils/channels.js';
2
3
  import ora from 'ora';
3
4
  import { spawn } from 'child_process';
4
5
  import fs from 'fs';
5
6
  import os from 'os';
6
7
  import path from 'path';
7
- import { SKILLS, getPackageVersion, getCommandContext, getAllCommandContexts, detectCurrentAgentTarget, DEFAULT_TARGET, PACKAGE_ROOT, SKILL_NAME, TARGET_DIRS, } from '../utils/config.js';
8
+ import { getCommandContext, getAllCommandContexts, detectCurrentAgentTarget, DEFAULT_TARGET, PACKAGE_ROOT, TARGET_DIRS, } from '../utils/config.js';
8
9
  import { ensureDir, installSkillFiles, readVersionRecord, writeVersionRecordWithFallback, } from '../utils/file.js';
9
10
  import { checkAlipayCli } from '../utils/alipay-cli.js';
10
11
  import { checkJq, isJqRequiredPlatform, resolveManagedJqAsset } from '../utils/jq.js';
11
- function resolveInstallPlan(cwd, target) {
12
+ function resolveInstallPlan(cwd, target, channel) {
12
13
  if (target !== 'all') {
13
- const context = getCommandContext(cwd, target);
14
+ const context = getCommandContext(cwd, target, channel);
14
15
  return { contexts: [context], primaryTargetDir: path.resolve(context.targetDir) };
15
16
  }
16
17
  const primaryTarget = detectCurrentAgentTarget() || DEFAULT_TARGET;
17
- const primaryContext = getCommandContext(cwd, primaryTarget);
18
- const contexts = getAllCommandContexts(cwd, primaryTarget);
18
+ const primaryContext = getCommandContext(cwd, primaryTarget, channel);
19
+ const contexts = getAllCommandContexts(cwd, primaryTarget, channel);
19
20
  const primaryTargetDir = path.resolve(primaryContext.targetDir);
20
21
  const ordered = [
21
22
  primaryContext,
@@ -24,19 +25,22 @@ function resolveInstallPlan(cwd, target) {
24
25
  return { contexts: ordered, primaryTargetDir };
25
26
  }
26
27
  export async function installCommand(cwd, options = {}) {
28
+ const channel = options.channel ?? 'stable';
29
+ const { skillName: SKILL_NAME, displayName } = getChannelConfig(channel);
30
+ const SKILLS = [{ name: SKILL_NAME, displayName }];
27
31
  const target = options.target ?? 'all';
28
32
  const skipTools = options.skipTools ?? false;
29
33
  const jqRequired = isJqRequiredPlatform();
30
34
  const jqPreparationSupported = resolveManagedJqAsset() !== null;
31
- const installPlan = resolveInstallPlan(cwd, target);
35
+ const installPlan = resolveInstallPlan(cwd, target, channel);
32
36
  const { contexts, primaryTargetDir } = installPlan;
33
- const version = getPackageVersion();
37
+ const version = getSkillVersion(PACKAGE_ROOT, channel);
34
38
  const targetDirLabels = contexts.map((ctx) => ctx.targetDirLabel);
35
39
  const targetSkillDirs = contexts.map((ctx) => path.join(ctx.targetDir, SKILL_NAME));
36
- console.log(chalk.cyan.bold(`\n🚀 @alipay/alipay-aipay v${version}\n`));
40
+ console.log(chalk.cyan.bold(`\n🚀 @alipay/alipay-aipay ${channel} v${version}\n`));
37
41
  console.log(chalk.gray('优先安装 Skill 文件;alipay-cli 和用户级 jq 可在后台准备,不调用系统包管理器\n'));
38
42
  console.log(chalk.gray(`安装目标: ${targetSkillDirs.join(', ')}`));
39
- console.log(chalk.gray(`${describeTargetSelection(os.homedir(), target, targetDirLabels, primaryTargetDir)}\n`));
43
+ console.log(chalk.gray(`${describeTargetSelection(os.homedir(), target, targetDirLabels, primaryTargetDir, SKILL_NAME)}\n`));
40
44
  // ========== 阶段 1: 环境检查 ==========
41
45
  let alipayCliOk = false;
42
46
  let jqOk = false;
@@ -112,12 +116,12 @@ export async function installCommand(cwd, options = {}) {
112
116
  try {
113
117
  const existingRecord = await readVersionRecord(ctx);
114
118
  if (existingRecord) {
115
- console.log(chalk.yellow(`检测到已有安装记录,直接覆盖更新: ${ctx.targetDirLabel}/alipay-aipay/`));
119
+ console.log(chalk.yellow(`检测到已有安装记录,直接覆盖更新: ${ctx.targetDirLabel}/${SKILL_NAME}/`));
116
120
  console.log(` 旧版本: ${existingRecord.version} 安装时间: ${existingRecord.installedAt}`);
117
121
  console.log('');
118
122
  }
119
123
  await ensureDir(ctx.targetDir);
120
- await installSkillFiles(PACKAGE_ROOT, ctx.targetDir);
124
+ await installSkillFiles(PACKAGE_ROOT, ctx.targetDir, channel);
121
125
  const record = {
122
126
  version,
123
127
  installedAt: new Date().toISOString(),
@@ -149,7 +153,7 @@ export async function installCommand(cwd, options = {}) {
149
153
  if (legacyRecordLabels.length > 0) {
150
154
  console.log(chalk.yellow('⚠️ 用户配置目录安装记录写入失败,已降级写入 Skill 目录内兼容记录。'));
151
155
  for (const targetDirLabel of legacyRecordLabels) {
152
- console.log(chalk.gray(` 记录位置: ${targetDirLabel}/alipay-aipay/.alipay-aipay-version`));
156
+ console.log(chalk.gray(` 记录位置: ${targetDirLabel}/${SKILL_NAME}/.alipay-aipay-version`));
153
157
  }
154
158
  console.log('');
155
159
  }
@@ -161,19 +165,19 @@ export async function installCommand(cwd, options = {}) {
161
165
  process.exit(1);
162
166
  }
163
167
  }
164
- function describeTargetSelection(targetRoot, target, targetDirLabels, primaryTargetDir) {
168
+ function describeTargetSelection(targetRoot, target, targetDirLabels, primaryTargetDir, skillName) {
165
169
  if (target === 'all') {
166
170
  const hasExistingAgentRoot = Object.keys(TARGET_DIRS)
167
171
  .map((targetName) => path.dirname(TARGET_DIRS[targetName]))
168
172
  .some((rootDir) => fs.existsSync(path.join(targetRoot, rootDir)));
169
173
  const primaryLabel = targetDirLabels.find((label) => path.resolve(path.isAbsolute(label) ? label : path.join(targetRoot, label)) === primaryTargetDir) || primaryTargetDir;
170
174
  if (!hasExistingAgentRoot && targetDirLabels.length === 1) {
171
- return `目标选择: --target all;优先安装当前 Agent 目标 ${primaryLabel}/alipay-aipay/`;
175
+ return `目标选择: --target all;优先安装当前 Agent 目标 ${primaryLabel}/${skillName}/`;
172
176
  }
173
- return `目标选择: --target all;当前 Agent 目标 ${primaryLabel}/alipay-aipay/ 优先且必须成功,其他已存在目标尽力安装`;
177
+ return `目标选择: --target all;当前 Agent 目标 ${primaryLabel}/${skillName}/ 优先且必须成功,其他已存在目标尽力安装`;
174
178
  }
175
179
  if (target === 'auto') {
176
- return `目标选择: --target auto,按当前 Agent/已有安装目录解析为 ${targetDirLabels[0]}/alipay-aipay/`;
180
+ return `目标选择: --target auto,按当前 Agent/已有安装目录解析为 ${targetDirLabels[0]}/${skillName}/`;
177
181
  }
178
182
  return `目标选择: --target ${target}`;
179
183
  }
@@ -1,21 +1,26 @@
1
1
  import inquirer from 'inquirer';
2
+ import { getChannelConfig } from '../utils/channels.js';
2
3
  import chalk from 'chalk';
3
4
  import ora from 'ora';
4
5
  import fs from 'fs/promises';
5
- import { SKILLS, getCommandContext, getAllCommandContexts } from '../utils/config.js';
6
+ import { getCommandContext, getAllCommandContexts } from '../utils/config.js';
6
7
  import { removeDir, readVersionRecord, resolveInstalledSkillPaths } from '../utils/file.js';
7
8
  export async function uninstallCommand(cwd, options = {}) {
9
+ const channel = options.channel ?? 'stable';
8
10
  const target = options.target ?? 'auto';
9
11
  if (target === 'all') {
10
- for (const ctx of getAllCommandContexts(cwd)) {
12
+ for (const ctx of getAllCommandContexts(cwd, undefined, channel)) {
11
13
  await uninstallResolvedContext(ctx);
12
14
  }
13
15
  return;
14
16
  }
15
- const ctx = getCommandContext(cwd, target);
17
+ const ctx = getCommandContext(cwd, target, channel);
16
18
  await uninstallResolvedContext(ctx);
17
19
  }
18
20
  async function uninstallResolvedContext(ctx) {
21
+ const channel = ctx.channel ?? 'stable';
22
+ const { skillName: SKILL_NAME, displayName } = getChannelConfig(channel);
23
+ const SKILLS = [{ name: SKILL_NAME, displayName }];
19
24
  // 检查是否有安装记录
20
25
  const record = await readVersionRecord(ctx);
21
26
  if (!record) {
@@ -1,52 +1,70 @@
1
1
  import inquirer from 'inquirer';
2
+ import semver from 'semver';
3
+ import { getChannelConfig, getSkillVersion, readInstalledVersion, skillVersionKind } from '../utils/channels.js';
2
4
  import chalk from 'chalk';
5
+ import path from 'path';
3
6
  import ora from 'ora';
4
- import { SKILLS, getPackageVersion, getCommandContext, getAllCommandContexts, PACKAGE_ROOT, SKILL_NAME, } from '../utils/config.js';
5
- import { ensureDir, installSkillFiles, readVersionRecord, migrateVersionRecord, writeVersionRecordWithFallback, } from '../utils/file.js';
7
+ import { getCommandContext, getAllCommandContexts, PACKAGE_ROOT, } from '../utils/config.js';
8
+ import { ensureDir, installSkillFiles, readVersionRecord, migrateVersionRecord, writeVersionRecordWithFallback, resolveInstalledSkillPaths, } from '../utils/file.js';
6
9
  import { checkForUpdates } from '../utils/npm.js';
7
10
  import { checkAlipayCli } from '../utils/alipay-cli.js';
8
11
  import { checkJq, isJqRequiredPlatform } from '../utils/jq.js';
9
12
  export async function updateCommand(cwd, options = {}) {
13
+ const channel = options.channel ?? 'stable';
10
14
  const target = options.target ?? 'auto';
11
15
  if (target === 'all') {
12
- for (const ctx of getAllCommandContexts(cwd)) {
16
+ for (const ctx of getAllCommandContexts(cwd, undefined, channel)) {
13
17
  await updateResolvedContext(ctx);
14
18
  }
15
19
  return;
16
20
  }
17
- const ctx = getCommandContext(cwd, target);
21
+ const ctx = getCommandContext(cwd, target, channel);
18
22
  await updateResolvedContext(ctx);
19
23
  }
20
24
  async function updateResolvedContext(ctx) {
21
- const currentPackageVersion = getPackageVersion();
25
+ const channel = ctx.channel ?? 'stable';
26
+ const { skillName: SKILL_NAME, displayName } = getChannelConfig(channel);
27
+ const SKILLS = [{ name: SKILL_NAME, displayName }];
28
+ const installCommandText = `npx -y @alipay/alipay-aipay@latest install${channel === 'pre' ? ' --channel pre' : ''}`;
29
+ const currentSkillVersion = getSkillVersion(PACKAGE_ROOT, channel);
22
30
  // 检查是否有安装记录
23
31
  const record = await readVersionRecord(ctx);
24
32
  if (!record) {
25
33
  console.log(chalk.yellow('\n未检测到已安装的支付宝 AI 付接入 Skill。'));
26
- console.log(chalk.gray(`请先运行 \`npx -y @alipay/alipay-aipay@latest install\` 安装到 ${ctx.targetDir}/。\n`));
34
+ console.log(chalk.gray(`请先运行 \`${installCommandText}\` 安装到 ${ctx.targetDir}/。\n`));
35
+ return;
36
+ }
37
+ const installedVersion = readInstalledVersion(path.join(ctx.targetDir, SKILL_NAME)) ?? record.version;
38
+ if ([installedVersion, currentSkillVersion].some(version => skillVersionKind(version, channel) === 'beta')) {
39
+ console.log(chalk.gray('beta 测试版本保持固定;如需换版,请手动运行所选 npm 包的 install 命令。'));
27
40
  return;
28
41
  }
29
42
  console.log(chalk.cyan.bold('\n🔄 检查更新...\n'));
30
43
  // 检查 npm 最新版本
31
44
  const spinner = ora('正在检查 npm 最新版本...').start();
32
45
  try {
33
- const versionInfo = await checkForUpdates();
46
+ resolveInstalledSkillPaths(ctx.targetDir, record.skills, [SKILL_NAME]);
47
+ const versionInfo = await checkForUpdates(channel);
34
48
  if (versionInfo.needsUpdate) {
35
- spinner.warn(chalk.yellow('当前执行的 alipay-aipay 包不是 npm latest,未执行更新。\n'));
49
+ spinner.warn(chalk.yellow('当前执行包中的所选渠道版本较旧,未执行更新。\n'));
36
50
  console.log(`当前执行版本: ${versionInfo.current}`);
37
51
  console.log(`npm latest: ${versionInfo.latest}`);
38
52
  console.log(chalk.gray('请运行以下命令安装最新 Skill:'));
39
- console.log(chalk.cyan(' npx -y @alipay/alipay-aipay@latest install\n'));
53
+ console.log(chalk.cyan(` ${installCommandText}\n`));
54
+ return;
55
+ }
56
+ if (semver.valid(record.version) && semver.gt(record.version, currentSkillVersion)) {
57
+ spinner.succeed('本地渠道版本较新,保留当前安装。');
40
58
  return;
41
59
  }
42
- if (record.version === currentPackageVersion) {
60
+ if (record.version === currentSkillVersion) {
43
61
  await migrateVersionRecord(ctx, record);
44
62
  spinner.succeed(chalk.green('Skill 文件已是当前执行包版本!\n'));
45
- console.log(`当前版本: ${currentPackageVersion}`);
63
+ console.log(`当前版本: ${currentSkillVersion}`);
46
64
  console.log(`安装时间: ${record.installedAt}`);
47
65
  }
48
66
  else {
49
- spinner.info(chalk.blue(`发现可安装版本: ${currentPackageVersion} (已安装: ${record.version})\n`));
67
+ spinner.info(chalk.blue(`发现可安装版本: ${currentSkillVersion} (已安装: ${record.version})\n`));
50
68
  // 显示更新信息
51
69
  console.log('将更新以下 Skill:\n');
52
70
  for (const skillName of record.skills) {
@@ -72,10 +90,10 @@ async function updateResolvedContext(ctx) {
72
90
  // 开始更新
73
91
  const updateSpinner = ora('正在更新 Skill 文件...').start();
74
92
  await ensureDir(ctx.targetDir);
75
- await installSkillFiles(PACKAGE_ROOT, ctx.targetDir);
76
- // 更新版本记录(用当前包的实际版本,而非 registry 上的最新版本)
93
+ await installSkillFiles(PACKAGE_ROOT, ctx.targetDir, channel);
94
+ // 更新版本记录:只记录当前包中所选 Skill 的版本。
77
95
  const newRecord = {
78
- version: currentPackageVersion,
96
+ version: currentSkillVersion,
79
97
  installedAt: new Date().toISOString(),
80
98
  skills: SKILLS.map((s) => s.name),
81
99
  alipayCliInstalled: record.alipayCliInstalled,
@@ -83,7 +101,7 @@ async function updateResolvedContext(ctx) {
83
101
  };
84
102
  await writeVersionRecordWithFallback(ctx, newRecord);
85
103
  updateSpinner.succeed(chalk.green('Skill 文件更新完成!\n'));
86
- console.log(`版本: ${record.version} → ${currentPackageVersion}`);
104
+ console.log(`版本: ${record.version} → ${currentSkillVersion}`);
87
105
  }
88
106
  console.log('');
89
107
  // 重新检查环境工具
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Command } from 'commander';
2
+ import { parseChannel } from './utils/channels.js';
2
3
  import chalk from 'chalk';
3
4
  import { getPackageVersion } from './utils/config.js';
4
5
  import { installCommand } from './commands/install.js';
@@ -22,6 +23,7 @@ program
22
23
  // install 命令
23
24
  program
24
25
  .command('install')
26
+ .option('--channel <channel>', 'Skill 渠道: stable | pre', parseChannel, 'stable')
25
27
  .description('安装支付宝 AI 付接入 Skill(Skill 文件优先完成,工具准备不阻塞安装)')
26
28
  .option('--target <target>', '安装目标: all | agents | codex | claude | auto', 'all')
27
29
  .option('--with-jq', '兼容参数;macOS/Linux 缺少 jq 时默认已在 detached 后台准备')
@@ -29,24 +31,27 @@ program
29
31
  .action(async (options) => {
30
32
  await installCommand(process.cwd(), {
31
33
  target: parseTarget(options.target),
34
+ channel: options.channel,
32
35
  skipTools: Boolean(options.skipTools),
33
36
  });
34
37
  });
35
38
  // uninstall 命令
36
39
  program
37
40
  .command('uninstall')
41
+ .option('--channel <channel>', 'Skill 渠道: stable | pre', parseChannel, 'stable')
38
42
  .description('卸载已安装的支付宝 AI 付接入 Skill')
39
43
  .option('--target <target>', '卸载目标: all | agents | codex | claude | auto', 'auto')
40
44
  .action(async (options) => {
41
- await uninstallCommand(process.cwd(), { target: parseTarget(options.target) });
45
+ await uninstallCommand(process.cwd(), { target: parseTarget(options.target), channel: options.channel });
42
46
  });
43
47
  // update 命令
44
48
  program
45
49
  .command('update')
50
+ .option('--channel <channel>', 'Skill 渠道: stable | pre', parseChannel, 'stable')
46
51
  .description('检查并更新支付宝 AI 付接入 Skill')
47
52
  .option('--target <target>', '更新目标: all | agents | codex | claude | auto', 'auto')
48
53
  .action(async (options) => {
49
- await updateCommand(process.cwd(), { target: parseTarget(options.target) });
54
+ await updateCommand(process.cwd(), { target: parseTarget(options.target), channel: options.channel });
50
55
  });
51
56
  program
52
57
  .command('prepare-tools', { hidden: true })
@@ -57,9 +62,10 @@ program
57
62
  });
58
63
  program
59
64
  .command('install-current', { hidden: true })
65
+ .option('--channel <channel>', 'Skill 渠道', parseChannel, 'stable')
60
66
  .description('精确覆盖当前运行中的 Skill 目录')
61
- .action(async () => {
62
- await installCurrentSkillCommand();
67
+ .action(async (options) => {
68
+ await installCurrentSkillCommand(options.channel);
63
69
  });
64
70
  // 默认行为:无参数时直接执行安装流程
65
71
  if (process.argv.length === 2) {
@@ -0,0 +1,67 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import semver from 'semver';
4
+ export const CHANNEL_FILE = 'references/normal/json/release-channel.json';
5
+ export function parseChannel(value) {
6
+ if (value === 'stable' || value === 'pre')
7
+ return value;
8
+ throw new Error('无效的 --channel;可选值: stable | pre');
9
+ }
10
+ export function getChannelConfig(channel = 'stable') {
11
+ parseChannel(channel);
12
+ return channel === 'pre'
13
+ ? { channel, skillName: 'alipay-aipay-pre', sourceDir: 'skill-pre', displayName: '支付宝 AI 付接入 Skill 预发版' }
14
+ : { channel, skillName: 'alipay-aipay', sourceDir: 'skill', displayName: '支付宝 AI 付接入 Skill' };
15
+ }
16
+ export function readInstalledChannel(skillDir) {
17
+ const source = fs.readFileSync(path.join(skillDir, 'SKILL.md'), 'utf8');
18
+ const declaredName = source.match(/^name:\s*(\S+)\s*$/m)?.[1];
19
+ const identity = declaredName === 'alipay-aipay-pre' ? 'pre' : 'stable';
20
+ try {
21
+ const file = path.join(skillDir, CHANNEL_FILE);
22
+ if (!fs.lstatSync(file).isFile())
23
+ throw new Error('渠道文件必须是普通文件');
24
+ const channel = parseChannel(JSON.parse(fs.readFileSync(file, 'utf8')).channel);
25
+ if (channel !== identity)
26
+ throw new Error('Skill 名称与渠道不一致');
27
+ return channel;
28
+ }
29
+ catch (error) {
30
+ if (error.code === 'ENOENT' && identity === 'stable')
31
+ return 'stable';
32
+ throw error;
33
+ }
34
+ }
35
+ export function skillVersionKind(version, channel) {
36
+ if (typeof version !== 'string')
37
+ return null;
38
+ const parsed = semver.parse(version);
39
+ if (!parsed)
40
+ return null;
41
+ const suffix = parsed.prerelease.join('.');
42
+ if (suffix === (channel === 'pre' ? 'pre' : ''))
43
+ return 'release';
44
+ const pattern = channel === 'pre' ? /^pre-beta(?:\d+|\.\d+)?$/u : /^beta(?:\d+|\.\d+)?$/u;
45
+ return pattern.test(suffix) ? 'beta' : null;
46
+ }
47
+ export function readInstalledVersion(skillDir) {
48
+ try {
49
+ const file = path.join(skillDir, 'VERSION');
50
+ if (!fs.lstatSync(file).isFile())
51
+ return null;
52
+ return fs.readFileSync(file, 'utf8').trim();
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ }
58
+ export function getSkillVersion(packageRoot, channel = 'stable') {
59
+ const config = getChannelConfig(channel);
60
+ const version = fs.readFileSync(path.join(packageRoot, config.sourceDir, 'VERSION'), 'utf8').trim();
61
+ const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
62
+ if (!semver.valid(version) || !skillVersionKind(version, channel) || pkg.alipayAipayChannels?.[channel] !== version) {
63
+ throw new Error(`渠道 ${channel} 的 VERSION 与 npm 元数据不一致或非法`);
64
+ }
65
+ return version;
66
+ }
67
+ //# sourceMappingURL=channels.js.map
@@ -4,6 +4,7 @@ import { createHash } from 'crypto';
4
4
  import { fileURLToPath } from 'url';
5
5
  import fs from 'fs';
6
6
  import { execFileSync } from 'child_process';
7
+ import { getChannelConfig } from './channels.js';
7
8
  // 获取当前包的根目录
8
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
10
  export const PACKAGE_ROOT = path.resolve(__dirname, '../../');
@@ -99,7 +100,8 @@ export function detectCurrentAgentTarget() {
99
100
  /**
100
101
  * 解析安装目标
101
102
  */
102
- export function resolveInstallTarget(cwd, target = 'auto') {
103
+ export function resolveInstallTarget(cwd, target = 'auto', channel = 'stable') {
104
+ const SKILL_NAME = getChannelConfig(channel).skillName;
103
105
  if (target === 'agents' || target === 'claude') {
104
106
  return target;
105
107
  }
@@ -153,15 +155,17 @@ export function getExtraSkillDirs() {
153
155
  .map((item) => item.trim())
154
156
  .filter((item) => item.length > 0 && !item.includes('\0'));
155
157
  }
156
- function createCommandContext(cwd, targetDirLabel) {
158
+ function createCommandContext(cwd, targetDirLabel, channel = 'stable') {
159
+ const SKILL_NAME = getChannelConfig(channel).skillName;
157
160
  const targetDir = path.isAbsolute(targetDirLabel)
158
161
  ? targetDirLabel
159
162
  : path.join(cwd, targetDirLabel);
160
163
  const skillDir = path.join(targetDir, SKILL_NAME);
161
164
  const resolvedTargetDir = path.resolve(targetDir);
162
- const versionFileName = `${createHash('sha256').update(resolvedTargetDir).digest('hex')}.json`;
165
+ const versionFileName = `${createHash('sha256').update(channel === 'stable' ? resolvedTargetDir : `${resolvedTargetDir}\0${channel}`).digest('hex')}.json`;
163
166
  return {
164
167
  cwd,
168
+ channel,
165
169
  targetDir,
166
170
  versionFile: path.join(os.homedir(), '.config', 'alipay-aipay', 'install-records', versionFileName),
167
171
  legacyVersionFile: path.join(skillDir, VERSION_FILE),
@@ -171,12 +175,12 @@ function createCommandContext(cwd, targetDirLabel) {
171
175
  /**
172
176
  * 为已经解析出的 skills 父目录构造命令上下文。
173
177
  */
174
- export function getCommandContextForTargetDir(targetDir) {
178
+ export function getCommandContextForTargetDir(targetDir, channel = 'stable') {
175
179
  if (!path.isAbsolute(targetDir) || targetDir.includes('\0')) {
176
180
  throw new Error('Skill 目标父目录必须是绝对路径');
177
181
  }
178
182
  const resolvedTargetDir = path.resolve(targetDir);
179
- return createCommandContext(resolvedTargetDir, resolvedTargetDir);
183
+ return createCommandContext(resolvedTargetDir, resolvedTargetDir, channel);
180
184
  }
181
185
  function getExistingInstallTargetNames(cwd) {
182
186
  return getAllInstallTargetNames().filter((targetName) => fs.existsSync(path.join(cwd, TARGET_ROOT_DIRS[targetName])));
@@ -185,17 +189,17 @@ function getExistingInstallTargetNames(cwd) {
185
189
  * 获取批量安装目标上下文。普通命令扫描用户 Home 下已有的内置 Agent 目录;
186
190
  * 若没有任何已存在目录,则使用调用方指定的回退目标。环境变量可追加兼容 Skill 目录。
187
191
  */
188
- export function getAllCommandContexts(cwd, fallbackTarget = DEFAULT_TARGET) {
192
+ export function getAllCommandContexts(cwd, fallbackTarget = DEFAULT_TARGET, channel = 'stable') {
189
193
  const extraSkillDirs = getExtraSkillDirs();
190
194
  const homeDir = os.homedir();
191
195
  const targetNames = getExistingInstallTargetNames(homeDir);
192
196
  if (targetNames.length === 0) {
193
197
  targetNames.push(fallbackTarget);
194
198
  }
195
- const contexts = targetNames.map((targetName) => createCommandContext(homeDir, TARGET_DIRS[targetName]));
199
+ const contexts = targetNames.map((targetName) => createCommandContext(homeDir, TARGET_DIRS[targetName], channel));
196
200
  const seen = new Set(contexts.map((ctx) => path.resolve(ctx.targetDir)));
197
201
  for (const extraDir of extraSkillDirs) {
198
- const ctx = createCommandContext(cwd, extraDir);
202
+ const ctx = createCommandContext(cwd, extraDir, channel);
199
203
  const resolved = path.resolve(ctx.targetDir);
200
204
  if (seen.has(resolved))
201
205
  continue;
@@ -207,11 +211,11 @@ export function getAllCommandContexts(cwd, fallbackTarget = DEFAULT_TARGET) {
207
211
  /**
208
212
  * 获取命令上下文
209
213
  */
210
- export function getCommandContext(_cwd, target = 'auto') {
214
+ export function getCommandContext(_cwd, target = 'auto', channel = 'stable') {
211
215
  const homeDir = os.homedir();
212
- const targetName = resolveInstallTarget(homeDir, target);
216
+ const targetName = resolveInstallTarget(homeDir, target, channel);
213
217
  const targetDirLabel = TARGET_DIRS[targetName];
214
- return createCommandContext(homeDir, targetDirLabel);
218
+ return createCommandContext(homeDir, targetDirLabel, channel);
215
219
  }
216
220
  /**
217
221
  * 获取包版本
@@ -2,7 +2,7 @@ import fs from 'fs/promises';
2
2
  import path from 'path';
3
3
  import { randomUUID } from 'crypto';
4
4
  import { setTimeout as delay } from 'timers/promises';
5
- import { SKILL_NAME, SKILL_DIR } from './config.js';
5
+ import { getChannelConfig, getSkillVersion, readInstalledChannel } from './channels.js';
6
6
  /**
7
7
  * 检查目录是否存在
8
8
  */
@@ -236,8 +236,8 @@ export async function writeVersionRecordWithFallback(ctx, record) {
236
236
  * 安装 Skill 文件到目标目录
237
237
  * 从包内 skill/ 目录复制 SKILL.md + references/ 到目标 skills 目录
238
238
  */
239
- export async function installSkillFiles(packageRoot, targetDir) {
240
- return installSkillFilesAtPath(packageRoot, path.join(targetDir, SKILL_NAME));
239
+ export async function installSkillFiles(packageRoot, targetDir, channel = 'stable') {
240
+ return installSkillFilesAtPath(packageRoot, path.join(targetDir, getChannelConfig(channel).skillName), { channel });
241
241
  }
242
242
  /**
243
243
  * 原子安装到已经确定的单个 Skill 目录。自更新使用事务 ID,便于超时恢复。
@@ -246,6 +246,8 @@ export async function installSkillFilesAtPath(packageRoot, skillTargetDir, optio
246
246
  if (!path.isAbsolute(skillTargetDir) || skillTargetDir.includes('\0')) {
247
247
  throw new Error('Skill 安装目录必须是绝对路径');
248
248
  }
249
+ const channel = options.channel ?? 'stable';
250
+ const { skillName: SKILL_NAME, sourceDir: SKILL_DIR } = getChannelConfig(channel);
249
251
  const transactionId = options.transactionId;
250
252
  if (transactionId && !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(transactionId)) {
251
253
  throw new Error('无效的 Skill 安装事务 ID');
@@ -253,7 +255,20 @@ export async function installSkillFilesAtPath(packageRoot, skillTargetDir, optio
253
255
  const resolvedSkillTargetDir = path.resolve(skillTargetDir);
254
256
  const targetDir = path.dirname(resolvedSkillTargetDir);
255
257
  const skillSourceDir = path.join(packageRoot, SKILL_DIR);
256
- const packageJson = JSON.parse(await fs.readFile(path.join(packageRoot, 'package.json'), 'utf-8'));
258
+ const skillVersion = getSkillVersion(packageRoot, channel);
259
+ if (readInstalledChannel(skillSourceDir) !== channel)
260
+ throw new Error('安装源渠道不匹配');
261
+ for (const file of ['SKILL.md', 'VERSION', 'references/runtime-entry.md']) {
262
+ if (!(await fs.lstat(path.join(skillSourceDir, file))).isFile())
263
+ throw new Error('Skill 安装源不完整');
264
+ }
265
+ const oppositeName = getChannelConfig(channel === 'stable' ? 'pre' : 'stable').skillName;
266
+ if (path.basename(resolvedSkillTargetDir) === oppositeName)
267
+ throw new Error('禁止覆盖另一渠道目录');
268
+ if (await pathExists(path.join(resolvedSkillTargetDir, 'SKILL.md'))) {
269
+ if (readInstalledChannel(resolvedSkillTargetDir) !== channel)
270
+ throw new Error('禁止跨渠道覆盖 Skill');
271
+ }
257
272
  await ensureDir(targetDir);
258
273
  const stagingDir = transactionId
259
274
  ? path.join(targetDir, `.${SKILL_NAME}-install-${transactionId}`)
@@ -266,9 +281,7 @@ export async function installSkillFilesAtPath(packageRoot, skillTargetDir, optio
266
281
  try {
267
282
  await fs.copyFile(path.join(skillSourceDir, 'SKILL.md'), path.join(stagingDir, 'SKILL.md'));
268
283
  await copyDirWithPerms(path.join(skillSourceDir, 'references'), path.join(stagingDir, 'references'));
269
- if (packageJson.version) {
270
- await fs.writeFile(path.join(stagingDir, 'VERSION'), `${packageJson.version}\n`, 'utf-8');
271
- }
284
+ await fs.copyFile(path.join(skillSourceDir, 'VERSION'), path.join(stagingDir, 'VERSION'));
272
285
  if (await pathExists(resolvedSkillTargetDir)) {
273
286
  try {
274
287
  await fs.rename(resolvedSkillTargetDir, backupDir);
@@ -286,8 +299,8 @@ export async function installSkillFilesAtPath(packageRoot, skillTargetDir, optio
286
299
  catch (installError) {
287
300
  const installErrorCode = installError.code;
288
301
  const sameVersionInstalled = ['EEXIST', 'ENOTEMPTY', 'ENOENT'].includes(installErrorCode ?? '')
289
- ? await waitForCompleteInstalledVersion(resolvedSkillTargetDir, packageJson.version)
290
- : await hasCompleteInstalledVersion(resolvedSkillTargetDir, packageJson.version);
302
+ ? await waitForCompleteInstalledVersion(resolvedSkillTargetDir, skillVersion)
303
+ : await hasCompleteInstalledVersion(resolvedSkillTargetDir, skillVersion);
291
304
  if (sameVersionInstalled) {
292
305
  if (previousInstallMoved) {
293
306
  await removeDir(backupDir);
@@ -303,7 +316,7 @@ export async function installSkillFilesAtPath(packageRoot, skillTargetDir, optio
303
316
  catch (restoreError) {
304
317
  const restoreErrorCode = restoreError.code;
305
318
  if (['EEXIST', 'ENOTEMPTY', 'ENOENT'].includes(restoreErrorCode ?? '') &&
306
- await waitForCompleteInstalledVersion(resolvedSkillTargetDir, packageJson.version)) {
319
+ await waitForCompleteInstalledVersion(resolvedSkillTargetDir, skillVersion)) {
307
320
  await removeDir(backupDir);
308
321
  previousInstallMoved = false;
309
322
  return;