@@ -527,6 +527,7 @@ export interface PullOptions {
527527 force ?: boolean ;
528528 bootstrap ?: boolean ;
529529 typeFilter ?: ResourceType [ ] ;
530+ resourceIds ?: string [ ] ;
530531}
531532
532533export interface PullResult {
@@ -543,23 +544,45 @@ export async function pullResourceType(
543544 changedFiles ?: Set < string > ;
544545 force ?: boolean ;
545546 bootstrap ?: boolean ;
547+ resourceIds ?: string [ ] ;
546548 } = { } ,
547549) : Promise < PullStats > {
548- const { changedFiles, force, bootstrap } = options ;
550+ const { changedFiles, force, bootstrap, resourceIds } = options ;
549551 console . log ( `\n📥 Pulling ${ resourceType } ...` ) ;
550552
551- const resources = ( await fetchAllResources ( resourceType ) ) ?? [ ] ;
553+ const allResources = ( await fetchAllResources ( resourceType ) ) ?? [ ] ;
552554
553- if ( ! Array . isArray ( resources ) ) {
555+ if ( ! Array . isArray ( allResources ) ) {
554556 console . log ( ` ⚠️ No ${ resourceType } found (API returned non-array)` ) ;
555557 return { created : 0 , updated : 0 , skipped : 0 } ;
556558 }
557559
558- console . log ( ` Found ${ resources . length } ${ resourceType } in Vapi` ) ;
560+ let resources = allResources ;
561+ if ( resourceIds ?. length ) {
562+ const requestedIds = new Set ( resourceIds ) ;
563+ resources = allResources . filter ( ( resource ) =>
564+ requestedIds . has ( resource . id ) ,
565+ ) ;
566+ const foundIds = new Set ( resources . map ( ( resource ) => resource . id ) ) ;
567+ const missingIds = resourceIds . filter ( ( id ) => ! foundIds . has ( id ) ) ;
568+
569+ console . log (
570+ ` Found ${ resources . length } matching ${ resourceType } in Vapi (requested ${ resourceIds . length } )` ,
571+ ) ;
572+ if ( missingIds . length > 0 ) {
573+ console . log (
574+ ` ⚠️ Requested IDs not found for ${ resourceType } : ${ missingIds . join ( ", " ) } ` ,
575+ ) ;
576+ }
577+ } else {
578+ console . log ( ` Found ${ resources . length } ${ resourceType } in Vapi` ) ;
579+ }
559580
560581 const reverseMap = buildReverseMap ( state , resourceType ) ;
561582 const credReverse = credentialReverseMap ( state ) ;
562- const newStateSection : Record < string , string > = { } ;
583+ const newStateSection : Record < string , string > = resourceIds ?. length
584+ ? { ...state [ resourceType ] }
585+ : { } ;
563586
564587 let created = 0 ;
565588 let updated = 0 ;
@@ -672,6 +695,15 @@ export async function runPull(options: PullOptions = {}): Promise<PullResult> {
672695 const force = options . force ?? process . argv . includes ( "--force" ) ;
673696 const bootstrap = options . bootstrap ?? BOOTSTRAP_SYNC ;
674697 const typeFilter = options . typeFilter ?? APPLY_FILTER . resourceTypes ;
698+ const resourceIds = options . resourceIds ?? APPLY_FILTER . resourceIds ;
699+
700+ if ( resourceIds ?. length ) {
701+ if ( ! typeFilter ?. length || typeFilter . length !== 1 ) {
702+ throw new Error (
703+ "Single-resource pull requires exactly one resource type. Example: npm run pull:dev -- squads --id <uuid>" ,
704+ ) ;
705+ }
706+ }
675707
676708 console . log (
677709 "═══════════════════════════════════════════════════════════════" ,
@@ -683,6 +715,9 @@ export async function runPull(options: PullOptions = {}): Promise<PullResult> {
683715 if ( typeFilter ?. length ) {
684716 console . log ( ` Filter: ${ typeFilter . join ( ", " ) } ` ) ;
685717 }
718+ if ( resourceIds ?. length ) {
719+ console . log ( ` IDs: ${ resourceIds . join ( ", " ) } ` ) ;
720+ }
686721 if ( bootstrap ) {
687722 console . log (
688723 " Mode: state sync only (remote resources are not written locally)" ,
@@ -749,48 +784,55 @@ export async function runPull(options: PullOptions = {}): Promise<PullResult> {
749784 changedFiles,
750785 force,
751786 bootstrap,
787+ resourceIds,
752788 } ) ;
753789 if ( shouldPull ( "assistants" ) )
754790 stats . assistants = await pullResourceType ( "assistants" , state , {
755791 changedFiles,
756792 force,
757793 bootstrap,
794+ resourceIds,
758795 } ) ;
759796 if ( shouldPull ( "structuredOutputs" ) )
760797 stats . structuredOutputs = await pullResourceType (
761798 "structuredOutputs" ,
762799 state ,
763- { changedFiles, force, bootstrap } ,
800+ { changedFiles, force, bootstrap, resourceIds } ,
764801 ) ;
765802 if ( shouldPull ( "squads" ) )
766803 stats . squads = await pullResourceType ( "squads" , state , {
767804 changedFiles,
768805 force,
769806 bootstrap,
807+ resourceIds,
770808 } ) ;
771809 if ( shouldPull ( "personalities" ) )
772810 stats . personalities = await pullResourceType ( "personalities" , state , {
773811 changedFiles,
774812 force,
775813 bootstrap,
814+ resourceIds,
776815 } ) ;
777816 if ( shouldPull ( "scenarios" ) )
778817 stats . scenarios = await pullResourceType ( "scenarios" , state , {
779818 changedFiles,
780819 force,
781820 bootstrap,
821+ resourceIds,
782822 } ) ;
783823 if ( shouldPull ( "simulations" ) )
784824 stats . simulations = await pullResourceType ( "simulations" , state , {
785825 changedFiles,
786826 force,
787827 bootstrap,
828+ resourceIds,
788829 } ) ;
789830 if ( shouldPull ( "simulationSuites" ) )
790831 stats . simulationSuites = await pullResourceType ( "simulationSuites" , state , {
791832 changedFiles,
792833 force,
793834 bootstrap,
835+ resourceIds,
794836 } ) ;
795837
796838 await saveState ( state ) ;
0 commit comments