@@ -16,6 +16,7 @@ import {
1616import * as DateTime from "effect/DateTime" ;
1717import * as Effect from "effect/Effect" ;
1818import * as Layer from "effect/Layer" ;
19+ import * as Option from "effect/Option" ;
1920import * as NodeCrypto from "@effect/platform-node/NodeCrypto" ;
2021import * as NodeServices from "@effect/platform-node/NodeServices" ;
2122import { expect , it } from "vite-plus/test" ;
@@ -708,3 +709,57 @@ it("readThread returns canonical speech with bounded text continuation and no ex
708709 ) . toBe ( true ) ;
709710 } ) . pipe ( Effect . provide ( layer ) , Effect . runPromise ) ;
710711} ) ;
712+
713+ it ( "scheduleTask from an MCP client uses the environment default model when the project has none" , async ( ) => {
714+ const globalDefault = {
715+ instanceId : ProviderInstanceId . make ( "claudeAgent" ) ,
716+ model : "claude-haiku" ,
717+ } ;
718+ const upserted : Array < unknown > = [ ] ;
719+ const layer = layerOrchestratorService . pipe (
720+ Layer . provide (
721+ Layer . mergeAll (
722+ unusedDelegationPolicyLayer ,
723+ ServerSettings . layerTest ( { defaultModelSelection : globalDefault } ) ,
724+ Layer . mock ( ThreadManagementService . ThreadManagementService ) ( { } ) ,
725+ Layer . mock ( ProviderRegistry . ProviderRegistry ) ( { getProviders : Effect . succeed ( [ ] ) } ) ,
726+ Layer . mock ( ProjectService . ProjectService ) ( {
727+ getById : ( ) =>
728+ Effect . succeed ( Option . some ( { id : projectId , defaultModelSelection : null } as never ) ) ,
729+ } ) ,
730+ Layer . mock ( SecretRequests . SecretRequests ) ( { } ) ,
731+ Layer . mock ( RemoteDelegation . RemoteDelegation ) ( { } ) ,
732+ Layer . mock ( ScheduledTaskService . ScheduledTaskService ) ( {
733+ upsert : ( input ) =>
734+ Effect . sync ( ( ) => upserted . push ( input . modelSelection ) ) . pipe (
735+ Effect . andThen ( Effect . die ( "upsert recorded" ) ) ,
736+ ) ,
737+ } ) ,
738+ Layer . mock ( ProviderAdapterRegistry . ProviderAdapterRegistryV2 ) ( {
739+ list : ( ) => Effect . succeed ( [ ] ) ,
740+ } ) ,
741+ NodeCrypto . layer ,
742+ ) ,
743+ ) ,
744+ ) ;
745+
746+ await Effect . gen ( function * ( ) {
747+ const service = yield * OrchestratorMcpService . OrchestratorMcpService ;
748+ yield * service
749+ . scheduleTask (
750+ {
751+ ...makeScope ( ) ,
752+ thread : undefined ,
753+ client : { sessionId : "session-1" , label : "Claude Code" , access : "auto" } ,
754+ } ,
755+ {
756+ projectId,
757+ prompt : "check in later" ,
758+ enabled : false ,
759+ schedule : { type : "interval" , everyMs : 3_600_000 } ,
760+ } ,
761+ )
762+ . pipe ( Effect . exit ) ;
763+ expect ( upserted ) . toEqual ( [ globalDefault ] ) ;
764+ } ) . pipe ( Effect . provide ( layer ) , Effect . runPromise ) ;
765+ } ) ;
0 commit comments