@@ -12,6 +12,7 @@ import {
1212 writeSkillLock ,
1313} from "bailian-cli-core" ;
1414import { emitBare , emitResult , formatTable } from "bailian-cli-runtime" ;
15+ import { planFanoutLinks , summarizeAgents } from "./dry-run-plan.ts" ;
1516
1617interface AddOutcome {
1718 name : string ;
@@ -57,26 +58,51 @@ export default defineCommand({
5758 exampleArgs : [ "--all" , "--name spark-video,bailian-model-recommend" ] ,
5859 async run ( ctx ) {
5960 const format = ctx . settings . outputExplicit ? ctx . settings . output : "json" ;
60- const agents = detectInstalledAgents ( ) ;
61+ const index = await fetchSkillsIndex ( ) ;
62+ const remoteNames = Object . keys ( index . skills ) ;
6163 const parsed = ctx . flags . all ? "all" : parseSkillNames ( ctx . flags . name , false ) ;
64+ const names = parsed === "all" ? remoteNames : parsed ;
65+ const agents = detectInstalledAgents ( ) ;
6266
6367 if ( ctx . settings . dryRun ) {
68+ const skills = names . map ( ( name ) => {
69+ const entry = index . skills [ name ] ;
70+ if ( ! entry ) {
71+ return {
72+ name,
73+ status : "failed" as const ,
74+ reason : "skill not found in registry" ,
75+ } ;
76+ }
77+ return {
78+ name,
79+ status : "install" as const ,
80+ publishedAt : entry . publishedAt ,
81+ links : planFanoutLinks ( name , agents ) ,
82+ } ;
83+ } ) ;
84+
6485 emitResult (
6586 {
6687 action : "skill.add" ,
6788 registry : getSkillRegistryBaseUrl ( ) ,
68- agents : agents . map ( ( agent ) => agent . id ) ,
69- skills : parsed ,
89+ agents : summarizeAgents ( agents ) ,
90+ skills,
7091 } ,
7192 format ,
7293 ) ;
94+
95+ const failed = skills . filter ( ( skill ) => skill . status === "failed" ) ;
96+ if ( failed . length > 0 ) {
97+ throw new BailianError (
98+ `${ failed . length } /${ skills . length } skill(s) failed to install` ,
99+ ExitCode . GENERAL ,
100+ "Check the reason for failed skills in the output; network failures can be retried with bl skill add" ,
101+ ) ;
102+ }
73103 return ;
74104 }
75105
76- const index = await fetchSkillsIndex ( ) ;
77- const remoteNames = Object . keys ( index . skills ) ;
78- const names = parsed === "all" ? remoteNames : parsed ;
79-
80106 const lock = readSkillLock ( ) ;
81107
82108 // collect-then-throw: a single skill failure only affects itself; successful ones are written to disk and lock as usual.
0 commit comments