@alipay/alipay-aipay 1.6.9-beta → 1.6.9-beta2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alipay/alipay-aipay",
3
- "version": "1.6.9-beta",
3
+ "version": "1.6.9-beta2",
4
4
  "description": "支付宝 AI 付接入 Skill 安装包 - 优先安装 Agent Skill,并在 macOS/Linux 后台准备用户级 CLI 工具",
5
5
  "type": "module",
6
6
  "bin": {
package/skill/VERSION CHANGED
@@ -1 +1 @@
1
- 1.6.9-beta
1
+ 1.6.9-beta2
@@ -1,7 +1,16 @@
1
+ const MAX_PLATFORM_LENGTH = 40;
2
+ const ASCII_PLATFORM_RE = /^[a-z0-9.]{1,40}$/u;
3
+
1
4
  export function normalizeAgentPlatform(value) {
2
- const normalized = String(value || '').trim().toLowerCase().replace(/[_\s-]/gu, '');
5
+ const normalizedInput = String(value || '').normalize('NFKC');
6
+ if (/\p{C}/u.test(normalizedInput)) return 'unknown';
7
+ const raw = normalizedInput.trim();
8
+ if (!raw || [...raw].length > MAX_PLATFORM_LENGTH || /[\\/:@?#%]/u.test(raw)) return 'unknown';
9
+
10
+ const normalized = raw.toLowerCase().replace(/[_\s-]/gu, '');
3
11
  if (normalized === 'claude') return 'claudecode';
4
- return /^[a-z0-9.]{1,40}$/u.test(normalized) ? normalized : 'unknown';
12
+ if (ASCII_PLATFORM_RE.test(normalized)) return normalized;
13
+ return /[\p{L}\p{M}\p{N}]/u.test(raw) ? raw : 'unknown';
5
14
  }
6
15
 
7
16
  // Consume host context before dispatch so Node runners and Shell children share it.
@@ -162,22 +162,30 @@ emit_control_field() {
162
162
  }
163
163
 
164
164
  init_dev_tool_name() {
165
- if [ -n "${DEV_TOOL_NAME:-}" ] && [ "$DEV_TOOL_NAME" != "unknown" ]; then
166
- export DEV_TOOL_NAME
167
- return
168
- fi
169
-
165
+ local EXISTING_DEV_TOOL_NAME="${DEV_TOOL_NAME:-}"
166
+ local AGENT_PLATFORM="${ALIPAY_AIPAY_AGENT_PLATFORM:-}"
170
167
  local COMMON_DIR
171
168
  COMMON_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
172
169
  local DETECT_SCRIPT="${COMMON_DIR}/detect_dev_tool.sh"
170
+ local DETECTED_DEV_TOOL_NAME="unknown"
173
171
 
174
172
  if [ -f "$DETECT_SCRIPT" ]; then
175
173
  # shellcheck source=/dev/null
176
174
  source "$DETECT_SCRIPT"
177
- DEV_TOOL_NAME="$(detect_dev_tool 2>/dev/null || echo unknown)"
175
+ if { [ -n "$AGENT_PLATFORM" ] && [ "$AGENT_PLATFORM" != "unknown" ]; } \
176
+ || { [ -z "$EXISTING_DEV_TOOL_NAME" ] || [ "$EXISTING_DEV_TOOL_NAME" = "unknown" ]; }; then
177
+ DETECTED_DEV_TOOL_NAME="$(detect_dev_tool 2>/dev/null || echo unknown)"
178
+ fi
178
179
  fi
179
180
 
180
- export DEV_TOOL_NAME="${DEV_TOOL_NAME:-unknown}"
181
+ if [ -n "$DETECTED_DEV_TOOL_NAME" ] && [ "$DETECTED_DEV_TOOL_NAME" != "unknown" ]; then
182
+ DEV_TOOL_NAME="$DETECTED_DEV_TOOL_NAME"
183
+ elif [ -n "$EXISTING_DEV_TOOL_NAME" ] && [ "$EXISTING_DEV_TOOL_NAME" != "unknown" ]; then
184
+ DEV_TOOL_NAME="$EXISTING_DEV_TOOL_NAME"
185
+ else
186
+ DEV_TOOL_NAME="unknown"
187
+ fi
188
+ export DEV_TOOL_NAME
181
189
  }
182
190
 
183
191
  init_root_intent_context() {
@@ -28,6 +28,10 @@ detect_dev_tool() {
28
28
  echo "codex"
29
29
  return
30
30
  fi
31
+ if [ -n "$OPENCLAW_SESSION_ID" ] || [ -n "$OPENCLAW_AGENT_ID" ]; then
32
+ echo "openclaw"
33
+ return
34
+ fi
31
35
  if [ -n "$TRAE_BRAND_NAME" ]; then
32
36
  echo "traeSolo"
33
37
  return
@@ -40,9 +44,11 @@ detect_dev_tool() {
40
44
  echo "qoder"
41
45
  return
42
46
  fi
43
- # The gateway supplies a normalized host identity from the Agent context.
44
- if [[ "${ALIPAY_AIPAY_AGENT_PLATFORM:-}" =~ ^[a-z0-9.]{1,40}$ ]]; then
45
- echo "$ALIPAY_AIPAY_AGENT_PLATFORM"
47
+ # The gateway supplies a validated, readable host identity from the Agent context.
48
+ local agent_platform="${ALIPAY_AIPAY_AGENT_PLATFORM:-}"
49
+ if [ -n "$agent_platform" ] && [ "$agent_platform" != "unknown" ] \
50
+ && [[ ! "$agent_platform" =~ [[:cntrl:]/\\:@?#%] ]]; then
51
+ echo "$agent_platform"
46
52
  return
47
53
  fi
48
54
  echo "unknown"
@@ -203,7 +203,8 @@ function shouldCloseRunAfterStage(event, state = {}) {
203
203
  return false;
204
204
  }
205
205
 
206
- const outboxRecordFields = new Set(['schema_ver', 'created_at', 'event']);
206
+ const outboxV1RecordFields = new Set(['schema_ver', 'created_at', 'event']);
207
+ const outboxV2RecordFields = new Set(['schema_ver', 'created_at', 'platform', 'event']);
207
208
  const metricEventFields = new Set([
208
209
  'schema_ver',
209
210
  'event_id',
@@ -509,8 +510,9 @@ function writeOutboxRecord(event, env = process.env) {
509
510
  const filename = outboxFilename(normalizedEvent);
510
511
  const finalPath = path.join(dir, filename);
511
512
  if (!writePrivateJson(finalPath, {
512
- schema_ver: 1,
513
+ schema_ver: 2,
513
514
  created_at: Date.now(),
515
+ platform: platformFromEnv(env),
514
516
  event: normalizedEvent
515
517
  })) return '';
516
518
  pruneOutbox(env);
@@ -922,10 +924,6 @@ function normalizeOS(platform = process.platform) {
922
924
  }
923
925
 
924
926
  export function platformFromEnv(env = process.env) {
925
- for (const key of ['ALIPAY_AIPAY_PLATFORM', 'AIPAY_AGENT_TYPE', 'DEV_TOOL_NAME', 'PLATFORM']) {
926
- const platform = normalizePlatform(env[key]);
927
- if (platform !== 'unknown') return platform;
928
- }
929
927
  if (env.CLAUDE_CODE_SESSION_ID || env.CLAUDE_SESSION_ID || env.CLAUDECODE || env.CLAUDE_CODE_ENTRYPOINT) return 'claudecode';
930
928
  if (env.OPENCLAW_SESSION_ID || env.OPENCLAW_AGENT_ID) return 'openclaw';
931
929
  if (env.CURSOR_TRACE_ID || env.CURSOR_SESSION_ID || env.CURSOR_AGENT || env.CURSOR_LAYOUT) return 'cursor';
@@ -935,7 +933,13 @@ export function platformFromEnv(env = process.env) {
935
933
  if (env.CODEX_CI || env.CODEX_THREAD_ID || env.CODEX_SESSION_ID || env.CODEX_SANDBOX_NETWORK_DISABLED !== undefined) return 'codex';
936
934
  if (env.TRAE_BRAND_NAME) return 'traesolo';
937
935
  if (env.QODER_CLI) return 'qoder';
938
- return normalizePlatform(env.ALIPAY_AIPAY_AGENT_PLATFORM);
936
+ const agentPlatform = normalizePlatform(env.ALIPAY_AIPAY_AGENT_PLATFORM);
937
+ if (agentPlatform !== 'unknown') return agentPlatform;
938
+ for (const key of ['ALIPAY_AIPAY_PLATFORM', 'AIPAY_AGENT_TYPE', 'DEV_TOOL_NAME', 'PLATFORM']) {
939
+ const platform = normalizePlatform(env[key]);
940
+ if (platform !== 'unknown') return platform;
941
+ }
942
+ return 'unknown';
939
943
  }
940
944
 
941
945
  function modelFromEnv(env = process.env) {
@@ -1092,7 +1096,7 @@ function normalizeMetricEvent(event) {
1092
1096
  return normalized;
1093
1097
  }
1094
1098
 
1095
- export function buildSyncLogReport(event, env = process.env) {
1099
+ export function buildSyncLogReport(event, env = process.env, dimensions = {}) {
1096
1100
  const normalizedEvent = normalizeMetricEvent(event);
1097
1101
  if (!normalizedEvent) return null;
1098
1102
  const skillVersion = skillVersionFromEvent(normalizedEvent);
@@ -1100,7 +1104,9 @@ export function buildSyncLogReport(event, env = process.env) {
1100
1104
  code: syncLogCode,
1101
1105
  msg: syncLogMsg,
1102
1106
  d1: normalizeOS(),
1103
- d2: platformFromEnv(env),
1107
+ d2: Object.prototype.hasOwnProperty.call(dimensions, 'platform')
1108
+ ? normalizePlatform(dimensions.platform)
1109
+ : platformFromEnv(env),
1104
1110
  d3: modelFromEnv(env),
1105
1111
  d4: skillVersion,
1106
1112
  d5: normalizedEvent.product_type || 'UNKNOWN',
@@ -1369,11 +1375,23 @@ function outboxTargetFilePending(file) {
1369
1375
  function readOutboxRecord(file) {
1370
1376
  try {
1371
1377
  const record = JSON.parse(fs.readFileSync(file, 'utf8'));
1372
- if (!hasOnlyFields(record, outboxRecordFields) || record.schema_ver !== 1) return null;
1378
+ if (record?.schema_ver === 1) {
1379
+ if (!hasOnlyFields(record, outboxV1RecordFields)) return null;
1380
+ } else if (record?.schema_ver === 2) {
1381
+ if (!hasOnlyFields(record, outboxV2RecordFields)) return null;
1382
+ if (typeof record.platform !== 'string' || normalizePlatform(record.platform) !== record.platform) return null;
1383
+ } else {
1384
+ return null;
1385
+ }
1373
1386
  if (!Number.isSafeInteger(record.created_at) || record.created_at <= 0) return null;
1374
1387
  const event = normalizeMetricEvent(record.event);
1375
1388
  if (!event) return null;
1376
- return { schema_ver: 1, created_at: record.created_at, event };
1389
+ return {
1390
+ schema_ver: record.schema_ver,
1391
+ created_at: record.created_at,
1392
+ ...(record.schema_ver === 2 ? { platform: record.platform } : {}),
1393
+ event
1394
+ };
1377
1395
  } catch {
1378
1396
  return null;
1379
1397
  }
@@ -1471,7 +1489,11 @@ export async function flushOutbox(env = process.env, {
1471
1489
  } catch {}
1472
1490
  continue;
1473
1491
  }
1474
- const report = buildSyncLogReport(record.event, env);
1492
+ const report = buildSyncLogReport(
1493
+ record.event,
1494
+ env,
1495
+ record.schema_ver === 2 ? { platform: record.platform } : {}
1496
+ );
1475
1497
  if (!report) {
1476
1498
  result.invalid += 1;
1477
1499
  try {
@@ -48,7 +48,7 @@ runtime 校验 active run、显式 `run_id`、clarify 已记录、stage 路线
48
48
 
49
49
  `c4/ext_info` 只允许 `user_input_after_clarify_intent`、`history_count`、`root_intent` 和 `progress_pct`。正式计数固定读取 event 生成锁内的 `counter_count`;不重复上传 `counter_count`。event 固定后,后续消息只影响后续 stage,不修改旧 event/c4。禁上传用户原文、input ID、文件名、路径、URL、密钥、账号、订单、截图、材料、授权信息、工具输出或堆栈原文。
50
50
 
51
- Yuyan 外层字段中的 `d1/d2/d3` 分别表示操作系统、宿主平台和模型。`d2` 先检查既有有效平台环境变量和自动识别信号,跳过 `unknown`/非法值;仍无法识别时使用 Agent 根据当前宿主身份随每条 runtime 命令传入的 `--agent-platform`(如 `WorkBuddy` 归一为 `workbuddy`),最后才为 `unknown`。gateway 将该上下文传给 Node 和 Shell 子进程,业务 CLI 的工具检测器也在自动识别失败时消费同一兜底,不写跨会话状态。模型只从显式模型上下文读取:优先 `ALIPAY_AIPAY_MODEL`,兼容 `AIPAY_MODEL`;runtime 将具体变体归一为 `gpt-5`、`gpt-4`、`claude`、`gemini`、`qwen`、`deepseek` 或 `llama` 等粗粒度家族。没有宿主模型字段或无法识别时使用 `unknown`,不得根据宿主平台名称臆测模型。Skill 脚本无法读取对话系统内部的模型上下文,宿主或 Agent 需要在调用 runtime 前提供该字段。
51
+ Yuyan 外层字段中的 `d1/d2/d3` 分别表示操作系统、宿主平台和模型。`d2` 优先使用当前宿主的明确自动识别信号,仍无法识别时使用 Agent 根据当前宿主身份随每条 runtime 命令传入的 `--agent-platform`;继承的通用平台变量只作为末级兼容值,不得遮蔽当前宿主。所有来源都跳过 `unknown`/非法值。该兜底不使用宿主名称枚举或映射表:ASCII 名称按既有规则归一,合法 Unicode 名称保留可读原文,最后才为 `unknown`。stage 进入 outbox 时固定当时的 `d2`,后续延迟上传或从其他宿主 flush 不得改变原事件归因;旧版 outbox 记录没有该快照时才按当前环境兼容生成。gateway 将该上下文传给 Node 和 Shell 子进程,业务 CLI 的工具检测器也按同一优先级消费,不写跨会话状态。模型只从显式模型上下文读取:优先 `ALIPAY_AIPAY_MODEL`,兼容 `AIPAY_MODEL`;runtime 将具体变体归一为 `gpt-5`、`gpt-4`、`claude`、`gemini`、`qwen`、`deepseek` 或 `llama` 等粗粒度家族。没有宿主模型字段或无法识别时使用 `unknown`,不得根据宿主平台名称臆测模型。Skill 脚本无法读取对话系统内部的模型上下文,宿主或 Agent 需要在调用 runtime 前提供该字段。
52
52
 
53
53
  ## 进度与上传
54
54
 
@@ -181,7 +181,7 @@ Step 1 的产品/MCC 唯一事实校验和方案送达、Step 2 的环境 READY
181
181
  ├─ AUTH_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION → 取得 CLI 私有状态目录权限后原样重试本命令一次
182
182
  ├─ AUTH_FLOW:LOGOUT_STILL_LOGGED_IN → 自动 mismatch 的 logout 后置条件未成立,按第 4 项同名分支停止
183
183
  └─ AUTH_FLOW:FAILED / 初始 mismatch 输出不满足唯一空 stdout 契约 → 停止并按错误输出恢复,禁止进入 Step 3.1
184
- 2. 仅 AUTH_FLOW:READY_TO_OPEN:独立送达 init stdout,再执行 node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth open --scope "$SCOPE" --sales-code "$SALES_CODE" --mcc-code "$MCC_CODE" --product-name "$PRODUCT_NAME" --mcc-name "$MCC_NAME" --mcc-context-receipt "$MCC_CONTEXT_RECEIPT" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"。 --agent-platform "<AGENT_PLATFORM>"`OPENED` stdout 为空;`OPEN_FAILED|GUI_UNAVAILABLE|LINK_ONLY` 时,宿主有内置浏览器打开/导航能力则用它打开本次已校验、已交付的同一 `officialUrl` 一次,禁止搜索、改写、自动填写或代替扫码。无该能力或仍失败时,执行 node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth manual-open 并独立送达 stdout。随后无需回复,执行 node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth wait --scope "$SCOPE" --sales-code "$SALES_CODE" --mcc-code "$MCC_CODE" --product-name "$PRODUCT_NAME" --mcc-name "$MCC_NAME" --mcc-context-receipt "$MCC_CONTEXT_RECEIPT" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT" --agent-platform "<AGENT_PLATFORM>"
184
+ 2. 仅 AUTH_FLOW:READY_TO_OPEN:独立送达 init stdout,再执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth open --scope "$SCOPE" --sales-code "$SALES_CODE" --mcc-code "$MCC_CODE" --product-name "$PRODUCT_NAME" --mcc-name "$MCC_NAME" --mcc-context-receipt "$MCC_CONTEXT_RECEIPT" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT" --agent-platform "<AGENT_PLATFORM>"`。`OPENED` stdout 为空;`OPEN_FAILED|GUI_UNAVAILABLE|LINK_ONLY` 时,宿主有内置浏览器打开/导航能力则用它打开本次已校验、已交付的同一 `officialUrl` 一次,禁止搜索、改写、自动填写或代替扫码。无该能力或仍失败时,执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth manual-open --agent-platform "<AGENT_PLATFORM>"` 并独立送达 stdout。随后无需回复,执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" auth wait --scope "$SCOPE" --sales-code "$SALES_CODE" --mcc-code "$MCC_CODE" --product-name "$PRODUCT_NAME" --mcc-name "$MCC_NAME" --mcc-context-receipt "$MCC_CONTEXT_RECEIPT" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT" --agent-platform "<AGENT_PLATFORM>"`
185
185
  ├─ open 返回 AUTH_FLOW:CONTEXT_MISMATCH → 不执行 wait;使用当前已确认的完整参数重新执行第 1 项
186
186
  ├─ open 返回 AUTH_FLOW:FAILED → 停止并按错误输出恢复,禁止执行 wait 或进入 Step 3.1
187
187
  ├─ AUTH_OPEN:OPENED|OPEN_FAILED|GUI_UNAVAILABLE|LINK_ONLY → 按上项完成宿主浏览器/手动提示降级后执行 wait;不影响已交付 URL
@@ -38,7 +38,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" render <messageId> --va
38
38
 
39
39
  首次路由前,Agent 在当前上下文自行回答“当前承载我的 Agent 工具叫什么”,从宿主明确身份、系统说明或当前工具上下文取得工具名称,记为 `AGENT_PLATFORM`(例如 `WorkBuddy`),不向用户提问、不把这段判断对客输出。不得把底层模型名称、项目名称、安装目录或用户举例当作当前宿主身份;无法确认时才使用 `unknown`。该事实仅保留当前对话,不写缓存;上下文丢失时重新判断。
40
40
 
41
- 从首条 bootstrap/start-run 起,本文件及所有 flow 登记的每条 runtime 命令均追加 `--agent-platform "<AGENT_PLATFORM>"`,将占位符替换为当前工具名称(例如 `--agent-platform "WorkBuddy"`);不使用环境变量前缀,不依赖前一次工具调用的进程环境。gateway 在业务参数解析前剥离此公共参数,规范化后传给当前进程及子进程。业务 CLI 的 `PLATFORM` 和遥测 Yuyan `d2` 各自优先沿用已有有效识别,只有识别不到时才采用此兜底;环境变量中的 `unknown` 或非法值不应提前终止遥测识别。工具名统一小写并去除空格、下划线和连字符,`WorkBuddy` 为 `workbuddy`;无法安全规范化仍为 `unknown`。该参数不改变业务确认、run_id、PLATFORM_ID 或模型字段。
41
+ 从首条 bootstrap/start-run 起,本文件及所有 flow 登记的每条 runtime 命令均追加 `--agent-platform "<AGENT_PLATFORM>"`,将占位符替换为当前工具名称;不使用环境变量前缀,不依赖前一次工具调用的进程环境。gateway 在业务参数解析前剥离此公共参数,规范化后传给当前进程及子进程。业务 CLI 的 `PLATFORM` 和遥测 Yuyan `d2` 优先使用当前宿主的明确自动识别信号,无法识别时采用本次命令的 Agent 宿名;继承的通用平台变量只能作为末级兼容值,不得遮蔽当前宿主。环境变量中的 `unknown` 或非法值不应提前终止遥测识别。该兜底不使用宿主名称枚举或映射表:纯 ASCII 名称统一小写并去除空格、下划线和连字符,合法 Unicode 名称保留可读原文;无法安全规范化仍为 `unknown`。该参数不改变业务确认、run_id、PLATFORM_ID 或模型字段。
42
42
 
43
43
  根 `SKILL.md` 启动器已经在读取本文件前确定本轮有效版本,并完成本对话所需的首次 `env refresh-alipay-cli` 或命中同路径、同版本的成功刷新事实。运行时禁止再次执行自更新、读取 `normal/self-update.md` 或切换其他副本;成功事实仍有效时不重复刷新 CLI,只按原始请求识别根意图并加载入口:
44
44