Agents workspace: roster, runs, and a readable run log; layout now eight workspaces
This commit is contained in:
@@ -373,3 +373,71 @@ func (c *Client) CostSummary(issueID string) (Cost, error) {
|
||||
func (c *Client) Health() error {
|
||||
return c.do("GET", "/api/health", nil, nil)
|
||||
}
|
||||
|
||||
// AgentRun is one heartbeat run in the company, whichever agent ran it.
|
||||
type AgentRun struct {
|
||||
ID string `json:"id"`
|
||||
AgentID string `json:"agentId"`
|
||||
Status string `json:"status"`
|
||||
Source string `json:"invocationSource"`
|
||||
StartedAt string `json:"createdAt"`
|
||||
FinishedAt string `json:"finishedAt"`
|
||||
ErrorCode string `json:"errorCode"`
|
||||
LastOutputAt string `json:"lastOutputAt"`
|
||||
LastOutputBytes int `json:"lastOutputBytes"`
|
||||
// The task a run worked on lives inside the run's context snapshot, not on
|
||||
// the run itself.
|
||||
Snapshot struct {
|
||||
IssueID string `json:"issueId"`
|
||||
TaskKey string `json:"taskKey"`
|
||||
} `json:"contextSnapshot"`
|
||||
}
|
||||
|
||||
// Runs returns every run in the company, newest first.
|
||||
func (c *Client) CompanyRuns() ([]AgentRun, error) {
|
||||
var out []AgentRun
|
||||
err := c.do("GET", "/api/companies/"+c.Company+"/heartbeat-runs", nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RunLog returns the recorded output of one run.
|
||||
func (c *Client) RunLog(runID string, maxBytes int) (string, error) {
|
||||
var raw []byte
|
||||
req, err := http.NewRequest("GET", c.BaseURL+"/api/heartbeat-runs/"+runID+"/log", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||
b, _ := io.ReadAll(io.LimitReader(resp.Body, 400))
|
||||
return "", fmt.Errorf("run log returned %d: %s", resp.StatusCode, snippet(b))
|
||||
}
|
||||
raw, err = io.ReadAll(io.LimitReader(resp.Body, int64(maxBytes)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(raw) == maxBytes {
|
||||
return string(raw) + "\n… (only the last " + fmt.Sprint(maxBytes) + " bytes are shown)", nil
|
||||
}
|
||||
return string(raw), nil
|
||||
}
|
||||
|
||||
// PauseAgent and ResumeAgent are the two ways to stop and start an agent.
|
||||
func (c *Client) PauseAgent(agentID string) error {
|
||||
return c.do("POST", "/api/agents/"+agentID+"/pause", map[string]any{}, nil)
|
||||
}
|
||||
|
||||
func (c *Client) ResumeAgent(agentID string) error {
|
||||
return c.do("POST", "/api/agents/"+agentID+"/resume", map[string]any{}, nil)
|
||||
}
|
||||
|
||||
// WakeAgent asks Paperclip to start a run for this agent now.
|
||||
func (c *Client) WakeAgent(agentID string) error {
|
||||
return c.do("POST", "/api/agents/"+agentID+"/wakeup",
|
||||
map[string]any{"source": "on_demand", "triggerDetail": "manual", "forceFreshSession": false}, nil)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user