@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 +1 -1
- package/skill/VERSION +1 -1
- package/skill/references/normal/scripts/agent_platform.mjs +11 -2
- package/skill/references/normal/scripts/common.sh +15 -7
- package/skill/references/normal/scripts/detect_dev_tool.sh +9 -3
- package/skill/references/normal/scripts/telemetry.mjs +34 -12
- package/skill/references/normal/telemetry.md +1 -1
- package/skill/references/onboarding/flow.md +1 -1
- package/skill/references/runtime-entry.md +1 -1
package/package.json
CHANGED
package/skill/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.6.9-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
166
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
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 {
|
|
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(
|
|
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`
|
|
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"
|
|
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>"
|
|
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
|
|