@@ -49,6 +49,7 @@ import type { ProviderInstance } from "../ProviderDriver.ts";
4949import { ProviderInstanceRegistry } from "../Services/ProviderInstanceRegistry.ts" ;
5050import { ProviderRegistry } from "../Services/ProviderRegistry.ts" ;
5151import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMaintenance.ts" ;
52+ import { makeManagedServerProvider } from "../makeManagedServerProvider.ts" ;
5253const decodeServerSettings = Schema . decodeSync ( ServerSettings ) ;
5354const encodeServerSettings = Schema . encodeSync ( ServerSettings ) ;
5455const encodedDefaultServerSettings = encodeServerSettings ( DEFAULT_SERVER_SETTINGS ) ;
@@ -845,6 +846,108 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsService.layerTest(), T
845846 } ) ,
846847 ) ;
847848
849+ it . effect ( "is the single startup refresh owner for managed provider instances" , ( ) =>
850+ Effect . scoped (
851+ Effect . gen ( function * ( ) {
852+ const codexDriver = ProviderDriverKind . make ( "codex" ) ;
853+ const codexInstanceId = ProviderInstanceId . make ( "codex" ) ;
854+ const initialProvider = {
855+ instanceId : codexInstanceId ,
856+ driver : codexDriver ,
857+ status : "warning" ,
858+ enabled : true ,
859+ installed : false ,
860+ auth : { status : "unknown" } ,
861+ checkedAt : "2026-04-29T10:00:00.000Z" ,
862+ version : null ,
863+ message : "Checking provider availability..." ,
864+ models : [ ] ,
865+ slashCommands : [ ] ,
866+ skills : [ ] ,
867+ } as const satisfies ServerProvider ;
868+ const { message : _message , ...initialProviderWithoutMessage } = initialProvider ;
869+ const refreshedProvider = {
870+ ...initialProviderWithoutMessage ,
871+ status : "ready" ,
872+ installed : true ,
873+ checkedAt : "2026-04-29T10:00:01.000Z" ,
874+ } as const satisfies ServerProvider ;
875+ const checkCalls = yield * Ref . make ( 0 ) ;
876+ const managedProvider = yield * makeManagedServerProvider < { readonly enabled : boolean } > (
877+ {
878+ maintenanceCapabilities : makeManualOnlyProviderMaintenanceCapabilities ( {
879+ provider : codexDriver ,
880+ packageName : null ,
881+ } ) ,
882+ getSettings : Effect . succeed ( { enabled : true } ) ,
883+ streamSettings : Stream . empty ,
884+ haveSettingsChanged : ( previous , next ) => previous . enabled !== next . enabled ,
885+ initialSnapshot : ( ) => Effect . succeed ( initialProvider ) ,
886+ checkProvider : Ref . update ( checkCalls , ( count ) => count + 1 ) . pipe (
887+ Effect . as ( refreshedProvider ) ,
888+ ) ,
889+ refreshInterval : "1 hour" ,
890+ } ,
891+ ) ;
892+
893+ yield * Effect . yieldNow ;
894+ assert . strictEqual (
895+ yield * Ref . get ( checkCalls ) ,
896+ 0 ,
897+ "managed providers must not self-start their own boot probe" ,
898+ ) ;
899+
900+ const instance = {
901+ instanceId : codexInstanceId ,
902+ driverKind : codexDriver ,
903+ continuationIdentity : {
904+ driverKind : codexDriver ,
905+ continuationKey : "codex:instance:codex" ,
906+ } ,
907+ displayName : undefined ,
908+ enabled : true ,
909+ snapshot : managedProvider ,
910+ adapter : { } as ProviderInstance [ "adapter" ] ,
911+ textGeneration : { } as ProviderInstance [ "textGeneration" ] ,
912+ } satisfies ProviderInstance ;
913+ const instanceRegistryLayer = Layer . succeed ( ProviderInstanceRegistry , {
914+ getInstance : ( instanceId ) =>
915+ Effect . succeed ( instanceId === codexInstanceId ? instance : undefined ) ,
916+ listInstances : Effect . succeed ( [ instance ] ) ,
917+ listUnavailable : Effect . succeed ( [ ] ) ,
918+ streamChanges : Stream . empty ,
919+ subscribeChanges : Effect . flatMap ( PubSub . unbounded < void > ( ) , ( pubsub ) =>
920+ PubSub . subscribe ( pubsub ) ,
921+ ) ,
922+ } ) ;
923+ const scope = yield * Scope . make ( ) ;
924+ yield * Effect . addFinalizer ( ( ) => Scope . close ( scope , Exit . void ) ) ;
925+ const runtimeServices = yield * Layer . build (
926+ ProviderRegistryLive . pipe (
927+ Layer . provideMerge ( instanceRegistryLayer ) ,
928+ Layer . provideMerge (
929+ ServerConfig . layerTest ( process . cwd ( ) , {
930+ prefix : "t3-provider-registry-single-startup-refresh-" ,
931+ } ) ,
932+ ) ,
933+ Layer . provideMerge ( NodeServices . layer ) ,
934+ ) ,
935+ ) . pipe ( Scope . provide ( scope ) ) ;
936+
937+ yield * Effect . gen ( function * ( ) {
938+ const registry = yield * ProviderRegistry ;
939+
940+ assert . deepStrictEqual ( yield * registry . getProviders , [ refreshedProvider ] ) ;
941+ assert . strictEqual (
942+ yield * Ref . get ( checkCalls ) ,
943+ 1 ,
944+ "ProviderRegistryLive should perform exactly one startup refresh" ,
945+ ) ;
946+ } ) . pipe ( Effect . provide ( runtimeServices ) ) ;
947+ } ) ,
948+ ) ,
949+ ) ;
950+
848951 it . effect ( "keeps consuming registry changes after one sync fails" , ( ) =>
849952 Effect . gen ( function * ( ) {
850953 const codexDriver = ProviderDriverKind . make ( "codex" ) ;
0 commit comments