@alipay/alipay-aipay 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/skill/SKILL.md +1 -1
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +51 -73
- package/skill/references/integration/modules/checklist.md +3 -3
- package/skill/references/integration/modules/product-decision.md +1 -1
- package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +11 -22
- package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +1 -1
- package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +4 -4
- package/skill/references/normal/alipay-cli-env.md +2 -2
- package/skill/references/normal/full-process-routing.md +17 -17
- package/skill/references/normal/json/customer-messages.json +13 -14
- package/skill/references/normal/rejection-guide.md +1 -1
- package/skill/references/normal/scripts/alipay_cli_env.mjs +8 -4
- package/skill/references/normal/scripts/flow_loader.mjs +2 -2
- package/skill/references/normal/scripts/integration_context_runner.mjs +3 -3
- package/skill/references/normal/scripts/integration_message_runner.mjs +3 -3
- package/skill/references/normal/scripts/interaction_reply.mjs +3 -3
- package/skill/references/normal/scripts/onboarding_discovery_runner.mjs +3 -3
- package/skill/references/normal/scripts/onboarding_message_runner.mjs +3 -3
- package/skill/references/normal/scripts/onboarding_recovery_runner.mjs +9 -7
- package/skill/references/normal/scripts/python_script_runner.mjs +10 -8
- package/skill/references/normal/scripts/render_customer_message.mjs +68 -59
- package/skill/references/normal/scripts/runtime.mjs +133 -0
- package/skill/references/normal/scripts/self_update.mjs +8 -6
- package/skill/references/normal/scripts/telemetry.mjs +27 -26
- package/skill/references/normal/self-update.md +2 -2
- package/skill/references/normal/telemetry.md +5 -5
- package/skill/references/onboarding/flow.md +67 -80
- package/skill/references/onboarding/modules/app-release.md +5 -5
- package/skill/references/onboarding/modules/authorization.md +1 -1
- package/skill/references/onboarding/modules/service-registration.md +4 -4
- package/skill/references/runtime-entry.md +30 -30
|
@@ -554,126 +554,126 @@ function validateVariantInputShape(messageId, variantName, variables) {
|
|
|
554
554
|
|
|
555
555
|
const managedEntrypoints = {
|
|
556
556
|
'product.unsupported': {
|
|
557
|
-
command: 'node scripts/
|
|
557
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message product-unsupported --product-name <产品名>',
|
|
558
558
|
reason: '不支持产品拒绝引导必须由 runner 接收产品名后托管输出,禁止 jq/printf 管道直调 renderer。'
|
|
559
559
|
},
|
|
560
560
|
'product.clarify': {
|
|
561
|
-
command: 'node
|
|
561
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message product-clarify,或代码开发上下文使用同一入口执行 integration-message product-clarify',
|
|
562
562
|
reason: '产品澄清属于通用托管消息,禁止用 printf/renderer 管道直接输出。'
|
|
563
563
|
},
|
|
564
564
|
'onboarding.enterprise.unsupported': {
|
|
565
|
-
command: 'node
|
|
565
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message enterprise-unsupported --variant <ONBOARDING_ONLY|FULL_PROCESS>',
|
|
566
566
|
reason: '企业账号停止分支必须由 Onboarding runner 输出,禁止空 JSON 管道直调 renderer。'
|
|
567
567
|
},
|
|
568
568
|
'onboarding.windows.redirect': {
|
|
569
|
-
command: 'node
|
|
569
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message platform-entry',
|
|
570
570
|
reason: 'Windows 产品开通入口必须由 runner 根据真实运行平台确定;非 Windows 不得输出该消息。'
|
|
571
571
|
},
|
|
572
572
|
'integration.start.confirm': {
|
|
573
|
-
command: 'node
|
|
574
|
-
reason: '
|
|
573
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --product-type <aipay|webpay|apppay> --project-path <absPath> --project-selection <CURRENT_PROJECT|OTHER_PROJECT|PREPARED_NEW_PROJECT> --language <language> --framework <framework>',
|
|
574
|
+
reason: '代码开发启动方案必须绑定 runner 同一次项目扫描的项目来源、代码状态和其他支付产品,禁止手写项目扫描事实。'
|
|
575
575
|
},
|
|
576
576
|
'integration.checklist.result': {
|
|
577
|
-
command: 'node
|
|
577
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant <AIPAY|WEBPAY|APPPAY> --project-path <absPath> --scope-receipt <receipt> --overall-result <result> --failed-items <items> --manual-items <items> ...',
|
|
578
578
|
reason: '最终 checklist 结论必须由 runner 统一接收最终证据并调用 renderer,同一次代码开发只输出一次。'
|
|
579
579
|
},
|
|
580
580
|
'integration.project_candidates.select': {
|
|
581
|
-
command: 'node
|
|
581
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message locate-projects --base-path <absDir> --search-input <current|relativeSubdir|absDir> --format message',
|
|
582
582
|
reason: '项目候选目录必须由 runner 轻量定位项目标记后统一输出,禁止手写候选列表或扫描整个大目录。'
|
|
583
583
|
},
|
|
584
584
|
'onboarding.mcc.clarify': {
|
|
585
|
-
command: 'node
|
|
585
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-clarify --product-type <aipay|webpay|apppay>',
|
|
586
586
|
reason: '产品已明确但用户尚未提供 MCC/经营描述时由 runner 绑定产品名称,禁止手写经营类目补问;检索无匹配时不得回到本消息。'
|
|
587
587
|
},
|
|
588
588
|
'onboarding.mcc.no_match': {
|
|
589
|
-
command: 'node
|
|
589
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-candidates --query <business-description> --product-type <aipay|webpay|apppay>',
|
|
590
590
|
reason: '用户已经提供经营描述但当前 MCC 表无确定匹配时,由 runner 输出独立恢复路径,禁止重新渲染初始 mcc-clarify 形成循环。'
|
|
591
591
|
},
|
|
592
592
|
'onboarding.mcc.candidates': {
|
|
593
|
-
command: 'node
|
|
593
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-candidates --query <business-description> --product-type <aipay|webpay|apppay>',
|
|
594
594
|
reason: '产品已明确且 MCC 存在多个相似候选时由 runner 绑定本地 MCC 表生成候选事实,禁止手写候选表。'
|
|
595
595
|
},
|
|
596
596
|
'onboarding.discovery.summary': {
|
|
597
|
-
command: 'node
|
|
597
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-discovery run --product-type <aipay|webpay|apppay> --sales-code <SALES_CODE>',
|
|
598
598
|
reason: '该 runner 执行本轮适用查询、校验原始脚本事实、输出唯一 DISCOVERY_RESULT envelope,并在同一次 stdout 生成摘要;禁止单独重放摘要。'
|
|
599
599
|
},
|
|
600
600
|
'onboarding.plan.confirm': {
|
|
601
|
-
command: 'node
|
|
602
|
-
reason: '
|
|
601
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-resolve-plan --query <经营描述|MCC编码|MCC名称> --product-type <aipay|webpay|apppay>,或已持有唯一 MCC 事实时使用同一入口执行 onboarding-message plan-confirm --product-type <...> --mcc-code <...> --mcc-name <...> --mcc-qualification <...>',
|
|
602
|
+
reason: '方案展示必须由 runner 绑定本轮唯一 MCC 事实和产品变体生成,避免 Agent 用 jq/printf/管道手写 renderer 输入。'
|
|
603
603
|
},
|
|
604
604
|
'materials.category.collect': {
|
|
605
|
-
command: 'node
|
|
605
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message material-collect --category <signing|service|application> --state <INITIAL|PARTIAL|INVALID|APP_MOBILE_INITIAL> --product-type <aipay|webpay|apppay> [--missing-fields <字段列表>]',
|
|
606
606
|
reason: '运行时禁止手写 categoryName/currentStatus/missingFields;runner 会归一化“签约资料”“AI 网页应用收款签约截图”“mobilePlatform”等常见别名后再调用 renderer。'
|
|
607
607
|
},
|
|
608
608
|
'service.create.summary': {
|
|
609
|
-
command: 'node
|
|
609
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message service-create-summary --service-name <name> --service-description <desc> --service-url <url> --service-pricing <amount> --service-schema <json>',
|
|
610
610
|
reason: '服务创建摘要必须由 runner 接收已校验五项资料后托管输出,禁止 jq/printf 管道直调 renderer。'
|
|
611
611
|
},
|
|
612
612
|
'onboarding.write.confirm': {
|
|
613
|
-
command: 'node
|
|
613
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message service-update-confirm --session-summary <summary> --subject-summary <summary> --service-id <id> --service-name <name> --service-description <desc> --service-url <url> --service-pricing <amount> --service-schema <json>',
|
|
614
614
|
reason: '服务修改确认必须由 runner 固定产品和动作,只绑定当前服务修改摘要,禁止 Agent 自行拼 actionTypes。'
|
|
615
615
|
},
|
|
616
616
|
'signing.operation.result': {
|
|
617
|
-
command: 'node
|
|
617
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message signing-result --actual-status <status> [--fee-display <fee>] --next-action <action>',
|
|
618
618
|
reason: '签约分支结果必须由 Onboarding runner 输出,避免直调 renderer 或手写状态。'
|
|
619
619
|
},
|
|
620
620
|
'service.operation.result': {
|
|
621
|
-
command: 'node
|
|
621
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message service-result --service-id <id> --actual-result <result>',
|
|
622
622
|
reason: '服务分支结果必须由 Onboarding runner 输出,避免直调 renderer 或手写状态。'
|
|
623
623
|
},
|
|
624
624
|
'application.harmony.manual_create': {
|
|
625
|
-
command: 'node
|
|
625
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-harmony-manual-create',
|
|
626
626
|
reason: 'HarmonyOS 移动应用边界必须由 Onboarding runner 输出,禁止空 JSON 管道直调 renderer。'
|
|
627
627
|
},
|
|
628
628
|
'application.reuse.no_key': {
|
|
629
|
-
command: 'node
|
|
629
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-reuse-no-key --app-id <appId>',
|
|
630
630
|
reason: '复用应用缺公钥提示必须由 runner 绑定当前完整 appId 后输出。'
|
|
631
631
|
},
|
|
632
632
|
'application.operation.result': {
|
|
633
|
-
command: 'node
|
|
633
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-result --app-id <id> --actual-status <status> --next-action <action>',
|
|
634
634
|
reason: '应用分支结果必须由 Onboarding runner 输出,避免直调 renderer 或手写状态。'
|
|
635
635
|
},
|
|
636
636
|
'application.candidates.facts': {
|
|
637
|
-
command: 'node
|
|
637
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-candidates --application-type <WEBAPP|MOBILEAPP> --candidates-json <APP_CANDIDATES_JSON>',
|
|
638
638
|
reason: '应用候选事实和适用选择提示必须由 runner 接收结构化候选数组并统一生成,禁止脚本或 Agent 拼接 Markdown 行。'
|
|
639
639
|
},
|
|
640
640
|
'application.candidate.select': {
|
|
641
|
-
command: 'node
|
|
641
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-candidates --application-type <WEBAPP|MOBILEAPP> --candidates-json <APP_CANDIDATES_JSON>',
|
|
642
642
|
reason: '应用候选选择必须由 runner 绑定同一份结构化候选快照生成,禁止脚本或 Agent 单独调用。'
|
|
643
643
|
},
|
|
644
644
|
'service.candidates.facts': {
|
|
645
|
-
command: 'node
|
|
645
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message service-candidates --candidates-json <SERVICE_CANDIDATES_JSON>',
|
|
646
646
|
reason: '服务候选事实和适用选择提示必须由 runner 接收结构化候选数组并统一生成,禁止脚本或 Agent 拼接 Markdown 行。'
|
|
647
647
|
},
|
|
648
648
|
'service.candidate.select': {
|
|
649
|
-
command: 'node
|
|
649
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message service-candidates --candidates-json <SERVICE_CANDIDATES_JSON>',
|
|
650
650
|
reason: '服务候选选择必须由 runner 绑定同一份结构化候选快照生成,禁止脚本或 Agent 单独调用。'
|
|
651
651
|
},
|
|
652
652
|
'process.partial_result': {
|
|
653
|
-
command: 'node
|
|
653
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message closeout --product-name <name> --process-result-title <title> --integration-result <result> --signing-result <result> --service-result <result> --application-result <result> --remaining-actions <actions> --next-flow-reminder <reminder>',
|
|
654
654
|
reason: '产品开通 Step 6 最终收口必须由 runner 统一合并代码开发状态、产品开通分支状态、最近应用分支结果和上线前关键点;禁止 Agent 手写、缩写或删减 AI 网页应用收款限制引导。'
|
|
655
655
|
},
|
|
656
656
|
'sandbox.android.client': {
|
|
657
|
-
command: 'node
|
|
657
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message sandbox-android-client',
|
|
658
658
|
reason: '沙箱支付宝 Android 下载说明必须由 Integration runner 输出,避免 Agent 为静态消息直调 renderer 或追加 shell 过滤。'
|
|
659
659
|
},
|
|
660
660
|
'auth.page': {
|
|
661
|
-
command: '
|
|
661
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth init --defer-open --scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>,页面 stdout 独立送达后使用同一入口执行 auth open ...',
|
|
662
662
|
reason: '授权页必须由 auth.sh 绑定本次 CLI deviceCode、固定产品/MCC 上下文和 URL 白名单;受控 opener 必须在页面消息独立送达后执行,后续 auth.pending 不得合并到同一条对客回复。',
|
|
663
663
|
allowedCallers: ['auth.sh']
|
|
664
664
|
},
|
|
665
665
|
'auth.pending': {
|
|
666
|
-
command: '
|
|
666
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth wait|confirm [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]',
|
|
667
667
|
reason: '授权待完成状态只能来自 auth.sh 有限轮询耗尽或登记肯定回复后的单次实际查询。',
|
|
668
668
|
allowedCallers: ['auth.sh']
|
|
669
669
|
},
|
|
670
670
|
'auth.expired': {
|
|
671
|
-
command: '
|
|
671
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth confirm [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>]',
|
|
672
672
|
reason: '授权过期状态只能来自本轮 auth.sh confirm 对 CLI 授权状态的实际查询。',
|
|
673
673
|
allowedCallers: ['auth.sh']
|
|
674
674
|
},
|
|
675
675
|
'auth.mismatch': {
|
|
676
|
-
command: '
|
|
676
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth mismatch --defer-open [--scope <scope> --sales-code <code> --mcc-code <code> --product-name <name> --mcc-name <name>],页面 stdout 独立送达后使用同一入口执行 auth open ...',
|
|
677
677
|
reason: 'scope 或 MCC 不匹配必须由 auth.sh 执行 logout 与重新授权链路,不能只输出提示。',
|
|
678
678
|
allowedCallers: ['auth.sh']
|
|
679
679
|
},
|
|
@@ -703,22 +703,22 @@ const managedEntrypoints = {
|
|
|
703
703
|
allowedCallers: ['error_handler.sh']
|
|
704
704
|
},
|
|
705
705
|
'application.key.page': {
|
|
706
|
-
command: '
|
|
706
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" app key --defer-open <appId> <publicKey>,页面 stdout 独立送达后使用同一入口执行 app open-key-page <appId>',
|
|
707
707
|
reason: '公钥确认页必须由 app.sh 调用 createKeyConfirmPage 后校验官方 URL;受控 opener 必须在页面消息独立送达后执行,后续 application.key.pending 不得合并到同一条对客回复。',
|
|
708
708
|
allowedCallers: ['app.sh']
|
|
709
709
|
},
|
|
710
710
|
'application.key.pending': {
|
|
711
|
-
command: '
|
|
711
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" app verify-key <appId> [publicKey] 或使用同一入口执行 app verify-key-and-audit <appId> [publicKey]',
|
|
712
712
|
reason: '公钥确认超时提示只能来自 app.sh 完成有限次数的实际公钥状态查询后。',
|
|
713
713
|
allowedCallers: ['app.sh']
|
|
714
714
|
},
|
|
715
715
|
'key_tool.download.result': {
|
|
716
|
-
command: '
|
|
716
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" key-tool [downloadDir]',
|
|
717
717
|
reason: '密钥工具下载成功消息必须来自下载脚本的实际下载路径、跳转校验和安装包校验结果。',
|
|
718
718
|
allowedCallers: ['download_key_tool.sh']
|
|
719
719
|
},
|
|
720
720
|
'key_tool.download.fallback': {
|
|
721
|
-
command: '
|
|
721
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" key-tool [downloadDir]',
|
|
722
722
|
reason: '密钥工具下载失败或不支持时必须由下载脚本统一给出官方手动下载兜底。',
|
|
723
723
|
allowedCallers: ['download_key_tool.sh']
|
|
724
724
|
}
|
|
@@ -837,6 +837,9 @@ export function validateCatalog() {
|
|
|
837
837
|
if (typeof inputHints.confirmInputHint !== 'string' || !inputHints.confirmInputHint) {
|
|
838
838
|
errors.push('缺少统一确认输入提示');
|
|
839
839
|
}
|
|
840
|
+
if (typeof inputHints.planAdjustmentHint !== 'string' || !inputHints.planAdjustmentHint) {
|
|
841
|
+
errors.push('缺少统一方案调整提示');
|
|
842
|
+
}
|
|
840
843
|
if (typeof inputHints.authorizationCompletionInputHint !== 'string' || !inputHints.authorizationCompletionInputHint) {
|
|
841
844
|
errors.push('缺少统一授权完成输入提示');
|
|
842
845
|
}
|
|
@@ -870,11 +873,11 @@ export function validateCatalog() {
|
|
|
870
873
|
if (message.blocking && allowedReplies.length > 0 && !['confirm', 'authorizationComplete', 'publicKeyConfirmationComplete', 'complete'].includes(message.inputHintType)) {
|
|
871
874
|
errors.push(`${message.messageId}: 阻塞回复消息必须声明合法 inputHintType`);
|
|
872
875
|
}
|
|
873
|
-
if (message.postRenderHintType !== undefined &&
|
|
876
|
+
if (message.postRenderHintType !== undefined && !['planAdjustment', 'scanReturn'].includes(message.postRenderHintType)) {
|
|
874
877
|
errors.push(`${message.messageId}: postRenderHintType 无效`);
|
|
875
878
|
}
|
|
876
|
-
if (message.postRenderHintType
|
|
877
|
-
errors.push(`${message.messageId}:
|
|
879
|
+
if (message.postRenderHintType && (message.blocking || JSON.stringify(message.allowedReplies || []) !== '[]')) {
|
|
880
|
+
errors.push(`${message.messageId}: postRenderHintType 只允许用于非阻塞且无回复枚举的消息`);
|
|
878
881
|
}
|
|
879
882
|
for (const id of message.requiredPolicyIds || []) {
|
|
880
883
|
if (!policyIds.has(id)) errors.push(`${message.messageId}: 未知 policyId ${id}`);
|
|
@@ -1247,9 +1250,15 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
|
|
|
1247
1250
|
if (!hint) throw new Error(`缺少 ${hintKey}`);
|
|
1248
1251
|
rendered = `${rendered}\n\n${hint}`;
|
|
1249
1252
|
}
|
|
1250
|
-
if (message.postRenderHintType
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1253
|
+
if (message.postRenderHintType) {
|
|
1254
|
+
const hintKeys = {
|
|
1255
|
+
planAdjustment: 'planAdjustmentHint',
|
|
1256
|
+
scanReturn: 'scanReturnHint'
|
|
1257
|
+
};
|
|
1258
|
+
const hintKey = hintKeys[message.postRenderHintType];
|
|
1259
|
+
if (!hintKey) throw new Error(`${messageId} 的 postRenderHintType 非法`);
|
|
1260
|
+
const hint = catalog.interactionPrompts?.[hintKey];
|
|
1261
|
+
if (!hint) throw new Error(`缺少 ${hintKey}`);
|
|
1253
1262
|
rendered = `${rendered}\n\n${hint}`;
|
|
1254
1263
|
}
|
|
1255
1264
|
emitMessageMetric(messageId, variantName, variables, telemetryContext);
|
|
@@ -1293,10 +1302,10 @@ async function readStdin() {
|
|
|
1293
1302
|
return input.trim() ? JSON.parse(input) : {};
|
|
1294
1303
|
}
|
|
1295
1304
|
|
|
1296
|
-
function inputJsonArg() {
|
|
1297
|
-
const index =
|
|
1305
|
+
function inputJsonArg(argv = process.argv) {
|
|
1306
|
+
const index = argv.indexOf('--input-json');
|
|
1298
1307
|
if (index < 0) return null;
|
|
1299
|
-
const value =
|
|
1308
|
+
const value = argv[index + 1];
|
|
1300
1309
|
if (value === undefined || value.startsWith('--')) throw new Error('参数 --input-json 缺少取值');
|
|
1301
1310
|
try {
|
|
1302
1311
|
return JSON.parse(value);
|
|
@@ -1305,42 +1314,42 @@ function inputJsonArg() {
|
|
|
1305
1314
|
}
|
|
1306
1315
|
}
|
|
1307
1316
|
|
|
1308
|
-
async function
|
|
1309
|
-
if (
|
|
1317
|
+
export async function runRenderCustomerMessageCli(argv = process.argv) {
|
|
1318
|
+
if (argv.includes('--check-catalog')) {
|
|
1310
1319
|
const errors = validateCatalog();
|
|
1311
1320
|
if (errors.length) throw new Error(errors.join('\n'));
|
|
1312
1321
|
console.log('customer message catalog: OK');
|
|
1313
1322
|
return;
|
|
1314
1323
|
}
|
|
1315
|
-
if (
|
|
1324
|
+
if (argv.includes('--validate-authorization-context')) {
|
|
1316
1325
|
validateAuthorizationContext(await readStdin());
|
|
1317
1326
|
console.log('authorization context: OK');
|
|
1318
1327
|
return;
|
|
1319
1328
|
}
|
|
1320
|
-
if (
|
|
1329
|
+
if (argv.includes('--build-authorization-url')) {
|
|
1321
1330
|
console.log(buildAuthorizationUrl(await readStdin()));
|
|
1322
1331
|
return;
|
|
1323
1332
|
}
|
|
1324
|
-
if (
|
|
1325
|
-
const schemaIndex =
|
|
1326
|
-
const messageId =
|
|
1327
|
-
const variantIndex =
|
|
1328
|
-
const variant = variantIndex >= 0 ?
|
|
1333
|
+
if (argv.includes('--schema')) {
|
|
1334
|
+
const schemaIndex = argv.indexOf('--schema');
|
|
1335
|
+
const messageId = argv[2] === '--schema' ? argv[schemaIndex + 1] : argv[2];
|
|
1336
|
+
const variantIndex = argv.indexOf('--variant');
|
|
1337
|
+
const variant = variantIndex >= 0 ? argv[variantIndex + 1] : 'DEFAULT';
|
|
1329
1338
|
if (!messageId || messageId.startsWith('--')) throw new Error('用法: render_customer_message.mjs --schema <messageId> [--variant NAME]');
|
|
1330
1339
|
console.log(JSON.stringify(getMessageSchema(messageId, variant), null, 2));
|
|
1331
1340
|
return;
|
|
1332
1341
|
}
|
|
1333
|
-
const messageId =
|
|
1334
|
-
const variantIndex =
|
|
1335
|
-
const variant = variantIndex >= 0 ?
|
|
1342
|
+
const messageId = argv[2];
|
|
1343
|
+
const variantIndex = argv.indexOf('--variant');
|
|
1344
|
+
const variant = variantIndex >= 0 ? argv[variantIndex + 1] : 'DEFAULT';
|
|
1336
1345
|
if (!messageId) throw new Error('用法: render_customer_message.mjs <messageId> [--variant NAME]');
|
|
1337
1346
|
assertManagedCliAllowed(messageId);
|
|
1338
|
-
const variables = inputJsonArg() ?? await readStdin();
|
|
1347
|
+
const variables = inputJsonArg(argv) ?? await readStdin();
|
|
1339
1348
|
console.log(renderMessageWithFallback(messageId, variant, variables));
|
|
1340
1349
|
}
|
|
1341
1350
|
|
|
1342
1351
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
1343
|
-
|
|
1352
|
+
runRenderCustomerMessageCli().catch((error) => {
|
|
1344
1353
|
console.error('当前步骤的标准消息无法安全生成,已停止后续动作。请按 MESSAGE_RENDER_ERROR 的具体原因修正输入;若消息目录或脚本缺失,再检查 Skill 文件完整性。');
|
|
1345
1354
|
console.error(`MESSAGE_RENDER_ERROR:${error.message}`);
|
|
1346
1355
|
process.exitCode = 1;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const referencesDir = path.resolve(scriptDir, '../..');
|
|
10
|
+
const flowDirs = Object.freeze({
|
|
11
|
+
integration: path.join(referencesDir, 'integration'),
|
|
12
|
+
onboarding: path.join(referencesDir, 'onboarding')
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const shellEntrypoints = Object.freeze({
|
|
16
|
+
sandbox: ['integration', 'sandbox_config.sh'],
|
|
17
|
+
auth: ['onboarding', 'auth.sh'],
|
|
18
|
+
'key-tool': ['onboarding', 'download_key_tool.sh'],
|
|
19
|
+
screenshots: ['onboarding', 'upload_screenshots.sh'],
|
|
20
|
+
sign: ['onboarding', 'ar_sign_apply.sh'],
|
|
21
|
+
service: ['onboarding', 'service.sh'],
|
|
22
|
+
app: ['onboarding', 'app.sh']
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const nodeEntrypoints = Object.freeze({
|
|
26
|
+
telemetry: ['telemetry.mjs', 'runTelemetryCli'],
|
|
27
|
+
flow: ['flow_loader.mjs', 'runFlowCli'],
|
|
28
|
+
'onboarding-message': ['onboarding_message_runner.mjs', 'runOnboardingMessageCli'],
|
|
29
|
+
'integration-message': ['integration_message_runner.mjs', 'runIntegrationMessageCli'],
|
|
30
|
+
render: ['render_customer_message.mjs', 'runRenderCustomerMessageCli'],
|
|
31
|
+
reply: ['interaction_reply.mjs', 'runInteractionReplyCli'],
|
|
32
|
+
'integration-context': ['integration_context_runner.mjs', 'runIntegrationContextCli'],
|
|
33
|
+
'onboarding-discovery': ['onboarding_discovery_runner.mjs', 'runOnboardingDiscoveryCli'],
|
|
34
|
+
'onboarding-recovery': ['onboarding_recovery_runner.mjs', 'runOnboardingRecoveryCli']
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const runtimeDomains = Object.freeze([
|
|
38
|
+
'self-update',
|
|
39
|
+
...Object.keys(nodeEntrypoints),
|
|
40
|
+
'env',
|
|
41
|
+
...Object.keys(shellEntrypoints),
|
|
42
|
+
'a2m'
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
function cliArgv(args) {
|
|
46
|
+
return [process.execPath, fileURLToPath(import.meta.url), ...args];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function runShell(script, cwd, args) {
|
|
50
|
+
const result = spawnSync('bash', [script, ...args], {
|
|
51
|
+
cwd,
|
|
52
|
+
env: process.env,
|
|
53
|
+
stdio: 'inherit',
|
|
54
|
+
shell: false
|
|
55
|
+
});
|
|
56
|
+
if (result.error) throw result.error;
|
|
57
|
+
process.exitCode = Number.isInteger(result.status) ? result.status : 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function shellPath(domain) {
|
|
61
|
+
const [flow, basename] = shellEntrypoints[domain];
|
|
62
|
+
const cwd = flowDirs[flow];
|
|
63
|
+
return [path.join(cwd, 'modules/scripts', basename), cwd];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function runtimeError(domain, error) {
|
|
67
|
+
const message = String(error?.message || error).replace(/[\r\n]/gu, ' ');
|
|
68
|
+
if (domain === 'self-update') return process.stderr.write('SELF_UPDATE:CHECK_FAILED\n');
|
|
69
|
+
if (domain === 'render') {
|
|
70
|
+
process.stderr.write('当前步骤的标准消息无法安全生成,已停止后续动作。请按 MESSAGE_RENDER_ERROR 的具体原因修正输入;若消息目录或脚本缺失,再检查 Skill 文件完整性。\n');
|
|
71
|
+
process.stderr.write(`MESSAGE_RENDER_ERROR:${message}\n`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const prefixes = {
|
|
75
|
+
flow: 'FLOW_LOADER_ERROR:',
|
|
76
|
+
'onboarding-message': 'ONBOARDING_MESSAGE_ERROR:',
|
|
77
|
+
'integration-message': 'INTEGRATION_MESSAGE_ERROR:',
|
|
78
|
+
reply: 'ALIPAY_AIPAY_INTERNAL:REPLY_VALIDATION_ERROR=',
|
|
79
|
+
'integration-context': 'ALIPAY_AIPAY_INTERNAL:INTEGRATION_CONTEXT_ERROR=',
|
|
80
|
+
'onboarding-discovery': 'ALIPAY_AIPAY_INTERNAL:DISCOVERY_RUNNER_ERROR=',
|
|
81
|
+
'onboarding-recovery': 'ALIPAY_AIPAY_INTERNAL:RECOVERY_RUNNER_ERROR=',
|
|
82
|
+
a2m: 'PYTHON_RUNNER_ERROR:'
|
|
83
|
+
};
|
|
84
|
+
process.stderr.write(`${prefixes[domain] || 'ALIPAY_AIPAY_INTERNAL:RUNTIME_ERROR='}${message}\n`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function dispatch(domain, args) {
|
|
88
|
+
if (shellEntrypoints[domain]) {
|
|
89
|
+
const [script, cwd] = shellPath(domain);
|
|
90
|
+
return runShell(script, cwd, args);
|
|
91
|
+
}
|
|
92
|
+
if (nodeEntrypoints[domain]) {
|
|
93
|
+
const [moduleName, exportName] = nodeEntrypoints[domain];
|
|
94
|
+
const result = await (await import(`./${moduleName}`))[exportName](cliArgv(args));
|
|
95
|
+
if (domain === 'telemetry') process.exitCode = result;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (domain === 'env') {
|
|
99
|
+
const { isWindowsPlatform } = await import('./platform_compat.mjs');
|
|
100
|
+
if (!isWindowsPlatform()) {
|
|
101
|
+
return runShell(path.join(scriptDir, 'alipay_cli_env.sh'), path.dirname(scriptDir), args);
|
|
102
|
+
}
|
|
103
|
+
const { runAlipayCliEnvCli } = await import('./alipay_cli_env.mjs');
|
|
104
|
+
return runAlipayCliEnvCli(cliArgv(args));
|
|
105
|
+
}
|
|
106
|
+
if (domain === 'self-update') {
|
|
107
|
+
const { runSelfUpdateCli } = await import('./self_update.mjs');
|
|
108
|
+
const outcome = runSelfUpdateCli(cliArgv(args));
|
|
109
|
+
const version = outcome.version ? `=${outcome.version.raw}` : '';
|
|
110
|
+
process.stderr.write(`SELF_UPDATE:${outcome.kind}${version}\n`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (domain === 'a2m') {
|
|
114
|
+
const { runPythonScriptCli } = await import('./python_script_runner.mjs');
|
|
115
|
+
const script = path.join(flowDirs.integration, 'modules/scripts/local_402_sandbox_pay.py');
|
|
116
|
+
return runPythonScriptCli(cliArgv([script, ...args]));
|
|
117
|
+
}
|
|
118
|
+
throw new Error(`用法: runtime.mjs <${runtimeDomains.join('|')}> ...`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function runRuntimeCli(argv = process.argv) {
|
|
122
|
+
const domain = argv[2] || '';
|
|
123
|
+
try {
|
|
124
|
+
await dispatch(domain, argv.slice(3));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
runtimeError(domain, error);
|
|
127
|
+
process.exitCode = domain === 'self-update' ? 0 : 1;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
132
|
+
runRuntimeCli();
|
|
133
|
+
}
|
|
@@ -127,8 +127,8 @@ function reportOutcome(outcome) {
|
|
|
127
127
|
process.stderr.write(`SELF_UPDATE:${outcome.kind}${version}\n`);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
function
|
|
131
|
-
const skillDir = parseArgs(
|
|
130
|
+
export function runSelfUpdateCli(argv = process.argv) {
|
|
131
|
+
const skillDir = parseArgs(argv);
|
|
132
132
|
const local = readLocalVersion(skillDir);
|
|
133
133
|
|
|
134
134
|
if (!local) {
|
|
@@ -153,8 +153,10 @@ function main() {
|
|
|
153
153
|
return { kind: installed ? 'VERIFY_FAILED' : 'INSTALL_FAILED' };
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
157
|
+
try {
|
|
158
|
+
reportOutcome(runSelfUpdateCli());
|
|
159
|
+
} catch {
|
|
160
|
+
reportOutcome({ kind: 'CHECK_FAILED' });
|
|
161
|
+
}
|
|
160
162
|
}
|
|
@@ -449,7 +449,7 @@ export function emitStageMetricAsync(stage, context = {}, env = process.env) {
|
|
|
449
449
|
export function emitMessageMetric(messageId, variantName, variables = {}, context = {}) {
|
|
450
450
|
try {
|
|
451
451
|
const event = messageMetricEvent(messageId, variantName, variables, context);
|
|
452
|
-
if (event?.stage === 'run.terminal'
|
|
452
|
+
if (event?.stage === 'run.terminal') updateExistingRunStateFromEvent(event);
|
|
453
453
|
return emitMetricEvent(event, { stream: null });
|
|
454
454
|
} catch {
|
|
455
455
|
return false;
|
|
@@ -458,7 +458,6 @@ export function emitMessageMetric(messageId, variantName, variables = {}, contex
|
|
|
458
458
|
|
|
459
459
|
export function emitTerminalMetric(context = {}) {
|
|
460
460
|
try {
|
|
461
|
-
if (!telemetryEnabled()) return false;
|
|
462
461
|
const event = stageMetricEvent('run.terminal', context);
|
|
463
462
|
if (!event) return false;
|
|
464
463
|
updateExistingRunStateFromEvent(event);
|
|
@@ -1251,6 +1250,32 @@ function emitTelemetryError(error) {
|
|
|
1251
1250
|
export async function runTelemetryCli(argv = process.argv) {
|
|
1252
1251
|
try {
|
|
1253
1252
|
const { command, args } = parseCliArgs(argv);
|
|
1253
|
+
if (command === 'start-run') {
|
|
1254
|
+
assertCliArgs(args, new Set(['root-intent', 'product-type', 'run-id']), 0);
|
|
1255
|
+
const state = createOrReuseRunState(args);
|
|
1256
|
+
if (!writeRunState(state) && telemetryEnabled(process.env)) {
|
|
1257
|
+
recordLocalTelemetryFailure('LOCAL_RUN_STATE_WRITE_FAILED', 'failed to write local telemetry run state');
|
|
1258
|
+
}
|
|
1259
|
+
if (telemetryEnabled(process.env)) {
|
|
1260
|
+
const event = stageMetricEvent('run.intent_detected', {
|
|
1261
|
+
runId: state.run_id,
|
|
1262
|
+
rootIntent: state.root_intent,
|
|
1263
|
+
productType: state.product_type
|
|
1264
|
+
});
|
|
1265
|
+
emitMetricEvent(event);
|
|
1266
|
+
}
|
|
1267
|
+
return 0;
|
|
1268
|
+
}
|
|
1269
|
+
if (command === 'current-run-id') {
|
|
1270
|
+
assertCliArgs(args, new Set(), 0);
|
|
1271
|
+
const state = canReadImplicitRunState(process.env) ? readRunState(process.env) : null;
|
|
1272
|
+
if (state?.run_id) {
|
|
1273
|
+
process.stderr.write(`${internalPrefix}RUN_ID=${state.run_id}\n`);
|
|
1274
|
+
} else {
|
|
1275
|
+
process.stderr.write(`${internalPrefix}RUN_ID_MISSING=true\n`);
|
|
1276
|
+
}
|
|
1277
|
+
return 0;
|
|
1278
|
+
}
|
|
1254
1279
|
if (command === 'upload-status' && args._.length === 0) {
|
|
1255
1280
|
assertCliArgs(args, new Set(), 0);
|
|
1256
1281
|
const status = readUploadStatus(process.env) || { schema_ver: 1, status: 'unknown' };
|
|
@@ -1280,30 +1305,6 @@ export async function runTelemetryCli(argv = process.argv) {
|
|
|
1280
1305
|
return 0;
|
|
1281
1306
|
}
|
|
1282
1307
|
if (!telemetryEnabled(process.env)) return 0;
|
|
1283
|
-
if (command === 'start-run') {
|
|
1284
|
-
assertCliArgs(args, new Set(['root-intent', 'product-type', 'run-id']), 0);
|
|
1285
|
-
const state = createOrReuseRunState(args);
|
|
1286
|
-
if (!writeRunState(state)) {
|
|
1287
|
-
recordLocalTelemetryFailure('LOCAL_RUN_STATE_WRITE_FAILED', 'failed to write local telemetry run state');
|
|
1288
|
-
}
|
|
1289
|
-
const event = stageMetricEvent('run.intent_detected', {
|
|
1290
|
-
runId: state.run_id,
|
|
1291
|
-
rootIntent: state.root_intent,
|
|
1292
|
-
productType: state.product_type
|
|
1293
|
-
});
|
|
1294
|
-
emitMetricEvent(event);
|
|
1295
|
-
return 0;
|
|
1296
|
-
}
|
|
1297
|
-
if (command === 'current-run-id') {
|
|
1298
|
-
assertCliArgs(args, new Set(), 0);
|
|
1299
|
-
const state = canReadImplicitRunState(process.env) ? readRunState(process.env) : null;
|
|
1300
|
-
if (state?.run_id) {
|
|
1301
|
-
process.stderr.write(`${internalPrefix}RUN_ID=${state.run_id}\n`);
|
|
1302
|
-
} else {
|
|
1303
|
-
process.stderr.write(`${internalPrefix}RUN_ID_MISSING=true\n`);
|
|
1304
|
-
}
|
|
1305
|
-
return 0;
|
|
1306
|
-
}
|
|
1307
1308
|
if (command !== 'stage' || args._.length !== 1) {
|
|
1308
1309
|
emitTelemetryError(new Error('invalid telemetry arguments'));
|
|
1309
1310
|
return 0;
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
根 `SKILL.md` 是跨 Agent 的最小启动器。本次 Agent 对话首次使用 `alipay-aipay` 时,必须在读取 `references/runtime-entry.md`、flow、模块、消息目录或业务脚本前只检查一次版本。执行前把根 `SKILL.md` 所在目录解析为规范化绝对路径 `<SKILL_DIR>`,并在当前 Agent 上下文记录一次性事实 `ALIPAY_AIPAY_SELF_UPDATE_CHECKED=true`;不写文件、不跨对话保存,也不是业务进度。同一对话内后续根流程、确认、补材料、候选选择、错误恢复、中断后继续、重复读取本 Skill 和 Full Process 子流程衔接均不重查。`<SKILL_DIR>` 是执行时替换的路径占位符,固定命令为:
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
|
-
node "<SKILL_DIR>/references/normal/scripts/
|
|
6
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" self-update check --skill-dir "<SKILL_DIR>"
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
`<SKILL_DIR>` 必须是刚触发的本份 `SKILL.md` 所在目录,且该目录包含 `SKILL.md`、`VERSION` 和 `references/runtime-entry.md`;不得换成 Agent 启动目录、用户项目目录、用户 Home、npm 包源码根或另一份 Skill 副本。禁止把固定命令改写成 shell
|
|
9
|
+
`<SKILL_DIR>` 必须是刚触发的本份 `SKILL.md` 所在目录,且该目录包含 `SKILL.md`、`VERSION` 和 `references/runtime-entry.md`;不得换成 Agent 启动目录、用户项目目录、用户 Home、npm 包源码根或另一份 Skill 副本。禁止把固定命令改写成 shell 变量赋值、命令替换、相对路径或依赖 Bash、PowerShell、CMD 的专属语法;只允许执行上方统一 runtime 单命令。
|
|
10
10
|
|
|
11
11
|
结果与规则:
|
|
12
12
|
|
|
@@ -5,21 +5,21 @@
|
|
|
5
5
|
## 运行契约
|
|
6
6
|
|
|
7
7
|
- 固定 stage 枚举、Yuyan 字段和低敏维度以 `scripts/telemetry.mjs` 的 `approvedStages`、事件构造器和测试为准。
|
|
8
|
-
- `start-run`
|
|
8
|
+
- `start-run` 始终创建或复用当前流程 `run_id`;该私有 run context 是 alipay-cli `PLATFORM_ID` 和终态生命周期的运行事实,不依赖事件采集开关。动作 runner/script 在遥测开启时使用异步子进程记录 stage。缺少 run、遥测关闭、落盘失败、网络失败和非 2xx 都不得改变业务 stdout、退出语义或 flow 转移。
|
|
9
9
|
- 前台只写用户系统临时目录下带 `alipay-aipay` 标识的私有 outbox,并启动后台补传;collector 返回 HTTP 2xx 后才删除记录。维护/测试进程不复用默认 run state,默认不远端上传。
|
|
10
|
-
- `PLATFORM_ID`
|
|
10
|
+
- `PLATFORM_ID` 必须等于当前流程 `run_id`,遥测开关不得令其缺失或改变;模型维度只读 `AIPAY_MODEL`,禁止读取用户项目通用 `MODEL` 推断。
|
|
11
11
|
- 遥测内部行统一使用 `ALIPAY_AIPAY_INTERNAL:` 前缀,禁止对客。
|
|
12
12
|
|
|
13
13
|
## Run 生命周期
|
|
14
14
|
|
|
15
15
|
- 根入口用 `root_intent + product_type` 判定复用或新建;组合不变时不按经过时长失效,`UNKNOWN` 补全为明确产品仍复用同一 `run_id`。只有明确换产品、切换根意图或已有 run 终态才重建;用户只说“重新开始/重新走流程/作废本轮流程”但组合没有变化时继续复用。
|
|
16
|
-
- 若宿主提供 `COZE_PROJECT_ID`、`MEOO_PROJECT_ID`,或 `MIAODA` 环境下的 `VITE_APP_ID`/`PLATFORM_ID`,新建 run
|
|
16
|
+
- 若宿主提供 `COZE_PROJECT_ID`、`MEOO_PROJECT_ID`,或 `MIAODA` 环境下的 `VITE_APP_ID`/`PLATFORM_ID`,新建 run 优先使用该项目 ID,不得被显式 run ID 或本地生成值覆盖。当前宿主项目 ID 与已有状态不兼容时静默跳过不兼容事件且不改写 run state。
|
|
17
17
|
- `integration_only` 由 checklist 最终消息终止;`full_process` 的 Integration 收口不终止,和 `onboarding_only` 一样由 Onboarding closeout 终止。
|
|
18
|
-
- 查看当前主键只使用 `current-run-id`,不得为查看而新建 run
|
|
18
|
+
- 查看当前主键只使用 `current-run-id`,不得为查看而新建 run。关闭遥测只停止 `METRIC_EVENT`、outbox、上传和 flush,不停止 run context 的创建、读取与终态记账;业务脚本继续继承 `PLATFORM_ID=<run_id>`。Agent 不手写环境变量前缀或改写 MCP payload。
|
|
19
19
|
|
|
20
20
|
## 诊断与补传
|
|
21
21
|
|
|
22
|
-
`node scripts/
|
|
22
|
+
`node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry upload-status` 只读取内部诊断状态。网络类失败且 outbox 有积压时,先执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry permissioned-flush-needed`;只有内部事实为 `PERMISSIONED_FLUSH_NEEDED=true` 时才申请一次可复用联网权限运行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry flush-outbox`。同一 Agent 会话只请求一次;已取得权限后可在后续阶段旁路触发同一异步命令。`flush-outbox` 只启动后台补传并立即返回;用户拒绝、后台失败或非 2xx 都保留 outbox 并继续业务。collector HTTP 结果、失败或待重试结果不得作为业务转移或完成条件。
|
|
23
23
|
|
|
24
24
|
## 修改要求
|
|
25
25
|
|