Switch to prefixed IDs and tell agents which Mac a message came from
This commit is contained in:
+25
-29
@@ -2,7 +2,6 @@ package agents
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"g.fc.run/ai/byre/internal/claude"
|
||||
"g.fc.run/ai/byre/internal/clients"
|
||||
"g.fc.run/ai/byre/internal/git"
|
||||
"g.fc.run/ai/byre/internal/ids"
|
||||
"g.fc.run/ai/byre/internal/mcp"
|
||||
"g.fc.run/ai/byre/internal/store"
|
||||
"g.fc.run/ai/byre/internal/terminal"
|
||||
@@ -186,7 +186,7 @@ func (m *Manager) taskFor(ctx context.Context, sess api.AgentSession) (api.Task,
|
||||
return m.store.GetTask(ctx, sess.TaskId)
|
||||
}
|
||||
|
||||
func (m *Manager) Create(ctx context.Context, task api.Task, creator api.User, prompt, model, sendID string, images ...string) (api.AgentSession, error) {
|
||||
func (m *Manager) Create(ctx context.Context, task api.Task, creator api.User, prompt, model, sendID, client string, images ...string) (api.AgentSession, error) {
|
||||
unlock := m.lockDelivery("create:" + task.Id)
|
||||
defer unlock()
|
||||
|
||||
@@ -201,12 +201,12 @@ func (m *Manager) Create(ctx context.Context, task api.Task, creator api.User, p
|
||||
}
|
||||
if found {
|
||||
slog.Info("first message to an unused session", "session", unused, "task", task.Id)
|
||||
return m.Send(ctx, unused, creator.Login, prompt, model, sendID, images...)
|
||||
return m.Send(ctx, unused, creator.Login, prompt, model, sendID, client, images...)
|
||||
}
|
||||
return m.create(ctx, task, creator, "", prompt, model, creator.Login, sendID, images)
|
||||
return m.create(ctx, task, creator, "", prompt, model, creator.Login, sendID, client, images)
|
||||
}
|
||||
|
||||
func (m *Manager) create(ctx context.Context, task api.Task, creator api.User, member, prompt, model, actor, sendID string, images []string) (api.AgentSession, error) {
|
||||
func (m *Manager) create(ctx context.Context, task api.Task, creator api.User, member, prompt, model, actor, sendID, client string, images []string) (api.AgentSession, error) {
|
||||
if creator.GitName == "" || creator.GitEmail == "" {
|
||||
return api.AgentSession{}, ErrNoGitIdentity
|
||||
}
|
||||
@@ -219,7 +219,7 @@ func (m *Manager) create(ctx context.Context, task api.Task, creator api.User, m
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
return m.turn(ctx, sess, task, actor, prompt, sendID, images)
|
||||
return m.turn(ctx, sess, task, actor, prompt, sendID, client, images)
|
||||
}
|
||||
|
||||
func (m *Manager) newSession(ctx context.Context, task api.Task, creator api.User, member, model string) (api.AgentSession, error) {
|
||||
@@ -233,14 +233,14 @@ func (m *Manager) newSession(ctx context.Context, task api.Task, creator api.Use
|
||||
}
|
||||
}
|
||||
|
||||
id := newUUID()
|
||||
id := ids.New(ids.Session)
|
||||
vendor := vendorOf(model)
|
||||
sess := api.AgentSession{
|
||||
Id: id,
|
||||
TaskId: task.Id,
|
||||
Vendor: vendor,
|
||||
Model: model,
|
||||
VendorSessionId: initialVendorSessionID(vendor, id),
|
||||
VendorSessionId: initialVendorSessionID(vendor),
|
||||
State: api.AgentSessionStateIdle,
|
||||
Role: api.Implementer,
|
||||
Member: member,
|
||||
@@ -252,7 +252,7 @@ func (m *Manager) newSession(ctx context.Context, task api.Task, creator api.Use
|
||||
return sess, err
|
||||
}
|
||||
|
||||
func (m *Manager) Send(ctx context.Context, sessionID, actor, text, model, sendID string, images ...string) (api.AgentSession, error) {
|
||||
func (m *Manager) Send(ctx context.Context, sessionID, actor, text, model, sendID, client string, images ...string) (api.AgentSession, error) {
|
||||
sess, err := m.store.GetSession(ctx, sessionID)
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
@@ -272,7 +272,7 @@ func (m *Manager) Send(ctx context.Context, sessionID, actor, text, model, sendI
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
|
||||
return m.turn(ctx, sess, task, actor, text, sendID, images)
|
||||
return m.turn(ctx, sess, task, actor, text, sendID, client, images)
|
||||
}
|
||||
|
||||
func (m *Manager) Interrupt(ctx context.Context, sessionID string) (api.AgentSession, error) {
|
||||
@@ -575,12 +575,12 @@ func (m *Manager) Usage(ctx context.Context) (Usage, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (m *Manager) turn(ctx context.Context, sess api.AgentSession, task api.Task, actor, text, sendID string, images []string) (api.AgentSession, error) {
|
||||
func (m *Manager) turn(ctx context.Context, sess api.AgentSession, task api.Task, actor, text, sendID, client string, images []string) (api.AgentSession, error) {
|
||||
err := m.startRunning(ctx, sess, task.Id, actor)
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
return m.launch(ctx, sess, task, actor, text, sendID, images)
|
||||
return m.launch(ctx, sess, task, actor, text, sendID, client, images)
|
||||
}
|
||||
|
||||
func (m *Manager) startRunning(ctx context.Context, sess api.AgentSession, taskID, actor string) error {
|
||||
@@ -602,20 +602,20 @@ func (m *Manager) startRunning(ctx context.Context, sess api.AgentSession, taskI
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) launch(ctx context.Context, sess api.AgentSession, task api.Task, actor, text, sendID string, images []string) (api.AgentSession, error) {
|
||||
imgs, compacting, err := m.recordMessage(ctx, sess, task, actor, text, sendID, images)
|
||||
func (m *Manager) launch(ctx context.Context, sess api.AgentSession, task api.Task, actor, text, sendID, client string, images []string) (api.AgentSession, error) {
|
||||
imgs, compacting, err := m.recordMessage(ctx, sess, task, actor, text, sendID, client, images)
|
||||
if err != nil {
|
||||
m.failStart(ctx, sess.Id, actor, err)
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
err = m.deliver(ctx, sess, task, actor, text, imgs, compacting)
|
||||
err = m.deliver(ctx, sess, task, actor, client, text, imgs, compacting)
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
return m.store.GetSession(ctx, sess.Id)
|
||||
}
|
||||
|
||||
func (m *Manager) deliver(ctx context.Context, sess api.AgentSession, task api.Task, actor, text string, imgs []image, compacting bool) error {
|
||||
func (m *Manager) deliver(ctx context.Context, sess api.AgentSession, task api.Task, actor, client, text string, imgs []image, compacting bool) error {
|
||||
l, err := m.ensureLive(ctx, sess, task)
|
||||
if err == nil {
|
||||
err = m.syncModel(ctx, l, sess.Model)
|
||||
@@ -626,7 +626,7 @@ func (m *Manager) deliver(ctx context.Context, sess api.AgentSession, task api.T
|
||||
}
|
||||
|
||||
m.beginTurn(l, compacting)
|
||||
err = m.send(ctx, l, agentText(actor, text), imgs)
|
||||
err = m.send(ctx, l, m.agentText(actor, client, text), imgs)
|
||||
if err != nil {
|
||||
m.endMergeTurn(sess.Id, false)
|
||||
return err
|
||||
@@ -640,6 +640,7 @@ func (m *Manager) deliverRecorded(ctx context.Context, sess api.AgentSession, ta
|
||||
return false, err
|
||||
}
|
||||
text, _ := ev.Payload["text"].(string)
|
||||
client, _ := ev.Payload["client"].(string)
|
||||
ids := []string{}
|
||||
raw, _ := ev.Payload["images"].([]any)
|
||||
for _, id := range raw {
|
||||
@@ -651,7 +652,7 @@ func (m *Manager) deliverRecorded(ctx context.Context, sess api.AgentSession, ta
|
||||
m.failStart(ctx, sess.Id, ev.Actor, err)
|
||||
return true, err
|
||||
}
|
||||
return true, m.deliver(ctx, sess, task, ev.Actor, text, imgs, isHandoffPrompt(ev.Actor, text))
|
||||
return true, m.deliver(ctx, sess, task, ev.Actor, client, text, imgs, isHandoffPrompt(ev.Actor, text))
|
||||
}
|
||||
|
||||
func (m *Manager) readImages(ctx context.Context, ids []string) ([]image, error) {
|
||||
@@ -702,12 +703,12 @@ func transition(ctx context.Context, st *store.Store, id string, from, to api.Ag
|
||||
}
|
||||
|
||||
func (m *Manager) message(ctx context.Context, sess api.AgentSession, task api.Task, l *live, actor, text string, images []string) error {
|
||||
imgs, compacting, err := m.recordMessage(ctx, sess, task, actor, text, "", images)
|
||||
imgs, compacting, err := m.recordMessage(ctx, sess, task, actor, text, "", "", images)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.beginTurn(l, compacting)
|
||||
return m.send(ctx, l, agentText(actor, text), imgs)
|
||||
return m.send(ctx, l, m.agentText(actor, "", text), imgs)
|
||||
}
|
||||
|
||||
func (m *Manager) send(ctx context.Context, l *live, text string, imgs []image) error {
|
||||
@@ -718,7 +719,7 @@ func (m *Manager) send(ctx context.Context, l *live, text string, imgs []image)
|
||||
return m.store.MarkSessionDelivered(ctx, l.id)
|
||||
}
|
||||
|
||||
func (m *Manager) recordMessage(ctx context.Context, sess api.AgentSession, task api.Task, actor, text, sendID string, images []string) ([]image, bool, error) {
|
||||
func (m *Manager) recordMessage(ctx context.Context, sess api.AgentSession, task api.Task, actor, text, sendID, client string, images []string) ([]image, bool, error) {
|
||||
implementer := sess.Role == api.Implementer
|
||||
if implementer && isMergeInPrompt(actor, text) {
|
||||
m.ownMerge(sess.Id, task.Id, task.WorktreePath)
|
||||
@@ -752,6 +753,9 @@ func (m *Manager) recordMessage(ctx context.Context, sess api.AgentSession, task
|
||||
if sendID != "" {
|
||||
payload["send_id"] = sendID
|
||||
}
|
||||
if client != "" {
|
||||
payload["client"] = client
|
||||
}
|
||||
err = m.store.RecordTurnMessage(ctx, sess.Id, newEvent(sess.Id, sess.Owner, task.ProjectId, task.Id, actor, "user.message", payload))
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
@@ -1473,11 +1477,3 @@ func decode(raw json.RawMessage) (any, error) {
|
||||
err := json.Unmarshal(raw, &v)
|
||||
return v, err
|
||||
}
|
||||
|
||||
func newUUID() string {
|
||||
b := make([]byte, 16)
|
||||
rand.Read(b)
|
||||
b[6] = b[6]&0x0f | 0x40
|
||||
b[8] = b[8]&0x3f | 0x80
|
||||
return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user