Lead messages mid-turn
This commit is contained in:
+2
-2
File diff suppressed because one or more lines are too long
@@ -139,8 +139,9 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
tool("send_message",
|
tool("send_message",
|
||||||
"Send a message to a task's agent; it starts a turn. Starts the agent when the task has none. The agent must be idle: "+
|
"Send a message to a task's agent; it starts a turn. Starts the agent when the task has none. "+
|
||||||
"if it is mid-turn, wait for it to finish the turn or interrupt it first.",
|
"If the agent is mid-turn, the message is queued like the human's: the agent reads it with its next tool call's result, "+
|
||||||
|
"or as its next turn if it makes no further tool call, and gets it only once.",
|
||||||
`{"type": "object", "properties": {
|
`{"type": "object", "properties": {
|
||||||
"task_id": {"type": "string"},
|
"task_id": {"type": "string"},
|
||||||
"text": {"type": "string"},
|
"text": {"type": "string"},
|
||||||
@@ -174,10 +175,13 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("Started an agent on %s with your message.", task.Id), nil
|
return fmt.Sprintf("Started an agent on %s with your message.", task.Id), nil
|
||||||
}
|
}
|
||||||
_, err = m.Send(ctx, sess.Id, leadActor(user.Login), args.Text, args.Model)
|
_, queued, err := m.Message(ctx, sess.Id, leadActor(user.Login), args.Text, args.Model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
if queued {
|
||||||
|
return fmt.Sprintf("Queued for %s's agent, which is mid-turn: it reads the message with its next tool call's result, or as its next turn.", task.Id), nil
|
||||||
|
}
|
||||||
return fmt.Sprintf("Sent to %s's agent.", task.Id), nil
|
return fmt.Sprintf("Sent to %s's agent.", task.Id), nil
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -39,40 +39,41 @@ func (m *Manager) lockDelivery(sessionID string) func() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Message(ctx context.Context, sessionID, actor, text, model string, images ...string) (api.AgentSession, error) {
|
func (m *Manager) Message(ctx context.Context, sessionID, actor, text, model string, images ...string) (api.AgentSession, bool, error) {
|
||||||
unlock := m.lockDelivery(sessionID)
|
unlock := m.lockDelivery(sessionID)
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
sess, err := m.store.GetSession(ctx, sessionID)
|
sess, err := m.store.GetSession(ctx, sessionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.AgentSession{}, err
|
return api.AgentSession{}, false, err
|
||||||
}
|
}
|
||||||
if sess.State != api.AgentSessionStateRunning || sess.Role != api.Implementer {
|
if sess.State != api.AgentSessionStateRunning || sess.Role != api.Implementer {
|
||||||
return m.Send(ctx, sessionID, actor, text, model, images...)
|
sess, err = m.Send(ctx, sessionID, actor, text, model, images...)
|
||||||
|
return sess, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if model != "" && model != sess.Model {
|
if model != "" && model != sess.Model {
|
||||||
err = checkModel(sess, model)
|
err = checkModel(sess, model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.AgentSession{}, err
|
return api.AgentSession{}, false, err
|
||||||
}
|
}
|
||||||
err = m.store.SetSessionModel(ctx, sess.Id, model, actor)
|
err = m.store.SetSessionModel(ctx, sess.Id, model, actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.AgentSession{}, err
|
return api.AgentSession{}, false, err
|
||||||
}
|
}
|
||||||
sess.Model = model
|
sess.Model = model
|
||||||
}
|
}
|
||||||
|
|
||||||
task, err := m.store.GetTask(ctx, sess.TaskId)
|
task, err := m.store.GetTask(ctx, sess.TaskId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.AgentSession{}, err
|
return api.AgentSession{}, false, err
|
||||||
}
|
}
|
||||||
err = m.store.AddTaskInput(ctx, store.TaskInput{TaskID: sess.TaskId, Actor: actor, Text: text, Images: images}, task.ProjectId, sess.Id)
|
err = m.store.AddTaskInput(ctx, store.TaskInput{TaskID: sess.TaskId, Actor: actor, Text: text, Images: images}, task.ProjectId, sess.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.AgentSession{}, err
|
return api.AgentSession{}, false, err
|
||||||
}
|
}
|
||||||
slog.Info("message queued", "session", sess.Id, "task", sess.TaskId, "actor", actor)
|
slog.Info("message queued", "session", sess.Id, "task", sess.TaskId, "actor", actor)
|
||||||
return sess, nil
|
return sess, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Withdraw(ctx context.Context, taskID string, inputID int64, actor string) error {
|
func (m *Manager) Withdraw(ctx context.Context, taskID string, inputID int64, actor string) error {
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ func (m *Manager) forwardFindings(taskID, reviewID string) {
|
|||||||
if s.State == api.AgentSessionStateCompleted {
|
if s.State == api.AgentSessionStateCompleted {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, err = m.Message(ctx, s.Id, "byre", findingsMessage(r), "")
|
_, _, err = m.Message(ctx, s.Id, "byre", findingsMessage(r), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("forward review findings", "review", reviewID, "session", s.Id, "err", err)
|
slog.Error("forward review findings", "review", reviewID, "session", s.Id, "err", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ func (m *Manager) messageTask(ctx context.Context, task api.Task, user api.User,
|
|||||||
_, err = m.create(ctx, task, user, text, "", actor, nil)
|
_, err = m.create(ctx, task, user, text, "", actor, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = m.Message(ctx, sess.Id, actor, text, "")
|
_, _, err = m.Message(ctx, sess.Id, actor, text, "")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -792,7 +792,7 @@ func (s *Server) SendMessage(w http.ResponseWriter, r *http.Request, sessionID s
|
|||||||
model = *req.Model
|
model = *req.Model
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, err := s.agents.Message(r.Context(), sessionID, actor(r), req.Text, model, images...)
|
sess, _, err := s.agents.Message(r.Context(), sessionID, actor(r), req.Text, model, images...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeAgentError(w, err)
|
writeAgentError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user