@petercjl/taobao-ai-ops 0.4.4 → 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 +6 -2
- package/src/cli.mjs +4 -4
- package/src/runtime.mjs +3 -3
- package/src/subscription.mjs +7 -4
- package/suite-manifest.json +3 -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
|
@@ -95,12 +95,16 @@ For explicit Boardmix file, media or object operations, select `boardmix-tools`.
|
|
|
95
95
|
|
|
96
96
|
## DMP 商品经营报告
|
|
97
97
|
|
|
98
|
-
用户提供淘宝/天猫商品ID,希望查看竞品经营趋势、推广方式/力度/效果、新老客成交结构或完整商品经营HTML报告时,选择 `dmp-product-report` 节点。独立拥有包为 `@petercjl/dmp-product-report`,逻辑Skill为 `dmp-product-report`;所需能力是 `@petercjl/tbcli` 的 DMP snapshot
|
|
98
|
+
用户提供淘宝/天猫商品ID,希望查看竞品经营趋势、推广方式/力度/效果、新老客成交结构或完整商品经营HTML报告时,选择 `dmp-product-report` 节点。独立拥有包为 `@petercjl/dmp-product-report`,逻辑Skill为 `dmp-product-report`;所需能力是 `@petercjl/tbcli` 的 DMP snapshot v2 与 itemSummary v1。兼容起点分别为报告包0.2.0、tbcli 0.12.0。
|
|
99
99
|
|
|
100
100
|
先运行 `taobao-ai-ops skill source --name dmp-product-report --json`,完整读取返回的当前Skill,按该Skill按需加载知识、适配与tbcli依赖,再运行 `taobao-ai-ops doctor --node dmp-product-report --json`。Doctor检查套件所选报告组件、Python与tbcli合同,不查询经营数据或证明账号权限。缺失/不兼容时保留结构化错误,恢复后回到预检;不借用另一全局tbcli来掩盖依赖问题。
|
|
101
101
|
|
|
102
102
|
通过 `taobao-ai-ops component run dmp-product-report ...` 执行子CLI主线。套件将其已注册tbcli入口传入应用;宿主能力集合的子Skill回执也包含同一依赖入口,任务内保留该版本集合。商品名称、链接、5张主图、店铺、已售、入口价和评价数由橙色淘宝买家浏览器读取;DMP统计由蓝色商家电商浏览器读取,两个角色的会话参数分别保留。登录和验证码由用户在对应窗口处理。
|
|
103
103
|
|
|
104
|
-
输入为目标商品ID
|
|
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/runtime.mjs
CHANGED
|
@@ -98,14 +98,14 @@ export async function doctor(id,mode='excel'){
|
|
|
98
98
|
if(n.component==='dmp-product-report'){
|
|
99
99
|
const record=componentRecord(n.component),records=componentRecords();
|
|
100
100
|
const atLeast=(value,min)=>{if(!/^\d+\.\d+\.\d+$/.test(value??''))return false;const a=value.split('.').map(Number),b=min.split('.').map(Number);for(let i=0;i<3;i++)if(a[i]!==b[i])return a[i]>b[i];return true;};
|
|
101
|
-
checks.push({id:'dmp-report-version',ok:atLeast(record.version,'0.
|
|
102
|
-
checks.push({id:'dmp-report-tbcli',ok:atLeast(records.tbcli?.version,'0.
|
|
101
|
+
checks.push({id:'dmp-report-version',ok:atLeast(record.version,'0.2.0'),value:record.version,minimum:'0.2.0'});
|
|
102
|
+
checks.push({id:'dmp-report-tbcli',ok:atLeast(records.tbcli?.version,'0.12.0'),value:records.tbcli?.version??null,minimum:'0.12.0'});
|
|
103
103
|
try{
|
|
104
104
|
const environment=componentEnvironment(n.component);
|
|
105
105
|
const versionRun=spawnSync(process.execPath,[record.entry,'version','--json'],{encoding:'utf8',timeout:15000,env:environment});let version;try{version=JSON.parse(versionRun.stdout);}catch{}
|
|
106
106
|
checks.push({id:'dmp-report-runtime',ok:versionRun.status===0&&version?.package===MANIFEST.components[n.component].package&&version?.version===record.version,value:version?.version??null});
|
|
107
107
|
const result=spawnSync(process.execPath,[record.entry,'doctor','--json'],{encoding:'utf8',timeout:90000,env:environment});let detail;try{detail=JSON.parse(result.stdout||result.stderr);}catch{detail={ok:false,code:'COMPONENT_DOCTOR_FAILED'};}
|
|
108
|
-
checks.push({id:'dmp-report-capabilities',ok:result.status===0&&detail.ok===true&&detail.tbcliSnapshot===
|
|
108
|
+
checks.push({id:'dmp-report-capabilities',ok:result.status===0&&detail.ok===true&&detail.tbcliSnapshot===2&&detail.subjectMode==='target-only'&&detail.tbcliItemSummary===1,value:detail});
|
|
109
109
|
}catch(e){checks.push({id:'dmp-report-dependencies',ok:false,code:e.code??'CAPABILITY_UNAVAILABLE',message:e.message});}
|
|
110
110
|
}
|
|
111
111
|
if(n.component==='competitor-visual-canvas'){
|
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');
|
package/suite-manifest.json
CHANGED
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
"skill": "dmp-product-report",
|
|
278
278
|
"component": "dmp-product-report",
|
|
279
279
|
"stage": "competitor-performance-research",
|
|
280
|
-
"method_version": "dmp-product-report@
|
|
280
|
+
"method_version": "dmp-product-report@2",
|
|
281
281
|
"requires_skills": [
|
|
282
282
|
"tbcli"
|
|
283
283
|
],
|
|
@@ -292,7 +292,6 @@
|
|
|
292
292
|
"authorized merchant and buyer browser sessions"
|
|
293
293
|
],
|
|
294
294
|
"optional": [
|
|
295
|
-
"explicit owned anchor ID",
|
|
296
295
|
"report date",
|
|
297
296
|
"new output directory",
|
|
298
297
|
"previous collected run for offline build/finalize"
|
|
@@ -304,8 +303,8 @@
|
|
|
304
303
|
"state": "child owns collection checkpoints, browser-role guards and report artifacts"
|
|
305
304
|
},
|
|
306
305
|
"required_component_contracts": {
|
|
307
|
-
"dmp-product-report": "0.
|
|
308
|
-
"tbcli": "0.
|
|
306
|
+
"dmp-product-report": "0.2.0+; bundled renderer and finalization contract",
|
|
307
|
+
"tbcli": "0.12.0+; dmp snapshot version 2 target-only subject, automatic owned-item execution context and itemSummary version 1"
|
|
309
308
|
},
|
|
310
309
|
"contract_resolution": "Resolve current exact child Skill and CLI capabilities; preserve the selected merchant/buyer endpoints and returned data availability."
|
|
311
310
|
}
|