aebb0c0c76
- Add ACP session manager for JSON-RPC 2.0 over stdin/stdout - Create jsonrpc package with Client for bidirectional communication - Update agent.sh to run auggie --acp mode - Add Docker client methods for container stdin/stdout attachment - Update lifecycle manager to use ACP instead of log streaming - Add new API endpoints: POST /prompt, POST /cancel, GET /session - Update AGENTS.md with ACP protocol documentation - Update OpenAPI spec with new endpoints and schemas This enables: - Sending prompts to running agents - Cancelling agent operations - Session management (create, load, resume) - Real-time progress updates via session/update notifications
82 lines
2.2 KiB
Go
82 lines
2.2 KiB
Go
package protocol
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
// MessageType represents the type of ACP message
|
|
type MessageType string
|
|
|
|
const (
|
|
// Agent → Backend message types
|
|
MessageTypeProgress MessageType = "progress"
|
|
MessageTypeLog MessageType = "log"
|
|
MessageTypeResult MessageType = "result"
|
|
MessageTypeError MessageType = "error"
|
|
MessageTypeStatus MessageType = "status"
|
|
MessageTypeHeartbeat MessageType = "heartbeat"
|
|
MessageTypeInputRequired MessageType = "input_required" // Agent requests input from user
|
|
MessageTypeSessionInfo MessageType = "session_info" // Agent reports session information
|
|
|
|
// Backend → Agent message types
|
|
MessageTypeControl MessageType = "control" // Control commands (pause, resume, stop)
|
|
MessageTypeInputResponse MessageType = "input_response" // Response to input_required
|
|
)
|
|
|
|
// Message represents an ACP protocol message
|
|
type Message struct {
|
|
Type MessageType `json:"type"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
AgentID string `json:"agent_id"`
|
|
TaskID string `json:"task_id"`
|
|
Data map[string]interface{} `json:"data"`
|
|
}
|
|
|
|
// NewMessage creates a new ACP message with the current timestamp
|
|
func NewMessage(msgType MessageType, agentID, taskID string, data map[string]interface{}) *Message {
|
|
return &Message{
|
|
Type: msgType,
|
|
Timestamp: time.Now().UTC(),
|
|
AgentID: agentID,
|
|
TaskID: taskID,
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
// MarshalJSON implements custom JSON marshaling
|
|
func (m *Message) MarshalJSON() ([]byte, error) {
|
|
type Alias Message
|
|
return json.Marshal(&struct {
|
|
*Alias
|
|
Timestamp string `json:"timestamp"`
|
|
}{
|
|
Alias: (*Alias)(m),
|
|
Timestamp: m.Timestamp.Format(time.RFC3339Nano),
|
|
})
|
|
}
|
|
|
|
// Parse parses a JSON string into an ACP message
|
|
func Parse(data []byte) (*Message, error) {
|
|
var msg Message
|
|
if err := json.Unmarshal(data, &msg); err != nil {
|
|
return nil, err
|
|
}
|
|
return &msg, nil
|
|
}
|
|
|
|
// IsValid checks if the message has required fields
|
|
func (m *Message) IsValid() bool {
|
|
if m.Type == "" {
|
|
return false
|
|
}
|
|
if m.AgentID == "" {
|
|
return false
|
|
}
|
|
if m.TaskID == "" {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|