@@ -6,13 +6,14 @@ import * as os from "os";
66import * as path from "path" ;
77import { GitFileHistory } from "../common/file-history" ;
88import { clearSessionState } from "../common/state" ;
9- import { getProjectCode , SessionManager , type SessionMessage } from "../session" ;
9+ import { getProjectCode , SessionManager , type SessionMessage , type SkillInfo } from "../session" ;
1010
1111const originalFetch = globalThis . fetch ;
1212const originalConsoleWarn = console . warn ;
1313const originalHome = process . env . HOME ;
1414const originalUserProfile = process . env . USERPROFILE ;
1515const tempDirs : string [ ] = [ ] ;
16+ const PLAN_MODE_STATUS_MESSAGE = "Set Plan Mode on. Awaiting <proposed_plan>." ;
1617
1718/** Set homedir in a cross-platform way (HOME on Unix, USERPROFILE on Windows). */
1819function setHomeDir ( dir : string ) : void {
@@ -522,6 +523,70 @@ test("SessionManager resolves bundled skill prompts", () => {
522523 assert . match ( prompt , / # S k i l l W r i t e r / ) ;
523524} ) ;
524525
526+ test ( "SessionManager appends plan mode status whenever the plan skill is selected" , async ( ) => {
527+ const workspace = createTempDir ( "deepcode-plan-skill-workspace-" ) ;
528+ const home = createTempDir ( "deepcode-plan-skill-home-" ) ;
529+ setHomeDir ( home ) ;
530+
531+ const manager = createSessionManager ( workspace , "machine-id-plan-skill" ) ;
532+ const planSkill = await getPlanSkill ( manager ) ;
533+
534+ const sessionId = await manager . createSession ( { text : "" , skills : [ planSkill ] } ) ;
535+ let messages = manager . listSessionMessages ( sessionId ) ;
536+ assert . equal ( countPlanModeStatusMessages ( messages ) , 1 ) ;
537+ assert . equal ( countLoadedSkillMessages ( messages , "plan" ) , 1 ) ;
538+
539+ await manager . replySession ( sessionId , { text : "" , skills : [ planSkill ] } ) ;
540+ messages = manager . listSessionMessages ( sessionId ) ;
541+ assert . equal ( countPlanModeStatusMessages ( messages ) , 2 ) ;
542+ assert . equal ( countLoadedSkillMessages ( messages , "plan" ) , 1 ) ;
543+ } ) ;
544+
545+ test ( "SessionManager appends plan mode status when the plan skill is auto-matched" , async ( ) => {
546+ const workspace = createTempDir ( "deepcode-plan-matched-workspace-" ) ;
547+ const home = createTempDir ( "deepcode-plan-matched-home-" ) ;
548+ setHomeDir ( home ) ;
549+
550+ const client = {
551+ chat : {
552+ completions : {
553+ create : async ( request : any ) => {
554+ if ( isSkillMatchingRequest ( request ) ) {
555+ return createSkillMatchingResponse ( [ "plan" ] ) ;
556+ }
557+ return createChatResponse ( "planned" , { prompt_tokens : 1 , completion_tokens : 1 , total_tokens : 2 } ) ;
558+ } ,
559+ } ,
560+ } ,
561+ } ;
562+ const manager = createMockedClientSessionManagerWithClient ( workspace , client ) ;
563+
564+ const sessionId = await manager . createSession ( { text : "Plan Mode for this change" } ) ;
565+ const messages = manager . listSessionMessages ( sessionId ) ;
566+ assert . equal ( countPlanModeStatusMessages ( messages ) , 1 ) ;
567+ assert . equal ( countLoadedSkillMessages ( messages , "plan" ) , 1 ) ;
568+ } ) ;
569+
570+ test ( "SessionManager appends plan mode status for deferred permission prompts" , async ( ) => {
571+ const workspace = createTempDir ( "deepcode-plan-deferred-workspace-" ) ;
572+ const home = createTempDir ( "deepcode-plan-deferred-home-" ) ;
573+ setHomeDir ( home ) ;
574+
575+ const manager = createSessionManager ( workspace , "machine-id-plan-deferred" ) ;
576+ const sessionId = await manager . createSession ( { text : "" } ) ;
577+ const planSkill = await getPlanSkill ( manager ) ;
578+
579+ await ( manager as any ) . appendDeferredPermissionPrompt (
580+ sessionId ,
581+ { text : "" , skills : [ planSkill ] } ,
582+ new AbortController ( )
583+ ) ;
584+
585+ const messages = manager . listSessionMessages ( sessionId ) ;
586+ assert . equal ( countPlanModeStatusMessages ( messages ) , 1 ) ;
587+ assert . equal ( countLoadedSkillMessages ( messages , "plan" ) , 1 ) ;
588+ } ) ;
589+
525590test ( "SessionManager excludes disabled skills by resolved skill name" , async ( ) => {
526591 const workspace = createTempDir ( "deepcode-disabled-skills-workspace-" ) ;
527592 const home = createTempDir ( "deepcode-disabled-skills-home-" ) ;
@@ -564,6 +629,7 @@ test("SessionManager excludes disabled skills by resolved skill name", async ()
564629 "renamed-disabled" : false ,
565630 "deepcode-self-refer" : false ,
566631 "skill-digester" : false ,
632+ plan : false ,
567633 "enabled-skill" : true ,
568634 } ,
569635 } ) ,
@@ -3400,6 +3466,20 @@ function createSessionManager(projectRoot: string, machineId: string): SessionMa
34003466 } ) ;
34013467}
34023468
3469+ async function getPlanSkill ( manager : SessionManager ) : Promise < SkillInfo > {
3470+ const planSkill = ( await manager . listSkills ( ) ) . find ( ( skill ) => skill . name === "plan" ) ;
3471+ assert . ok ( planSkill ) ;
3472+ return planSkill ;
3473+ }
3474+
3475+ function countPlanModeStatusMessages ( messages : SessionMessage [ ] ) : number {
3476+ return messages . filter ( ( message ) => message . role === "system" && message . content === PLAN_MODE_STATUS_MESSAGE ) . length ;
3477+ }
3478+
3479+ function countLoadedSkillMessages ( messages : SessionMessage [ ] , skillName : string ) : number {
3480+ return messages . filter ( ( message ) => message . role === "system" && message . meta ?. skill ?. name === skillName ) . length ;
3481+ }
3482+
34033483function createNotifyingSessionManager (
34043484 projectRoot : string ,
34053485 responses : unknown [ ] ,
@@ -3536,8 +3616,8 @@ function isSkillMatchingRequest(request: any): boolean {
35363616 return request ?. response_format ?. type === "json_object" ;
35373617}
35383618
3539- function createSkillMatchingResponse ( ) : unknown {
3540- return { choices : [ { message : { content : '{" skillNames":[]}' } } ] } ;
3619+ function createSkillMatchingResponse ( skillNames : string [ ] = [ ] ) : unknown {
3620+ return { choices : [ { message : { content : JSON . stringify ( { skillNames } ) } } ] } ;
35413621}
35423622
35433623function createChatResponse ( content : string , usage : Record < string , unknown > ) : unknown {
0 commit comments