Documentation
¶
Overview ¶
Package daemon implements the long-running ttal manager-plane process.
The daemon starts all agent sessions (tmux for Claude Code), bridges messages between Telegram and agent runtimes via a Unix socket, watches JSONL output files to forward agent responses to Telegram, and manages the worker lifecycle through fsnotify-based cleanup and PR watchers. It is managed by launchd and handles all inter-agent and human-agent messaging for every configured team from a single process.
Plane: manager
Index ¶
- Constants
- func AskAgent(ctx context.Context, req ask.Request, onEvent func(ask.Event)) error
- func Breathe(req BreatheRequest) error
- func CloseWindow(req CloseWindowRequest) error
- func Install() error
- func IsRunning() (bool, int, error)
- func Restart() error
- func Run() error
- func Send(req SendRequest) error
- func SocketPath() (string, error)
- func Start() error
- func Stop() error
- func Uninstall() error
- type AdvanceRequest
- type AdvanceResponse
- type AskHumanRequest
- type AskHumanResponse
- type BotCommand
- type BreatheRequest
- type CloseWindowRequest
- type CommentAddRequest
- type CommentAddResponse
- type CommentEntry
- type CommentGetRequest
- type CommentGetResponse
- type CommentListRequest
- type CommentListResponse
- type PRCIFailureDetail
- type PRCIFailureDetailsResponse
- type PRCIStatus
- type PRCIStatusResponse
- type PRCheckMergeableRequest
- type PRCreateRequest
- type PRGetCIFailureDetailsRequest
- type PRGetCombinedStatusRequest
- type PRGetPRRequest
- type PRGetPRResponse
- type PRMergeRequest
- type PRModifyRequest
- type PRResponse
- type SendRequest
- type SendResponse
- type StatusResponse
- type StatusUpdateRequest
- type TaskCompleteRequest
- type UsageData
Constants ¶
const ( AdvanceStatusAdvanced = "advanced" AdvanceStatusNeedsLGTM = "needs_lgtm" AdvanceStatusRejected = "rejected" AdvanceStatusError = "error" AdvanceStatusNoPipeline = "no_pipeline" AdvanceStatusComplete = "complete" )
Advance status constants.
Variables ¶
This section is empty.
Functions ¶
func AskAgent ¶ added in v1.10.0
AskAgent sends an ask request to the daemon and streams NDJSON events via the callback. Blocks until the stream completes (done or error terminal event received).
Uses no total deadline since agent loops run for many minutes. The NDJSON stream keeps the connection alive — idle timeouts aren't a concern. Lifecycle is controlled by context cancellation (e.g. Ctrl-C → SIGINT).
func Breathe ¶ added in v1.4.0
func Breathe(req BreatheRequest) error
Breathe sends a breathe request to the daemon, asking it to restart an agent's CC session with a fresh context window and the provided handoff prompt.
func CloseWindow ¶ added in v1.8.0
func CloseWindow(req CloseWindowRequest) error
CloseWindow asks the daemon to close a tmux window. Fire-and-forget: errors are returned but callers should treat them as non-fatal.
func Install ¶
func Install() error
Install installs the launchd plist and creates a config template if needed.
func IsRunning ¶
IsRunning checks whether the daemon is running by inspecting the pid file. Uses fixed path at ~/.ttal/daemon.pid.
func Restart ¶
func Restart() error
Restart performs an atomic daemon restart using launchctl kickstart -k. This kills the running process and lets launchd relaunch it immediately, avoiding the race condition in a Stop+Start (bootout+bootstrap) sequence.
func Run ¶
func Run() error
Run starts the daemon in the foreground. This is what launchd calls. Config-driven: loads all teams from config.toml, no database required.
func Send ¶
func Send(req SendRequest) error
Send connects to the daemon socket and sends a message via HTTP. Returns an error if the daemon is not running or if delivery fails.
func SocketPath ¶
SocketPath returns the path to the daemon unix socket. TTAL_SOCKET_PATH overrides the default. Delegates to config.SocketPath() to keep a single source of truth.
Types ¶
type AdvanceRequest ¶ added in v1.7.0
type AdvanceRequest struct {
TaskUUID string `json:"task_uuid"`
AgentName string `json:"agent_name"` // from TTAL_AGENT_NAME env in caller session
Team string `json:"team"` // TODO: remove after in-flight request compat window (~2026 Q3)
}
AdvanceRequest is the request body for POST /pipeline/advance.
type AdvanceResponse ¶ added in v1.7.0
type AdvanceResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Stage string `json:"stage"` // new stage name if advanced
Reviewer string `json:"reviewer,omitempty"` // reviewer agent name if NeedsLGTM
Assignee string `json:"assignee,omitempty"` // stage assignee role (e.g. "designer", "worker")
Agent string `json:"agent,omitempty"` // resolved agent name (e.g. "mira", "kestrel")
}
AdvanceResponse is the response body for POST /pipeline/advance.
func AdvanceClient ¶ added in v1.7.0
func AdvanceClient(req AdvanceRequest) (AdvanceResponse, error)
AdvanceClient sends an advance request to the daemon and blocks until response.
type AskHumanRequest ¶ added in v1.3.0
type AskHumanRequest struct {
Question string `json:"question"`
Options []string `json:"options,omitempty"`
AgentName string `json:"agent_name,omitempty"` // from TTAL_AGENT_NAME
Session string `json:"session,omitempty"` // from tmux session name
}
AskHumanRequest is the CLI → daemon POST body for POST /ask/human.
type AskHumanResponse ¶ added in v1.3.0
type AskHumanResponse struct {
OK bool `json:"ok"`
Answer string `json:"answer,omitempty"`
Skipped bool `json:"skipped,omitempty"`
Error string `json:"error,omitempty"`
}
AskHumanResponse is the daemon → CLI JSON response for /ask/human.
func AskHuman ¶ added in v1.3.0
func AskHuman(req AskHumanRequest) (AskHumanResponse, error)
AskHuman sends a question to a human via Telegram and blocks until answered. Returns the response with the human's answer, or Skipped=true on timeout/skip.
type BotCommand ¶
type BotCommand struct {
Command string `json:"command"`
Description string `json:"description"`
OriginalName string `json:"-"` // original name before sanitization (for dispatch to agent)
}
BotCommand represents a bot command for the menu.
func AllCommands ¶
func AllCommands(discovered []BotCommand) []BotCommand
AllCommands returns the full command list: static commands + discovered dynamic commands.
func DiscoverCommands ¶
func DiscoverCommands() []BotCommand
DiscoverCommands reads command-category skills from the default skill registry.
type BreatheRequest ¶ added in v1.4.0
type BreatheRequest struct {
Team string `json:"team,omitempty"` // defaults to "default"
Agent string `json:"agent"` // agent name
Handoff string `json:"handoff"` // handoff prompt content
SessionName string `json:"session_name,omitempty"` // current tmux session name (if known)
}
BreatheRequest asks the daemon to restart an agent with a fresh context window.
type CloseWindowRequest ¶ added in v1.8.0
type CloseWindowRequest struct {
Session string `json:"session"` // tmux session name
Window string `json:"window"` // tmux window name (reviewer agent name from pipelines.toml)
}
CloseWindowRequest asks the daemon to close a tmux window. Used by ttal comment lgtm to auto-close the reviewer's window after LGTM.
type CommentAddRequest ¶ added in v1.7.0
type CommentAddRequest struct {
Target string `json:"target"` // taskwarrior task UUID
Author string `json:"author"`
Body string `json:"body"`
// Optional PR context for mirroring to remote PR
ProviderType string `json:"provider_type,omitempty"`
Owner string `json:"owner,omitempty"`
Repo string `json:"repo,omitempty"`
PRIndex int64 `json:"pr_index,omitempty"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
CommentAddRequest asks the daemon to add a comment to a task.
type CommentAddResponse ¶ added in v1.7.0
type CommentAddResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
ID string `json:"id,omitempty"`
Round int `json:"round,omitempty"`
}
CommentAddResponse is the daemon's response for a comment add.
func CommentAdd ¶ added in v1.7.0
func CommentAdd(req CommentAddRequest) (CommentAddResponse, error)
CommentAdd asks the daemon to add a comment to a task.
type CommentEntry ¶ added in v1.7.0
type CommentEntry struct {
Author string `json:"author"`
Body string `json:"body"`
Round int `json:"round"`
CreatedAt string `json:"created_at"`
}
CommentEntry is a single comment in a CommentListResponse.
type CommentGetRequest ¶ added in v1.7.0
type CommentGetRequest struct {
Target string `json:"target"` // taskwarrior task UUID
Round int `json:"round"`
}
CommentGetRequest asks the daemon to get comments for a specific round. Team is omitted — daemon injects from mcfg.DefaultTeamName(), consistent with CommentListRequest.
type CommentGetResponse ¶ added in v1.7.0
type CommentGetResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Comments []CommentEntry `json:"comments,omitempty"`
}
CommentGetResponse is the daemon's response for a comment get.
func CommentGet ¶ added in v1.7.0
func CommentGet(req CommentGetRequest) (CommentGetResponse, error)
CommentGet asks the daemon for comments at a specific round.
type CommentListRequest ¶ added in v1.7.0
type CommentListRequest struct {
Target string `json:"target"` // taskwarrior task UUID
}
CommentListRequest asks the daemon to list comments on a task.
type CommentListResponse ¶ added in v1.7.0
type CommentListResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Comments []CommentEntry `json:"comments,omitempty"`
}
CommentListResponse is the daemon's response for a comment list.
func CommentList ¶ added in v1.7.0
func CommentList(req CommentListRequest) (CommentListResponse, error)
CommentList asks the daemon to list comments on a task.
type PRCIFailureDetail ¶ added in v1.6.0
type PRCIFailureDetail struct {
JobName string `json:"job_name"`
WorkflowName string `json:"workflow_name"`
HTMLURL string `json:"html_url"`
LogTail string `json:"log_tail"`
}
PRCIFailureDetail is a single CI failure entry.
type PRCIFailureDetailsResponse ¶ added in v1.6.0
type PRCIFailureDetailsResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Details []PRCIFailureDetail `json:"details,omitempty"`
}
PRCIFailureDetailsResponse is the daemon's response for GetCIFailureDetails.
func PRGetCIFailureDetails ¶ added in v1.6.0
func PRGetCIFailureDetails(req PRGetCIFailureDetailsRequest) (PRCIFailureDetailsResponse, error)
PRGetCIFailureDetails asks the daemon to fetch CI failure details.
type PRCIStatus ¶ added in v1.6.0
type PRCIStatus struct {
Context string `json:"context"`
State string `json:"state"`
Description string `json:"description"`
TargetURL string `json:"target_url"`
}
PRCIStatus is a single CI check status.
type PRCIStatusResponse ¶ added in v1.6.0
type PRCIStatusResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
State string `json:"state,omitempty"`
Statuses []PRCIStatus `json:"statuses,omitempty"`
}
PRCIStatusResponse is the daemon's response for GetCombinedStatus.
func PRGetCombinedStatus ¶ added in v1.6.0
func PRGetCombinedStatus(req PRGetCombinedStatusRequest) (PRCIStatusResponse, error)
PRGetCombinedStatus asks the daemon to fetch CI status for a commit.
type PRCheckMergeableRequest ¶ added in v1.6.0
type PRCheckMergeableRequest struct {
ProviderType string `json:"provider_type"`
Owner string `json:"owner"`
Repo string `json:"repo"`
Index int64 `json:"index"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRCheckMergeableRequest asks the daemon to check if a PR is mergeable.
type PRCreateRequest ¶ added in v1.6.0
type PRCreateRequest struct {
ProviderType string `json:"provider_type"` // "forgejo" or "github"
Owner string `json:"owner"`
Repo string `json:"repo"`
Head string `json:"head"` // source branch
Base string `json:"base"` // target branch
Title string `json:"title"`
Body string `json:"body"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRCreateRequest asks the daemon to create a PR via the authenticated provider.
type PRGetCIFailureDetailsRequest ¶ added in v1.6.0
type PRGetCIFailureDetailsRequest struct {
ProviderType string `json:"provider_type"`
Owner string `json:"owner"`
Repo string `json:"repo"`
SHA string `json:"sha"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRGetCIFailureDetailsRequest asks the daemon to fetch CI failure details.
type PRGetCombinedStatusRequest ¶ added in v1.6.0
type PRGetCombinedStatusRequest struct {
ProviderType string `json:"provider_type"`
Owner string `json:"owner"`
Repo string `json:"repo"`
SHA string `json:"sha"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRGetCombinedStatusRequest asks the daemon to fetch CI status for a commit.
type PRGetPRRequest ¶ added in v1.6.0
type PRGetPRRequest struct {
ProviderType string `json:"provider_type"`
Owner string `json:"owner"`
Repo string `json:"repo"`
Index int64 `json:"index"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRGetPRRequest asks the daemon to fetch a PR (for HeadSHA resolution in CI commands).
type PRGetPRResponse ¶ added in v1.6.0
type PRGetPRResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
HeadSHA string `json:"head_sha,omitempty"`
Merged bool `json:"merged,omitempty"`
Mergeable bool `json:"mergeable,omitempty"`
Title string `json:"title,omitempty"`
}
PRGetPRResponse is the daemon's response for GetPR.
func PRGetPR ¶ added in v1.6.0
func PRGetPR(req PRGetPRRequest) (PRGetPRResponse, error)
PRGetPR asks the daemon to fetch a PR.
type PRMergeRequest ¶ added in v1.6.0
type PRMergeRequest struct {
ProviderType string `json:"provider_type"`
Owner string `json:"owner"`
Repo string `json:"repo"`
Index int64 `json:"index"`
DeleteBranch bool `json:"delete_branch"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRMergeRequest asks the daemon to squash-merge a PR.
type PRModifyRequest ¶ added in v1.6.0
type PRModifyRequest struct {
ProviderType string `json:"provider_type"`
Owner string `json:"owner"`
Repo string `json:"repo"`
Index int64 `json:"index"`
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
ProjectAlias string `json:"project_alias,omitempty"` // for per-project GitHub token resolution
}
PRModifyRequest asks the daemon to edit a PR title/body.
type PRResponse ¶ added in v1.6.0
type PRResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
PRURL string `json:"pr_url,omitempty"`
PRIndex int64 `json:"pr_index,omitempty"`
HeadSHA string `json:"head_sha,omitempty"`
AlreadyMerged bool `json:"already_merged,omitempty"`
}
PRResponse is the daemon's response for PR operations.
func PRCheckMergeable ¶ added in v1.6.0
func PRCheckMergeable(req PRCheckMergeableRequest) (PRResponse, error)
PRCheckMergeable asks the daemon to check if a PR is mergeable.
func PRCreate ¶ added in v1.6.0
func PRCreate(req PRCreateRequest) (PRResponse, error)
PRCreate asks the daemon to create a PR via the authenticated provider.
func PRMerge ¶ added in v1.6.0
func PRMerge(req PRMergeRequest) (PRResponse, error)
PRMerge asks the daemon to squash-merge a PR.
func PRModify ¶ added in v1.6.0
func PRModify(req PRModifyRequest) (PRResponse, error)
PRModify asks the daemon to edit a PR title/body.
type SendRequest ¶
type SendRequest struct {
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Team string `json:"team,omitempty"`
Message string `json:"message"`
}
SendRequest is the JSON message sent to the daemon. Direction is determined by which fields are set:
From only: agent → human via Telegram To only: system/hook → agent via tmux From + To: agent → agent via tmux with attribution
Team disambiguates when agent names collide across teams.
type SendResponse ¶
SendResponse is the JSON reply from the daemon.
type StatusResponse ¶
type StatusResponse struct {
OK bool `json:"ok"`
Agents []status.AgentStatus `json:"agents,omitempty"`
Error string `json:"error,omitempty"`
}
StatusResponse returns agent status data.
func QueryStatus ¶
func QueryStatus(team, agent string) (*StatusResponse, error)
QueryStatus connects to the daemon and queries agent status via HTTP.
type StatusUpdateRequest ¶
type StatusUpdateRequest struct {
Type string `json:"type"` // "statusUpdate"
Team string `json:"team,omitempty"` // team name (defaults to "default")
Agent string `json:"agent"` // agent name
ContextUsedPct float64 `json:"context_used_pct"` // percentage of context used
ContextRemainingPct float64 `json:"context_remaining_pct"` // percentage remaining
ModelID string `json:"model_id"` // model identifier
SessionID string `json:"session_id"` // session identifier
}
StatusUpdateRequest writes agent context status to the daemon. Wire format: {"type":"statusUpdate","agent":"kestrel","context_used_pct":45.2,...}
type TaskCompleteRequest ¶ added in v1.0.0
type TaskCompleteRequest struct {
Type string `json:"type"` // "taskComplete"
TaskUUID string `json:"task_uuid"`
Team string `json:"team,omitempty"` // defaults to "default"
Spawner string `json:"spawner,omitempty"` // "team:agent", optional
Desc string `json:"desc,omitempty"` // task description for the notification message
PRID string `json:"pr_id,omitempty"` // PR number for the notification message
PRTitle string `json:"pr_title,omitempty"` // PR title (preferred over Desc for notifications)
}
TaskCompleteRequest notifies the daemon that a task has been marked done. Wire format: {"type":"taskComplete","task_uuid":"...","team":"default",...}
type UsageData ¶ added in v1.0.0
type UsageData struct {
SessionUsage *float64 `json:"sessionUsage,omitempty"`
SessionResetAt string `json:"sessionResetAt,omitempty"`
WeeklyUsage *float64 `json:"weeklyUsage,omitempty"`
WeeklyResetAt string `json:"weeklyResetAt,omitempty"`
FetchedAt time.Time `json:"fetchedAt"`
Error string `json:"error,omitempty"`
}
UsageData holds the parsed Claude.ai usage response.
Source Files
¶
- adapters.go
- advance.go
- agents.go
- ask_handler.go
- ask_human.go
- botcommands.go
- cleanup.go
- comment_handler.go
- daemon.go
- deliver.go
- doc.go
- heartbeat.go
- launchd.go
- notifbot.go
- pr_handler.go
- prwatch.go
- reactions.go
- reminder.go
- routing.go
- socket.go
- taskcomplete.go
- telegram.go
- telegram_reply.go
- usage_poller.go
- watcher_bridge.go
- window_handler.go