Skip to content

Commit ae5d5e4

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
feat(pi): add update branch mode
1 parent fa8a56a commit ae5d5e4

13 files changed

Lines changed: 1121 additions & 188 deletions

File tree

apps/docs/content/docs/en/workflows/blocks/pi.mdx

Lines changed: 59 additions & 30 deletions
Large diffs are not rendered by default.

apps/sim/blocks/blocks/pi.test.ts

Lines changed: 105 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { PI_SEARCH_PROVIDERS } from '@/executor/handlers/pi/keys'
2222

2323
const searchProviderField = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'searchProvider')
2424
const searchApiKeyField = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'searchApiKey')
25+
const targetBranchField = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'targetBranch')
2526

2627
function 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

Comments
 (0)