@alipay/alipay-aipay 1.5.8-beta2 → 1.5.8-beta3

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.5.8-beta2",
3
+ "version": "1.5.8-beta3",
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.5.8-beta2
1
+ 1.5.8-beta3
@@ -203,6 +203,7 @@ Step 1 的产品/MCC 唯一事实校验和方案送达、Step 2 的环境 READY
203
203
  ├─ AUTH_FLOW:READY_TO_OPEN → 输出非阻塞授权页,执行第 2 项
204
204
  │ └─ 若同时存在 AUTH_STATE:SAVE_FAILED:授权页 stdout 已送达,后续 open 仅可降级为 AUTH_OPEN:LINK_ONLY;wait/confirm 仍使用本条命令显式上下文继续,禁止重新生成授权页
205
205
  ├─ 底层 init 命中 SCOPE_MISMATCH / MCC_MISMATCH → runtime 在同一命令内自动调用既有第 4 项,只透传 mismatch 的最终结果;唯一 AUTH_AUTO_MISMATCH 仅供内部诊断,不是终态
206
+ ├─ AUTH_FLOW:AUTH_REQUIRED → 当前失效会话已按脚本后置条件处理;原样重新执行第 1 项一次,生成当前上下文的新授权页;再次命中则停止循环
206
207
  ├─ AUTH_FLOW:RETRY_WITH_NETWORK → 取得联网权限后重试同一完整命令
207
208
  ├─ AUTH_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION → 取得 CLI 私有状态目录权限后原样重试本命令一次
208
209
  ├─ AUTH_FLOW:LOGOUT_STILL_LOGGED_IN → 自动 mismatch 的 logout 后置条件未成立,按第 4 项同名分支停止
@@ -216,6 +217,7 @@ Step 1 的产品/MCC 唯一事实校验和方案送达、Step 2 的环境 READY
216
217
  ├─ AUTH_FLOW:PENDING → 输出 auth.pending,等待用户明确表示扫码已完成
217
218
  ├─ AUTH_FLOW:EXPIRED → 重新执行第 1 项生成授权链接
218
219
  ├─ AUTH_FLOW:CONTEXT_MISMATCH → 当前动作未执行 login --complete/logout;使用当前已确认的完整参数重新执行第 1 项
220
+ ├─ AUTH_FLOW:AUTH_REQUIRED → 当前授权会话已失效,旧页面不再作为恢复依据;原样重新执行第 1 项一次,再次命中则停止循环
219
221
  ├─ AUTH_FLOW:RETRY_WITH_NETWORK → 取得联网权限后重试同一完整命令
220
222
  ├─ AUTH_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION → 保留当前授权页短时状态,取得 CLI 私有状态目录权限后原样重试当前 wait 命令一次
221
223
  ├─ AUTH_FLOW:FAILED → 停止并按错误输出恢复,禁止进入 Step 3.1
@@ -22,6 +22,7 @@
22
22
  - `AUTH_FLOW:PENDING`:有限轮询耗尽或单次恢复查询尚未得到有效本机登录态;不等于失败,也不证明用户未扫码。
23
23
  - `AUTH_FLOW:EXPIRED`:当前页面实际返回过期,旧页面和旧回复失效,重新执行 flow 登记的 init。
24
24
  - `AUTH_FLOW:SCOPE_MISMATCH|MCC_MISMATCH`:只能走 `auth.sh mismatch`。统一 runtime 的 `auth init` 在底层 init 唯一返回 mismatch 且 stdout 为空时,会在同一命令内自动调用既有 `auth.sh mismatch`,抑制中间 mismatch 终态并只透传最终结果;`wait|confirm` 返回 mismatch 时仍按 flow 显式调用 mismatch。logout 后置条件未成立前不得重授权;仍登录返回 `AUTH_FLOW:LOGOUT_STILL_LOGGED_IN`。
25
+ - `AUTH_FLOW:AUTH_REQUIRED`:`whoami` 或已认证资源校验已证明当前 CLI 会话失效,且脚本已完成既有 logout 后置条件处理;按 flow 原样重新执行当前上下文的 `auth init` 一次,旧授权页不再作为恢复依据,再次命中时停止循环。
25
26
  - `AUTH_FLOW:RETRY_WITH_NETWORK`:当前 Agent 环境无法确认结果,申请联网权限后原样重试同一命令;不得解释为用户本机登录失败。
26
27
  - `AUTH_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`:授权状态命令 preflight 失败,或实际输出命中 CLI 私有状态写失败证据。可恢复阶段 stdout 为空;仅允许当前受控 runtime 命令访问 CLI 私有状态目录后原样重试一次;`wait|confirm` 保留短时授权状态,不重建授权页。Agent 禁止读取、列举、打印或复制已有凭据与日志;拒绝、不支持或重试仍命中同一 marker 时才输出最小失败说明。
27
28
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  | 内部分类 | 已验证触发 | 恢复边界 |
8
8
  | --- | --- | --- |
9
- | `MCP_AUTH_ERROR` | HTTP 401、`Authorization is empty`、非法认证信息 | 停止查询组;logout 后置条件成立后重授权。仍登录则阻断;不可确认或无网络时只重试同一动作,不解释为用户本机或支付宝业务失败 |
9
+ | `MCP_AUTH_ERROR` | HTTP 401、`Authorization is empty`、非法认证信息、`用户未登录`、`not_logged_in` 等明确登录失效证据;已认证资源动作顶层或 `data.logged_in=false` | 停止查询组;logout 后置条件成立后重授权。仍登录则阻断;不可确认或无网络时只重试同一动作,不解释为用户本机或支付宝业务失败 |
10
10
  | `AUTH_MISMATCH` | `mccCode is not auth`、`salesProductCodes is not auth`、`scope is not auth` | 停止当前动作,只进 `auth.sh mismatch`;logout 后置条件未成立前禁重授权 |
11
11
  | `MCP_SERVICE_ERROR` / `SERVICE_UNSTABLE` | 已识别连接、网络或服务异常 | 按下方有限重试规则处理;耗尽后记录受影响分支,依赖允许时继续其他独立分支,最终统一收口 |
12
12
  | `DISCOVERY_FLOW:RETRY_WITH_NETWORK` | discovery 子查询重试耗尽,且原始输出包含 DNS、连接、timeout、socket/TLS、`fetch failed`、`network_error`、`网络连接失败` 或连接前沙箱禁网强证据 | 只在无授权阻断时输出一次;暂存首次 stdout,申请联网权限后原样重试同一 discovery 命令一次。拒绝、不支持或再次命中时停止申请,只送达最新一次既有 stdout |
@@ -17,7 +17,7 @@
17
17
  | `CLI_ERROR:<message>` | CLI 失败、异常结构或结果不可唯一解析 | 隐藏原始输出,停止并按登记 CLI 错误恢复,不猜成功或空结果 |
18
18
  | `SUCCESS` | 唯一合法成功结构 | 才允许进入当前脚本的业务字段解析 |
19
19
 
20
- 发现阶段的单分支失败不得伪装为空列表,也不得回滚其他已成功分支;认证失效或授权不匹配属于查询组全局阻断,重新授权后恢复尚未执行的查询,主体一致性无法确认时重新查询全部适用状态。
20
+ 发现阶段的单分支失败不得伪装为空列表,也不得回滚其他已成功分支;认证失效或授权不匹配属于查询组全局阻断,重新授权后恢复尚未执行的查询,主体一致性无法确认时重新查询全部适用状态。`logged_in=false` 只在已认证的签约、服务、应用和上传等资源动作中属于认证失效;`auth.sh whoami` 的成功未登录结果仍是正常登录入口,失败响应即使携带该字段也不能证明已退出。
21
21
 
22
22
  discovery runner 和截图上传这类并发/分组动作不得让每个子进程各自 logout。子脚本在分组环境下只上报认证失效事实;由 flow 登记的唯一授权恢复入口执行一次 logout 后置条件确认。三张截图同时认证失败时只允许产生一个全局认证恢复 marker。
23
23
 
@@ -324,7 +324,7 @@ query_security_key() {
324
324
  return 1
325
325
  fi
326
326
 
327
- if ! handle_error "$RESULT"; then
327
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
328
328
  return 1
329
329
  fi
330
330
 
@@ -353,7 +353,7 @@ query_application_info() {
353
353
  return 1
354
354
  fi
355
355
 
356
- if ! handle_error "$RESULT"; then
356
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
357
357
  return 1
358
358
  fi
359
359
 
@@ -590,7 +590,7 @@ app_list() {
590
590
  fi
591
591
 
592
592
  # 错误检测
593
- if ! handle_error "$RESULT"; then
593
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
594
594
  exit 1
595
595
  fi
596
596
 
@@ -701,7 +701,7 @@ app_create() {
701
701
  fi
702
702
 
703
703
  # 错误检测
704
- if ! handle_error "$RESULT"; then
704
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
705
705
  emit_control "APPLICATION_CREATE_RESULT=FAILED"
706
706
  exit 1
707
707
  fi
@@ -782,7 +782,7 @@ app_key() {
782
782
  fi
783
783
 
784
784
  # 错误检测
785
- if ! handle_error "$RESULT"; then
785
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
786
786
  emit_control "KEY_PAGE_RESULT=FAILED"
787
787
  exit 1
788
788
  fi
@@ -900,7 +900,7 @@ submit_application_audit() {
900
900
  fi
901
901
 
902
902
  # 错误检测
903
- if ! handle_error "$RESULT"; then
903
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
904
904
  emit_control "APPLICATION_AUDIT_RESULT=FAILED"
905
905
  exit 1
906
906
  fi
@@ -239,7 +239,7 @@ elif [ "$RETRY_RC" -ne 0 ]; then
239
239
  fi
240
240
 
241
241
  # 错误检测(先于业务解析,handle_error 内部会自动解包信封)
242
- if ! handle_error "$RESULT"; then
242
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
243
243
  emit_control "SIGN_APPLY_RESULT=FAILED"
244
244
  exit 1
245
245
  fi
@@ -529,9 +529,12 @@ validate_current_authorization() {
529
529
  }
530
530
 
531
531
  mcc_verify_unwrapped=$(unwrap_mcp "$mcc_verify_result")
532
- mcc_error_type=$(detect_error "$mcc_verify_result")
532
+ mcc_error_type=$(detect_error "$mcc_verify_result" "MCP_AUTHENTICATED_CALL")
533
533
  if [ "$mcc_error_type" = "AUTH_MISMATCH" ]; then
534
534
  mcc_match="false"
535
+ elif [ "$mcc_error_type" = "MCP_AUTH_ERROR" ]; then
536
+ handle_error "$mcc_verify_result" "MCP_AUTHENTICATED_CALL" || true
537
+ return 1
535
538
  elif [ "$mcc_error_type" != "SUCCESS" ]; then
536
539
  echo "❌ MCC 校验失败"
537
540
  emit_control "AUTH_FLOW:FAILED"
@@ -322,9 +322,11 @@ extract_checked_errors() {
322
322
 
323
323
  # ─── 统一错误检测 ──────────────────────────────────────────────────────────
324
324
  # 参数: $1 - CLI 执行结果文本(原始输出,含信封或不含)
325
+ # $2 - 可选调用上下文;MCP_AUTHENTICATED_CALL 允许识别资源响应中的明确未登录状态
325
326
  # 返回: MCP_AUTH_ERROR | MCP_SERVICE_ERROR | AUTH_MISMATCH | SERVICE_UNSTABLE | CLI_LOCAL_FS_PERMISSION | ERROR:xxx | CLI_ERROR:xxx | SUCCESS
326
327
  detect_error() {
327
328
  local CLI_RESULT="$1"
329
+ local ERROR_CONTEXT="${2:-}"
328
330
 
329
331
  # 空输入视为异常,不应被当作 SUCCESS
330
332
  if [ -z "$CLI_RESULT" ]; then
@@ -340,8 +342,93 @@ detect_error() {
340
342
  # 先解包 MCP 信封,再进行错误检测
341
343
  local UNWRAPPED=$(unwrap_mcp "$CLI_RESULT")
342
344
 
343
- # 1. 优先检测 MCP 认证错误
344
- if echo "$UNWRAPPED" | grep -qiE "HTTP 401|Authorization is empty|非法的认证信息"; then
345
+ # 1. 优先检测 MCP 认证错误。保留既有强证据;新增中文和 token 证据
346
+ # 仅扫描失败形态,避免成功候选名称或描述中的同名文本触发误判。
347
+ if echo "$UNWRAPPED" | grep -qiE \
348
+ "HTTP[[:space:]]*401|Authorization is empty|非法的认证信息"; then
349
+ echo "MCP_AUTH_ERROR"
350
+ return
351
+ fi
352
+
353
+ local AUTH_FAILURE_SHAPED=false
354
+ if ! echo "$UNWRAPPED" | jq -e . >/dev/null 2>&1 ||
355
+ echo "$UNWRAPPED" | jq -e '
356
+ (type == "object") and (
357
+ any(.. | objects; .success? == false) or
358
+ (.error? != null) or
359
+ (.errorCode? != null) or
360
+ ((.errorMessage? | type) == "string" and .errorMessage != "") or
361
+ ((.errorMsg? | type) == "string" and .errorMsg != "") or
362
+ (((.code? // "") | tostring) as $code |
363
+ $code != "" and $code != "0" and $code != "10000") or
364
+ any(.. | objects; (.error? != null) or (.errorCode? != null))
365
+ )
366
+ ' >/dev/null 2>&1; then
367
+ AUTH_FAILURE_SHAPED=true
368
+ fi
369
+ if [ "$AUTH_FAILURE_SHAPED" = "true" ] &&
370
+ echo "$UNWRAPPED" | grep -qiE \
371
+ "用户未登录|not[ _-]+logged[ _-]+in|(authorization|authentication|login)[-[:space:]_:=]+(is[-[:space:]_:=]+)?required|(access|auth|authentication|authorization)[ _-]+token[-[:space:]_:=]+(is[-[:space:]_:=]+)?(missing|expired)|(missing|expired)[-[:space:]_:=]+(access|auth|authentication|authorization)[ _-]+token"; then
372
+ echo "MCP_AUTH_ERROR"
373
+ return
374
+ fi
375
+
376
+ if echo "$UNWRAPPED" | jq -e --arg context "$ERROR_CONTEXT" '
377
+ def is_auth_code:
378
+ type == "string" and (
379
+ ascii_downcase as $code |
380
+ [
381
+ "not_logged_in",
382
+ "login_required",
383
+ "unauthenticated",
384
+ "authorization_required",
385
+ "auth_required",
386
+ "access_token_missing",
387
+ "access_token_expired",
388
+ "auth_token_missing",
389
+ "auth_token_expired"
390
+ ] |
391
+ index($code) != null
392
+ );
393
+ [
394
+ .code?, .errorCode?, .status?, .reason?,
395
+ (.error? | objects | (.code?, .errorCode?, .status?, .reason?)),
396
+ (.. | objects | .error? | objects | (.code?, .errorCode?, .status?, .reason?)),
397
+ (
398
+ .. | objects | select(has("errorCode")) | .errorCode? |
399
+ if type == "object" then (.code?, .status?, .reason?) else . end
400
+ )
401
+ ] +
402
+ (
403
+ if any(.. | objects; .success? == false) then
404
+ [.. | objects | (.code?, .status?, .reason?)]
405
+ else
406
+ []
407
+ end
408
+ ) +
409
+ (
410
+ if $context == "MCP_AUTHENTICATED_CALL" and (.data? | type) == "object" then
411
+ [.data.code?, .data.status?, .data.reason?]
412
+ else
413
+ []
414
+ end
415
+ ) |
416
+ any(is_auth_code)
417
+ ' >/dev/null 2>&1; then
418
+ echo "MCP_AUTH_ERROR"
419
+ return
420
+ fi
421
+
422
+ # whoami 的 logged_in=false 是正常登录入口事实,不能全局当作错误;仅已认证
423
+ # CLI/MCP 资源动作返回顶层或 data.logged_in=false 时提升为认证失效。
424
+ if [ "$ERROR_CONTEXT" = "MCP_AUTHENTICATED_CALL" ] &&
425
+ echo "$UNWRAPPED" | jq -e '
426
+ (type == "object") and (
427
+ ((.logged_in? | type) == "boolean" and .logged_in == false) or
428
+ ((.data? | type) == "object" and
429
+ (.data.logged_in? | type) == "boolean" and .data.logged_in == false)
430
+ )
431
+ ' >/dev/null 2>&1; then
345
432
  echo "MCP_AUTH_ERROR"
346
433
  return
347
434
  fi
@@ -647,10 +734,12 @@ handle_service_unstable() {
647
734
 
648
735
  # ─── 统一错误处理入口 ──────────────────────────────────────────────────────
649
736
  # 参数: $1 - CLI 执行结果文本(原始输出,含信封或不含)
737
+ # $2 - 可选调用上下文,透传给 detect_error
650
738
  # 返回: 0=成功, 1=当前动作失败(由主流程判断恢复、阻断或继续独立分支)
651
739
  handle_error() {
652
740
  local CLI_RESULT="$1"
653
- local ERROR_TYPE=$(detect_error "$CLI_RESULT")
741
+ local ERROR_CONTEXT="${2:-}"
742
+ local ERROR_TYPE=$(detect_error "$CLI_RESULT" "$ERROR_CONTEXT")
654
743
  # 解包一次供 CLI_ERROR 分支使用(其他分支由各自的 handler 自己解包)
655
744
  local _UNWRAPPED=$(unwrap_mcp "$CLI_RESULT")
656
745
 
@@ -85,7 +85,7 @@ if [ "$RETRY_RC" -ne 0 ]; then
85
85
  fi
86
86
 
87
87
  # 错误检测
88
- if ! handle_error "$RESULT"; then
88
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
89
89
  exit 1
90
90
  fi
91
91
 
@@ -107,7 +107,7 @@ fetch_service_page() {
107
107
  return 1
108
108
  fi
109
109
 
110
- if ! handle_error "$RESULT"; then
110
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
111
111
  return 1
112
112
  fi
113
113
 
@@ -385,7 +385,7 @@ service_save() {
385
385
  fi
386
386
 
387
387
  # 错误检测
388
- if ! handle_error "$RESULT"; then
388
+ if ! handle_error "$RESULT" "MCP_AUTHENTICATED_CALL"; then
389
389
  emit_control "SERVICE_SAVE_RESULT=FAILED"
390
390
  exit 1
391
391
  fi
@@ -84,7 +84,7 @@ wait
84
84
  # 解析图片引用值(兼容 file upload 返回 fileKey 或 URL 字段)
85
85
  parse_image_ref() {
86
86
  local RAW=$(cat "$1")
87
- if [ "$(detect_error "$RAW")" != "SUCCESS" ]; then
87
+ if [ "$(detect_error "$RAW" "MCP_AUTHENTICATED_CALL")" != "SUCCESS" ]; then
88
88
  return 1
89
89
  fi
90
90
  # alipay-cli file upload 可能返回 MCP 信封,先解包
@@ -122,11 +122,11 @@ PAY_REF=$(parse_image_ref "$TMP_PAY")
122
122
  check_upload_error() {
123
123
  local RAW=$(cat "$1")
124
124
  local ERROR_TYPE
125
- ERROR_TYPE=$(detect_error "$RAW")
125
+ ERROR_TYPE=$(detect_error "$RAW" "MCP_AUTHENTICATED_CALL")
126
126
  if [ "$ERROR_TYPE" = "MCP_AUTH_ERROR" ] && [ "${UPLOAD_AUTH_ERROR_SEEN:-false}" = "true" ]; then
127
127
  return 1
128
128
  fi
129
- if ! handle_error "$RAW"; then
129
+ if ! handle_error "$RAW" "MCP_AUTHENTICATED_CALL"; then
130
130
  if [ "$ERROR_TYPE" = "MCP_AUTH_ERROR" ]; then
131
131
  UPLOAD_AUTH_ERROR_SEEN=true
132
132
  fi