Add Antigravity (agy) as a third agent backend for gemini-* models
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
package agents
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"g.fc.run/ai/byre/internal/antigravity"
|
||||
)
|
||||
|
||||
type agySteps struct {
|
||||
mu sync.Mutex
|
||||
text map[int]*strings.Builder
|
||||
tools map[string]bool
|
||||
}
|
||||
|
||||
func newAgySteps() *agySteps {
|
||||
return &agySteps{text: map[int]*strings.Builder{}, tools: map[string]bool{}}
|
||||
}
|
||||
|
||||
func (m *Manager) handleAntigravity(ctx context.Context, l *live, p antigravityProcess, ev antigravity.Event) error {
|
||||
switch ev.Kind {
|
||||
case "init":
|
||||
return nil
|
||||
|
||||
case "step_update":
|
||||
su, err := ev.StepUpdate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.agyStep(ctx, l, p, ev, su)
|
||||
|
||||
case "result":
|
||||
res, err := ev.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.agyTurnEnded(ctx, l, p, res)
|
||||
}
|
||||
|
||||
raw := map[string]any{}
|
||||
err := json.Unmarshal(ev.Raw, &raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.emit(ctx, l, agentActor, "agent.vendor", raw)
|
||||
}
|
||||
|
||||
func (m *Manager) agyStep(ctx context.Context, l *live, p antigravityProcess, ev antigravity.Event, su antigravity.StepUpdate) error {
|
||||
switch su.StepType {
|
||||
case "user_input":
|
||||
return nil
|
||||
|
||||
case "agent_response":
|
||||
p.steps.mu.Lock()
|
||||
b := p.steps.text[su.StepIndex]
|
||||
if b == nil {
|
||||
b = &strings.Builder{}
|
||||
p.steps.text[su.StepIndex] = b
|
||||
}
|
||||
b.WriteString(su.TextDelta)
|
||||
done := su.State != "ACTIVE"
|
||||
if done {
|
||||
delete(p.steps.text, su.StepIndex)
|
||||
}
|
||||
p.steps.mu.Unlock()
|
||||
|
||||
if su.TextDelta != "" {
|
||||
m.store.Broadcast(m.event(l, agentActor, "agent.delta", map[string]any{"text": su.TextDelta}))
|
||||
}
|
||||
text := strings.TrimSpace(b.String())
|
||||
if !done || text == "" {
|
||||
return nil
|
||||
}
|
||||
m.mu.Lock()
|
||||
l.lastText = text
|
||||
m.mu.Unlock()
|
||||
return m.emit(ctx, l, agentActor, "agent.message", map[string]any{"text": text})
|
||||
|
||||
case "tool":
|
||||
id := fmt.Sprintf("%s/%d", su.ConversationID, su.StepIndex)
|
||||
info := antigravity.ToolInfo{Name: su.ToolName}
|
||||
if su.ToolInfo != nil {
|
||||
info = *su.ToolInfo
|
||||
}
|
||||
p.steps.mu.Lock()
|
||||
called := p.steps.tools[id]
|
||||
p.steps.tools[id] = su.State == "ACTIVE"
|
||||
if su.State != "ACTIVE" {
|
||||
delete(p.steps.tools, id)
|
||||
}
|
||||
p.steps.mu.Unlock()
|
||||
|
||||
if !called {
|
||||
name, input, err := agyToolCall(su.ToolName, info.Parameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.emit(ctx, l, agentActor, "agent.tool_call", map[string]any{"id": id, "name": name, "input": input})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if su.State == "ACTIVE" {
|
||||
return nil
|
||||
}
|
||||
content := info.Output
|
||||
if info.Error != "" {
|
||||
content = info.Error
|
||||
}
|
||||
return m.emit(ctx, l, agentActor, "agent.tool_result", map[string]any{"tool_use_id": id, "is_error": su.State != "DONE" || info.Error != "", "content": content})
|
||||
}
|
||||
|
||||
raw := map[string]any{}
|
||||
err := json.Unmarshal(ev.Raw, &raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.emit(ctx, l, agentActor, "agent.vendor", raw)
|
||||
}
|
||||
|
||||
func agyToolCall(name string, params json.RawMessage) (string, any, error) {
|
||||
switch name {
|
||||
case "run_command":
|
||||
p := struct {
|
||||
CommandLine string
|
||||
}{}
|
||||
err := json.Unmarshal(params, &p)
|
||||
return "Bash", map[string]any{"command": p.CommandLine}, err
|
||||
case "call_mcp_tool":
|
||||
p := struct {
|
||||
ServerName string
|
||||
ToolName string
|
||||
Arguments json.RawMessage
|
||||
}{}
|
||||
err := json.Unmarshal(params, &p)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
args, err := decode(p.Arguments)
|
||||
return "mcp__" + strings.TrimPrefix(p.ServerName, "byre_") + "__" + p.ToolName, args, err
|
||||
}
|
||||
input, err := decode(params)
|
||||
return name, input, err
|
||||
}
|
||||
|
||||
func (m *Manager) agyTurnEnded(ctx context.Context, l *live, p antigravityProcess, res antigravity.Result) error {
|
||||
m.mu.Lock()
|
||||
final := l.lastText
|
||||
m.mu.Unlock()
|
||||
|
||||
success := res.Status == "SUCCESS"
|
||||
bounce := false
|
||||
if success && l.implementer() {
|
||||
var err error
|
||||
bounce, err = m.takeBounce(ctx, l, final)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if bounce {
|
||||
err := m.emit(ctx, l, "byre", "user.message", map[string]any{"text": proseQuestionNudge, "mid_turn": true, "bounce": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.mu.Lock()
|
||||
l.lastText = ""
|
||||
m.mu.Unlock()
|
||||
go func() {
|
||||
err := p.s.Send(proseQuestionNudge)
|
||||
if err != nil {
|
||||
slog.Error("send prose question nudge", "session", l.id, "err", err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
r := endResult{
|
||||
subtype: strings.ToLower(res.Status),
|
||||
isError: !success,
|
||||
result: final,
|
||||
}
|
||||
if !success {
|
||||
r.result = res.Error
|
||||
}
|
||||
r.payload = map[string]any{
|
||||
"subtype": r.subtype,
|
||||
"is_error": r.isError,
|
||||
"result": r.result,
|
||||
}
|
||||
return m.turnEnded(ctx, l, r)
|
||||
}
|
||||
|
||||
func (m *Manager) agyBeforeModel(l *live) antigravity.HookFunc {
|
||||
return func(ctx context.Context, input json.RawMessage) (map[string]any, error) {
|
||||
in := struct {
|
||||
InvocationNum int `json:"invocationNum"`
|
||||
}{}
|
||||
err := json.Unmarshal(input, &in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if in.InvocationNum == 0 || l.reviewID != "" {
|
||||
return map[string]any{}, nil
|
||||
}
|
||||
mt := m.deliverMidTurn(ctx, l)
|
||||
if mt.text == "" {
|
||||
return map[string]any{}, nil
|
||||
}
|
||||
return map[string]any{"injectSteps": []map[string]any{{"userMessage": mt.text}}}, nil
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,9 @@ func (m *Manager) Fork(ctx context.Context, src api.Task, project api.Project, n
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
}
|
||||
if srcSess.Vendor == api.Antigravity {
|
||||
return api.Task{}, fmt.Errorf("%w: snapshot %d of task %s is from an Antigravity session, and agy can't fork a conversation", ErrConflict, n, src.Id)
|
||||
}
|
||||
events, err := m.store.TaskEvents(ctx, src.Id, 0, -1)
|
||||
if err != nil {
|
||||
return api.Task{}, err
|
||||
|
||||
+43
-39
@@ -35,15 +35,16 @@ const agentActor = "agent"
|
||||
const restartNotice = "byre restarted while you were mid-turn, so your last turn was cut off. Re-check the working tree (git status and the files you were editing) before continuing where you left off."
|
||||
|
||||
type Manager struct {
|
||||
store *store.Store
|
||||
worktreeRoot string
|
||||
leadRoot string
|
||||
handsRoot string
|
||||
codexHome string
|
||||
status func(context.Context) (api.Status, error)
|
||||
addProject func(ctx context.Context, name, repoPath, createdBy string) (api.Project, error)
|
||||
clients *clients.Registry
|
||||
terminals *terminal.Terminals
|
||||
store *store.Store
|
||||
worktreeRoot string
|
||||
leadRoot string
|
||||
handsRoot string
|
||||
codexHome string
|
||||
antigravityRoot string
|
||||
status func(context.Context) (api.Status, error)
|
||||
addProject func(ctx context.Context, name, repoPath, createdBy string) (api.Project, error)
|
||||
clients *clients.Registry
|
||||
terminals *terminal.Terminals
|
||||
|
||||
mu sync.Mutex
|
||||
live map[string]*live
|
||||
@@ -125,37 +126,38 @@ func (l *live) implementer() bool {
|
||||
return l.owner == "" && l.reviewID == ""
|
||||
}
|
||||
|
||||
func New(st *store.Store, worktreeRoot, leadRoot, handsRoot, codexHome string, status func(context.Context) (api.Status, error), addProject func(ctx context.Context, name, repoPath, createdBy string) (api.Project, error), clientRegistry *clients.Registry, terminals *terminal.Terminals) *Manager {
|
||||
func New(st *store.Store, worktreeRoot, leadRoot, handsRoot, codexHome, antigravityRoot string, status func(context.Context) (api.Status, error), addProject func(ctx context.Context, name, repoPath, createdBy string) (api.Project, error), clientRegistry *clients.Registry, terminals *terminal.Terminals) *Manager {
|
||||
m := &Manager{
|
||||
store: st,
|
||||
worktreeRoot: worktreeRoot,
|
||||
leadRoot: leadRoot,
|
||||
handsRoot: handsRoot,
|
||||
codexHome: codexHome,
|
||||
status: status,
|
||||
addProject: addProject,
|
||||
clients: clientRegistry,
|
||||
terminals: terminals,
|
||||
live: map[string]*live{},
|
||||
starting: map[string]*start{},
|
||||
deliverLocks: map[string]*sessionLock{},
|
||||
rateLimits: map[api.AgentSessionVendor]map[string]any{},
|
||||
leadAnswered: map[string]bool{},
|
||||
paneFocus: map[string]api.PaneFocus{},
|
||||
paneReported: map[string]time.Time{},
|
||||
paneMoved: map[string]time.Time{},
|
||||
humanMoved: map[string]time.Time{},
|
||||
moveRefused: map[string]bool{},
|
||||
startedTodo: map[string]time.Time{},
|
||||
startRefused: map[string]bool{},
|
||||
finishing: map[string]bool{},
|
||||
handoffModel: map[string]string{},
|
||||
mergeTurns: map[string]mergeTurn{},
|
||||
signals: make(chan []api.Event, 1024),
|
||||
snaps: map[string]*snapState{},
|
||||
merges: map[string]*projectMerge{},
|
||||
bad: newBadLines(),
|
||||
watchStop: make(chan struct{}),
|
||||
store: st,
|
||||
worktreeRoot: worktreeRoot,
|
||||
leadRoot: leadRoot,
|
||||
handsRoot: handsRoot,
|
||||
codexHome: codexHome,
|
||||
antigravityRoot: antigravityRoot,
|
||||
status: status,
|
||||
addProject: addProject,
|
||||
clients: clientRegistry,
|
||||
terminals: terminals,
|
||||
live: map[string]*live{},
|
||||
starting: map[string]*start{},
|
||||
deliverLocks: map[string]*sessionLock{},
|
||||
rateLimits: map[api.AgentSessionVendor]map[string]any{},
|
||||
leadAnswered: map[string]bool{},
|
||||
paneFocus: map[string]api.PaneFocus{},
|
||||
paneReported: map[string]time.Time{},
|
||||
paneMoved: map[string]time.Time{},
|
||||
humanMoved: map[string]time.Time{},
|
||||
moveRefused: map[string]bool{},
|
||||
startedTodo: map[string]time.Time{},
|
||||
startRefused: map[string]bool{},
|
||||
finishing: map[string]bool{},
|
||||
handoffModel: map[string]string{},
|
||||
mergeTurns: map[string]mergeTurn{},
|
||||
signals: make(chan []api.Event, 1024),
|
||||
snaps: map[string]*snapState{},
|
||||
merges: map[string]*projectMerge{},
|
||||
bad: newBadLines(),
|
||||
watchStop: make(chan struct{}),
|
||||
}
|
||||
go m.signalLoop()
|
||||
go m.readCodexRateLimit()
|
||||
@@ -814,6 +816,8 @@ func (m *Manager) startLive(ctx context.Context, sess api.AgentSession, task api
|
||||
switch l.vendor {
|
||||
case api.Codex:
|
||||
l.sess, err = m.startCodex(sctx, sess, l, g, servers, stdio, env)
|
||||
case api.Antigravity:
|
||||
l.sess, err = m.startAntigravity(sctx, sess, l, g, servers, stdio, env)
|
||||
default:
|
||||
l.sess, err = m.startClaude(sctx, sess, l, g, servers, stdio, env)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,11 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"g.fc.run/ai/byre/internal/antigravity"
|
||||
"g.fc.run/ai/byre/internal/api"
|
||||
"g.fc.run/ai/byre/internal/claude"
|
||||
"g.fc.run/ai/byre/internal/codex"
|
||||
@@ -32,7 +35,7 @@ type agentProcess interface {
|
||||
}
|
||||
|
||||
func initialVendorSessionID(vendor api.AgentSessionVendor, id string) string {
|
||||
if vendor == api.Codex {
|
||||
if vendor != api.Claude {
|
||||
return ""
|
||||
}
|
||||
return id
|
||||
@@ -238,3 +241,86 @@ func (p codexProcess) drive(m *Manager, l *live) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type antigravityProcess struct {
|
||||
s *antigravity.Session
|
||||
steps *agySteps
|
||||
}
|
||||
|
||||
func (m *Manager) startAntigravity(ctx context.Context, sess api.AgentSession, l *live, g string, servers []*mcp.Server, stdio []mcp.Stdio, env []string) (agentProcess, error) {
|
||||
opts := antigravity.Options{
|
||||
Dir: filepath.Join(m.antigravityRoot, sess.Id),
|
||||
Cwd: l.dir,
|
||||
Model: sess.Model,
|
||||
Resume: sess.VendorSessionId,
|
||||
GitName: l.gitName,
|
||||
GitEmail: l.gitEmail,
|
||||
Env: env,
|
||||
Guidance: g,
|
||||
Notes: strings.TrimSpace(l.notes),
|
||||
Reminder: g,
|
||||
MCPServers: servers,
|
||||
StdioMCP: stdio,
|
||||
Hooks: map[string]antigravity.HookFunc{"PreInvocation": m.agyBeforeModel(l)},
|
||||
OnBadLine: func(line []byte, reason string) { m.recordBadLine(l, line, reason) },
|
||||
}
|
||||
|
||||
s, err := antigravity.Start(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("start agy: %w", err)
|
||||
}
|
||||
if sess.VendorSessionId == "" {
|
||||
err = m.store.SetVendorSessionID(ctx, sess.Id, s.ID())
|
||||
if err != nil {
|
||||
s.Kill()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return antigravityProcess{s: s, steps: newAgySteps()}, nil
|
||||
}
|
||||
|
||||
func (p antigravityProcess) send(ctx context.Context, text string, images []image) error {
|
||||
imgs := []antigravity.Image{}
|
||||
for _, img := range images {
|
||||
imgs = append(imgs, antigravity.Image{MediaType: img.mediaType, Data: img.data})
|
||||
}
|
||||
return p.s.Send(text, imgs...)
|
||||
}
|
||||
|
||||
func (p antigravityProcess) interrupt(ctx context.Context) error {
|
||||
return p.s.Interrupt()
|
||||
}
|
||||
|
||||
func (p antigravityProcess) setModel(ctx context.Context, model string) error {
|
||||
return p.s.SetModel(model)
|
||||
}
|
||||
|
||||
func (p antigravityProcess) kill() { p.s.Kill() }
|
||||
func (p antigravityProcess) pid() int { return p.s.Pid() }
|
||||
func (p antigravityProcess) lastLine() time.Time { return p.s.LastLine() }
|
||||
func (p antigravityProcess) exited() bool { return p.s.Exited() }
|
||||
|
||||
func (p antigravityProcess) discard() {
|
||||
for range p.s.Events() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p antigravityProcess) drive(m *Manager, l *live) {
|
||||
ctx := context.Background()
|
||||
for ev := range p.s.Events() {
|
||||
start := time.Now()
|
||||
if wait := start.Sub(ev.Read); wait > 200*time.Millisecond {
|
||||
slog.Info("agent event waited", "session", l.id, "event", ev.Kind, "wait", wait)
|
||||
}
|
||||
err := m.handleAntigravity(ctx, l, p, ev)
|
||||
if err != nil {
|
||||
slog.Error("record agent event", "session", l.id, "event", ev.Kind, "err", err)
|
||||
}
|
||||
if isDecodeError(err) {
|
||||
m.recordBadLine(l, ev.Raw, fmt.Sprintf("decode %s: %s", ev.Kind, err))
|
||||
}
|
||||
if took := time.Since(start); took > 200*time.Millisecond {
|
||||
slog.Info("agent event slow", "session", l.id, "event", ev.Kind, "took", took)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (m *Manager) subtaskTools(l *live) []mcp.Tool {
|
||||
`{"type": "object", "properties": {
|
||||
"title": {"type": "string", "description": "Short task title, shown in the task list."},
|
||||
"prompt": {"type": "string", "description": "The new agent's first message: a complete, self-contained brief."},
|
||||
"model": {"type": "string", "description": "Model for the new agent: gpt-* models run on Codex, every other model on Claude Code. Defaults to this session's model."}
|
||||
"model": {"type": "string", "description": "Model for the new agent: gpt-* models run on Codex, gemini-* models on Antigravity, every other model on Claude Code. Defaults to this session's model."}
|
||||
}, "required": ["title", "prompt"]}`,
|
||||
func(ctx context.Context, creator api.User, raw json.RawMessage) (string, error) {
|
||||
args := struct {
|
||||
|
||||
@@ -652,7 +652,7 @@ const workflowFileHelp = "A workflow's file is YAML: an optional description, th
|
||||
"after (the names of the stages whose outputs it gets; it starts once all of them have finished; absent means the previous stage in the list, and for the first stage none; [] means it starts from the brief), " +
|
||||
"base (parent, the default: branch from the commit its one after stage finished at, or for a stage with none, from where the workflow was started; main: branch from the default branch; " +
|
||||
"refused on a stage with more than one after stage, which always branches from the default branch and is told the branches it can merge), " +
|
||||
"model (which also picks the vendor: gpt-* models run on Codex, every other model on Claude Code) and prompt (the stage agent's instructions). " +
|
||||
"model (which also picks the vendor: gpt-* models run on Codex, gemini-* models on Antigravity, every other model on Claude Code) and prompt (the stage agent's instructions). " +
|
||||
"In place of model, agents (a list of at least two, each with name, model and prompt) runs the stage as a team: those agents work in the stage's one task and worktree and talk through a shared board; " +
|
||||
"each gets the stage's prompt and then its own; the first agent finishes the stage. " +
|
||||
"Every stage runs as its own task. Exactly one stage is final (no other stage comes after it), and cycles are refused. " +
|
||||
|
||||
@@ -0,0 +1,581 @@
|
||||
package antigravity
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"g.fc.run/ai/byre/internal/mcp"
|
||||
)
|
||||
|
||||
const maxRuleBytes = 24000
|
||||
|
||||
type HookFunc func(ctx context.Context, input json.RawMessage) (map[string]any, error)
|
||||
|
||||
type Options struct {
|
||||
Dir string
|
||||
Cwd string
|
||||
Model string
|
||||
Resume string
|
||||
GitName string
|
||||
GitEmail string
|
||||
Env []string
|
||||
Guidance string
|
||||
Notes string
|
||||
Reminder string
|
||||
MCPServers []*mcp.Server
|
||||
StdioMCP []mcp.Stdio
|
||||
Hooks map[string]HookFunc
|
||||
OnBadLine func(line []byte, reason string)
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
MediaType string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Kind string
|
||||
Raw json.RawMessage
|
||||
Read time.Time
|
||||
}
|
||||
|
||||
type Usage struct {
|
||||
InputTokens int `json:"input_tokens"`
|
||||
OutputTokens int `json:"output_tokens"`
|
||||
ThinkingTokens int `json:"thinking_tokens"`
|
||||
CacheReadTokens int `json:"cache_read_tokens"`
|
||||
TotalTokens int `json:"total_tokens"`
|
||||
}
|
||||
|
||||
type ToolInfo struct {
|
||||
Name string `json:"name"`
|
||||
Parameters json.RawMessage `json:"parameters"`
|
||||
Output string `json:"output"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type StepUpdate struct {
|
||||
ConversationID string `json:"conversation_id"`
|
||||
StepIndex int `json:"step_index"`
|
||||
State string `json:"state"`
|
||||
StepType string `json:"step_type"`
|
||||
TextDelta string `json:"text_delta"`
|
||||
ToolName string `json:"tool_name"`
|
||||
ToolInfo *ToolInfo `json:"tool_info"`
|
||||
DurationSeconds float64 `json:"duration_seconds"`
|
||||
Usage *Usage `json:"usage"`
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
ConversationID string `json:"conversation_id"`
|
||||
Status string `json:"status"`
|
||||
Response string `json:"response"`
|
||||
Error string `json:"error"`
|
||||
DurationSeconds float64 `json:"duration_seconds"`
|
||||
NumTurns int `json:"num_turns"`
|
||||
Usage Usage `json:"usage"`
|
||||
}
|
||||
|
||||
var knownEvents = map[string]bool{"init": true, "step_update": true, "result": true}
|
||||
|
||||
func (e Event) payload(v any) error {
|
||||
fields := map[string]json.RawMessage{}
|
||||
err := json.Unmarshal(e.Raw, &fields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(fields[e.Kind], v)
|
||||
}
|
||||
|
||||
func (e Event) StepUpdate() (StepUpdate, error) {
|
||||
su := StepUpdate{}
|
||||
return su, e.payload(&su)
|
||||
}
|
||||
|
||||
func (e Event) Result() (Result, error) {
|
||||
res := Result{}
|
||||
return res, e.payload(&res)
|
||||
}
|
||||
|
||||
type proc struct {
|
||||
cmd *exec.Cmd
|
||||
stdin io.WriteCloser
|
||||
done chan struct{}
|
||||
expected bool
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
opts Options
|
||||
|
||||
mu sync.Mutex
|
||||
p *proc
|
||||
model string
|
||||
killed bool
|
||||
images int
|
||||
|
||||
idMu sync.Mutex
|
||||
convID string
|
||||
|
||||
events chan Event
|
||||
dead chan struct{}
|
||||
dieOnce sync.Once
|
||||
started chan struct{}
|
||||
initOnce sync.Once
|
||||
|
||||
srv *http.Server
|
||||
base string
|
||||
servers map[string]*mcp.Server
|
||||
lastLine atomic.Int64
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, opts Options) (*Session, error) {
|
||||
if len(opts.Guidance) > maxRuleBytes || len(opts.Notes) > maxRuleBytes {
|
||||
return nil, fmt.Errorf("guidance (%d bytes) and notes (%d bytes) must each fit agy's %d-byte rule limit", len(opts.Guidance), len(opts.Notes), maxRuleBytes)
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token := rand.Text()
|
||||
|
||||
s := &Session{
|
||||
opts: opts,
|
||||
model: opts.Model,
|
||||
convID: opts.Resume,
|
||||
events: make(chan Event, 256),
|
||||
dead: make(chan struct{}),
|
||||
started: make(chan struct{}),
|
||||
base: "http://" + ln.Addr().String() + "/" + token,
|
||||
servers: map[string]*mcp.Server{},
|
||||
}
|
||||
for _, srv := range opts.MCPServers {
|
||||
s.servers[srv.Name] = srv
|
||||
}
|
||||
s.lastLine.Store(time.Now().UnixNano())
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("POST /"+token+"/mcp/{server}", s.serveMCP)
|
||||
mux.HandleFunc("POST /"+token+"/hook/{event}", s.serveHook)
|
||||
s.srv = &http.Server{Handler: mux}
|
||||
go s.srv.Serve(ln)
|
||||
|
||||
err = s.writePlugin()
|
||||
if err != nil {
|
||||
s.die()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
err = s.spawnLocked()
|
||||
s.mu.Unlock()
|
||||
if err != nil {
|
||||
s.die()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-s.started:
|
||||
return s, nil
|
||||
case <-s.dead:
|
||||
return nil, errors.New("agy exited before it started a conversation")
|
||||
case <-ctx.Done():
|
||||
s.Kill()
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) pluginDir() string {
|
||||
return filepath.Join(s.opts.Dir, ".agents", "plugins", "byre")
|
||||
}
|
||||
|
||||
func (s *Session) writePlugin() error {
|
||||
dir := s.pluginDir()
|
||||
err := os.MkdirAll(filepath.Join(dir, "rules"), 0o755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
servers := map[string]any{}
|
||||
for _, srv := range s.opts.MCPServers {
|
||||
servers[srv.Name] = map[string]any{"url": s.base + "/mcp/" + srv.Name}
|
||||
}
|
||||
for _, srv := range s.opts.StdioMCP {
|
||||
servers[srv.Name] = map[string]any{"command": srv.Command, "args": srv.Args}
|
||||
}
|
||||
|
||||
hooks := map[string]any{}
|
||||
for event := range s.opts.Hooks {
|
||||
hooks[event] = []map[string]any{{
|
||||
"type": "command",
|
||||
"command": fmt.Sprintf("curl -sS --max-time 25 --data-binary @- %s/hook/%s", s.base, event),
|
||||
"timeout": 30,
|
||||
}}
|
||||
}
|
||||
|
||||
files := map[string]any{
|
||||
"plugin.json": map[string]any{"name": "byre"},
|
||||
"mcp_config.json": map[string]any{"mcpServers": servers},
|
||||
"hooks.json": map[string]any{"byre": hooks},
|
||||
}
|
||||
for name, v := range files {
|
||||
b, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(filepath.Join(dir, name), b, 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = os.WriteFile(filepath.Join(dir, "rules", "AGENTS.md"), []byte(s.opts.Guidance), 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s.opts.Notes == "" {
|
||||
return nil
|
||||
}
|
||||
return os.WriteFile(filepath.Join(dir, "rules", "notes.md"), []byte("---\ntrigger: always_on\n---\n"+s.opts.Notes), 0o644)
|
||||
}
|
||||
|
||||
func (s *Session) serveMCP(w http.ResponseWriter, r *http.Request) {
|
||||
srv := s.servers[r.PathValue("server")]
|
||||
if srv == nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
msg := struct {
|
||||
ID json.RawMessage `json:"id"`
|
||||
}{}
|
||||
err = json.Unmarshal(body, &msg)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if len(msg.ID) == 0 {
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
return
|
||||
}
|
||||
resp, err := srv.Handle(r.Context(), body)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
func (s *Session) serveHook(w http.ResponseWriter, r *http.Request) {
|
||||
event := r.PathValue("event")
|
||||
fn := s.opts.Hooks[event]
|
||||
if fn == nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
out, err := fn(r.Context(), body)
|
||||
if err != nil {
|
||||
slog.Error("agy hook failed", "event", event, "err", err)
|
||||
out = map[string]any{}
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(out)
|
||||
}
|
||||
|
||||
func (s *Session) spawnLocked() error {
|
||||
args := []string{
|
||||
"--input-format", "stream-json",
|
||||
"--output-format", "stream-json",
|
||||
"--dangerously-skip-permissions",
|
||||
"--add-dir", s.opts.Dir,
|
||||
}
|
||||
if s.model != "" {
|
||||
args = append(args, "--model", s.model)
|
||||
}
|
||||
if id := s.ID(); id != "" {
|
||||
args = append(args, "--conversation", id)
|
||||
}
|
||||
args = append(args, "--print", "")
|
||||
|
||||
cmd := exec.Command("agy", args...)
|
||||
cmd.Dir = s.opts.Cwd
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GIT_AUTHOR_NAME="+s.opts.GitName,
|
||||
"GIT_AUTHOR_EMAIL="+s.opts.GitEmail,
|
||||
"GIT_COMMITTER_NAME="+s.opts.GitName,
|
||||
"GIT_COMMITTER_EMAIL="+s.opts.GitEmail,
|
||||
)
|
||||
cmd.Env = append(cmd.Env, s.opts.Env...)
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return fmt.Errorf("start agy: %w", err)
|
||||
}
|
||||
|
||||
p := &proc{cmd: cmd, stdin: stdin, done: make(chan struct{})}
|
||||
s.p = p
|
||||
go s.readLoop(p, stdout)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) readLoop(p *proc, stdout io.Reader) {
|
||||
r := bufio.NewReader(stdout)
|
||||
for {
|
||||
line, err := r.ReadBytes('\n')
|
||||
line = bytes.TrimRight(line, "\r\n")
|
||||
if len(line) > 0 {
|
||||
s.lastLine.Store(time.Now().UnixNano())
|
||||
s.handleLine(line)
|
||||
}
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
slog.Error("read agy stdout", "err", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
p.cmd.Wait()
|
||||
close(p.done)
|
||||
|
||||
s.mu.Lock()
|
||||
expected := p.expected && !s.killed
|
||||
s.mu.Unlock()
|
||||
if !expected {
|
||||
s.die()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) handleLine(line []byte) {
|
||||
read := time.Now()
|
||||
if line[0] != '{' {
|
||||
s.badLine(line, "not a JSON object")
|
||||
return
|
||||
}
|
||||
env := struct {
|
||||
Event string `json:"event"`
|
||||
ConversationID string `json:"conversation_id"`
|
||||
}{}
|
||||
err := json.Unmarshal(line, &env)
|
||||
if err != nil {
|
||||
s.badLine(line, err.Error())
|
||||
return
|
||||
}
|
||||
if !knownEvents[env.Event] {
|
||||
s.badLine(line, fmt.Sprintf("unrecognised event %q", env.Event))
|
||||
}
|
||||
if env.Event == "init" {
|
||||
s.idMu.Lock()
|
||||
if s.convID == "" {
|
||||
s.convID = env.ConversationID
|
||||
}
|
||||
s.idMu.Unlock()
|
||||
s.initOnce.Do(func() { close(s.started) })
|
||||
}
|
||||
s.events <- Event{Kind: env.Event, Raw: append(json.RawMessage{}, line...), Read: read}
|
||||
}
|
||||
|
||||
func (s *Session) die() {
|
||||
s.dieOnce.Do(func() {
|
||||
close(s.events)
|
||||
close(s.dead)
|
||||
s.srv.Close()
|
||||
err := os.RemoveAll(s.opts.Dir)
|
||||
if err != nil {
|
||||
slog.Error("remove agy session dir", "dir", s.opts.Dir, "err", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Session) restartLocked() error {
|
||||
p := s.p
|
||||
select {
|
||||
case <-p.done:
|
||||
case <-time.After(10 * time.Second):
|
||||
p.cmd.Process.Kill()
|
||||
<-p.done
|
||||
}
|
||||
return s.spawnLocked()
|
||||
}
|
||||
|
||||
func (s *Session) Events() <-chan Event {
|
||||
return s.events
|
||||
}
|
||||
|
||||
func (s *Session) ID() string {
|
||||
s.idMu.Lock()
|
||||
defer s.idMu.Unlock()
|
||||
return s.convID
|
||||
}
|
||||
|
||||
func (s *Session) Pid() int {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.p.cmd.Process.Pid
|
||||
}
|
||||
|
||||
func (s *Session) LastLine() time.Time {
|
||||
return time.Unix(0, s.lastLine.Load())
|
||||
}
|
||||
|
||||
func (s *Session) Exited() bool {
|
||||
select {
|
||||
case <-s.dead:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type block struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func (s *Session) Send(text string, images ...Image) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.killed {
|
||||
return errors.New("agy session was killed")
|
||||
}
|
||||
if s.p.expected {
|
||||
err := s.restartLocked()
|
||||
if err != nil {
|
||||
s.die()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
content := []block{}
|
||||
if s.opts.Reminder != "" {
|
||||
content = append(content, block{Type: "text", Text: "<system-reminder>\n" + s.opts.Reminder + "\n</system-reminder>"})
|
||||
}
|
||||
for _, img := range images {
|
||||
s.images++
|
||||
path := filepath.Join(s.opts.Dir, "images", fmt.Sprintf("%d.%s", s.images, strings.TrimPrefix(img.MediaType, "image/")))
|
||||
err := os.MkdirAll(filepath.Dir(path), 0o755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(path, img.Data, 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content = append(content, block{Type: "text", Text: "The human attached an image, saved at " + path + "; view it with view_file."})
|
||||
}
|
||||
content = append(content, block{Type: "text", Text: text})
|
||||
|
||||
b, err := json.Marshal(map[string]any{
|
||||
"event": "user",
|
||||
"message": map[string]any{"role": "user", "content": content},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.p.stdin.Write(append(b, '\n'))
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Session) Interrupt() error {
|
||||
s.mu.Lock()
|
||||
p := s.p
|
||||
p.expected = true
|
||||
err := p.cmd.Process.Signal(syscall.SIGINT)
|
||||
s.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
<-p.done
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.killed {
|
||||
s.die()
|
||||
return
|
||||
}
|
||||
if s.p != p {
|
||||
return
|
||||
}
|
||||
err := s.spawnLocked()
|
||||
if err != nil {
|
||||
slog.Error("restart agy after interrupt", "err", err)
|
||||
s.die()
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) SetModel(model string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if model == s.model {
|
||||
return nil
|
||||
}
|
||||
s.model = model
|
||||
s.p.expected = true
|
||||
s.p.stdin.Close()
|
||||
err := s.restartLocked()
|
||||
if err != nil {
|
||||
s.die()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Session) Kill() {
|
||||
s.mu.Lock()
|
||||
s.killed = true
|
||||
p := s.p
|
||||
s.mu.Unlock()
|
||||
|
||||
if p != nil {
|
||||
p.cmd.Process.Kill()
|
||||
<-p.done
|
||||
}
|
||||
s.die()
|
||||
}
|
||||
|
||||
func (s *Session) badLine(line []byte, reason string) {
|
||||
slog.Warn("bad agy line", "reason", reason, "line", string(line))
|
||||
if s.opts.OnBadLine != nil {
|
||||
s.opts.OnBadLine(line, reason)
|
||||
}
|
||||
}
|
||||
+241
-238
@@ -86,13 +86,16 @@ func (e AgentSessionState) Valid() bool {
|
||||
|
||||
// Defines values for AgentSessionVendor.
|
||||
const (
|
||||
Claude AgentSessionVendor = "claude"
|
||||
Codex AgentSessionVendor = "codex"
|
||||
Antigravity AgentSessionVendor = "antigravity"
|
||||
Claude AgentSessionVendor = "claude"
|
||||
Codex AgentSessionVendor = "codex"
|
||||
)
|
||||
|
||||
// Valid indicates whether the value is a known member of the AgentSessionVendor enum.
|
||||
func (e AgentSessionVendor) Valid() bool {
|
||||
switch e {
|
||||
case Antigravity:
|
||||
return true
|
||||
case Claude:
|
||||
return true
|
||||
case Codex:
|
||||
@@ -596,10 +599,10 @@ type AgentSession struct {
|
||||
// TaskId Empty for a lead session.
|
||||
TaskId string `json:"task_id"`
|
||||
|
||||
// Vendor Follows from the model the session was created with: gpt-* models run on Codex, every other model on Claude Code.
|
||||
// Vendor Follows from the model the session was created with: gpt-* models run on Codex, gemini-* models on Antigravity, every other model on Claude Code.
|
||||
Vendor AgentSessionVendor `json:"vendor"`
|
||||
|
||||
// VendorSessionId Claude Code's session id, chosen by byre; or the Codex thread id, empty until the session's first turn starts its thread.
|
||||
// VendorSessionId Claude Code's session id, chosen by byre; or the Codex thread id or Antigravity conversation id, empty until the session first starts.
|
||||
VendorSessionId string `json:"vendor_session_id"`
|
||||
}
|
||||
|
||||
@@ -609,7 +612,7 @@ type AgentSessionRole string
|
||||
// AgentSessionState defines model for AgentSession.State.
|
||||
type AgentSessionState string
|
||||
|
||||
// AgentSessionVendor Follows from the model the session was created with: gpt-* models run on Codex, every other model on Claude Code.
|
||||
// AgentSessionVendor Follows from the model the session was created with: gpt-* models run on Codex, gemini-* models on Antigravity, every other model on Claude Code.
|
||||
type AgentSessionVendor string
|
||||
|
||||
// Attachment defines model for Attachment.
|
||||
@@ -1090,7 +1093,7 @@ type Stage struct {
|
||||
// Base Where the stage's task branches from. parent (the default): the commit its one after stage finished at, or for a stage with none, where the workflow was started from. main: the project's default branch. Refused on a stage with more than one after stage, which always branches from the default branch.
|
||||
Base *StageBase `json:"base,omitempty"`
|
||||
|
||||
// Model The stage agent's model, which also picks its vendor: gpt-* models run on Codex, every other model on Claude Code. Required without agents, refused with them.
|
||||
// Model The stage agent's model, which also picks its vendor: gpt-* models run on Codex, gemini-* models on Antigravity, every other model on Claude Code. Required without agents, refused with them.
|
||||
Model string `json:"model,omitempty"`
|
||||
|
||||
// Name One line of 1 to 100 characters, unique within the workflow.
|
||||
@@ -3798,238 +3801,238 @@ var swaggerSpec = []string{
|
||||
"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",
|
||||
"ewA=",
|
||||
"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",
|
||||
"YssYaXgUony5VOY7NGNvqefefX6vIk0fP/7vAQA=",
|
||||
}
|
||||
|
||||
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
|
||||
|
||||
@@ -69,7 +69,7 @@ func New(dataDir string, portFirst int) (*Server, error) {
|
||||
}
|
||||
}
|
||||
|
||||
s.agents = agents.New(s.store, filepath.Join(dataDir, "worktrees"), filepath.Join(dataDir, "leads"), filepath.Join(dataDir, "hands"), filepath.Join(dataDir, "codex"), s.status, s.createProject, s.clients, s.terminals)
|
||||
s.agents = agents.New(s.store, filepath.Join(dataDir, "worktrees"), filepath.Join(dataDir, "leads"), filepath.Join(dataDir, "hands"), filepath.Join(dataDir, "codex"), filepath.Join(dataDir, "antigravity"), s.status, s.createProject, s.clients, s.terminals)
|
||||
err = s.agents.Recover(context.Background())
|
||||
if err != nil {
|
||||
s.store.Close()
|
||||
|
||||
@@ -15,8 +15,11 @@ var ErrInvalid = errors.New("invalid workflow")
|
||||
const maxNameRunes = 100
|
||||
|
||||
func VendorOf(model string) api.AgentSessionVendor {
|
||||
if strings.HasPrefix(model, "gpt-") {
|
||||
switch {
|
||||
case strings.HasPrefix(model, "gpt-"):
|
||||
return api.Codex
|
||||
case strings.HasPrefix(model, "gemini-"):
|
||||
return api.Antigravity
|
||||
}
|
||||
return api.Claude
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user