Add Antigravity (agy) as a third agent backend for gemini-* models
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user