@petercjl/taobao-ai-ops 0.4.5 → 0.4.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.
- package/UPDATE.md +2 -0
- package/package.json +1 -1
- package/skills/taobao-ai-operations/SKILL.md +4 -0
- package/src/cli.mjs +4 -4
- package/src/subscription.mjs +7 -4
package/UPDATE.md
CHANGED
|
@@ -11,3 +11,5 @@
|
|
|
11
11
|
宿主安装完整候选后,在任务和审批空闲时切换并刷新 Skill。下载失败、离线、候选验证失败、用户修改过受管 Skill 或宿主刷新失败时,保留上一套。更新只涉及选定宿主的订阅目录,配置和凭据留在包外。插件详情显示实际成员版本及上次检查结果。
|
|
12
12
|
|
|
13
13
|
开发者:每次检查都以当前壳的注册表为准,与 previous 回执比较成员身份、版本和所需 Skill;`collection prepare` 返回独立候选,宿主验证后才激活。回执中的运行环境必须跟随 CLI 调用,当前任务内保持同一版本。新集合入口不接管历史全局 npm 安装;历史安装继续通过其已声明的维护入口操作。
|
|
14
|
+
|
|
15
|
+
开发者:迁移已批准的跨兼容版本组件时,在collection check/prepare中显式传入 `--accept-component-upgrades ID,ID` 并保留previous回执。该参数仅批准列出的组件升级,不批准降级;其余不兼容组件继续保留原版本。DMP快照v2迁移选择 `tbcli,dmp-product-report`,候选doctor通过后再激活。
|
package/package.json
CHANGED
|
@@ -104,3 +104,7 @@ For explicit Boardmix file, media or object operations, select `boardmix-tools`.
|
|
|
104
104
|
输入为目标商品ID,可补充报告日与新输出目录;已有证据可按子合同离线build/finalize。接口需要的本店商品参数由tbcli自动从当前账户发现,报告仅采用目标商品侧数据。输出包括自包含HTML、商品资料、近7天/前7天、近30天/前30天及8个完整自然周证据、CSV、ViewModel、分析和校验。run产生draft后继续按子Skill完成分析和finalize;一句结论与编号证据、经营策略解读及最终概览均由子应用的当前知识方法承接。返回套件主线第4步保留成果或第6步交付。
|
|
105
105
|
|
|
106
106
|
报告模板和分析知识继续由独立报告包维护,运行不依赖commerce-ui。套件负责注册、安装更新、精确Skill来源解析、依赖传递和预检。商品资料的页面展示口径与DMP分期统计分别解释;本次可用范围以平台实际返回为准。
|
|
107
|
+
|
|
108
|
+
### DMP配套版本迁移
|
|
109
|
+
|
|
110
|
+
用户授权更新DMP报告和取数链路时,检查当前集合的blocked成员。若报告包0.2与tbcli 0.12因跨兼容版本而保留旧版,使用旧回执和 `collection prepare --accept-component-upgrades tbcli,dmp-product-report` 明确迁移这两个组件;其他不兼容组件维持原选择。核对候选DMP doctor及真实版本后再切换宿主入口。该操作按用户已授权的组件范围执行,不扩大到其他Agent或未选组件。
|
package/src/cli.mjs
CHANGED
|
@@ -9,10 +9,10 @@ import {checkUpdate,installUpdate} from './update.mjs';
|
|
|
9
9
|
import {collectionCheck,collectionPrepare} from './subscription.mjs';
|
|
10
10
|
import fs from 'node:fs/promises';
|
|
11
11
|
const print=v=>console.log(JSON.stringify(v,null,2));
|
|
12
|
-
function options(args){const out={};for(let i=0;i<args.length;i++){const k=args[i];if(['--json','--adopt','--yes'].includes(k))out[k.slice(2)]=true;else if(['--directory','--previous','--path','--agent','--target-dir','--name','--node','--profile','--mode','--run-dir','--input','--out','--candidate','--query','--tag','--context','--run-id'].includes(k)){if(!args[i+1]||args[i+1].startsWith('--'))throw fail('USAGE',`${k} needs a value`);out[k.slice(2).replace(/-([a-z])/g,(_,c)=>c.toUpperCase())]=args[++i];}else throw fail('USAGE',`Unknown option ${k}`);}return out;}
|
|
12
|
+
function options(args){const out={};for(let i=0;i<args.length;i++){const k=args[i];if(['--json','--adopt','--yes'].includes(k))out[k.slice(2)]=true;else if(['--accept-component-upgrades','--directory','--previous','--path','--agent','--target-dir','--name','--node','--profile','--mode','--run-dir','--input','--out','--candidate','--query','--tag','--context','--run-id'].includes(k)){if(!args[i+1]||args[i+1].startsWith('--'))throw fail('USAGE',`${k} needs a value`);out[k.slice(2).replace(/-([a-z])/g,(_,c)=>c.toUpperCase())]=args[++i];}else throw fail('USAGE',`Unknown option ${k}`);}return out;}
|
|
13
13
|
export async function main(argv){
|
|
14
14
|
const [command,action,...rest]=argv;
|
|
15
|
-
if(!command||['help','--help','-h'].includes(command))return console.log(`taobao-ai-ops ${PACKAGE.version}\nversion | nodes list | node show ID | capabilities\ncollection check [--previous RECEIPT] --json | collection prepare --directory NEW --yes --json [--previous RECEIPT]\ndoctor --node ID [--mode excel|nas]\nskill source [--name NAME] | skill status|install|update --agent AGENT [--profile research] [--adopt]\ncomponents status|check|install [--agent AGENT --yes]\ncomponents register --name ID --path CHECKOUT --yes [--mode npm]\ncomponent run ID [arguments...] | script NODE SCRIPT [arguments...] | tool run TOOL [arguments...]\nworkflow plan|status --run-dir DIR [--node ID] [--input FILE]\nhandoff create --node ID --input FILE --out FILE [--candidate PATH --query QUERY]\nupdate check|install [--tag latest] [--agent AGENT --yes]`);
|
|
15
|
+
if(!command||['help','--help','-h'].includes(command))return console.log(`taobao-ai-ops ${PACKAGE.version}\nversion | nodes list | node show ID | capabilities\ncollection check [--previous RECEIPT] --json | collection prepare --directory NEW --yes --json [--previous RECEIPT] [--accept-component-upgrades ID,ID]\ndoctor --node ID [--mode excel|nas]\nskill source [--name NAME] | skill status|install|update --agent AGENT [--profile research] [--adopt]\ncomponents status|check|install [--agent AGENT --yes]\ncomponents register --name ID --path CHECKOUT --yes [--mode npm]\ncomponent run ID [arguments...] | script NODE SCRIPT [arguments...] | tool run TOOL [arguments...]\nworkflow plan|status --run-dir DIR [--node ID] [--input FILE]\nhandoff create --node ID --input FILE --out FILE [--candidate PATH --query QUERY]\nupdate check|install [--tag latest] [--agent AGENT --yes]`);
|
|
16
16
|
if(['version','--version'].includes(command))return action==='--json'?print({ok:true,package:PACKAGE.name,version:PACKAGE.version}):console.log(PACKAGE.version);
|
|
17
17
|
if(command==='script')return runScript(action,rest[0],rest.slice(1));
|
|
18
18
|
if(command==='component'&&action==='run'){
|
|
@@ -25,11 +25,11 @@ export async function main(argv){
|
|
|
25
25
|
}
|
|
26
26
|
if(command==='nodes'&&action==='list')return print(MANIFEST.nodes);
|
|
27
27
|
if(command==='node'&&action==='show')return print(nodeFor(rest[0]));
|
|
28
|
-
if(command==='capabilities')return print({package:PACKAGE.name,version:PACKAGE.version,...MANIFEST,collectionContract:{schemaVersion:1,manifest:'sealwork.collection.json',check:['collection','check','--json'],prepare:['collection','prepare','--directory','{newDirectory}','--yes','--json'],previousOption:'--previous',installationMode:'host-owned-generation',hostDiscoveryAuthority:'host'}});
|
|
28
|
+
if(command==='capabilities')return print({package:PACKAGE.name,version:PACKAGE.version,...MANIFEST,collectionContract:{schemaVersion:1,manifest:'sealwork.collection.json',check:['collection','check','--json'],prepare:['collection','prepare','--directory','{newDirectory}','--yes','--json'],previousOption:'--previous',migrationOption:'--accept-component-upgrades',migrationPolicy:'Explicitly approved component IDs may cross compatibility boundaries; unselected incompatible versions stay pinned; downgrades stay blocked',installationMode:'host-owned-generation',hostDiscoveryAuthority:'host'}});
|
|
29
29
|
if(command==='doctor'){const opts=options(argv.slice(1));const r=await doctor(opts.node,opts.mode);print(r);if(!r.ok)process.exitCode=1;return;}
|
|
30
30
|
const opts=options(rest);
|
|
31
31
|
if(command==='collection'){
|
|
32
|
-
if(action==='check')return print(await collectionCheck(opts.previous?JSON.parse(await fs.readFile(opts.previous,'utf8')):undefined));
|
|
32
|
+
if(action==='check')return print(await collectionCheck(opts.previous?JSON.parse(await fs.readFile(opts.previous,'utf8')):undefined,undefined,opts.acceptComponentUpgrades));
|
|
33
33
|
if(action==='prepare')return print(await collectionPrepare(opts));
|
|
34
34
|
}
|
|
35
35
|
|
package/src/subscription.mjs
CHANGED
|
@@ -10,7 +10,9 @@ export function compatible(current,next){
|
|
|
10
10
|
const a=current.split('.').map(Number),b=next.split('.').map(Number);
|
|
11
11
|
return a[0]===b[0]&&(a[0]!==0||a[1]===b[1])&&next.localeCompare(current,undefined,{numeric:true})>=0;
|
|
12
12
|
}
|
|
13
|
-
export async function collectionCheck(previous,registry=fetch){
|
|
13
|
+
export async function collectionCheck(previous,registry=fetch,approved=[]){
|
|
14
|
+
const selected=new Set(typeof approved==='string'?approved.split(',').map(x=>x.trim()).filter(Boolean):approved);
|
|
15
|
+
for(const id of selected)if(!Object.hasOwn(MANIFEST.components,id))throw fail('UNKNOWN_COMPONENT',id);
|
|
14
16
|
if(previous&&(previous.package!==PACKAGE.name||!Array.isArray(previous.members)||!stable(previous.version)))throw fail('INVALID_PREVIOUS_COLLECTION','Previous receipt must belong to this collection');
|
|
15
17
|
const members=[];
|
|
16
18
|
for(const [id,c] of Object.entries(MANIFEST.components)){
|
|
@@ -19,9 +21,10 @@ export async function collectionCheck(previous,registry=fetch){
|
|
|
19
21
|
const metadata=await response.json();
|
|
20
22
|
if(metadata.name!==c.package||!stable(metadata.version))throw fail('INVALID_REGISTRY_IDENTITY',c.package);
|
|
21
23
|
const old=previous?.members?.find(m=>m.package===c.package);
|
|
22
|
-
const
|
|
24
|
+
const explicitMigration=Boolean(old&&selected.has(id)&&metadata.version.localeCompare(old.version,undefined,{numeric:true})>=0);
|
|
25
|
+
const accepted=!old||compatible(old.version,metadata.version)||explicitMigration;
|
|
23
26
|
members.push({id,package:c.package,version:accepted?metadata.version:old.version,available:metadata.version,
|
|
24
|
-
bin:c.bin,skills:c.skills,blocked:!accepted});
|
|
27
|
+
bin:c.bin,skills:c.skills,blocked:!accepted,explicitMigration});
|
|
25
28
|
}
|
|
26
29
|
const changed=previous?.version!==PACKAGE.version||JSON.stringify(members.map(m=>[m.id,m.package,m.version,m.skills]))!==JSON.stringify(previous?.members?.map(m=>[m.id,m.package,m.version,m.skills]));
|
|
27
30
|
return {ok:true,schemaVersion:1,package:PACKAGE.name,version:PACKAGE.version,changed,members};
|
|
@@ -69,7 +72,7 @@ export async function collectionPrepare(opts,services={}){
|
|
|
69
72
|
const directory=path.resolve(opts.directory);
|
|
70
73
|
if(await stat(directory))throw fail('TARGET_EXISTS','Candidate directory must be new');
|
|
71
74
|
const previous=opts.previous?JSON.parse(await fs.readFile(opts.previous,'utf8')):undefined;
|
|
72
|
-
const plan=await collectionCheck(previous,services.registry);
|
|
75
|
+
const plan=await collectionCheck(previous,services.registry,opts.acceptComponentUpgrades);
|
|
73
76
|
await fs.mkdir(directory,{recursive:true,mode:0o700});
|
|
74
77
|
try{
|
|
75
78
|
const shell=path.join(directory,'shell'),runtime=path.join(directory,'runtime'),skills=path.join(directory,'skills');
|