@@ -22,6 +22,7 @@ import { PI_SEARCH_PROVIDERS } from '@/executor/handlers/pi/keys'
2222
2323const searchProviderField = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'searchProvider' )
2424const searchApiKeyField = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'searchApiKey' )
25+ const targetBranchField = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'targetBranch' )
2526
2627function searchKeyVisible ( values : Record < string , unknown > ) : boolean {
2728 return evaluateSubBlockCondition ( searchApiKeyField ?. condition , values )
@@ -84,69 +85,73 @@ describe('Pi block search fields', () => {
8485 } )
8586} )
8687
87- describe ( 'Pi Create PR Babysit surface' , ( ) => {
88- it ( 'offers exactly Create PR, Review Code, and Local Dev as top-level modes' , ( ) => {
88+ describe ( 'Pi cloud authoring surface' , ( ) => {
89+ it ( 'offers Create PR, Update Branch , Review Code, and Local Dev as top-level modes' , ( ) => {
8990 const mode = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'mode' )
9091 const options =
9192 typeof mode ?. options === 'function'
9293 ? mode . options ( )
9394 : ( mode ?. options as Array < { id : string } > | undefined )
9495
95- expect ( options ?. map ( ( { id } ) => id ) ) . toEqual ( [ 'cloud' , 'cloud_review' , 'local' ] )
96+ expect ( options ?. map ( ( { id } ) => id ) ) . toEqual ( [ 'cloud' , 'cloud_branch' , ' cloud_review', 'local' ] )
9697 } )
9798
98- it ( 'declares the toggle, required reviewer mentions, advanced rounds, and result outputs' , ( ) => {
99- const toggle = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'babysitMode' )
100- const maxRounds = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'maxRounds' )
101- const mentions = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'reviewMentions' )
102-
103- expect ( toggle ) . toMatchObject ( {
104- type : 'switch' ,
105- defaultValue : false ,
106- condition : { field : 'mode' , value : 'cloud' } ,
107- } )
108- expect ( maxRounds ) . toMatchObject ( {
109- type : 'short-input' ,
110- defaultValue : '3' ,
111- mode : 'advanced' ,
112- condition : {
113- field : 'mode' ,
114- value : 'cloud' ,
115- and : { field : 'babysitMode' , value : true } ,
116- } ,
117- } )
118- expect ( mentions ) . toMatchObject ( {
119- type : 'short-input' ,
120- defaultValue : '' ,
121- hideDividerBefore : true ,
122- required : {
123- field : 'mode' ,
124- value : 'cloud' ,
125- and : { field : 'babysitMode' , value : true } ,
126- } ,
127- condition : {
128- field : 'mode' ,
129- value : 'cloud' ,
130- and : { field : 'babysitMode' , value : true } ,
131- } ,
132- } )
133- for ( const output of [
134- 'rounds' ,
135- 'threadsClean' ,
136- 'checksGreen' ,
137- 'threadsResolved' ,
138- 'commitsPushed' ,
139- 'stopReason' ,
140- ] ) {
141- expect ( PiBlock . outputs [ output ] ) . toMatchObject ( {
99+ it . each ( [ 'cloud' , 'cloud_branch' ] ) (
100+ 'declares Babysit controls and outputs for %s' ,
101+ ( authoringMode ) => {
102+ const toggle = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'babysitMode' )
103+ const maxRounds = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'maxRounds' )
104+ const mentions = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'reviewMentions' )
105+
106+ expect ( toggle ) . toMatchObject ( {
107+ type : 'switch' ,
108+ defaultValue : false ,
109+ condition : { field : 'mode' , value : [ 'cloud' , 'cloud_branch' ] } ,
110+ } )
111+ expect ( maxRounds ) . toMatchObject ( {
112+ type : 'short-input' ,
113+ defaultValue : '3' ,
114+ mode : 'advanced' ,
142115 condition : {
143116 field : 'mode' ,
144- value : 'cloud' ,
117+ value : [ 'cloud' , 'cloud_branch' ] ,
145118 and : { field : 'babysitMode' , value : true } ,
146119 } ,
147120 } )
121+ expect ( mentions ) . toMatchObject ( {
122+ type : 'short-input' ,
123+ defaultValue : '' ,
124+ hideDividerBefore : true ,
125+ required : {
126+ field : 'mode' ,
127+ value : [ 'cloud' , 'cloud_branch' ] ,
128+ and : { field : 'babysitMode' , value : true } ,
129+ } ,
130+ condition : {
131+ field : 'mode' ,
132+ value : [ 'cloud' , 'cloud_branch' ] ,
133+ and : { field : 'babysitMode' , value : true } ,
134+ } ,
135+ } )
136+ for ( const output of [
137+ 'rounds' ,
138+ 'threadsClean' ,
139+ 'checksGreen' ,
140+ 'threadsResolved' ,
141+ 'commitsPushed' ,
142+ 'stopReason' ,
143+ ] ) {
144+ expect ( PiBlock . outputs [ output ] ) . toMatchObject ( {
145+ condition : {
146+ field : 'mode' ,
147+ value : [ 'cloud' , 'cloud_branch' ] ,
148+ and : { field : 'babysitMode' , value : true } ,
149+ } ,
150+ } )
151+ }
152+ expect ( evaluateSubBlockCondition ( toggle ?. condition , { mode : authoringMode } ) ) . toBe ( true )
148153 }
149- } )
154+ )
150155
151156 it ( 'requires a task and hides Draft PR while Babysit Mode is enabled' , ( ) => {
152157 const task = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === 'task' )
@@ -167,4 +172,55 @@ describe('Pi Create PR Babysit surface', () => {
167172 expect ( evaluateSubBlockCondition ( pullNumber ?. condition , { mode : 'cloud' } ) ) . toBe ( false )
168173 expect ( evaluateSubBlockCondition ( pullNumber ?. condition , { mode : 'cloud_review' } ) ) . toBe ( true )
169174 } )
175+
176+ it ( 'requires the target branch only in Update Branch mode' , ( ) => {
177+ expect ( targetBranchField ?. type ) . toBe ( 'short-input' )
178+ expect ( targetBranchField ?. required ) . toBe ( true )
179+ expect ( evaluateSubBlockCondition ( targetBranchField ?. condition , { mode : 'cloud_branch' } ) ) . toBe (
180+ true
181+ )
182+ expect ( evaluateSubBlockCondition ( targetBranchField ?. condition , { mode : 'cloud' } ) ) . toBe ( false )
183+ expect ( evaluateSubBlockCondition ( targetBranchField ?. condition , { mode : 'cloud_review' } ) ) . toBe (
184+ false
185+ )
186+ expect ( evaluateSubBlockCondition ( targetBranchField ?. condition , { mode : 'local' } ) ) . toBe ( false )
187+ } )
188+
189+ it ( 'declares the target branch input and branch output for cloud authoring modes' , ( ) => {
190+ expect ( PiBlock . inputs . targetBranch ) . toBeDefined ( )
191+ expect (
192+ evaluateSubBlockCondition ( PiBlock . outputs . branch . condition , { mode : 'cloud_branch' } )
193+ ) . toBe ( true )
194+ expect ( evaluateSubBlockCondition ( PiBlock . outputs . branch . condition , { mode : 'cloud' } ) ) . toBe (
195+ true
196+ )
197+ expect (
198+ evaluateSubBlockCondition ( PiBlock . outputs . branch . condition , { mode : 'cloud_review' } )
199+ ) . toBe ( false )
200+ } )
201+
202+ it ( 'reuses skills and memory fields, including their dependent controls' , ( ) => {
203+ for ( const id of [
204+ 'skills' ,
205+ 'memoryType' ,
206+ 'conversationId' ,
207+ 'slidingWindowSize' ,
208+ 'slidingWindowTokens' ,
209+ ] ) {
210+ const field = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === id )
211+ expect (
212+ evaluateSubBlockCondition ( field ?. condition , {
213+ mode : 'cloud_branch' ,
214+ memoryType : id === 'slidingWindowTokens' ? 'sliding_window_tokens' : 'sliding_window' ,
215+ } )
216+ ) . toBe ( true )
217+ }
218+ } )
219+
220+ it ( 'hides Create PR and Review Code-specific fields' , ( ) => {
221+ for ( const id of [ 'baseBranch' , 'branchName' , 'draft' , 'prTitle' , 'prBody' , 'pullNumber' ] ) {
222+ const field = PiBlock . subBlocks . find ( ( subBlock ) => subBlock . id === id )
223+ expect ( evaluateSubBlockCondition ( field ?. condition , { mode : 'cloud_branch' } ) ) . toBe ( false )
224+ }
225+ } )
170226} )
0 commit comments