Skip to content

Commit 805c9e1

Browse files
authored
perf: remove blocking I/O from ExecuteAgentAction mutation (Refs: beans-bbg1) (#152)
## Summary - Removed all blocking I/O (git status checks, forge API calls, worktree listing) from the `ExecuteAgentAction` mutation resolver, which was causing a noticeable delay between clicking action buttons and the message appearing in chat - Simplified action prompts to let agents gather their own context instead of pre-fetching it — the agent will run `git status`, `gh pr view`, etc. as part of doing the actual work - The `AgentActions` query (which powers button visibility/disabled state) is unaffected and still does its own context gathering ## Test plan - [x] Unit tests pass (`TestExecuteAgentAction`, `TestAgentActionRegistry`) - [ ] Manual: click Review, Learn, Commit, Create PR buttons — messages should appear in chat noticeably faster - [ ] Manual: verify commit action still produces appropriate commit messages - [ ] Manual: verify create-pr action still correctly handles all states (no PR, existing PR, failing checks, mergeable)
1 parent 3ccf767 commit 805c9e1

3 files changed

Lines changed: 31 additions & 92 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
# beans-bbg1
3+
title: Remove pre-fetched context from ExecuteAgentAction, let agents gather their own context
4+
status: completed
5+
type: task
6+
priority: normal
7+
created_at: 2026-03-18T09:59:28Z
8+
updated_at: 2026-03-18T10:01:19Z
9+
---
10+
11+
## Summary of Changes
12+
13+
Removed all blocking I/O (git status checks, forge API calls, worktree listing) from the `ExecuteAgentAction` mutation resolver. The mutation now only passes static context (working directory path, main repo path, forge CLI name) to prompt generation. The agents themselves will inspect git state and PR status as needed.
14+
15+
Simplified prompts:
16+
- **commit**: Single prompt that tells the agent to inspect git status itself
17+
- **create-pr**: Single unified prompt that tells the agent to check PR state and take the appropriate action, instead of pre-branching into 4 different prompts based on pre-fetched state
18+
- **integrate**: Unchanged (only used `MainRepoPath`, which is a path lookup, not I/O)
19+
- **review/learn/tests**: Already didn't use context, unchanged

internal/graph/agent_helpers.go

Lines changed: 12 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package graph
22

33
import (
44
"fmt"
5-
"strings"
65

76
"github.com/hmans/beans/internal/agent"
8-
"github.com/hmans/beans/internal/gitutil"
97
"github.com/hmans/beans/internal/graph/model"
108
"github.com/hmans/beans/pkg/forge"
119
)
@@ -306,61 +304,15 @@ REMINDER: Do NOT push anything to any remote. The integrate action is purely loc
306304
},
307305
PromptFunc: func(ctx actionContext) string {
308306
cli := ctx.ForgeCLI
309-
if ctx.PullRequest != nil {
310-
// PR Merged — no action needed; the destroy button handles cleanup
311-
if ctx.PullRequest.State == "merged" {
312-
return ""
313-
}
314-
315-
// Fix Tests — checks failed, inspect and fix
316-
if !ctx.HasChanges && !ctx.HasUnpushedCommits && ctx.PullRequest.Checks == forge.CheckStatusFail {
317-
return fmt.Sprintf(`CI checks have failed on pull request %s.
318-
319-
Investigate the failures and fix them:
320-
321-
1. Inspect the failed checks: %s pr checks %d
322-
2. View the logs of the failed run to understand what went wrong: %s run view --log-failed (pick the relevant run ID from the checks output)
323-
3. Fix the issue in the code.
324-
4. Run the project's test suite locally to verify the fix.
325-
5. Create a commit with the fix and push: git push
326-
327-
After pushing, the checks will re-run automatically.`, ctx.PullRequest.URL, cli, ctx.PullRequest.Number, cli)
328-
}
329-
330-
// Merge PR — everything is pushed, checks pass, ready to merge
331-
if !ctx.HasChanges && !ctx.HasUnpushedCommits && ctx.PullRequest.CanMerge() {
332-
return fmt.Sprintf(`The pull request %s is ready to merge. All checks are passing and the PR is approved.
333-
334-
Merge the PR using: %s pr merge %d
335-
336-
IMPORTANT: %s pr merge requires a merge strategy flag in non-interactive mode.
337-
Before merging, check which strategies are allowed on this repo:
338-
%s repo view --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed
339-
Then pass the appropriate flag (--merge, --squash, or --rebase).
340-
341-
Do NOT switch branches or check out main after merging — stay on the current branch.`, ctx.PullRequest.URL, cli, ctx.PullRequest.Number, cli, cli)
342-
}
343-
344-
// Update PR — push latest commits
345-
return fmt.Sprintf(`A pull request already exists for this branch: %s
346-
347-
Push the latest changes to update it:
348-
349-
1. If there are uncommitted changes, create a commit first (following the usual commit guidelines).
350-
2. Push to the remote: git push
351-
3. If the push fails because the remote is ahead, pull with rebase first: git pull --rebase && git push
352-
4. Optionally update the PR title/body if the scope has changed: %s pr edit --title "..." --body "..."`, ctx.PullRequest.URL, cli)
353-
}
354-
355-
// No PR yet — create one
356-
return fmt.Sprintf(`Create a pull request for this branch. Follow these steps:
357-
358-
1. If there are uncommitted changes, create a commit first (following the usual commit guidelines).
359-
2. Push the branch to the remote: git push -u origin HEAD
360-
3. Create the PR using: %s pr create --title "..." --body "..."
361-
- Derive the PR title from the branch name and commit messages. Use a conventional commit style prefix.
362-
- Write a meaningful PR body summarizing the changes.
363-
- Include any relevant bean IDs.
307+
return fmt.Sprintf(`Manage the pull request for this branch. Check the current state and take the appropriate action:
308+
309+
1. Check if a PR already exists: %[1]s pr view
310+
2. Check for uncommitted changes (git status) and unpushed commits (git log @{upstream}..HEAD).
311+
3. Based on the state:
312+
- **No PR exists**: Commit any uncommitted changes, push the branch (git push -u origin HEAD), and create a PR (%[1]s pr create). Derive the title from commit messages using conventional commit style. Include relevant bean IDs.
313+
- **PR exists, has local changes or unpushed commits**: Commit if needed, then push (git push). Update the PR title/body if the scope changed.
314+
- **PR exists, everything pushed, checks failing**: Inspect the failed checks (%[1]s pr checks, %[1]s run view --log-failed), fix the issue, test locally, commit and push.
315+
- **PR exists, everything pushed, checks pass, mergeable**: Merge it. Use %[1]s repo view --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed to pick the right strategy, then %[1]s pr merge with the appropriate flag. Do NOT switch branches after merging.
364316
4. Report the PR URL when done.`, cli)
365317
},
366318
Visible: func(ctx actionContext) bool {
@@ -399,26 +351,9 @@ Push the latest changes to update it:
399351
},
400352
}
401353

402-
// commitPrompt inspects the working directory to generate an appropriate commit prompt.
403-
func commitPrompt(ctx actionContext) string {
404-
changes, err := gitutil.FileChanges(ctx.WorkDir)
405-
if err != nil || len(changes) == 0 {
406-
return "Create a commit. Examine the git diff and commit the changes with an appropriate message."
407-
}
408-
409-
allBeans := true
410-
for _, c := range changes {
411-
if !strings.HasPrefix(c.Path, ".beans/") {
412-
allBeans = false
413-
break
414-
}
415-
}
416-
417-
if allBeans {
418-
return "Create a commit. The only uncommitted changes are bean files. Examine them and commit with an appropriate message describing the bean updates (e.g. status changes, new beans, archived beans)."
419-
}
420-
421-
return "Create a commit. Make sure there is an associated bean that is up to date, and possibly even marked as completed if you are done with the change. Then only commit changes related to that change."
354+
// commitPrompt generates a commit prompt. The agent will inspect git state itself.
355+
func commitPrompt(_ actionContext) string {
356+
return "Create a commit. Examine the current git status and diff, then commit with an appropriate message. If there are non-bean changes, make sure there is an associated bean that is up to date. If the only changes are bean files, describe the bean updates in the commit message."
422357
}
423358

424359
// findAgentAction looks up an action by ID, returning nil if not found.

internal/graph/schema.resolvers.go

Lines changed: 0 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)