@petercjl/taobao-ai-ops 0.2.0 → 0.2.1
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/README.md +6 -0
- package/package.json +1 -1
- package/skills/taobao-ai-operations/SKILL.md +6 -0
- package/src/cli.mjs +5 -3
- package/src/components.mjs +40 -1
- package/src/runtime.mjs +6 -0
- package/src/skill-manager.mjs +4 -1
- package/suite-manifest.json +44 -7
package/README.md
CHANGED
|
@@ -59,3 +59,9 @@ taobao-ai-ops tool run tbcli capabilities --json
|
|
|
59
59
|
Node >=20。Python 研究依赖通过稳定解释器准备;TAOBAO_AI_OPS_PYTHON 可指定已配置解释器。脚本和报告模板来自实际组件目录。原生图片理解由当前 Agent 提供;缺失时报告而非缩减流程。
|
|
60
60
|
|
|
61
61
|
本地 macOS 确定性安装、更新与恢复测试单独记录;Windows/SealSeek 的真实宿主安装和端到端行为尚待验证。CI 发布前须先有可安装的类目独立包;所有发布通过 GitHub Actions OIDC。
|
|
62
|
+
|
|
63
|
+
## Audio production
|
|
64
|
+
|
|
65
|
+
The `seedaudio-tools` node registers the independent `@petercjl/seedaudiocli` package and its canonical `seedaudiocli` Skill. Install with `taobao-ai-ops skill install --agent codex --name seedaudiocli` (or the actual SealSeek target). Discover its source with `taobao-ai-ops skill source --name seedaudiocli --json`, read the complete current Skill and relative resources, then invoke `taobao-ai-ops component run seedaudiocli ...` or `tool run seedaudiocli ...`. Return task IDs and output files to the caller's audio acceptance flow. A missing component requires `components install --agent AGENT --yes`; missing credentials require importing the administrator-provided file through the component CLI.
|
|
66
|
+
|
|
67
|
+
Before every audio component invocation, the suite checks stable latest, installs a newer component into a separate generation and synchronizes registered managed Skill targets. Configuration and task history remain in user directories. Registry/install failures retain the previous version. Local development checkouts remain Git-managed. `TAOBAO_AI_OPS_AUTO_UPDATE=0` pins the installed set for a specific run. Other components keep their declared update policy. The suite owns installation and invocation; the audio package owns provider integration, validation, authentication, generation and recovery. Prompts and output acceptance belong to the caller.
|
package/package.json
CHANGED
|
@@ -43,3 +43,9 @@ Missing native image observation stops product visual analysis; an unverified su
|
|
|
43
43
|
## QA and maintenance
|
|
44
44
|
|
|
45
45
|
Confirm the selected node, actual source path, method version, source hashes and full output contract. Keep every Skill's tests independent and exercise suite installation, dependency closure and handoffs separately. Suite targets are implemented, with actual Agent/OS runtime evidence recorded separately. Clean-context regression requires an explicit user request. New business nodes enter the suite registry only with an independent I → S → O, execution and QA contract.
|
|
46
|
+
|
|
47
|
+
## Audio production
|
|
48
|
+
|
|
49
|
+
The `seedaudio-tools` node registers the independent `@petercjl/seedaudiocli` package and its canonical `seedaudiocli` Skill. Install with `taobao-ai-ops skill install --agent codex --name seedaudiocli` (or the actual SealSeek target). Discover its source with `taobao-ai-ops skill source --name seedaudiocli --json`, read the complete current Skill and relative resources, then invoke `taobao-ai-ops component run seedaudiocli ...` or `tool run seedaudiocli ...`. Return task IDs and output files to the caller's audio acceptance flow. A missing component requires `components install --agent AGENT --yes`; missing credentials require importing the administrator-provided file through the component CLI.
|
|
50
|
+
|
|
51
|
+
Before every audio component invocation, the suite checks stable latest, installs a newer component into a separate generation and synchronizes registered managed Skill targets. Configuration and task history remain in user directories. Registry/install failures retain the previous version. Local development checkouts remain Git-managed. `TAOBAO_AI_OPS_AUTO_UPDATE=0` pins the installed set for a specific run. Other components keep their declared update policy. The suite owns installation and invocation; the audio package owns provider integration, validation, authentication, generation and recovery. Prompts and output acceptance belong to the caller.
|
package/src/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import {spawnSync} from 'node:child_process';
|
|
3
3
|
import {MANIFEST,PACKAGE,nodeFor,source,nodeVersion,fileHashes,digest,fail,componentRecords,componentRecord} from './core.mjs';
|
|
4
|
-
import {checkComponents,installComponents,registerComponent} from './components.mjs';
|
|
4
|
+
import {checkComponents,installComponents,registerComponent,prepareComponentRun} from './components.mjs';
|
|
5
5
|
import {targetRoot,status,install} from './skill-manager.mjs';
|
|
6
6
|
import {runScript,doctor,toolEntry} from './runtime.mjs';
|
|
7
7
|
import {plan,workflowStatus,createHandoff} from './workflow.mjs';
|
|
@@ -14,10 +14,12 @@ export async function main(argv){
|
|
|
14
14
|
if(['version','--version'].includes(command))return console.log(PACKAGE.version);
|
|
15
15
|
if(command==='script')return runScript(action,rest[0],rest.slice(1));
|
|
16
16
|
if(command==='component'&&action==='run'){
|
|
17
|
-
|
|
17
|
+
await prepareComponentRun(rest[0]);
|
|
18
|
+
const record=componentRecord(rest[0]);const r=spawnSync(process.execPath,[record.entry,...rest.slice(1)],{stdio:'inherit',env:{...process.env,TBCLI_UPDATE_CHECK:'0',SYCMCLI_DISABLE_AUTO_UPDATE:'1',SEEDAUDIO_AUTO_UPDATE:'0'}});if(r.error)throw fail('EXECUTION_FAILED',r.error.message);process.exitCode=r.status??1;return;
|
|
18
19
|
}
|
|
19
20
|
if(command==='tool'&&action==='run'){
|
|
20
|
-
|
|
21
|
+
await prepareComponentRun(MANIFEST.tools[rest[0]]?.component);
|
|
22
|
+
const entry=toolEntry(rest[0]);const r=spawnSync(entry.command,[...entry.args,...rest.slice(1)],{stdio:'inherit',env:{...process.env,TBCLI_UPDATE_CHECK:'0',SYCMCLI_DISABLE_AUTO_UPDATE:'1',SEEDAUDIO_AUTO_UPDATE:'0'}});if(r.error)throw fail('CAPABILITY_UNAVAILABLE',r.error.message);process.exitCode=r.status??1;return;
|
|
21
23
|
}
|
|
22
24
|
if(command==='nodes'&&action==='list')return print(MANIFEST.nodes);
|
|
23
25
|
if(command==='node'&&action==='show')return print(nodeFor(rest[0]));
|
package/src/components.mjs
CHANGED
|
@@ -15,7 +15,7 @@ export async function inspectComponent(id,root){
|
|
|
15
15
|
if(!p.bin?.[c.bin]||!entry.startsWith(path.resolve(root)+path.sep))throw fail('INVALID_COMPONENT_ENTRY',id);
|
|
16
16
|
const sources={};
|
|
17
17
|
for(const skill of c.skills){
|
|
18
|
-
const r=spawnSync(process.execPath,[entry,'skill','source','--json'],{encoding:'utf8',timeout:30000,env:{...process.env,TBCLI_UPDATE_CHECK:'0',SYCMCLI_DISABLE_AUTO_UPDATE:'1'}});
|
|
18
|
+
const r=spawnSync(process.execPath,[entry,'skill','source','--json'],{encoding:'utf8',timeout:30000,env:{...process.env,TBCLI_UPDATE_CHECK:'0',SYCMCLI_DISABLE_AUTO_UPDATE:'1',SEEDAUDIO_AUTO_UPDATE:'0'}});
|
|
19
19
|
if(r.status!==0)throw fail('COMPONENT_SOURCE_FAILED',r.stderr||id);
|
|
20
20
|
const envelope=JSON.parse(r.stdout);
|
|
21
21
|
if(envelope.ok===false)throw fail('COMPONENT_SOURCE_FAILED',id, envelope.error);
|
|
@@ -75,3 +75,42 @@ export async function installComponents(opts,services={}){
|
|
|
75
75
|
}catch(e){await save(old);throw e;}
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
// Only components declaring this policy update on invocation; other lifecycle stays explicit.
|
|
80
|
+
export async function prepareComponentRun(id,services={}){
|
|
81
|
+
if(!MANIFEST.components[id]?.automatic_update || process.env.TAOBAO_AI_OPS_AUTO_UPDATE==='0')return;
|
|
82
|
+
if(componentRecords()[id]?.development)return;
|
|
83
|
+
return locked(async()=>{
|
|
84
|
+
const old=componentRecords(),c=MANIFEST.components[id];
|
|
85
|
+
let latest;
|
|
86
|
+
try{
|
|
87
|
+
const r=await (services.registry||fetch)(`https://registry.npmjs.org/${encodeURIComponent(c.package)}/latest`,{signal:AbortSignal.timeout(8000)});
|
|
88
|
+
if(!r.ok)throw Error('registry');const p=await r.json();
|
|
89
|
+
if(p.name!==c.package||!/^\d+\.\d+\.\d+$/.test(p.version))throw Error('version');latest=p.version;
|
|
90
|
+
}catch{if(!old[id])throw fail('COMPONENT_NOT_INSTALLED','Install components while online');console.error('[taobao-ai-ops] Update check unavailable; using installed audio component.');return;}
|
|
91
|
+
const newer=(a,b)=>{const x=a.split('.').map(Number),y=b.split('.').map(Number);for(let i=0;i<3;i++)if(x[i]!==y[i])return x[i]>y[i];return false;};
|
|
92
|
+
if(old[id]&&!newer(latest,old[id].version))return;
|
|
93
|
+
const generation=path.join(stateRoot(),'component-generations',randomUUID());await fs.mkdir(generation,{recursive:true});
|
|
94
|
+
await fs.writeFile(path.join(generation,'previous-components.json'),JSON.stringify(old),{flag:'wx'});
|
|
95
|
+
const roots=[];
|
|
96
|
+
for(const name of await fs.readdir(path.join(stateRoot(),'skill-targets')).catch(()=>[])){
|
|
97
|
+
const info=JSON.parse(await fs.readFile(path.join(stateRoot(),'skill-targets',name),'utf8'));
|
|
98
|
+
const owner=JSON.parse(await fs.readFile(path.join(info.root,'.taobao-ai-ops-managed.json'),'utf8').catch(()=>'{}'));
|
|
99
|
+
if(c.skills.some(skill=>owner.skills?.[skill]))roots.push(info.root);
|
|
100
|
+
}
|
|
101
|
+
const synced=[];
|
|
102
|
+
try{
|
|
103
|
+
await (services.npm||npm)(['install','--prefix',generation,'--no-audit','--no-fund','--ignore-scripts',`${c.package}@${latest}`]);
|
|
104
|
+
const record=await inspectComponent(id,path.join(generation,'node_modules',...c.package.split('/')));
|
|
105
|
+
if(record.version!==latest)throw fail('COMPONENT_VERSION_MISMATCH',id);
|
|
106
|
+
await save({...old,[id]:record});
|
|
107
|
+
for(const targetDir of roots){await install({targetDir,name:c.skills[0]});synced.push(targetDir);}
|
|
108
|
+
console.error(`[taobao-ai-ops] ${id} updated to ${latest}.`);
|
|
109
|
+
}catch(e){
|
|
110
|
+
await save(old);
|
|
111
|
+
for(const targetDir of synced)await install({targetDir,name:c.skills[0]});
|
|
112
|
+
if(!old[id])throw e;
|
|
113
|
+
console.error(`[taobao-ai-ops] ${e.code||'UPDATE_FAILED'}; using previous audio component.`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
package/src/runtime.mjs
CHANGED
|
@@ -53,6 +53,12 @@ export async function doctor(id,mode='excel'){
|
|
|
53
53
|
checks.push({id:'procli-runtime',ok:result.status===0&&version===record.version,value:version});
|
|
54
54
|
checks.push({id:'procli-contract',ok:fs.existsSync(path.join(source(n),'capabilities.json'))});
|
|
55
55
|
}
|
|
56
|
+
if(n.component==='seedaudiocli'){
|
|
57
|
+
const record=componentRecord(n.component);
|
|
58
|
+
const result=spawnSync(process.execPath,[record.entry,'doctor','--json'],{encoding:'utf8',timeout:30000,env:{...pythonEnvironment(),SEEDAUDIO_AUTO_UPDATE:'0'}});
|
|
59
|
+
let detail;try{detail=JSON.parse(result.stdout);}catch{detail={code:'COMPONENT_DOCTOR_FAILED'};}
|
|
60
|
+
checks.push({id:'seedaudio-runtime-and-config',ok:result.status===0,value:detail});
|
|
61
|
+
}
|
|
56
62
|
if(n.id==='category-research')checks.push({id:'report-runtime',ok:['assets/report-template.html','assets/chart-views.js'].every(p=>fs.existsSync(path.join(source(n),p)))});
|
|
57
63
|
if(n.id==='product-research'){
|
|
58
64
|
const componentRequire=createRequire(path.join(componentRecord(n.component).root,'package.json'));
|
package/src/skill-manager.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import {randomUUID} from 'node:crypto';
|
|
4
|
+
import {randomUUID,createHash} from 'node:crypto';
|
|
5
5
|
import {PACKAGE,source,nodeVersion,closure,json,stat,fileHashes,digest,fail,stateRoot} from './core.mjs';
|
|
6
6
|
|
|
7
7
|
const OWNER='.taobao-ai-ops-managed.json';
|
|
@@ -79,6 +79,9 @@ export async function install(opts,options={}){
|
|
|
79
79
|
const ownerPath=path.join(root,OWNER);if(await stat(ownerPath))await fs.copyFile(ownerPath,path.join(transaction,'previous-owner.json'));
|
|
80
80
|
await fs.writeFile(path.join(transaction,'transaction.json'),JSON.stringify({package:PACKAGE.name,root,results},null,2),{flag:'wx'});
|
|
81
81
|
const pending=path.join(root,`${OWNER}.${randomUUID()}.pending`);await fs.writeFile(pending,JSON.stringify(old,null,2),{flag:'wx'});await fs.rename(pending,ownerPath);
|
|
82
|
+
const registry=path.join(stateRoot(),'skill-targets');await fs.mkdir(registry,{recursive:true});
|
|
83
|
+
const registration=path.join(registry,createHash('sha256').update(root).digest('hex')+'.json');
|
|
84
|
+
if(!await stat(registration))await fs.writeFile(registration,JSON.stringify({root}),{flag:'wx'});
|
|
82
85
|
return {ok:true,package:PACKAGE.name,version:PACKAGE.version,targetRoot:root,transaction,skills:results};
|
|
83
86
|
}catch(e){for(const item of changed.reverse()){if(item.backup)await restore(item.backup,item.dest,item.inPlace);else if(await stat(item.dest))await fs.rm(item.dest,{recursive:true,force:true});}throw e;}
|
|
84
87
|
finally{await fs.rmdir(lock);}
|
package/suite-manifest.json
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"tbcli-tools",
|
|
10
10
|
"sycmcli-tools",
|
|
11
11
|
"html-report",
|
|
12
|
-
"project-management"
|
|
12
|
+
"project-management",
|
|
13
|
+
"seedaudio-tools"
|
|
13
14
|
]
|
|
14
15
|
},
|
|
15
16
|
"nodes": [
|
|
@@ -20,9 +21,13 @@
|
|
|
20
21
|
"stage": "shared-reporting",
|
|
21
22
|
"method_version": "commerce-ui-template-pack@1",
|
|
22
23
|
"requires_skills": [],
|
|
23
|
-
"python_imports": [
|
|
24
|
+
"python_imports": [
|
|
25
|
+
"jsonschema"
|
|
26
|
+
],
|
|
24
27
|
"scripts": [],
|
|
25
|
-
"native_requirements": [
|
|
28
|
+
"native_requirements": [
|
|
29
|
+
"browser.report.inspect"
|
|
30
|
+
]
|
|
26
31
|
},
|
|
27
32
|
{
|
|
28
33
|
"id": "operations",
|
|
@@ -107,7 +112,9 @@
|
|
|
107
112
|
"python_imports": [],
|
|
108
113
|
"scripts": [],
|
|
109
114
|
"native_requirements": [],
|
|
110
|
-
"optional_tools": [
|
|
115
|
+
"optional_tools": [
|
|
116
|
+
"dws"
|
|
117
|
+
]
|
|
111
118
|
},
|
|
112
119
|
{
|
|
113
120
|
"id": "tbcli-tools",
|
|
@@ -128,6 +135,16 @@
|
|
|
128
135
|
"python_imports": [],
|
|
129
136
|
"scripts": [],
|
|
130
137
|
"native_requirements": []
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "seedaudio-tools",
|
|
141
|
+
"skill": "seedaudiocli",
|
|
142
|
+
"component": "seedaudiocli",
|
|
143
|
+
"stage": "visual-production-audio",
|
|
144
|
+
"requires_skills": [],
|
|
145
|
+
"python_imports": [],
|
|
146
|
+
"scripts": [],
|
|
147
|
+
"native_requirements": []
|
|
131
148
|
}
|
|
132
149
|
],
|
|
133
150
|
"tools": {
|
|
@@ -158,6 +175,11 @@
|
|
|
158
175
|
"minimum_version": "0.5.0",
|
|
159
176
|
"executable_env": "TAOBAO_AI_OPS_YCCLI",
|
|
160
177
|
"role": "authorized Yuce monthly collection; optional for supplied Excel"
|
|
178
|
+
},
|
|
179
|
+
"seedaudiocli": {
|
|
180
|
+
"package": "@petercjl/seedaudiocli",
|
|
181
|
+
"component": "seedaudiocli",
|
|
182
|
+
"role": "audio generation, reference voices, image-conditioned audio and task recovery"
|
|
161
183
|
}
|
|
162
184
|
},
|
|
163
185
|
"targets": {
|
|
@@ -171,18 +193,25 @@
|
|
|
171
193
|
"during_run": "installed-component-set",
|
|
172
194
|
"automatic_install": false,
|
|
173
195
|
"offline": "keep-current",
|
|
174
|
-
"source_checkout": "git-managed"
|
|
196
|
+
"source_checkout": "git-managed",
|
|
197
|
+
"automatic_components": [
|
|
198
|
+
"seedaudiocli"
|
|
199
|
+
]
|
|
175
200
|
},
|
|
176
201
|
"components": {
|
|
177
202
|
"procli": {
|
|
178
203
|
"package": "@petercjl/procli",
|
|
179
204
|
"bin": "procli",
|
|
180
|
-
"skills": [
|
|
205
|
+
"skills": [
|
|
206
|
+
"project-management"
|
|
207
|
+
]
|
|
181
208
|
},
|
|
182
209
|
"html-report": {
|
|
183
210
|
"package": "@petercjl/commerce-ui",
|
|
184
211
|
"bin": "commerce-ui",
|
|
185
|
-
"skills": [
|
|
212
|
+
"skills": [
|
|
213
|
+
"compact-commerce-ui"
|
|
214
|
+
]
|
|
186
215
|
},
|
|
187
216
|
"category-research": {
|
|
188
217
|
"package": "@petercjl/yuce-category-opportunity-report",
|
|
@@ -211,6 +240,14 @@
|
|
|
211
240
|
"skills": [
|
|
212
241
|
"sycmcli"
|
|
213
242
|
]
|
|
243
|
+
},
|
|
244
|
+
"seedaudiocli": {
|
|
245
|
+
"package": "@petercjl/seedaudiocli",
|
|
246
|
+
"bin": "seedaudiocli",
|
|
247
|
+
"skills": [
|
|
248
|
+
"seedaudiocli"
|
|
249
|
+
],
|
|
250
|
+
"automatic_update": true
|
|
214
251
|
}
|
|
215
252
|
}
|
|
216
253
|
}
|