perf(rpc): use bd daemon protocol to reduce subprocess overhead
Replace bd subprocess calls in gt commands with daemon RPC when available. Each subprocess call has ~40ms overhead for Go binary startup, so using the daemon's Unix socket protocol significantly reduces latency. Changes: - Add RPC client to beads package (beads_rpc.go) - Modify List/Show/Update/Close methods to try RPC first, fall back to subprocess - Replace runBdPrime() with direct content output (avoids bd subprocess) - Replace checkPendingEscalations() to use beads.List() with RPC - Replace hook.go bd subprocess calls with beads package methods The RPC client: - Connects to daemon via Unix socket at .beads/bd.sock - Uses JSON-based request/response protocol (same as bd daemon) - Falls back gracefully to subprocess if daemon unavailable - Lazy-initializes connection on first use Performance improvement targets (from bd-2zd.2): - gt prime < 100ms (was 5.8s with subprocess chain) - gt hook < 100ms (was ~323ms) Closes: bd-2zd.2
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
"github.com/steveyegge/gastown/internal/events"
|
||||
"github.com/steveyegge/gastown/internal/runtime"
|
||||
"github.com/steveyegge/gastown/internal/style"
|
||||
"github.com/steveyegge/gastown/internal/workspace"
|
||||
)
|
||||
@@ -185,15 +184,8 @@ func runHook(_ *cobra.Command, args []string) error {
|
||||
fmt.Printf("%s Replacing completed bead %s...\n", style.Dim.Render("ℹ"), existing.ID)
|
||||
if !hookDryRun {
|
||||
if hasAttachment {
|
||||
// Close completed molecule bead (use bd close --force for pinned)
|
||||
closeArgs := []string{"close", existing.ID, "--force",
|
||||
"--reason=Auto-replaced by gt hook (molecule complete)"}
|
||||
if sessionID := runtime.SessionIDFromEnv(); sessionID != "" {
|
||||
closeArgs = append(closeArgs, "--session="+sessionID)
|
||||
}
|
||||
closeCmd := exec.Command("bd", closeArgs...)
|
||||
closeCmd.Stderr = os.Stderr
|
||||
if err := closeCmd.Run(); err != nil {
|
||||
// Close completed molecule bead (use force for pinned)
|
||||
if err := b.CloseForced(existing.ID, "Auto-replaced by gt hook (molecule complete)"); err != nil {
|
||||
return fmt.Errorf("closing completed bead %s: %w", existing.ID, err)
|
||||
}
|
||||
} else {
|
||||
@@ -234,15 +226,9 @@ func runHook(_ *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hook the bead using bd update (discovery-based approach)
|
||||
// Run from town root so bd can find routes.jsonl for prefix-based routing.
|
||||
// This is essential for hooking convoys (hq-* prefix) stored in town beads.
|
||||
hookCmd := exec.Command("bd", "update", beadID, "--status=hooked", "--assignee="+agentID)
|
||||
if townRoot, err := workspace.FindFromCwd(); err == nil {
|
||||
hookCmd.Dir = townRoot
|
||||
}
|
||||
hookCmd.Stderr = os.Stderr
|
||||
if err := hookCmd.Run(); err != nil {
|
||||
// Hook the bead using beads package (uses RPC when daemon available)
|
||||
status := beads.StatusHooked
|
||||
if err := b.Update(beadID, beads.UpdateOptions{Status: &status, Assignee: &agentID}); err != nil {
|
||||
return fmt.Errorf("hooking bead: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -340,29 +339,13 @@ func detectRole(cwd, townRoot string) RoleInfo {
|
||||
return ctx
|
||||
}
|
||||
|
||||
// runBdPrime runs `bd prime` and outputs the result.
|
||||
// This provides beads workflow context to the agent.
|
||||
// runBdPrime outputs beads workflow context directly.
|
||||
// This replaces the bd subprocess call to eliminate ~40ms startup overhead.
|
||||
func runBdPrime(workDir string) {
|
||||
cmd := exec.Command("bd", "prime")
|
||||
cmd.Dir = workDir
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
// Skip if bd prime fails (beads might not be available)
|
||||
// But log stderr if present for debugging
|
||||
if errMsg := strings.TrimSpace(stderr.String()); errMsg != "" {
|
||||
fmt.Fprintf(os.Stderr, "bd prime: %s\n", errMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
output := strings.TrimSpace(stdout.String())
|
||||
if output != "" {
|
||||
content := beads.GetPrimeContent(workDir)
|
||||
if content != "" {
|
||||
fmt.Println()
|
||||
fmt.Println(output)
|
||||
fmt.Println(content)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,34 +689,20 @@ func ensureBeadsRedirect(ctx RoleContext) {
|
||||
|
||||
// checkPendingEscalations queries for open escalation beads and displays them prominently.
|
||||
// This is called on Mayor startup to surface issues needing human attention.
|
||||
// Uses beads package which leverages RPC when daemon is available.
|
||||
func checkPendingEscalations(ctx RoleContext) {
|
||||
// Query for open escalations using bd list with tag filter
|
||||
cmd := exec.Command("bd", "list", "--status=open", "--tag=escalation", "--json")
|
||||
cmd.Dir = ctx.WorkDir
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
// Query for open escalations using beads package (uses RPC when available)
|
||||
b := beads.New(ctx.WorkDir)
|
||||
escalations, err := b.List(beads.ListOptions{
|
||||
Status: "open",
|
||||
Label: "escalation",
|
||||
Priority: -1,
|
||||
})
|
||||
if err != nil || len(escalations) == 0 {
|
||||
// Silently skip - escalation check is best-effort
|
||||
return
|
||||
}
|
||||
|
||||
// Parse JSON output
|
||||
var escalations []struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Priority int `json:"priority"`
|
||||
Description string `json:"description"`
|
||||
Created string `json:"created"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(stdout.Bytes(), &escalations); err != nil || len(escalations) == 0 {
|
||||
// No escalations or parse error
|
||||
return
|
||||
}
|
||||
|
||||
// Count by severity
|
||||
critical := 0
|
||||
high := 0
|
||||
|
||||
Reference in New Issue
Block a user