@@ -6,7 +6,6 @@ import { FSUtil } from "@opencode-ai/core/fs-util"
66import { InstanceState } from "@/effect/instance-state"
77import { RuntimeFlags } from "@/effect/runtime-flags"
88import { PartID } from "./schema"
9- import { MessageV2 } from "./message-v2"
109import { Session } from "./session"
1110import PROMPT_PLAN from "./prompt/plan.txt"
1211import BUILD_SWITCH from "./prompt/build-switch.txt"
@@ -25,23 +24,33 @@ export const apply = Effect.fn("SessionReminders.apply")(function* (input: {
2524
2625 if ( ! flags . experimentalPlanMode ) {
2726 if ( input . agent . name === "plan" ) {
27+ const text = yield * Effect . gen ( function * ( ) {
28+ if ( ! input . agent . planReminder ) return PROMPT_PLAN
29+ const state = yield * planState ( input . session , fsys )
30+ return render ( input . agent . planReminder , state . planReminder )
31+ } )
2832 userMessage . parts . push ( {
2933 id : PartID . ascending ( ) ,
3034 messageID : userMessage . info . id ,
3135 sessionID : userMessage . info . sessionID ,
3236 type : "text" ,
33- text : PROMPT_PLAN ,
37+ text,
3438 synthetic : true ,
3539 } )
3640 }
3741 const wasPlan = input . messages . some ( ( msg ) => msg . info . role === "assistant" && msg . info . agent === "plan" )
3842 if ( wasPlan && input . agent . name === "build" ) {
43+ const text = yield * Effect . gen ( function * ( ) {
44+ if ( ! input . agent . buildSwitchReminder ) return BUILD_SWITCH
45+ const state = yield * planState ( input . session , fsys )
46+ return render ( input . agent . buildSwitchReminder , state . buildSwitch )
47+ } )
3948 userMessage . parts . push ( {
4049 id : PartID . ascending ( ) ,
4150 messageID : userMessage . info . id ,
4251 sessionID : userMessage . info . sessionID ,
4352 type : "text" ,
44- text : BUILD_SWITCH ,
53+ text,
4554 synthetic : true ,
4655 } )
4756 }
@@ -50,17 +59,17 @@ export const apply = Effect.fn("SessionReminders.apply")(function* (input: {
5059
5160 const assistantMessage = input . messages . findLast ( ( msg ) => msg . info . role === "assistant" )
5261 if ( input . agent . name !== "plan" && assistantMessage ?. info . agent === "plan" ) {
53- const ctx = yield * InstanceState . context
54- const plan = Session . plan ( input . session , ctx )
55- const exists = yield * fsys . existsSafe ( plan )
62+ const state = yield * planState ( input . session , fsys )
5663 const part = yield * sessions . updatePart ( {
5764 id : PartID . ascending ( ) ,
5865 messageID : userMessage . info . id ,
5966 sessionID : userMessage . info . sessionID ,
6067 type : "text" ,
61- text : exists
62- ? `${ BUILD_SWITCH } \n\nA plan file exists at ${ plan } . You should execute on the plan defined within it`
63- : BUILD_SWITCH ,
68+ text : input . agent . buildSwitchReminder
69+ ? render ( input . agent . buildSwitchReminder , state . buildSwitch )
70+ : state . exists
71+ ? `${ BUILD_SWITCH } \n\n${ state . buildSwitch } `
72+ : BUILD_SWITCH ,
6473 synthetic : true ,
6574 } )
6675 userMessage . parts . push ( part )
@@ -69,24 +78,38 @@ export const apply = Effect.fn("SessionReminders.apply")(function* (input: {
6978
7079 if ( input . agent . name !== "plan" || assistantMessage ?. info . agent === "plan" ) return input . messages
7180
72- const ctx = yield * InstanceState . context
73- const plan = Session . plan ( input . session , ctx )
74- const exists = yield * fsys . existsSafe ( plan )
75- if ( ! exists ) yield * fsys . ensureDir ( path . dirname ( plan ) ) . pipe ( Effect . catch ( Effect . die ) )
81+ const state = yield * planState ( input . session , fsys )
82+ if ( ! state . exists ) yield * fsys . ensureDir ( path . dirname ( state . filepath ) ) . pipe ( Effect . catch ( Effect . die ) )
7683 const part = yield * sessions . updatePart ( {
7784 id : PartID . ascending ( ) ,
7885 messageID : userMessage . info . id ,
7986 sessionID : userMessage . info . sessionID ,
8087 type : "text" ,
81- text : PLAN_MODE . replace ( "${planInfo}" , ( ) =>
82- exists
83- ? `A plan file already exists at ${ plan } . You can read it and make incremental edits using the edit tool.`
84- : `No plan file exists yet. You should create your plan at ${ plan } using the write tool.` ,
85- ) ,
88+ text : input . agent . planReminder ? render ( input . agent . planReminder , state . planReminder ) : render ( PLAN_MODE , state . planReminder ) ,
8689 synthetic : true ,
8790 } )
8891 userMessage . parts . push ( part )
8992 return input . messages
9093} )
9194
95+ function render ( template : string , planInfo : string ) {
96+ return template . replaceAll ( "${planInfo}" , planInfo )
97+ }
98+
99+ function planState ( session : Session . Info , fsys : FSUtil . Interface ) {
100+ return Effect . gen ( function * ( ) {
101+ const ctx = yield * InstanceState . context
102+ const filepath = Session . plan ( session , ctx )
103+ const exists = yield * fsys . existsSafe ( filepath )
104+ return {
105+ exists,
106+ filepath,
107+ planReminder : exists
108+ ? `A plan file already exists at ${ filepath } . You can read it and make incremental edits using the edit tool.`
109+ : `No plan file exists yet. You should create your plan at ${ filepath } using the write tool.` ,
110+ buildSwitch : exists ? `A plan file exists at ${ filepath } . You should execute on the plan defined within it` : "" ,
111+ }
112+ } )
113+ }
114+
92115export * as SessionReminders from "./reminders"
0 commit comments