@alipay/alipay-aipay 1.7.6-beta.1 → 1.7.6

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.
Files changed (39) hide show
  1. package/bin/alipay-aipay.js +3 -2
  2. package/bin/windows-node-bootstrap.mjs +58 -0
  3. package/dist/commands/install-current.js +17 -1
  4. package/dist/commands/install.js +27 -3
  5. package/dist/commands/update.js +22 -5
  6. package/dist/utils/file.js +14 -6
  7. package/package.json +2 -2
  8. package/skill/SKILL.md +44 -11
  9. package/skill/VERSION +1 -1
  10. package/skill/references/normal/scripts/channel_offer.mjs +154 -94
  11. package/skill/references/normal/scripts/runtime.mjs +1 -0
  12. package/skill/references/normal/scripts/self_update.mjs +37 -4
  13. package/skill/references/normal/scripts/session_skill.mjs +98 -0
  14. package/skill/references/normal/scripts/windows/architecture.ps1 +55 -0
  15. package/skill/references/normal/scripts/windows/bootstrap-node.ps1 +174 -0
  16. package/skill/references/normal/self-update.md +10 -2
  17. package/skill-pre/SKILL.md +12 -7
  18. package/skill-pre/references/integration/flow.md +18 -18
  19. package/skill-pre/references/integration/modules/checklist.md +3 -3
  20. package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +27 -27
  21. package/skill-pre/references/normal/full-process-routing.md +1 -1
  22. package/skill-pre/references/normal/json/policy-rules.json +1 -1
  23. package/skill-pre/references/normal/scripts/alipay_cli_env.mjs +1 -1
  24. package/skill-pre/references/normal/scripts/preview_runtime.mjs +3 -2
  25. package/skill-pre/references/normal/scripts/runtime.mjs +6 -0
  26. package/skill-pre/references/normal/scripts/self_update.mjs +37 -4
  27. package/skill-pre/references/normal/scripts/session_skill.mjs +98 -0
  28. package/skill-pre/references/normal/scripts/windows/architecture.mjs +34 -0
  29. package/skill-pre/references/normal/scripts/windows/architecture.ps1 +55 -0
  30. package/skill-pre/references/normal/scripts/windows/bootstrap-node.ps1 +41 -7
  31. package/skill-pre/references/normal/scripts/windows/cli-install.mjs +1 -1
  32. package/skill-pre/references/normal/scripts/windows/preflight.mjs +3 -2
  33. package/skill-pre/references/normal/scripts/windows/routing.mjs +18 -4
  34. package/skill-pre/references/normal/self-update.md +10 -2
  35. package/skill-pre/references/normal/windows-environment.md +12 -4
  36. package/skill-pre/references/onboarding/flow.md +2 -0
  37. package/skill-pre/references/runtime-entry.md +1 -1
  38. package/skill/references/normal/json/npm-origin.json +0 -1
  39. package/skill-pre/references/normal/json/npm-origin.json +0 -1
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  if (process.platform === 'win32' && Number(process.versions.node.split('.')[0]) < 18) {
4
- console.error('Windows 安装需要 Node.js >=18 及其配套 npm/npx。请安装受支持的 Node.js LTS,重新打开终端后再执行安装命令:https://nodejs.org/en/download');
5
- process.exitCode = 1;
4
+ import('./windows-node-bootstrap.mjs').then(({bootstrapInstallerNode}) => {
5
+ process.exitCode=bootstrapInstallerNode();
6
+ }).catch(() => { process.exitCode=1; });
6
7
  } else {
7
8
  import('../dist/index.js').catch((err) => {
8
9
  console.error('Failed to start CLI:', err);
@@ -0,0 +1,58 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import {fileURLToPath} from 'node:url';
4
+ import {spawnSync} from 'node:child_process';
5
+
6
+ const entry=fileURLToPath(new URL('./alipay-aipay.js',import.meta.url));
7
+ const script=fileURLToPath(new URL('../skill-pre/references/normal/scripts/windows/bootstrap-node.ps1',import.meta.url));
8
+ const guidance='Windows 安装需要 Node.js >=18 及其配套 npm/npx。自动准备未完成,请按实际原因恢复后重试,或使用官方安装入口:https://nodejs.org/en/download';
9
+ const reasons={
10
+ DOWNLOAD_FAILED:'官方 Node 文件下载失败,请恢复网络后明确重试。',
11
+ INTEGRITY_FAILED:'Node 下载文件校验失败,未启用该文件。',
12
+ RETRY_BUDGET_EXHAUSTED:'自动准备次数已用尽;请修复环境后通过已下载包的 bootstrap-node.ps1 -Mode repair -RequireNpm 最多修复一次。',
13
+ ENVIRONMENT_BUSY:'另一项 Node 准备正在运行,请等待其结束。',
14
+ UNSUPPORTED_PLATFORM:'自动准备仅支持 Windows 原生 x64 环境。',
15
+ ARCHITECTURE_CHECK_FAILED:'无法确认本机架构,请恢复系统架构探测。',
16
+ };
17
+
18
+ // Runs before importing npm installer dependencies, including on Node 16.
19
+ // Only child PATH is changed; never replace the user's existing Node or policy.
20
+ export function bootstrapInstallerNode({args=process.argv.slice(2),env=process.env,
21
+ run=spawnSync,restart=spawnSync,exists=fs.existsSync,realpath=fs.realpathSync,write=s=>process.stderr.write(s)}={}) {
22
+ if (!['install','update','install-current'].includes(args[0]) || env.ALIPAY_AIPAY_NODE_BOOTSTRAPPED==='1') {
23
+ write(guidance+'\n'); return 1;
24
+ }
25
+ const ps=path.win32.join(env.SystemRoot||'C:\\Windows','System32/WindowsPowerShell/v1.0/powershell.exe');
26
+ const childEnv=Object.fromEntries(Object.entries(env).filter(([key])=>key.toLowerCase()!=='psmodulepath'));
27
+ const invoke=mode=>run(ps,['-NoProfile','-NonInteractive','-File',script,'-Mode',mode,'-RequireNpm'],
28
+ {encoding:'utf8',shell:false,windowsHide:true,env:childEnv,timeout:mode==='check'?120000:360000,maxBuffer:65536});
29
+ const parse=result=>{
30
+ if (result.error || ![0,78].includes(result.status)) throw Error('NODE_BOOTSTRAP_FAILED');
31
+ const lines=(result.stderr||'').split(/\r?\n/u).filter(line=>line.startsWith('ALIPAY_AIPAY_INTERNAL:NODE_BOOTSTRAP='));
32
+ if (lines.length!==1) throw Error('NODE_BOOTSTRAP_FAILED');
33
+ const value=JSON.parse(lines[0].slice('ALIPAY_AIPAY_INTERNAL:NODE_BOOTSTRAP='.length));
34
+ if ((value.status==='READY') !== (result.status===0)) throw Error('NODE_BOOTSTRAP_FAILED');
35
+ return value;
36
+ };
37
+ try {
38
+ let result=parse(invoke('check'));
39
+ if (result.status==='NEEDS_SETUP') {
40
+ write('正在用户目录准备独立的 Node.js LTS 和 npm/npx;保留已有 Node 安装。\n');
41
+ result=parse(invoke('prepare'));
42
+ }
43
+ if (result.status!=='READY' && reasons[result.reason]) {
44
+ write(reasons[result.reason]+'\n');
45
+ if (result.reason==='RETRY_BUDGET_EXHAUSTED') write(`引导脚本:${script}\n`);
46
+ }
47
+ if (result.status!=='READY' || !/^\d+\.\d+\.\d+$/u.test(result.version||'') || Number(result.version.split('.')[0])<18 ||
48
+ !path.isAbsolute(result.nodePath||'') || !exists(result.nodePath) || realpath(result.nodePath)!==result.nodePath) throw Error('NODE_BOOTSTRAP_FAILED');
49
+ const runtimeEnv={...env,ALIPAY_AIPAY_NODE_BOOTSTRAPPED:'1'};
50
+ const oldPath=Object.entries(runtimeEnv).find(([key])=>key.toLowerCase()==='path')?.[1]||'';
51
+ for (const key of Object.keys(runtimeEnv)) if (key.toLowerCase()==='path') delete runtimeEnv[key];
52
+ runtimeEnv.PATH=[path.dirname(result.nodePath),oldPath].join(';');
53
+ runtimeEnv.npm_node_execpath=result.nodePath;
54
+ runtimeEnv.npm_execpath=path.join(path.dirname(result.nodePath),'node_modules/npm/bin/npm-cli.js');
55
+ const launched=restart(result.nodePath,[entry,...args],{env:runtimeEnv,stdio:'inherit',shell:false,windowsHide:true});
56
+ return !launched.error && Number.isInteger(launched.status)?launched.status:1;
57
+ } catch { write(guidance+'\n'); return 1; }
58
+ }
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs/promises';
2
2
  import { getChannelConfig, getSkillVersion, readInstalledChannel, readInstalledVersion, skillVersionKind } from '../utils/channels.js';
3
3
  import path from 'path';
4
+ import { pathToFileURL } from 'url';
4
5
  import process from 'process';
5
6
  import { getCommandContextForTargetDir, PACKAGE_ROOT, } from '../utils/config.js';
6
7
  import { installSkillFilesAtPath, readVersionRecord, writeVersionRecordWithFallback, } from '../utils/file.js';
@@ -43,7 +44,22 @@ async function installBoundCurrentSkill(target, transactionId, channel) {
43
44
  ? getCommandContextForTargetDir(path.dirname(skillDir), channel)
44
45
  : null;
45
46
  const previousRecord = context ? await readVersionRecord(context) : null;
46
- await installSkillFilesAtPath(PACKAGE_ROOT, skillDir, { transactionId, channel });
47
+ try {
48
+ await installSkillFilesAtPath(PACKAGE_ROOT, skillDir, { transactionId, channel });
49
+ }
50
+ catch (error) {
51
+ const failure = error;
52
+ if (process.platform !== 'win32' || !['BACKUP', 'TARGET_PREPARE'].includes(failure.phase || '') ||
53
+ !['EPERM', 'EACCES', 'EBUSY'].includes(failure.code || ''))
54
+ throw error;
55
+ const sessionModule = pathToFileURL(path.join(PACKAGE_ROOT, 'skill', 'references', 'normal', 'scripts', 'session_skill.mjs')).href;
56
+ const { createSessionSkill } = await import(sessionModule);
57
+ const packageVersion = JSON.parse(await fs.readFile(path.join(PACKAGE_ROOT, 'package.json'), 'utf8')).version;
58
+ const receipt = createSessionSkill({ sourceDir: path.join(PACKAGE_ROOT, channel === 'pre' ? 'skill-pre' : 'skill'), channel,
59
+ version: getSkillVersion(PACKAGE_ROOT, channel), packageVersion, targetDir: skillDir });
60
+ process.stderr.write(`ALIPAY_AIPAY_INTERNAL:SELF_UPDATE_SESSION_RESULT=${JSON.stringify(receipt)}\n`);
61
+ return;
62
+ }
47
63
  if (context && previousRecord) {
48
64
  await writeVersionRecordWithFallback(context, {
49
65
  ...previousRecord,
@@ -5,8 +5,9 @@ import { spawn } from 'child_process';
5
5
  import fs from 'fs';
6
6
  import os from 'os';
7
7
  import path from 'path';
8
+ import { pathToFileURL } from 'url';
8
9
  import { getCommandContext, getAllCommandContexts, detectCurrentAgentTarget, DEFAULT_TARGET, PACKAGE_ROOT, TARGET_DIRS, } from '../utils/config.js';
9
- import { ensureDir, installSkillFiles, readVersionRecord, writeVersionRecordWithFallback, } from '../utils/file.js';
10
+ import { installSkillFiles, readVersionRecord, writeVersionRecordWithFallback, } from '../utils/file.js';
10
11
  import { checkAlipayCli } from '../utils/alipay-cli.js';
11
12
  import { checkJq, isJqRequiredPlatform, resolveManagedJqAsset } from '../utils/jq.js';
12
13
  function resolveInstallPlan(cwd, target, channel) {
@@ -125,8 +126,26 @@ export async function installCommand(cwd, options = {}) {
125
126
  console.log(` 旧版本: ${existingRecord.version} 安装时间: ${existingRecord.installedAt}`);
126
127
  console.log('');
127
128
  }
128
- await ensureDir(ctx.targetDir);
129
- await installSkillFiles(PACKAGE_ROOT, ctx.targetDir, channel);
129
+ try {
130
+ await installSkillFiles(PACKAGE_ROOT, ctx.targetDir, channel);
131
+ }
132
+ catch (error) {
133
+ const failure = error;
134
+ if (process.platform !== 'win32' ||
135
+ path.resolve(ctx.targetDir) !== primaryTargetDir || !['BACKUP', 'TARGET_PREPARE'].includes(failure.phase || '') ||
136
+ !['EPERM', 'EACCES', 'EBUSY'].includes(failure.code || ''))
137
+ throw error;
138
+ const sessionModule = pathToFileURL(path.join(PACKAGE_ROOT, 'skill', 'references', 'normal', 'scripts', 'session_skill.mjs')).href;
139
+ const { createSessionSkill } = await import(sessionModule);
140
+ const receipt = createSessionSkill({ sourceDir: path.join(PACKAGE_ROOT, channel === 'pre' ? 'skill-pre' : 'skill'), channel, version,
141
+ packageVersion: JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8')).version,
142
+ targetDir: targetSkillDir });
143
+ spinner.warn(chalk.yellow('原 Skill 目录未更新;已准备仅供当前会话加载的新版副本。'));
144
+ console.log(`请当前 Agent 读取 ${path.join(receipt.skillDir, 'SKILL.md')} 并按该版本启动协议继续;后续命令使用此目录。下次会话仍可能加载原目录旧版。`);
145
+ const prefix = process.env.ALIPAY_AIPAY_CHANNEL_OFFER_INSTALL === '1' ? 'CHANNEL_SESSION_RESULT' : 'SKILL_SESSION_READY';
146
+ process.stderr.write(`ALIPAY_AIPAY_INTERNAL:${prefix}=${JSON.stringify(receipt)}\n`);
147
+ return;
148
+ }
130
149
  const record = {
131
150
  version,
132
151
  installedAt: new Date().toISOString(),
@@ -162,6 +181,11 @@ export async function installCommand(cwd, options = {}) {
162
181
  }
163
182
  console.log('');
164
183
  }
184
+ // Private receipt for the Windows channel handoff; public install output is unchanged.
185
+ if (channel === 'pre' && process.env.ALIPAY_AIPAY_CHANNEL_OFFER_INSTALL === '1') {
186
+ const skillDir = fs.realpathSync(path.join(primaryTargetDir, SKILL_NAME));
187
+ process.stderr.write(`ALIPAY_AIPAY_INTERNAL:CHANNEL_INSTALL_RESULT=${JSON.stringify({ channel, version, skillDir })}\n`);
188
+ }
165
189
  printSummary(alipayCliOk, jqOk, true, version, installedSkillDirs, skipTools, deferWindowsTools, jqRequired, jqPreparationSupported, backgroundPreparation);
166
190
  }
167
191
  catch (error) {
@@ -3,9 +3,11 @@ import semver from 'semver';
3
3
  import { getChannelConfig, getSkillVersion, readInstalledVersion, skillVersionKind } from '../utils/channels.js';
4
4
  import chalk from 'chalk';
5
5
  import path from 'path';
6
+ import fs from 'fs';
7
+ import { pathToFileURL } from 'url';
6
8
  import ora from 'ora';
7
9
  import { getCommandContext, getAllCommandContexts, PACKAGE_ROOT, } from '../utils/config.js';
8
- import { ensureDir, installSkillFiles, readVersionRecord, migrateVersionRecord, writeVersionRecordWithFallback, resolveInstalledSkillPaths, } from '../utils/file.js';
10
+ import { installSkillFiles, readVersionRecord, migrateVersionRecord, writeVersionRecordWithFallback, resolveInstalledSkillPaths, } from '../utils/file.js';
9
11
  import { checkForUpdates } from '../utils/npm.js';
10
12
  import { checkAlipayCli } from '../utils/alipay-cli.js';
11
13
  import { checkJq, isJqRequiredPlatform } from '../utils/jq.js';
@@ -14,14 +16,14 @@ export async function updateCommand(cwd, options = {}) {
14
16
  const target = options.target ?? 'auto';
15
17
  if (target === 'all') {
16
18
  for (const ctx of getAllCommandContexts(cwd, undefined, channel)) {
17
- await updateResolvedContext(ctx);
19
+ await updateResolvedContext(ctx, false);
18
20
  }
19
21
  return;
20
22
  }
21
23
  const ctx = getCommandContext(cwd, target, channel);
22
24
  await updateResolvedContext(ctx);
23
25
  }
24
- async function updateResolvedContext(ctx) {
26
+ async function updateResolvedContext(ctx, allowSessionFallback = true) {
25
27
  const channel = ctx.channel ?? 'stable';
26
28
  const { skillName: SKILL_NAME, displayName } = getChannelConfig(channel);
27
29
  const SKILLS = [{ name: SKILL_NAME, displayName }];
@@ -89,8 +91,23 @@ async function updateResolvedContext(ctx) {
89
91
  }
90
92
  // 开始更新
91
93
  const updateSpinner = ora('正在更新 Skill 文件...').start();
92
- await ensureDir(ctx.targetDir);
93
- await installSkillFiles(PACKAGE_ROOT, ctx.targetDir, channel);
94
+ try {
95
+ await installSkillFiles(PACKAGE_ROOT, ctx.targetDir, channel);
96
+ }
97
+ catch (error) {
98
+ const failure = error;
99
+ if (!allowSessionFallback || process.platform !== 'win32' || !['BACKUP', 'TARGET_PREPARE'].includes(failure.phase || '') ||
100
+ !['EPERM', 'EACCES', 'EBUSY'].includes(failure.code || ''))
101
+ throw error;
102
+ const { createSessionSkill } = await import(pathToFileURL(path.join(PACKAGE_ROOT, 'skill/references/normal/scripts/session_skill.mjs')).href);
103
+ const receipt = createSessionSkill({ sourceDir: path.join(PACKAGE_ROOT, channel === 'pre' ? 'skill-pre' : 'skill'), channel,
104
+ version: currentSkillVersion, packageVersion: JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8')).version,
105
+ targetDir: path.join(ctx.targetDir, SKILL_NAME) });
106
+ updateSpinner.warn('原 Skill 目录未更新;已准备仅供当前会话加载的新版副本。');
107
+ console.log(`请当前 Agent 读取 ${path.join(receipt.skillDir, 'SKILL.md')} 并按该版本启动协议继续;后续命令使用此目录。下次会话仍可能加载原目录旧版。`);
108
+ process.stderr.write(`ALIPAY_AIPAY_INTERNAL:SKILL_SESSION_READY=${JSON.stringify(receipt)}\n`);
109
+ return;
110
+ }
94
111
  // 更新版本记录:只记录当前包中所选 Skill 的版本。
95
112
  const newRecord = {
96
113
  version: currentSkillVersion,
@@ -287,13 +287,21 @@ export async function installSkillFilesAtPath(packageRoot, skillTargetDir, optio
287
287
  if (readInstalledChannel(resolvedSkillTargetDir) !== channel)
288
288
  throw new Error('禁止跨渠道覆盖 Skill');
289
289
  }
290
- await ensureDir(targetDir);
291
- const stagingDir = transactionId
292
- ? path.join(targetDir, `.${SKILL_NAME}-install-${transactionId}`)
293
- : await fs.mkdtemp(path.join(targetDir, `.${SKILL_NAME}-install-`));
290
+ let stagingDir;
291
+ try {
292
+ await ensureDir(targetDir);
293
+ stagingDir = transactionId
294
+ ? path.join(targetDir, `.${SKILL_NAME}-install-${transactionId}`)
295
+ : await fs.mkdtemp(path.join(targetDir, `.${SKILL_NAME}-install-`));
296
+ if (transactionId)
297
+ await fs.mkdir(stagingDir, { mode: 0o700 });
298
+ }
299
+ catch (error) {
300
+ if (process.platform === 'win32')
301
+ Object.assign(error, { phase: 'TARGET_PREPARE' });
302
+ throw error;
303
+ }
294
304
  const backupDir = path.join(targetDir, `.${SKILL_NAME}-backup-${transactionId || randomUUID()}`);
295
- if (transactionId)
296
- await fs.mkdir(stagingDir, { mode: 0o700 });
297
305
  let previousInstallMoved = false;
298
306
  let stagingCommitted = false;
299
307
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alipay/alipay-aipay",
3
- "version": "1.7.6-beta.1",
3
+ "version": "1.7.6",
4
4
  "description": "支付宝 AI 付接入 Skill 安装包 - 优先安装 Agent Skill,并在 macOS/Linux 后台准备用户级 CLI 工具",
5
5
  "type": "module",
6
6
  "bin": {
@@ -55,7 +55,7 @@
55
55
  "typescript": "^5.3.3"
56
56
  },
57
57
  "alipayAipayChannels": {
58
- "stable": "1.7.2",
58
+ "stable": "1.7.3",
59
59
  "pre": "1.7.5-pre"
60
60
  }
61
61
  }
package/skill/SKILL.md CHANGED
@@ -11,7 +11,27 @@ description: >-
11
11
 
12
12
  ## 前置启动协议
13
13
 
14
- 本目录的 `references/normal/json/release-channel.json` 固定当前渠道;正式版为 `stable`,预发版为 `pre`。自更新只比较 npm latest 元数据中的本渠道 Skill 版本与本地 `VERSION`,不以 npm 包版本判断是否需要更新,不切换或扫描另一渠道。缺少合法渠道元数据时保留当前版本。来自 npm beta 包的安装目录带有内部来源文件 `references/normal/json/npm-origin.json`,测试期间固定当前目录,不查询 latest、不自动升级或转正;常规版本仍只接收本渠道正式版本。此判断由同一自更新命令完成,Agent 不自行判断或修改 VERSION。
14
+ 首次使用 `npx.cmd -y @alipay/alipay-aipay@latest install` 前,需要本机先有能启动 npx 的 Node.js 及配套 npm/npx;若包已下载且安装器能运行,但 Windows Node 低于 18,安装器会在加载自身依赖前复用或准备独立的官方 Node LTS 并重新执行原命令一次。npm 的严格 engines 策略或过旧运行时若在包启动前拒绝执行,此包内恢复无法运行。Skill 业务仍要求 Node >=18;Node 执行 JavaScript,npm/npx 获取并启动安装包,不能互相替代。若命令无法启动,先在已授权范围内准备官方 Node.js LTS 并重新打开终端,或按组织策略让宿主发现已有工具;此时 Skill 尚未下载,不能声称包内引导已执行。不要为运行安装命令修改 PowerShell 执行策略;有配套工具时使用 `npx.cmd`。下列引导只用于已经落盘的 Skill。
15
+
16
+ Windows 优先复用本轮安装时已经验证合格的 Node 绝对路径,不要求它加入 PATH。只有尚未绑定本轮 Node 时,在下面的自更新前先尝试直接执行 PATH 中的 `node.exe -p "JSON.stringify({version:process.versions.node,platform:process.platform,arch:process.arch,executable:process.execPath})"`。只有退出 0、输出为唯一 JSON 对象、`platform=win32`、版本为合法且 >=18 的 SemVer、`executable` 是本机普通文件的规范化绝对路径时,才绑定该 Node 并跳过 PowerShell 文件引导。其他结果不作为可用 Node。此只读探测不执行业务、不访问会话正文、不改变采集选择。先确定当前 Skill 的规范化绝对路径 `<SKILL_DIR>`;PATH 探测未找到合格 Node 时,再用下列固定 PowerShell 引导检查常见安装目录及此前准备的用户级 Node:
17
+
18
+ ```powershell
19
+ powershell.exe -NoProfile -NonInteractive -File "<SKILL_DIR>/references/normal/scripts/windows/bootstrap-node.ps1" -Mode check
20
+ ```
21
+
22
+ 引导只接受唯一 stderr `ALIPAY_AIPAY_INTERNAL:NODE_BOOTSTRAP=<JSON>`。`status=READY` 且退出 0 时,校验 `nodePath` 为本机普通文件的规范化绝对路径、`version` 为合法且 >=18 的 SemVer,绑定该 Node。无论经哪个只读入口取得 Node,后续所有文档中的 `node` 均用绑定的绝对路径通过宿主进程参数数组调用。在 PowerShell 中使用 `& "<NODE_EXE>" "<SKILL_DIR>/references/normal/scripts/runtime.mjs" ...`;仅替换解释器,runtime 绝对路径及参数保持不变。不能依赖引导子进程更改父进程 PATH,不能因绑定 Node 重新执行已完成的自更新或采集选择。
23
+
24
+ 仅 `NEEDS_SETUP` 且当前请求已有依赖准备授权时执行一次:
25
+
26
+ ```powershell
27
+ powershell.exe -NoProfile -NonInteractive -File "<SKILL_DIR>/references/normal/scripts/windows/bootstrap-node.ps1" -Mode prepare
28
+ ```
29
+
30
+ 用户明确修复并要求重试时,最多一次使用同一入口 `-Mode repair`。该预算按用户目录保存,不随 Agent 重入清零。自动准备最多一次;只有用户明确修复并重试才额外 repair 一次。每个官方文件的临时网络故障最多请求两次,单次 30 秒;校验失败不重试下载。安装只下载官方 LTS Windows x64 ZIP 和官方 SHA-256 清单,校验后解压到用户目录;需要修复 npm/npx 工具链时,同一引导附加 `-RequireNpm`,独立验证配套 npm 和 npx 可运行;不覆盖已有 Node、不修改系统或用户 PATH、不提权、不改变执行策略。Windows PowerShell 5.1 的有效执行策略若禁止 `.ps1`,此引导在检查常见目录前就可能被阻止,不能承诺自动发现或准备 Node。此时请用户按组织策略让宿主可发现已安装的合格 Node,或从 [Node.js 官方下载页](https://nodejs.org/en/download) 安装并重启宿主;不得以 `Invoke-Expression`、执行策略覆盖、WSL 或循环安装绕过限制。脚本安装失败、版本校验失败或返回非 READY 时也停止启动并说明实际缺项。该入口用于已经存在的 Skill 目录;首次通过 npm/npx 获取 Skill 的用户仍需先有可用 Node/npm。
31
+
32
+
33
+
34
+ 本目录的 `references/normal/json/release-channel.json` 固定当前渠道;正式版为 `stable`,预发版为 `pre`。自更新只比较 npm latest 元数据中的本渠道 Skill 版本与本地 `VERSION`,不以 npm 包版本判断是否需要更新,不切换或扫描另一渠道。缺少合法渠道元数据时保留当前版本。 本地 beta 测试版本固定使用当前版本,不查询 npm、不自动升级或转正;常规版本只接收本渠道非 beta 版本。此判断由同一自更新命令完成,Agent 不自行判断或修改 VERSION。
15
35
 
16
36
  本次 Agent 对话首次使用 `alipay-aipay` 时,先把本文件所在目录解析为规范化绝对路径 `<SKILL_DIR>`,记录一次性事实 `ALIPAY_AIPAY_SELF_UPDATE_CHECKED=true`,再执行以下单条命令。`<SKILL_DIR>` 是执行时替换的路径占位符;禁止用 shell 变量赋值、命令替换或依赖特定 shell:
17
37
 
@@ -24,11 +44,16 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" self-update check --ski
24
44
  stderr 只允许出现以下一个内部终态;不得向用户展示 marker 或 npm/npx 原始输出:
25
45
 
26
46
  - `SELF_UPDATE:UPDATED=<合法 SemVer>`:当前 Skill 目录已原子切换到新版。
47
+ - `SELF_UPDATE:SESSION_READY=<合法 SemVer>`:全局目录未更新,已核验当前会话的新版本副本及路径。
27
48
  - `SELF_UPDATE:CURRENT=<合法 SemVer>`:继续当前版本。
28
49
  - `SELF_UPDATE:RETRY_WITH_NETWORK`:registry 或安装阶段网络不可达;可申请联网后原样重试本命令一次。
29
50
  - `SELF_UPDATE:SKIPPED_NETWORK_RESTRICTED|CHECK_FAILED|INSTALL_FAILED|VERIFY_FAILED`:静默继续当前可用版本,不重试、不申请权限。
30
51
 
31
- `UPDATED` 后先废弃旧 loaded 事实,禁止继续读取更新前版本的任何业务文档,后续命令使用新版同一 `SKILL_DIR`;其他终态继续当前可用版本,其他终态同样不再读取本启动器或 `self-update.md` 补充规则。
52
+ `UPDATED` 后先废弃旧 loaded 事实,禁止继续读取更新前版本的任何业务文档,后续命令使用新版同一 `SKILL_DIR`;除 `SESSION_READY` 外的其他终态继续当前可用版本,其他终态同样不再读取本启动器或 `self-update.md` 补充规则。
53
+
54
+ `SESSION_READY` 是 Windows 目录占用或权限失败的有限恢复:只有替换前的备份/暂存准备失败,安装器才从本次精确 npm 包创建并逐文件 SHA-256 复核独立副本;不混合覆盖原目录,不更新全局安装记录。必须同时取得唯一 `ALIPAY_AIPAY_INTERNAL:SELF_UPDATE_SESSION_SKILL_DIR=<JSON 字符串>`,用已核验的绝对路径重绑 `SKILL_DIR`,明确告知“全局目录未更新,当前会话使用已校验的新版本;下次会话仍可能加载旧版”。废弃旧 loaded/CLI 刷新事实,保留本渠道自更新已检查事实,立即读取新路径的 `SKILL.md` 并继续其余启动协议,禁止再次自更新。内测版仍需按新路径/版本完成声明及服务/采集选择,安装意图不得代替采集同意。路径 marker 缺失、冲突或新入口不可读时,不切换、不声称更新成功,使用仍可用的原目录或说明入口不可用。
55
+
56
+ 手工 npm 安装/更新遇到同类 Windows 故障时,只有安装器返回唯一 `SKILL_SESSION_READY` 回执并给出已校验的新 `SKILL.md` 路径才可加载该副本;仍须说明全局未更新并执行新启动协议。副本位于用户目录 `.alipay-aipay/session-skills`,不在 Agent 自动发现目录内;不注册为全局版本、不扫描其他已安装副本、不在使用中自动删除。副本自更新验证本地内容后固定本次版本,后续全局更新仍需解除原目录占用/权限问题并重新安装。
32
57
 
33
58
  版本确定后、首次 CLI 刷新及任何业务入口之前,若当前对话没有绑定该正式版规范化路径的 `ALIPAY_AIPAY_CHANNEL_OFFER_RESOLVED=true`,先执行一次:
34
59
 
@@ -36,7 +61,7 @@ stderr 只允许出现以下一个内部终态;不得向用户展示 marker
36
61
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer show
37
62
  ```
38
63
 
39
- 非 Windows 只返回唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=SKIPPED`,不展示正文,记录已处理并继续。Windows 返回唯一 `WAITING` 时,必须先将 stdout 原文作为独立可见消息送达并等待用户回复;在该回复前不得刷新 CLI、加载业务入口、创建遥测 run 或安装内测版。同一对话后续根触发不重复展示。用户本轮原始请求已明确要求安装使用内测版时,该意图可作为当前提示的回复直接判定,无需再索取一次“确认”;其他情况只使用提示送达后的用户原始回复。判断仅使用:
64
+ 非 Windows 只返回唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=SKIPPED`,不展示正文,记录已处理并继续。Windows 返回唯一 `WAITING` 时,必须先将 stdout 原文作为独立可见消息送达并等待用户回复;在该回复前不得刷新 CLI、加载业务入口、创建遥测 run 或安装内测版。同一对话后续根触发不重复展示。用户本轮原始请求已明确要求安装使用内测版时,该意图可作为当前提示的回复直接判定,无需再索取一次“确认”;其他情况只使用提示送达后的用户原始回复。保留原始任务和已有材料;本轮安装意图只用于渠道选择,不代替后续采集同意、登录或业务写入授权。判断仅使用:
40
65
 
41
66
  ```text
42
67
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer decide --reply "<USER_REPLY>"
@@ -44,21 +69,29 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer decide --
44
69
 
45
70
  仅唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=PRE` 可进入内测安装;`STABLE` 表示继续本正式版,记录已处理并按下文刷新 CLI。`UNDECIDED` 表示用户在提问或表达不确定,先回答或澄清,仍等待明确选择;不能把业务催促、泛泛的“继续/OK/1”或通用 `reply confirm` 当作内测授权。任一错误或 marker 不唯一时停止渠道切换,禁止安装。用户以后明确提出切换时,可重新进行这一选择,不受已处理事实限制。
46
71
 
47
- `PRE` 后先执行固定只读预检。常规正式版核对 npm latest 的预发渠道是否包含 Windows 改造版;来自 npm beta 包的正式版只核对 npm `beta` 标签,要求包版本与当前安装来源文件一致、其中 stable 版本与当前 `VERSION` 一致,并包含支持 Windows 的内测版。两者均以线上事实为准,本地工作区或尚未发布的版本不能代替:
72
+ `PRE` 后先执行固定只读预检,确认 npm latest 的预发渠道已包含 Windows 改造版;本地当前工作区或尚未发布的版本不能代替线上事实:
48
73
 
49
74
  ```text
50
75
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer available
51
76
  ```
52
77
 
53
- 仅唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=AVAILABLE` 才安装。常规正式版仍执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer install --reply "<USER_REPLY>"`。来自 npm beta 包的正式版必须先取得唯一合法的 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER_PACKAGE_VERSION=<npm beta SemVer>` 和 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER_PRE_VERSION=<内测版 Skill 版本>`,再执行:
78
+ 仅唯一 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER=AVAILABLE` 才执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer install --reply "<USER_REPLY>"`,传入此前被判为 `PRE` 的同一条用户原始回复;安装器会在执行前再次确认明确选择和线上版本。Windows 优先复用当前 Node 附带或已有 npm 缓存中的 npm/npx JS 入口,其次查找现成 `.cmd` shim;缺少 npm 命令或 npm 查询进程失败时,版本核验最多回退一次只读查询 npm 官方 registry。此步骤不下载 Node、不创建临时 shim 或修改 PATH。`UNAVAILABLE|CHECK_FAILED`、安装失败与核验失败均按下方恢复规则处理。`CHANNEL_OFFER_REASON` 只用于解释实际失败类别,禁止展示原始内部 marker、npm 输出或敏感诊断。
54
79
 
55
- ```text
56
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" channel-offer install --reply "<USER_REPLY>" --expected-package-version "<核验得到的 npm beta 版本>" --expected-pre-version "<核验得到的内测版 Skill 版本>"
57
- ```
80
+ 安装入口优先依据当前正式版安装路径绑定同类 Agent 的 Home 安装目标,不让其他 Agent 的残留环境变量决定本轮加载目录。安装器在当前主目标成功或 Windows 已校验会话副本就绪后返回对应结构化结果;channel-offer 会复核实际目录的完整性、`pre` 渠道及 `VERSION` 与本次线上版本完全一致,来自 npm beta 包时还复核安装来源。只有安装退出码为 0、唯一 `CHANNEL_OFFER=INSTALLED|SESSION_READY`、唯一 `CHANNEL_OFFER_PRE_VERSION` 及唯一 `CHANNEL_OFFER_SKILL_DIR=<JSON 字符串>` 时,才从 JSON 字符串取得实际内测版绝对路径。禁止从安装计划、旧内测路径或“进程退出 0”推定成功。该目录须可由当前 Agent 读取;读取失败也按核验失败处理。
81
+
82
+ `SESSION_READY` 表示原全局内测目录未更新,当前会话从已校验的新路径加载;必须告知用户这个区别,不能称全局安装成功。正式版本身为会话副本时,渠道安装目标由已校验回执中的原 Agent 目标继承。
83
+
84
+ 校验通过后,在当前 Agent 上下文记录正式版渠道选择已处理及实际内测版路径,废弃正式版业务入口与 CLI 刷新事实,立即读取实际内测版的 `SKILL.md`,按其启动协议继续原任务。不能重新触发正式版推荐循环,不能继续旧内测副本,也不能把同意安装的回复复用为会话采集同意。内测版声明须完整展示并等待新的服务/采集选择;选择“仅使用服务”后照常继续任务。把原任务与安装授权一并保留给 Windows 环境入口,避免丢失已取得的依赖准备授权,但不代替登录或签约确认。
85
+
86
+ 恢复规则(预算仅保存在当前 Agent 对话上下文,不写业务状态):
58
87
 
59
- `USER_REPLY` 必须是此前判为 `PRE` 的同一条用户原始回复。安装器重新查询线上标签;包版本、正式版版本或内测版版本变化时在写入前停止,成功时使用核验所得精确 npm 包版本。Windows 优先复用当前 Node 附带或已有 npm 缓存中的 npm/npx JS 入口,其次查找现成 `.cmd` shim;缺少 npm 命令时版本核验可只读查询 npm 官方 registry。此步骤不下载 Node、不创建临时 shim 或修改 PATH。`UNAVAILABLE|CHECK_FAILED` 时说明线上内测版尚不可核实或尚未包含 Windows 能力,保留正式版并停在当前选择,不安装旧内测版;用户可明确要求继续正式版。核验器输出的内部 `CHANNEL_OFFER_REASON` 只用于区分工具、网络或元数据失败,不对客。仅安装退出码为 0 且唯一 `CHANNEL_OFFER=INSTALLED` 时,才从安装器报告的当前 Agent 目标目录核验 `alipay-aipay-pre/SKILL.md`、`VERSION` 和 `references/runtime-entry.md` 均为普通文件,渠道为 `pre`、版本不低于 `1.7.4-pre`;来自 npm beta 包时还须核对内测版 `VERSION` 等于刚才线上核验的版本,且其 `npm-origin.json` 与正式版安装来源的包版本和标签一致。该目录还须确实可由当前 Agent 加载;不能从旧预发版路径或当前正式版目录推定安装成功。核验成功后废弃正式版入口及刷新事实,使用实际预发版规范化绝对路径重新读取其 `SKILL.md` 并按预发版启动协议继续原任务。安装失败或核验失败时保持正式版,不宣称切换成功,也不进入预发业务流程。此选择发生在正式版 telemetry 启动前,不为渠道提示或预发安装创建正式版 run。
88
+ - `UNAVAILABLE`:线上目标缺少 Windows 内测能力或来源不匹配,不安装;说明实际原因,可继续正式版或等版本可用后按用户明确要求重新核验。不得将其笼统归因为网络,也不得改用另一个 npm 标签。
89
+ - `CHECK_FAILED`:网络/工具/元数据核验失败不等于内测版不存在。网络权限恢复或用户明确重试时,最多重跑一次 `available`;成功后再安装。元数据非法且未变化时不循环重试。
90
+ - `INSTALL_FAILED` 且原因为 `INSTALL_NETWORK_FAILED`:恢复网络后最多重试一次同一安装动作。`INSTALL_PATH_BLOCKED`:说明目录被占用或权限不足,先关闭占用该目录的终端/编辑器或按组织策略恢复写权限,再最多重试一次;不提权、不删除旧 Skill、不混合复制新旧文件。`NPM_TOOLCHAIN_MISSING`:说明缺少配套 npm/npx,先复用已有 Node 配套工具或按已有授权修复工具链,再最多重试一次。
91
+ - `INSTALL_TIMEOUT` 或其他安装失败:状态未知,不自动再次写入;说明失败并提供恢复后重试或继续正式版的选择。用户确认安装进程已结束、故障已处理后最多重试一次,不并发启动安装器。
92
+ - `VERIFY_FAILED`、成功 marker 缺失/冲突或安装目录无法读取:不宣称已切换,不加载旧版替代;说明安装结果未通过核验,修复后最多重新安装一次并完整复核。耗尽预算仍保留可用正式版,等待用户选择修复环境或继续正式版,不自动转站点、不重新展示推荐循环。
60
93
 
61
- 来自 npm beta 包的 `available` 和 `install` 还须各取得唯一合法的 `ALIPAY_AIPAY_INTERNAL:CHANNEL_OFFER_PRE_VERSION=<内测版 Skill 版本>`,两次值完全一致,且安装后目录中的 `VERSION` 等于该值;任一缺失或冲突都不视为切换成功。现有对客提示保持原文,其中手动 `@latest` 安装命令属于常规发布路径;本测试包收到明确内测意图后必须走上述受控切换,不能执行该手动命令代替。
94
+ 上述安装重试始终使用已保存、原先判为 `PRE` 的同一条完整回复;用户后来拒绝或切回正式版则立即取消重试。选择继续正式版时记录已处理并执行下文 CLI 刷新,保留原任务,不要求重复描述需求。此选择发生在正式版 telemetry 启动前,不为渠道提示或预发安装创建正式版 run。
62
95
 
63
96
  仅确定继续正式版后,若当前上下文没有与规范化 `SKILL_DIR`、合法 `VERSION` 绑定的 `ALIPAY_AIPAY_CLI_REFRESHED=true`,必须刷新一次 `alipay-cli`;不得因自更新已检查而跳过。仅唯一终态 `READY` 可在当前对话上下文记录该成功事实、路径和版本,不写缓存或业务状态;三者仍可用且一致时,后续根触发、确认、补材料、候选选择、恢复、中断继续和 Full Process 衔接均不重复刷新。
64
97
 
@@ -68,4 +101,4 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" env refresh-alipay-cli
68
101
 
69
102
  stderr 只允许一个 `ALIPAY_AIPAY_INTERNAL:ALIPAY_CLI_REFRESH=<READY|RETRY_WITH_NETWORK|RETRY_WITH_LOCAL_FS_PERMISSION|FAILED|VERIFY_FAILED>`,stdout 必须为空,安装器及版本输出不得对客。前两种重试终态分别只允许取得网络权限或 `~/.local/bin` 写权限后原样重试一次;其他终态静默继续,并以之后环境检查和业务脚本的实际 CLI 可用性为准。路径或版本变化、上下文压缩导致事实不可用、用户明确要求刷新,或环境检查证明 CLI 缺失/损坏时清除旧事实并按同一预算重试;非 `READY` 不得循环。
70
103
 
71
- 完成本次所需刷新或命中成功事实后,只完整读取同一 `SKILL_DIR` 的 `references/runtime-entry.md`,在当前上下文记录 `ALIPAY_AIPAY_RUNTIME_ENTRY_LOADED=true` 和规范化路径,再按原请求路由。同一对话后续确认、补材料、候选选择、恢复、中断继续、重复触发和 Full Process 衔接,入口事实存在、路径未变且入口规则仍在时,跳过版本检查和入口重读。仅 `UPDATED`、路径变化或上下文压缩导致规则不可用时重读;事实不落盘。
104
+ 完成本次所需刷新或命中成功事实后,只完整读取同一 `SKILL_DIR` 的 `references/runtime-entry.md`,在当前上下文记录 `ALIPAY_AIPAY_RUNTIME_ENTRY_LOADED=true` 和规范化路径,再按原请求路由。同一对话后续确认、补材料、候选选择、恢复、中断继续、重复触发和 Full Process 衔接,入口事实存在、路径未变且入口规则仍在时,跳过版本检查和入口重读。仅 `UPDATED|SESSION_READY`、路径变化或上下文压缩导致规则不可用时重读;事实不落盘。
package/skill/VERSION CHANGED
@@ -1 +1 @@
1
- 1.7.2
1
+ 1.7.3