@alipay/alipay-aipay 1.6.6 → 1.6.7-beta
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 +2 -2
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +22 -20
- package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +8 -29
- package/skill/references/integration/modules/scripts/sandbox_config.sh +2 -0
- package/skill/references/normal/full-process-routing.md +13 -11
- package/skill/references/normal/integration-worker.md +79 -0
- package/skill/references/normal/scripts/alipay_cli_env.mjs +0 -3
- package/skill/references/normal/scripts/alipay_cli_env.sh +0 -4
- package/skill/references/normal/scripts/common.sh +11 -0
- package/skill/references/normal/scripts/flow_loader.mjs +0 -19
- package/skill/references/normal/scripts/integration_message_runner.mjs +26 -53
- package/skill/references/normal/scripts/interaction_reply.mjs +2 -2
- package/skill/references/normal/scripts/onboarding_discovery_runner.mjs +4 -1
- package/skill/references/normal/scripts/onboarding_message_runner.mjs +33 -23
- package/skill/references/normal/scripts/onboarding_recovery_runner.mjs +2 -2
- package/skill/references/normal/scripts/render_customer_message.mjs +3 -3
- package/skill/references/normal/scripts/runtime.mjs +5 -23
- package/skill/references/normal/scripts/telemetry.mjs +368 -434
- package/skill/references/normal/telemetry.md +3 -4
- package/skill/references/onboarding/flow.md +14 -14
- package/skill/references/onboarding/modules/scripts/app.sh +1 -0
- package/skill/references/onboarding/modules/scripts/ar_sign_apply.sh +3 -1
- package/skill/references/onboarding/modules/scripts/auth.sh +4 -1
- package/skill/references/onboarding/modules/scripts/service.sh +2 -0
- package/skill/references/runtime-entry.md +12 -8
|
@@ -10,7 +10,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
10
10
|
|
|
11
11
|
import { isWindowsPlatform } from './platform_compat.mjs';
|
|
12
12
|
import { renderMessage } from './render_customer_message.mjs';
|
|
13
|
-
import {
|
|
13
|
+
import { emitStageMetricAsync, startTelemetryRun } from './telemetry.mjs';
|
|
14
14
|
|
|
15
15
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
16
16
|
const inspectorPath = path.join(scriptDir, 'project_route_inspector.sh');
|
|
@@ -373,32 +373,8 @@ function runUnixInspector(args, failureContext, jsonContext) {
|
|
|
373
373
|
return parseSingleJson(inspected.stdout, jsonContext);
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
-
function
|
|
377
|
-
|
|
378
|
-
if (!homeInput) throw new Error('无法确定用户目录;请提供明确的新项目路径');
|
|
379
|
-
const homePath = normalizeBasePath(homeInput);
|
|
380
|
-
const container = path.join(homePath, 'alipay-aipay-projects');
|
|
381
|
-
if (fs.existsSync(container)) {
|
|
382
|
-
const stat = fs.lstatSync(container);
|
|
383
|
-
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
384
|
-
throw new Error('默认项目父目录不可用;请提供明确的新项目路径');
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
for (let index = 1; index <= 50; index += 1) {
|
|
388
|
-
const suffix = index === 1 ? '' : `-${index}`;
|
|
389
|
-
const candidate = path.join(container, `pay-demo${suffix}`);
|
|
390
|
-
if (!fs.existsSync(candidate)) return candidate;
|
|
391
|
-
const stat = fs.lstatSync(candidate);
|
|
392
|
-
if (stat.isDirectory() && !stat.isSymbolicLink() && !hasDirectoryEntries(candidate)) return candidate;
|
|
393
|
-
}
|
|
394
|
-
throw new Error('默认项目目录已被占用;请提供明确的新项目路径');
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function parseNewProjectPath(input, targetPath) {
|
|
398
|
-
if (targetPath !== undefined) return sanitizeProjectInput(targetPath);
|
|
399
|
-
if (looksLikeExplicitPath(input)) return input;
|
|
400
|
-
if (isDefaultNewProjectRequest(input)) return defaultNewProjectPath();
|
|
401
|
-
throw new Error('自然语言新建请求必须由 Agent 解析后通过 --target-path 提供明确目标;禁止把用户原话当作目录名');
|
|
376
|
+
function parseNewProjectPath(projectPath) {
|
|
377
|
+
return sanitizeProjectInput(projectPath);
|
|
402
378
|
}
|
|
403
379
|
|
|
404
380
|
function normalizePotentialPath(candidate) {
|
|
@@ -830,13 +806,16 @@ function runResolveProject(args) {
|
|
|
830
806
|
if (!['existing', 'new'].includes(intent)) throw new Error('intent 非法,仅支持 existing、new');
|
|
831
807
|
const basePath = normalizeBasePath(required(args, 'base-path'));
|
|
832
808
|
const input = sanitizeProjectInput(required(args, 'project-input'));
|
|
809
|
+
if (args['target-path'] !== undefined) {
|
|
810
|
+
throw new Error('参数 --target-path 已移除;现有项目和新建项目都使用 --project-path 传递真实路径');
|
|
811
|
+
}
|
|
812
|
+
const pathInput = sanitizeProjectInput(required(args, 'project-path'));
|
|
833
813
|
|
|
834
814
|
if (intent === 'existing') {
|
|
835
|
-
if (args['target-path'] !== undefined) throw new Error('--target-path 仅支持 --intent new');
|
|
836
815
|
if (isExplicitNewProjectRequest(input)) {
|
|
837
816
|
throw new Error('明确新建项目请求必须使用 --intent new,不能改用当前项目');
|
|
838
817
|
}
|
|
839
|
-
const existingInput = parseExistingProjectPath(
|
|
818
|
+
const existingInput = parseExistingProjectPath(pathInput);
|
|
840
819
|
const candidate = currentProjectAliases.has(existingInput) ? basePath : resolveAgainstBase(existingInput, basePath);
|
|
841
820
|
const projectPath = fs.existsSync(candidate) ? fs.realpathSync(candidate) : candidate;
|
|
842
821
|
if (!fs.existsSync(projectPath) || !fs.statSync(projectPath).isDirectory()) {
|
|
@@ -846,7 +825,7 @@ function runResolveProject(args) {
|
|
|
846
825
|
const prefix = currentProjectAliases.has(existingInput)
|
|
847
826
|
? '当前目录不是可识别的项目根,不能直接作为现有项目扫描'
|
|
848
827
|
: '该路径未识别到项目根标记,不能确认是服务端项目根';
|
|
849
|
-
const searchBasePath = currentProjectAliases.has(
|
|
828
|
+
const searchBasePath = currentProjectAliases.has(existingInput) ? basePath : projectPath;
|
|
850
829
|
throw projectRootError(searchBasePath, prefix, basePath);
|
|
851
830
|
}
|
|
852
831
|
return JSON.stringify({
|
|
@@ -857,7 +836,7 @@ function runResolveProject(args) {
|
|
|
857
836
|
});
|
|
858
837
|
}
|
|
859
838
|
|
|
860
|
-
const newPathInput = parseNewProjectPath(
|
|
839
|
+
const newPathInput = parseNewProjectPath(pathInput);
|
|
861
840
|
if (currentProjectAliases.has(newPathInput)) {
|
|
862
841
|
throw new Error('新项目必须明确尚不存在或为空的子目录名');
|
|
863
842
|
}
|
|
@@ -1031,7 +1010,9 @@ function resolveFramework(args, projectPath, projectSelection, language) {
|
|
|
1031
1010
|
? sanitizeFramework(args.framework)
|
|
1032
1011
|
: '';
|
|
1033
1012
|
const suppliedSource = typeof args['framework-source'] === 'string' ? args['framework-source'] : '';
|
|
1034
|
-
if (suppliedSource && !frameworkSources.has(suppliedSource))
|
|
1013
|
+
if (suppliedSource && !frameworkSources.has(suppliedSource)) {
|
|
1014
|
+
throw new Error('framework-source 非法,仅支持 EXPLICIT、DEFAULT_NEW_PROJECT、PROJECT_INFERRED、PROJECT_STRUCTURE_FALLBACK');
|
|
1015
|
+
}
|
|
1035
1016
|
|
|
1036
1017
|
if (!suppliedSource) {
|
|
1037
1018
|
return suppliedFramework
|
|
@@ -1054,7 +1035,7 @@ function runFrameworkResolve(args) {
|
|
|
1054
1035
|
const language = normalizeLanguage(required(args, 'language'));
|
|
1055
1036
|
const projectSelection = required(args, 'project-selection');
|
|
1056
1037
|
if (!['NEW_PROJECT', 'PREPARED_NEW_PROJECT', 'CURRENT_PROJECT', 'OTHER_PROJECT'].includes(projectSelection)) {
|
|
1057
|
-
throw new Error('project-selection
|
|
1038
|
+
throw new Error('project-selection 非法,仅支持 CURRENT_PROJECT、OTHER_PROJECT、NEW_PROJECT、PREPARED_NEW_PROJECT');
|
|
1058
1039
|
}
|
|
1059
1040
|
let projectPath = '';
|
|
1060
1041
|
if (projectSelection === 'CURRENT_PROJECT' || projectSelection === 'OTHER_PROJECT') {
|
|
@@ -1066,6 +1047,10 @@ function runFrameworkResolve(args) {
|
|
|
1066
1047
|
}
|
|
1067
1048
|
|
|
1068
1049
|
function startConfirmationFacts(args) {
|
|
1050
|
+
const rootIntent = required(args, 'root-intent');
|
|
1051
|
+
if (!['integration_only', 'full_process'].includes(rootIntent)) {
|
|
1052
|
+
throw new Error('root-intent 仅支持 integration_only、full_process');
|
|
1053
|
+
}
|
|
1069
1054
|
const productType = required(args, 'product-type');
|
|
1070
1055
|
const mapping = productVariants[productType];
|
|
1071
1056
|
if (!mapping) throw new Error('product-type 非法,仅支持 aipay、webpay、apppay');
|
|
@@ -1098,6 +1083,7 @@ function startConfirmationFacts(args) {
|
|
|
1098
1083
|
}
|
|
1099
1084
|
|
|
1100
1085
|
return {
|
|
1086
|
+
rootIntent,
|
|
1101
1087
|
productType,
|
|
1102
1088
|
variant: mapping.variant,
|
|
1103
1089
|
productName,
|
|
@@ -1123,8 +1109,10 @@ function renderStartConfirmation(facts) {
|
|
|
1123
1109
|
});
|
|
1124
1110
|
}
|
|
1125
1111
|
|
|
1126
|
-
export function createStartConfirmation(args) {
|
|
1127
|
-
|
|
1112
|
+
export async function createStartConfirmation(args) {
|
|
1113
|
+
const facts = startConfirmationFacts(args);
|
|
1114
|
+
await startTelemetryRun(facts.rootIntent, facts.productType);
|
|
1115
|
+
return renderStartConfirmation(facts);
|
|
1128
1116
|
}
|
|
1129
1117
|
|
|
1130
1118
|
export function createChecklistScopeReceipt(productType, projectPath) {
|
|
@@ -1231,7 +1219,7 @@ function runProductClarify() {
|
|
|
1231
1219
|
function runProductUnsupported(args) {
|
|
1232
1220
|
return renderMessage('product.unsupported', 'DEFAULT', {
|
|
1233
1221
|
productName: required(args, 'product-name')
|
|
1234
|
-
}
|
|
1222
|
+
});
|
|
1235
1223
|
}
|
|
1236
1224
|
|
|
1237
1225
|
function runWindowsSandboxSetup() {
|
|
@@ -1313,12 +1301,6 @@ function checklistInputFromArgs(args) {
|
|
|
1313
1301
|
return input;
|
|
1314
1302
|
}
|
|
1315
1303
|
|
|
1316
|
-
function terminalReasonForChecklist(input) {
|
|
1317
|
-
if (input.overallResult === '通过') return 'completed';
|
|
1318
|
-
if (input.overallResult === '未通过' || input.blockingDefectState === 'PRESENT') return 'integration_blocked';
|
|
1319
|
-
return 'partial_with_remaining_actions';
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
1304
|
async function runChecklistResult(args) {
|
|
1323
1305
|
const variant = required(args, 'variant');
|
|
1324
1306
|
if (!['AIPAY', 'WEBPAY', 'APPPAY'].includes(variant)) throw new Error('variant 非法,仅支持 AIPAY、WEBPAY、APPPAY');
|
|
@@ -1361,17 +1343,8 @@ async function runChecklistResult(args) {
|
|
|
1361
1343
|
input.nextFlowReminder = '代码开发校验通过后将自动进入支付产品-产品开通;未通过时停留在代码开发。';
|
|
1362
1344
|
}
|
|
1363
1345
|
}
|
|
1346
|
+
emitStageMetricAsync('integration.complete_coding', { productType: variant.toLowerCase() });
|
|
1364
1347
|
const rendered = renderMessage('integration.checklist.result', variant, input);
|
|
1365
|
-
if (input.executionMode === '仅代码开发') {
|
|
1366
|
-
emitTerminalMetric({
|
|
1367
|
-
rootIntent: 'integration_only',
|
|
1368
|
-
productType: variant,
|
|
1369
|
-
...terminalMetricContextFromArgs(args, {
|
|
1370
|
-
rootIntent: 'integration_only',
|
|
1371
|
-
terminalReason: terminalReasonForChecklist(input)
|
|
1372
|
-
})
|
|
1373
|
-
});
|
|
1374
|
-
}
|
|
1375
1348
|
return rendered;
|
|
1376
1349
|
}
|
|
1377
1350
|
|
|
@@ -1386,7 +1359,7 @@ export async function runIntegrationMessageCli(argv = process.argv) {
|
|
|
1386
1359
|
return;
|
|
1387
1360
|
}
|
|
1388
1361
|
if (command === 'start-confirm') {
|
|
1389
|
-
console.log(createStartConfirmation(args));
|
|
1362
|
+
console.log(await createStartConfirmation(args));
|
|
1390
1363
|
process.stderr.write(`${internalPrefix}CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm\n`);
|
|
1391
1364
|
return;
|
|
1392
1365
|
}
|
|
@@ -4,7 +4,7 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import {
|
|
7
|
+
import { recordTelemetryUserInput } from './telemetry.mjs';
|
|
8
8
|
|
|
9
9
|
const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
|
|
10
10
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -125,7 +125,7 @@ export function runInteractionReplyCli(argv = process.argv) {
|
|
|
125
125
|
if (command !== 'confirm' || typeof args.reply !== 'string' || !args.reply) {
|
|
126
126
|
throw new Error('用法: interaction_reply.mjs confirm --reply <用户原始回复> --input-id <本地用户输入幂等键>');
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
recordTelemetryUserInput(required(args, 'input-id'));
|
|
129
129
|
const decision = isAffirmativeReply(args.reply) ? 'CONFIRMED' : 'REJECTED';
|
|
130
130
|
process.stderr.write(`${internalPrefix}REPLY_DECISION=${decision}\n`);
|
|
131
131
|
if (decision === 'REJECTED') process.exitCode = 2;
|
|
@@ -293,7 +293,6 @@ async function runDiscovery(args) {
|
|
|
293
293
|
const salesCode = required(args, 'sales-code');
|
|
294
294
|
if (salesCode !== productSalesCodes[productType]) throw new Error('sales-code 与 product-type 不匹配');
|
|
295
295
|
const reusedSigning = reusedSigningBranch(args, productType);
|
|
296
|
-
emitStageMetricAsync('onboarding.discovery.start', { productType });
|
|
297
296
|
|
|
298
297
|
const signingPromise = reusedSigning
|
|
299
298
|
? Promise.resolve(null)
|
|
@@ -324,6 +323,10 @@ async function runDiscovery(args) {
|
|
|
324
323
|
: { query_status: 'NOT_APPLICABLE', applicable: false },
|
|
325
324
|
application: applicationBranch(applicationResult)
|
|
326
325
|
};
|
|
326
|
+
if (envelope.signing.query_status === 'SUCCESS'
|
|
327
|
+
&& (envelope.signing.sign_status === 'SIGNED_EFFECTIVE' || envelope.signing.sign_status === 'SIGN_SUBMITTED')) {
|
|
328
|
+
emitStageMetricAsync('onboarding.confirm_signing', { productType });
|
|
329
|
+
}
|
|
327
330
|
if (globalBlocker) {
|
|
328
331
|
envelope.global_blocker = globalBlocker;
|
|
329
332
|
envelope.auth_recovery_action = recoveryAction;
|
|
@@ -13,9 +13,7 @@ import {
|
|
|
13
13
|
} from './render_customer_message.mjs';
|
|
14
14
|
import {
|
|
15
15
|
currentRunContext,
|
|
16
|
-
|
|
17
|
-
emitTerminalMetric,
|
|
18
|
-
terminalMetricContextFromArgs
|
|
16
|
+
startTelemetryRun,
|
|
19
17
|
} from './telemetry.mjs';
|
|
20
18
|
|
|
21
19
|
const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
|
|
@@ -159,12 +157,31 @@ async function readStdin() {
|
|
|
159
157
|
function runPlatformEntry(args = {}) {
|
|
160
158
|
if (!isWindowsPlatform()) return '';
|
|
161
159
|
const runContext = currentRunContext();
|
|
162
|
-
if (
|
|
160
|
+
if (runContext?.terminal) {
|
|
161
|
+
throw new Error('Windows 产品开通引导缺少有效的当前 Onboarding run context');
|
|
162
|
+
}
|
|
163
|
+
const rootIntent = runContext?.root_intent || process.env.ALIPAY_AIPAY_ROOT_INTENT || process.env.ROOT_INTENT || '';
|
|
164
|
+
if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
165
|
+
throw new Error('Windows 产品开通引导缺少有效的当前 Onboarding run context');
|
|
166
|
+
}
|
|
167
|
+
const platformId = runContext?.run_id
|
|
168
|
+
|| platformIdFromEnv(process.env)
|
|
169
|
+
|| '';
|
|
170
|
+
if (!platformId) {
|
|
163
171
|
throw new Error('Windows 产品开通引导缺少有效的当前 Onboarding run context');
|
|
164
172
|
}
|
|
165
173
|
return renderMessage('onboarding.windows.redirect', 'DEFAULT', {
|
|
166
|
-
officialUrl: buildWindowsOnboardingRedirectUrl(
|
|
167
|
-
}
|
|
174
|
+
officialUrl: buildWindowsOnboardingRedirectUrl(platformId)
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function platformIdFromEnv(env = process.env) {
|
|
179
|
+
const candidate = env.COZE_PROJECT_ID
|
|
180
|
+
|| env.MEOO_PROJECT_ID
|
|
181
|
+
|| (env.MIAODA ? env.VITE_APP_ID || env.PLATFORM_ID || '' : '');
|
|
182
|
+
return typeof candidate === 'string' && candidate && !/[\u0000-\u001f\u007f,^=]/u.test(candidate)
|
|
183
|
+
? candidate
|
|
184
|
+
: '';
|
|
168
185
|
}
|
|
169
186
|
|
|
170
187
|
function parseJsonArg(args, name, label) {
|
|
@@ -188,15 +205,13 @@ function runEnterpriseUnsupported(args) {
|
|
|
188
205
|
return renderMessage(
|
|
189
206
|
'onboarding.enterprise.unsupported',
|
|
190
207
|
variant,
|
|
191
|
-
{}
|
|
192
|
-
terminalMetricContextFromArgs(args, { terminalReason: 'enterprise_account_unsupported' })
|
|
208
|
+
{}
|
|
193
209
|
);
|
|
194
210
|
}
|
|
195
211
|
|
|
196
212
|
async function runMccClarify(args) {
|
|
197
213
|
const productType = required(args, 'product-type');
|
|
198
214
|
const product = productFor({ ...args, 'product-type': productType });
|
|
199
|
-
emitStageMetricAsync('onboarding.mcc_prepare.start', { productType });
|
|
200
215
|
return renderMessage('onboarding.mcc.clarify', 'DEFAULT', {
|
|
201
216
|
productName: product.productName
|
|
202
217
|
}, { productType });
|
|
@@ -693,8 +708,13 @@ function requireCustomerMessageDelivery(messageId, message) {
|
|
|
693
708
|
}
|
|
694
709
|
|
|
695
710
|
async function runPlanConfirm(args) {
|
|
711
|
+
const rootIntent = required(args, 'root-intent');
|
|
712
|
+
if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
713
|
+
throw new Error('root-intent 仅支持 onboarding_only、full_process');
|
|
714
|
+
}
|
|
696
715
|
const productType = required(args, 'product-type');
|
|
697
716
|
productFor({ ...args, 'product-type': productType });
|
|
717
|
+
await startTelemetryRun(rootIntent, productType);
|
|
698
718
|
const mccRunContext = captureMccRunContext();
|
|
699
719
|
return requireCustomerMessageDelivery('onboarding.plan.confirm', renderPlanConfirm(productType, {
|
|
700
720
|
mccCode: required(args, 'mcc-code'),
|
|
@@ -707,8 +727,11 @@ async function runPlanConfirm(args) {
|
|
|
707
727
|
async function runMccResolvePlan(args) {
|
|
708
728
|
const productType = required(args, 'product-type');
|
|
709
729
|
productFor({ ...args, 'product-type': productType });
|
|
730
|
+
const rootIntent = currentRunContext(process.env)?.root_intent || process.env.ALIPAY_AIPAY_ROOT_INTENT || process.env.ROOT_INTENT || '';
|
|
731
|
+
if (['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
732
|
+
await startTelemetryRun(rootIntent, productType);
|
|
733
|
+
}
|
|
710
734
|
const mccRunContext = captureMccRunContext();
|
|
711
|
-
emitStageMetricAsync('onboarding.mcc_prepare.start', { productType, runId: mccRunContext.runId });
|
|
712
735
|
const query = required(args, 'query');
|
|
713
736
|
const selected = optional(args, 'select');
|
|
714
737
|
const selectionReceipt = optional(args, 'selection-receipt');
|
|
@@ -1117,19 +1140,6 @@ function closeoutInputFromArgs(args) {
|
|
|
1117
1140
|
async function runCloseout(args) {
|
|
1118
1141
|
const variables = closeoutInputFromArgs(args);
|
|
1119
1142
|
const rendered = renderMessage('process.partial_result', 'DEFAULT', variables);
|
|
1120
|
-
const terminalReason = args['root-intent'] === 'full_process' && variables.integrationResult !== '已完成'
|
|
1121
|
-
? 'partial_with_remaining_actions'
|
|
1122
|
-
: variables.processResultTitle === '支付产品-产品开通已完成'
|
|
1123
|
-
? 'completed'
|
|
1124
|
-
: 'partial_with_remaining_actions';
|
|
1125
|
-
emitTerminalMetric({
|
|
1126
|
-
productName: variables.productName,
|
|
1127
|
-
rootIntent: args['root-intent'],
|
|
1128
|
-
...terminalMetricContextFromArgs(args, {
|
|
1129
|
-
rootIntent: args['root-intent'],
|
|
1130
|
-
terminalReason
|
|
1131
|
-
})
|
|
1132
|
-
});
|
|
1133
1143
|
return rendered;
|
|
1134
1144
|
}
|
|
1135
1145
|
|
|
@@ -5,7 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { isAffirmativeReply } from './interaction_reply.mjs';
|
|
8
|
-
import {
|
|
8
|
+
import { recordTelemetryUserInput } from './telemetry.mjs';
|
|
9
9
|
|
|
10
10
|
const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
|
|
11
11
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -34,7 +34,7 @@ function required(args, name) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function assertRegisteredReply(args, kind) {
|
|
37
|
-
|
|
37
|
+
recordTelemetryUserInput(required(args, 'input-id'));
|
|
38
38
|
if (!isAffirmativeReply(required(args, 'reply'))) {
|
|
39
39
|
process.stderr.write(`${internalPrefix}RECOVERY_INPUT_REJECTED=${kind}\n`);
|
|
40
40
|
process.exitCode = 2;
|
|
@@ -238,7 +238,7 @@ function expectedMccRunIdFromContext(context = {}) {
|
|
|
238
238
|
|
|
239
239
|
function assertCurrentMccRun(receiptPayload, env = process.env, expectedRunId = '') {
|
|
240
240
|
const currentRunId = normalizeExpectedMccRunId(expectedRunId) || activeMccRunId(env);
|
|
241
|
-
if (
|
|
241
|
+
if (receiptPayload.run_id && receiptPayload.run_id !== currentRunId) {
|
|
242
242
|
throw new Error('MCC 上下文回执不属于当前 run');
|
|
243
243
|
}
|
|
244
244
|
}
|
|
@@ -904,7 +904,7 @@ const managedEntrypoints = {
|
|
|
904
904
|
reason: 'runner 按真实平台输出。'
|
|
905
905
|
},
|
|
906
906
|
'integration.start.confirm': {
|
|
907
|
-
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>',
|
|
907
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --root-intent <integration_only|full_process> --product-type <aipay|webpay|apppay> --project-path <absPath> --project-selection <CURRENT_PROJECT|OTHER_PROJECT|PREPARED_NEW_PROJECT> --language <language> --framework <framework>',
|
|
908
908
|
reason: '绑定同次项目扫描事实。'
|
|
909
909
|
},
|
|
910
910
|
'integration.checklist.result': {
|
|
@@ -932,7 +932,7 @@ const managedEntrypoints = {
|
|
|
932
932
|
reason: 'runner 执行发现并输出摘要。'
|
|
933
933
|
},
|
|
934
934
|
'onboarding.plan.confirm': {
|
|
935
|
-
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query <经营描述|MCC编码> --product-type <aipay|webpay|apppay>,或已持有唯一动态 MCC 回执时使用 onboarding-message plan-confirm --product-type <...> --mcc-code <...> --mcc-name <...> --mcc-qualification <...> --mcc-context-receipt <...>',
|
|
935
|
+
command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query <经营描述|MCC编码> --product-type <aipay|webpay|apppay>,或已持有唯一动态 MCC 回执时使用 onboarding-message plan-confirm --root-intent <onboarding_only|full_process> --product-type <...> --mcc-code <...> --mcc-name <...> --mcc-qualification <...> --mcc-context-receipt <...>',
|
|
936
936
|
reason: 'mcc.sh 绑定当前产品支持类目、详情和特殊资质;plan-confirm 只用于已验证唯一事实。'
|
|
937
937
|
},
|
|
938
938
|
'materials.category.collect': {
|
|
@@ -5,6 +5,8 @@ import path from 'node:path';
|
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
|
|
8
|
+
import { startTelemetryRun } from './telemetry.mjs';
|
|
9
|
+
|
|
8
10
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
9
11
|
const referencesDir = path.resolve(scriptDir, '../..');
|
|
10
12
|
const flowDirs = Object.freeze({
|
|
@@ -128,25 +130,12 @@ function assertEnumOption(options, name, allowedValues, { required = true } = {}
|
|
|
128
130
|
return value;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
function appendOptionalTerminalCountOptions(targetArgs, options) {
|
|
132
|
-
for (const name of ['user-input-count-total', 'user-input-count-after-flow-start', 'flow-start-observed']) {
|
|
133
|
-
if (Object.prototype.hasOwnProperty.call(options, name)) targetArgs.push(`--${name}`, requiredOption(options, name));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function startTelemetryRun(rootIntent, productType, inputId = '') {
|
|
138
|
-
const telemetryArgs = ['start-run', '--root-intent', rootIntent];
|
|
139
|
-
if (productType) telemetryArgs.push('--product-type', productType);
|
|
140
|
-
if (inputId) telemetryArgs.push('--input-id', inputId);
|
|
141
|
-
const { runTelemetryCli } = await import('./telemetry.mjs');
|
|
142
|
-
await runTelemetryCli(cliArgv(telemetryArgs));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
133
|
async function runIntegrationBootstrap(args) {
|
|
146
134
|
const options = parseRuntimeArgs(args);
|
|
147
135
|
assertOnlyOptions(options, ['root-intent', 'product-type', 'input-id']);
|
|
148
136
|
const rootIntent = assertEnumOption(options, 'root-intent', ['integration_only']);
|
|
149
137
|
const productType = assertEnumOption(options, 'product-type', ['aipay', 'webpay', 'apppay'], { required: false });
|
|
138
|
+
process.env.ALIPAY_AIPAY_ROOT_INTENT = rootIntent;
|
|
150
139
|
await startTelemetryRun(rootIntent, productType, options['input-id']);
|
|
151
140
|
const { runFlowCli } = await import('./flow_loader.mjs');
|
|
152
141
|
runFlowCli(cliArgv(['integration', 'entry']));
|
|
@@ -154,20 +143,13 @@ async function runIntegrationBootstrap(args) {
|
|
|
154
143
|
|
|
155
144
|
async function runOnboardingBootstrap(args) {
|
|
156
145
|
const options = parseRuntimeArgs(args);
|
|
157
|
-
assertOnlyOptions(options, [
|
|
158
|
-
'root-intent',
|
|
159
|
-
'product-type',
|
|
160
|
-
'input-id',
|
|
161
|
-
'user-input-count-total',
|
|
162
|
-
'user-input-count-after-flow-start',
|
|
163
|
-
'flow-start-observed'
|
|
164
|
-
]);
|
|
146
|
+
assertOnlyOptions(options, ['root-intent', 'product-type', 'input-id']);
|
|
165
147
|
const rootIntent = assertEnumOption(options, 'root-intent', ['onboarding_only']);
|
|
166
148
|
const productType = assertEnumOption(options, 'product-type', ['aipay', 'webpay', 'apppay'], { required: false });
|
|
149
|
+
process.env.ALIPAY_AIPAY_ROOT_INTENT = rootIntent;
|
|
167
150
|
await startTelemetryRun(rootIntent, productType, options['input-id']);
|
|
168
151
|
const { runOnboardingMessageCli } = await import('./onboarding_message_runner.mjs');
|
|
169
152
|
const platformEntryArgs = ['platform-entry'];
|
|
170
|
-
appendOptionalTerminalCountOptions(platformEntryArgs, options);
|
|
171
153
|
await runOnboardingMessageCli(cliArgv(platformEntryArgs));
|
|
172
154
|
const { isWindowsPlatform } = await import('./platform_compat.mjs');
|
|
173
155
|
if (isWindowsPlatform()) return;
|