Skip to content

Commit 4a701c4

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
feat(pi): manage pull requests in update mode
1 parent 5fa94fe commit 4a701c4

12 files changed

Lines changed: 681 additions & 224 deletions

File tree

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

Lines changed: 37 additions & 34 deletions
Large diffs are not rendered by default.

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('Pi block search fields', () => {
7676
})
7777

7878
describe('Pi cloud authoring surface', () => {
79-
it('offers Create PR, Update Branch, Review Code, and Local Dev as top-level modes', () => {
79+
it('offers Create PR, Update PR, Review Code, and Local Dev as top-level modes', () => {
8080
const mode = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'mode')
8181
const options =
8282
typeof mode?.options === 'function'
@@ -163,7 +163,7 @@ describe('Pi cloud authoring surface', () => {
163163
expect(evaluateSubBlockCondition(pullNumber?.condition, { mode: 'cloud_review' })).toBe(true)
164164
})
165165

166-
it('requires the target branch only in Update Branch mode', () => {
166+
it('requires the target branch only in Update PR mode', () => {
167167
expect(targetBranchField?.type).toBe('short-input')
168168
expect(targetBranchField?.required).toBe(true)
169169
expect(evaluateSubBlockCondition(targetBranchField?.condition, { mode: 'cloud_branch' })).toBe(
@@ -207,10 +207,22 @@ describe('Pi cloud authoring surface', () => {
207207
}
208208
})
209209

210-
it('hides Create PR and Review Code-specific fields', () => {
211-
for (const id of ['baseBranch', 'branchName', 'draft', 'prTitle', 'prBody', 'pullNumber']) {
210+
it('shows PR metadata controls and hides Create PR and Review Code-only fields', () => {
211+
for (const id of ['baseBranch', 'prTitle', 'prBody', 'prState']) {
212+
const field = PiBlock.subBlocks.find((subBlock) => subBlock.id === id)
213+
expect(evaluateSubBlockCondition(field?.condition, { mode: 'cloud_branch' })).toBe(true)
214+
}
215+
for (const id of ['branchName', 'draft', 'pullNumber']) {
212216
const field = PiBlock.subBlocks.find((subBlock) => subBlock.id === id)
213217
expect(evaluateSubBlockCondition(field?.condition, { mode: 'cloud_branch' })).toBe(false)
214218
}
219+
const prState = PiBlock.subBlocks.find((subBlock) => subBlock.id === 'prState')
220+
expect(
221+
evaluateSubBlockCondition(prState?.condition, {
222+
mode: 'cloud_branch',
223+
babysitMode: true,
224+
})
225+
).toBe(false)
226+
expect(PiBlock.inputs.prState).toBeDefined()
215227
})
216228
})

apps/sim/blocks/blocks/pi.ts

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ const CLOUD_WITHOUT_BABYSIT: {
8181
value: 'cloud',
8282
and: { field: 'babysitMode', value: true, not: true },
8383
}
84+
const CLOUD_BRANCH_WITHOUT_BABYSIT: {
85+
field: 'mode'
86+
value: 'cloud_branch'
87+
and: { field: 'babysitMode'; value: true; not: true }
88+
} = {
89+
field: 'mode',
90+
value: 'cloud_branch',
91+
and: { field: 'babysitMode', value: true, not: true },
92+
}
8493
const LOCAL: { field: 'mode'; value: 'local' } = { field: 'mode', value: 'local' }
8594
const AUTHORING_MODES: {
8695
field: 'mode'
@@ -127,14 +136,14 @@ export const PiBlock: BlockConfig<PiResponse> = {
127136
description: 'Run an autonomous coding agent on a repo',
128137
authMode: AuthMode.ApiKey,
129138
longDescription:
130-
'The Pi Coding Agent runs the Pi harness against a real repository. Create PR opens a new pull request, Update Branch pushes to an existing branch without force-pushing, Review Code posts a structured review, and Local Dev edits files over SSH. Create PR and Update Branch can optionally babysit their pull request through trusted bot reviews and required checks. Authoring modes can reuse skills and conversation memory. Any mode can optionally get one web_search tool backed by your own key.',
139+
'The Pi Coding Agent runs the Pi harness against a real repository. Create PR opens a new pull request, Update PR pushes to an existing branch and creates or updates its pull request, Review Code posts a structured review, and Local Dev edits files over SSH. Create PR and Update PR can optionally babysit their pull request through trusted bot reviews and required checks. Authoring modes can reuse skills and conversation memory. Any mode can optionally get one web_search tool backed by your own key.',
131140
bestPractices: `
132141
- Use Create PR for hands-off changes against a GitHub repo where a reviewable PR is the deliverable.
133-
- Use Update Branch to continue work on an existing remote branch, including one previously created by Pi.
134-
- Enable Babysit Mode on Create PR or Update Branch when trusted review bots and required checks should be monitored and fixed in bounded rounds.
142+
- Use Update PR to continue work on an existing remote branch and create or update its pull request.
143+
- Enable Babysit Mode on Create PR or Update PR when trusted review bots and required checks should be monitored and fixed in bounded rounds.
135144
- Use Review Code to analyze an existing PR and leave summary + inline review comments.
136145
- Use Local Dev to edit a repo on your own machine; expose the machine on a public hostname/tunnel so Sim can reach it over SSH.
137-
- Create PR and Update Branch require your own provider API key because the model runs in the sandbox. Review Code keeps the model key in Sim and can use either BYOK or a hosted key.
146+
- Create PR and Update PR require your own provider API key because the model runs in the sandbox. Review Code keeps the model key in Sim and can use either BYOK or a hosted key.
138147
- Internet Search is off by default and always needs your own key for the selected provider, from the block field or Settings > BYOK. Leave it on None unless the task genuinely needs external information.
139148
`,
140149
category: 'blocks',
@@ -164,9 +173,9 @@ export const PiBlock: BlockConfig<PiResponse> = {
164173
description: 'Runs in an isolated sandbox, clones your repo, and opens a PR',
165174
},
166175
{
167-
label: 'Update Branch',
176+
label: 'Update PR',
168177
id: 'cloud_branch',
169-
description: 'Checks out an existing branch, makes changes, and pushes commits back',
178+
description: 'Updates an existing branch and creates or updates its pull request',
170179
},
171180
{
172181
label: 'Review Code',
@@ -245,7 +254,7 @@ export const PiBlock: BlockConfig<PiResponse> = {
245254
paramVisibility: 'user-only',
246255
placeholder: 'GitHub personal access token',
247256
tooltip:
248-
'Personal access token used for GitHub access. Create PR needs clone/push/PR permissions; Update Branch needs clone/push permissions. With Babysit Mode, either also needs pull request, check/Actions read, thread write, and issue comment permissions. Review Code needs clone + review permissions.',
257+
'Personal access token used for GitHub access. Create PR and Update PR both need clone, push, and pull request read/write permissions. With Babysit Mode, either also needs check/Actions reads, thread writes, and issue comments. Review Code needs clone + review permissions.',
249258
required: true,
250259
condition: CLOUD_ANY,
251260
},
@@ -254,8 +263,9 @@ export const PiBlock: BlockConfig<PiResponse> = {
254263
title: 'Base Branch',
255264
type: 'short-input',
256265
placeholder: 'e.g., main (defaults to the repository default branch)',
257-
tooltip: 'The branch the pull request is opened against; the repo is cloned from it too.',
258-
condition: CLOUD,
266+
tooltip:
267+
'Create PR clones this branch and opens against it. Update PR changes an existing pull request only when set, or uses it when creating a missing pull request.',
268+
condition: CLOUD_AUTHORING,
259269
},
260270
{
261271
id: 'targetBranch',
@@ -273,7 +283,7 @@ export const PiBlock: BlockConfig<PiResponse> = {
273283
type: 'switch',
274284
defaultValue: false,
275285
description:
276-
'Use the branch PR, request the configured bot reviews, and fix trusted feedback and required checks in bounded rounds.',
286+
'Create or update the branch PR, request the configured bot reviews, and fix trusted feedback and required checks in bounded rounds.',
277287
condition: CLOUD_AUTHORING,
278288
},
279289
{
@@ -304,21 +314,36 @@ export const PiBlock: BlockConfig<PiResponse> = {
304314
mode: 'advanced',
305315
condition: CLOUD_WITHOUT_BABYSIT,
306316
},
317+
{
318+
id: 'prState',
319+
title: 'PR State',
320+
type: 'dropdown',
321+
defaultValue: 'preserve',
322+
options: [
323+
{ label: 'Leave unchanged', id: 'preserve' },
324+
{ label: 'Draft', id: 'draft' },
325+
{ label: 'Ready for review', id: 'ready' },
326+
],
327+
tooltip:
328+
'State for an existing pull request. When a pull request must be created, Leave unchanged uses the Create PR default and opens it as a draft.',
329+
mode: 'advanced',
330+
condition: CLOUD_BRANCH_WITHOUT_BABYSIT,
331+
},
307332
{
308333
id: 'prTitle',
309334
title: 'PR Title',
310335
type: 'short-input',
311-
placeholder: 'Generated from the run when blank',
336+
placeholder: 'Generated for a new PR; preserves an existing PR when blank',
312337
mode: 'advanced',
313-
condition: CLOUD,
338+
condition: CLOUD_AUTHORING,
314339
},
315340
{
316341
id: 'prBody',
317342
title: 'PR Body',
318343
type: 'long-input',
319-
placeholder: 'Generated from the run when blank',
344+
placeholder: 'Generated for a new PR; preserves an existing PR when blank',
320345
mode: 'advanced',
321-
condition: CLOUD,
346+
condition: CLOUD_AUTHORING,
322347
},
323348
{
324349
id: 'pullNumber',
@@ -542,19 +567,23 @@ export const PiBlock: BlockConfig<PiResponse> = {
542567
inputs: {
543568
mode: {
544569
type: 'string',
545-
description: 'Execution mode: Create PR, Update Branch, Review Code, or Local Dev',
570+
description: 'Execution mode: Create PR, Update PR, Review Code, or Local Dev',
546571
},
547572
task: { type: 'string', description: 'Instruction for the coding agent' },
548573
model: { type: 'string', description: 'AI model to use' },
549574
owner: { type: 'string', description: 'GitHub repository owner (cloud modes)' },
550575
repo: { type: 'string', description: 'GitHub repository name (cloud modes)' },
551576
githubToken: { type: 'string', description: 'GitHub token (cloud modes)' },
552-
baseBranch: { type: 'string', description: 'Base branch for the PR (Create PR)' },
577+
baseBranch: { type: 'string', description: 'Base branch for the pull request' },
553578
branchName: { type: 'string', description: 'Branch to create (Create PR)' },
554-
targetBranch: { type: 'string', description: 'Existing branch to update (Update Branch)' },
579+
targetBranch: { type: 'string', description: 'Existing branch to update (Update PR)' },
555580
draft: { type: 'boolean', description: 'Open the PR as a draft (Create PR)' },
556-
prTitle: { type: 'string', description: 'Pull request title (Create PR)' },
557-
prBody: { type: 'string', description: 'Pull request body (Create PR)' },
581+
prTitle: { type: 'string', description: 'Pull request title' },
582+
prBody: { type: 'string', description: 'Pull request body' },
583+
prState: {
584+
type: 'string',
585+
description: 'Existing pull request state: preserve, draft, or ready (Update PR)',
586+
},
558587
babysitMode: {
559588
type: 'boolean',
560589
description: 'Babysit trusted bot reviews and required checks after authoring',

apps/sim/executor/handlers/pi/backend.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,19 @@ export interface PiCloudBabysitOptions {
115115
executionId?: string
116116
}
117117

118-
/** Parameters for a cloud (E2B) Pi run that updates an existing branch. */
118+
export type PiPullRequestState = 'preserve' | 'draft' | 'ready'
119+
120+
/** Parameters for a cloud (E2B) Pi run that updates an existing branch and its pull request. */
119121
export interface PiCloudBranchRunParams extends PiContextualRunParams {
120122
mode: 'cloud_branch'
121123
owner: string
122124
repo: string
123125
githubToken: string
124126
targetBranch: string
127+
baseBranch?: string
128+
prTitle?: string
129+
prBody?: string
130+
prState: PiPullRequestState
125131
babysit?: PiCloudBabysitOptions
126132
}
127133

0 commit comments

Comments
 (0)