api

package
v0.0.0-...-c163130 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2026 License: MIT Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultBehavior = "plan"

DefaultBehavior is the reserved behavior name used when a CreateTaskRequest omits both behavior and behavior_spec. Projects are expected to define a behavior with this name in project.yaml's task_behaviors (typically with readonly: true) so that bare-task creation routes to a planning/triage step.

Variables

This section is empty.

Functions

func BuildFlatItems

func BuildFlatItems(tasks []*orchestrator.Task, projectNames map[string]string) []components.TreeItem

BuildFlatItems returns tasks as a flat list (Depth=0, HasChildren=false, ParentID=""). Used for the "closed" status view where tree structure is irrelevant.

func BuildTreeItems

func BuildTreeItems(tasks []*orchestrator.Task, projectNames map[string]string) []components.TreeItem

BuildTreeItems takes a flat task list and returns items in DFS tree order with depth and visual-parent info. Siblings appear in input order. Tasks whose ParentID is absent from the list are treated as roots. Cycles in ParentID references are detected via a visited set and skipped.

projectNames maps project ID to display name; pass nil to skip name resolution.

Types

type ActionApplication

type ActionApplication struct {
	Task         *orchestrator.Task   `json:"task"`
	Action       *orchestrator.Action `json:"action"`
	MatchedHooks []string             `json:"matched_hooks,omitempty"`
}

type ActionHandler

type ActionHandler struct {
	Service WorkflowService
}

func (*ActionHandler) Apply

func (h *ActionHandler) Apply(w http.ResponseWriter, r *http.Request)

func (*ActionHandler) Routes

func (h *ActionHandler) Routes() chi.Router

type ActionStore

type ActionStore interface {
	CreateAction(action *orchestrator.Action) error
	ListActionsByTask(taskID string) ([]*orchestrator.Action, error)
}

type AnswerTaskRequest

type AnswerTaskRequest struct {
	QuestionID string `json:"question_id"`
	Answer     string `json:"answer"`
}

type ApplyActionRequest

type ApplyActionRequest struct {
	Type    string          `json:"type"`
	Payload json.RawMessage `json:"payload,omitempty"`
}

type BrokerHandler

type BrokerHandler struct {
	Registry BrokerRegistry
}

func (*BrokerHandler) Register

func (h *BrokerHandler) Register(w http.ResponseWriter, r *http.Request)

func (*BrokerHandler) Routes

func (h *BrokerHandler) Routes() chi.Router

type BrokerRegisterRequest

type BrokerRegisterRequest struct {
	Commands        map[string]orchestrator.HostCommandSpec `json:"commands"`
	BuiltinPolicies map[string]sandbox.BuiltinPolicy        `json:"builtin_policies,omitempty"`
	ProjectID       string                                  `json:"project_id,omitempty"`
}

type BrokerRegisterResponse

type BrokerRegisterResponse struct {
	Token  string `json:"token"`
	Socket string `json:"socket"`
	// ResolvedHostCommands echoes back the absolute-path-keyed map produced by
	// dispatcher.ResolveHostCommands. The caller (boid exec) feeds this into
	// SandboxRuntimeInfo so shim bind-mount targets line up with the broker's
	// policy keys without re-resolving on the client side.
	ResolvedHostCommands map[string]orchestrator.CommandDef `json:"resolved_host_commands,omitempty"`
}

type BrokerRegistry

type BrokerRegistry interface {
	RegisterBrokerCommands(commands map[string]orchestrator.HostCommandSpec, builtinPolicies map[string]sandbox.BuiltinPolicy, projectID string) (*BrokerRegisterResponse, error)
}

type CommandDispatcher

type CommandDispatcher interface {
	ExecuteCommand(ctx context.Context, projectID, commandName string) (*ExecuteCommandResult, error)
}

CommandDispatcher launches a named command as an interactive daemon-side job.

type CommandResponse

type CommandResponse struct {
	Command            []string                                `json:"command"`
	Env                map[string]string                       `json:"env,omitempty"`
	HostCommands       map[string]orchestrator.HostCommandSpec `json:"host_commands,omitempty"`
	AdditionalBindings []orchestrator.BindMount                `json:"additional_bindings,omitempty"`
	Readonly           bool                                    `json:"readonly,omitempty"`
}

CommandResponse is the API response for GET /api/projects/:id/commands/:name.

type CommandSummary

type CommandSummary struct {
	Name     string   `json:"name"`
	Command  []string `json:"command"`
	Readonly bool     `json:"readonly,omitempty"`
}

CommandSummary is a single entry in the GET /api/projects/:id/commands response.

type CreateProjectRequest

type CreateProjectRequest struct {
	WorkDir string `json:"work_dir"`
}

type CreateTaskRequest

type CreateTaskRequest struct {
	ID               string                     `json:"id,omitempty"`
	ProjectID        string                     `json:"project_id"`
	Title            string                     `json:"title"`
	Description      string                     `json:"description,omitempty"`
	Behavior         string                     `json:"behavior,omitempty"`
	BehaviorSpec     *orchestrator.BehaviorSpec `json:"behavior_spec,omitempty"`
	RemoteID         string                     `json:"remote_id,omitempty"`
	DataSourceID     string                     `json:"datasource_id,omitempty"`
	Payload          json.RawMessage            `json:"payload,omitempty"`
	Instructions     json.RawMessage            `json:"instructions,omitempty"`
	AutoStart        bool                       `json:"auto_start,omitempty"`
	Traits           []string                   `json:"traits,omitempty"`
	Readonly         *bool                      `json:"readonly,omitempty"`
	Worktree         *bool                      `json:"worktree,omitempty"`
	BranchPrefix     *string                    `json:"branch_prefix,omitempty"`
	BaseBranch       *string                    `json:"base_branch,omitempty"`
	DependsOn        []string                   `json:"depends_on,omitempty"`
	DependsOnPayload string                     `json:"depends_on_payload,omitempty"`
	Ref              string                     `json:"ref,omitempty"`
	ParentID         string                     `json:"parent_id,omitempty"`
}

type DeviceGCStore

type DeviceGCStore interface {
	DeleteRevokedDevices(ctx context.Context, dryRun bool) (int64, error)
}

type DuplicateTaskRequest

type DuplicateTaskRequest struct {
	AutoStart bool `json:"auto_start"`
}

type ExecuteCommandResult

type ExecuteCommandResult struct {
	JobID     string `json:"job_id"`
	AttachURL string `json:"attach_url"`
}

ExecuteCommandResult is the response for POST /api/projects/{id}/commands/{name}/execute.

type GCAppService

type GCAppService struct {
	Store       GCStore
	DeviceStore DeviceGCStore // optional; deletes revoked devices on GC
}

func (*GCAppService) GC

func (s *GCAppService) GC(olderThan time.Duration, dryRun bool) (*orchestrator.GCResult, error)

GC implements orchestrator.GCStore so GCAppService can be passed to GCLoop.

func (*GCAppService) Run

func (s *GCAppService) Run(olderThan time.Duration, dryRun bool) (*orchestrator.GCResult, error)

type GCHandler

type GCHandler struct {
	Service GCService
}

func (*GCHandler) Routes

func (h *GCHandler) Routes() chi.Router

func (*GCHandler) Run

func (h *GCHandler) Run(w http.ResponseWriter, r *http.Request)

type GCService

type GCService interface {
	Run(olderThan time.Duration, dryRun bool) (*orchestrator.GCResult, error)
}

type GCStore

type GCStore interface {
	GC(olderThan time.Duration, dryRun bool) (*orchestrator.GCResult, error)
}

type GateService

type GateService interface {
	ReplayGate(ctx context.Context, taskID string, req ReplayGateRequest) (*ReplayGateResult, error)
	ListGatesForStatus(taskID, status string) ([]orchestrator.Gate, error)
}

GateService provides gate replay and gate listing operations.

type GlobalJobStore

type GlobalJobStore interface {
	ListJobsWithContext(filter JobListFilter) ([]JobWithContext, error)
}

GlobalJobStore supports cross-task job listing with context (task title, project name).

type HookService

type HookService interface {
	ReplayHook(ctx context.Context, taskID string, req ReplayHookRequest) (*ReplayHookResult, error)
	ListHooksForStatus(taskID, status string) ([]orchestrator.Hook, error)
}

HookService provides hook replay and hook listing operations.

type ImportError

type ImportError struct {
	Line     int    `json:"line"`
	RemoteID string `json:"remote_id"`
	Error    string `json:"error"`
}

type ImportResult

type ImportResult struct {
	Created int           `json:"created"`
	Skipped int           `json:"skipped"`
	Errors  []ImportError `json:"errors"`
}

type Job

type Job struct {
	ID             string    `json:"id"`
	TaskID         string    `json:"task_id"`
	ProjectID      string    `json:"project_id"`
	HandlerID      string    `json:"handler_id"`
	Role           string    `json:"role"`
	RuntimeID      string    `json:"runtime_id,omitempty"`
	WorkspacePath  string    `json:"workspace_path,omitempty"`
	Interactive    bool      `json:"interactive"`
	TTY            bool      `json:"tty"`
	Status         JobStatus `json:"status"`
	ExitCode       int       `json:"exit_code,omitempty"`
	Output         string    `json:"output,omitempty"`
	ExecutionState string    `json:"execution_state,omitempty"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

type JobCompletion

type JobCompletion struct {
	Output   string
	ExitCode int
}

type JobDoneRequest

type JobDoneRequest struct {
	ExitCode int    `json:"exit_code"`
	Output   string `json:"output,omitempty"`
}

type JobHandler

type JobHandler struct {
	Jobs       JobStore
	Global     GlobalJobStore // optional: enables cross-task listing when task_id is absent
	Service    WorkflowService
	LogReader  JobLogReader // optional: enables static GET /{id}/log
	SSEHandler http.Handler // optional: enables SSE streaming for GET /{id}/log?follow=true
}

func (*JobHandler) Done

func (h *JobHandler) Done(w http.ResponseWriter, r *http.Request)

func (*JobHandler) Get

func (h *JobHandler) Get(w http.ResponseWriter, r *http.Request)

func (*JobHandler) List

func (h *JobHandler) List(w http.ResponseWriter, r *http.Request)

func (*JobHandler) Log

func (h *JobHandler) Log(w http.ResponseWriter, r *http.Request)

func (*JobHandler) Routes

func (h *JobHandler) Routes() chi.Router

type JobLifecycle

type JobLifecycle interface {
	CompleteJob(jobID string, result JobCompletion)
	UnregisterJob(jobID string)
	CleanupTaskWindow(taskID string)
	StopJobRuntime(runtimeID string)
}

type JobListFilter

type JobListFilter struct {
	Status      string
	Interactive *bool // nil = no filter
}

JobListFilter specifies optional filters for global job listing.

type JobLogReader

type JobLogReader interface {
	ReadJobLog(runtimeID string) ([]byte, error)
}

JobLogReader reads the transcript log for a given runtime.

type JobLogSSEHandler

type JobLogSSEHandler struct {
	Subscriber dispatcher.RuntimeSubscriber
	Registry   *auth.ConnectionRegistry
}

JobLogSSEHandler streams live job output as Server-Sent Events on GET /{id}/log?follow=true.

func (*JobLogSSEHandler) ServeHTTP

func (h *JobLogSSEHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type JobStatus

type JobStatus string
const (
	JobStatusRunning   JobStatus = "running"
	JobStatusCompleted JobStatus = "completed"
	JobStatusFailed    JobStatus = "failed"
)

type JobStore

type JobStore interface {
	GetJob(id string) (*Job, error)
	ListJobsByTask(taskID string) ([]*Job, error)
	UpdateJob(job *Job) error
}

type JobWithContext

type JobWithContext struct {
	Job
	TaskTitle   string `json:"task_title"`
	ProjectName string `json:"project_name"`
}

JobWithContext extends Job with task and project metadata for the TUI global view.

type LoginHandler

type LoginHandler struct {
	Pairing loginPairing
	Signer  loginSigner
	Store   loginDeviceStore
	Limiter loginRateLimiter
}

LoginHandler handles /login and /auth.

func (*LoginHandler) GetAuth

func (h *LoginHandler) GetAuth(w http.ResponseWriter, r *http.Request)

func (*LoginHandler) GetLogin

func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request)

func (*LoginHandler) PostLogin

func (h *LoginHandler) PostLogin(w http.ResponseWriter, r *http.Request)

type MetaStore

type MetaStore interface {
	Get(id string) (*orchestrator.ProjectMeta, bool)
}

type Notifier

type Notifier interface {
	Notify(ctx context.Context, ev notify.Event) error
}

Notifier sends an agent-driven notification for a task. Implementations typically exec a user-configured command. nil-safe at the call site: TaskAppService.NotifyTask returns an error when Notify is unset.

type NotifyTaskRequest

type NotifyTaskRequest struct {
	Message    string `json:"message"`
	Ask        string `json:"ask,omitempty"`
	QuestionID string `json:"question_id,omitempty"`
	SessionID  string `json:"session_id,omitempty"`
	Progress   string `json:"progress,omitempty"`
}

type Pairer

type Pairer interface {
	Issue(ctx context.Context, label string) (string, error)
}

WebManagementHandler serves the CLI management API at /api/web/*. All routes are accessible only via UNIX socket (CLI control plane). Pairer issues pairing codes.

type ProjectAppService

type ProjectAppService struct {
	Projects ProjectRepository
	Meta     interface {
		Load(workDir string) (*orchestrator.ProjectMeta, error)
		Get(id string) (*orchestrator.ProjectMeta, bool)
		Remove(id string)
		LoadAll(projects []*orchestrator.Project) []error
	}
}

func (*ProjectAppService) CreateProject

func (s *ProjectAppService) CreateProject(workDir string) (*orchestrator.Project, error)

func (*ProjectAppService) DeleteProject

func (s *ProjectAppService) DeleteProject(id string) error

func (*ProjectAppService) GetCommand

func (s *ProjectAppService) GetCommand(id, name string) (*CommandResponse, error)

func (*ProjectAppService) GetProject

func (s *ProjectAppService) GetProject(id string) (*orchestrator.Project, error)

func (*ProjectAppService) ListCommands

func (s *ProjectAppService) ListCommands(id string) ([]CommandSummary, error)

func (*ProjectAppService) ListProjects

func (s *ProjectAppService) ListProjects(workspaceID string) ([]*orchestrator.Project, error)

func (*ProjectAppService) ListWorkspaces

func (s *ProjectAppService) ListWorkspaces() ([]*orchestrator.WorkspaceSummary, error)

func (*ProjectAppService) ReloadProjects

func (s *ProjectAppService) ReloadProjects() (*ProjectReloadResult, error)

func (*ProjectAppService) ResolveProjectRef

func (s *ProjectAppService) ResolveProjectRef(ref string) ([]*orchestrator.Project, error)

ResolveProjectRef resolves ref to matching projects with the following priority:

  1. id exact match (returns immediately on first hit)
  2. name exact match (all projects with that name)
  3. name substring match, case-insensitive

Returns a single-element slice on unambiguous match, a multi-element slice on ambiguous match, or StatusError{404} when nothing matches.

func (*ProjectAppService) SetProjectWorkspace

func (s *ProjectAppService) SetProjectWorkspace(id, workspaceID string) (*orchestrator.Project, error)

type ProjectHandler

type ProjectHandler struct {
	Service    ProjectService
	Dispatcher CommandDispatcher // optional; nil disables the execute endpoint
}

func (*ProjectHandler) Create

func (h *ProjectHandler) Create(w http.ResponseWriter, r *http.Request)

func (*ProjectHandler) Delete

func (h *ProjectHandler) Delete(w http.ResponseWriter, r *http.Request)

func (*ProjectHandler) ExecuteCommand

func (h *ProjectHandler) ExecuteCommand(w http.ResponseWriter, r *http.Request)

func (*ProjectHandler) Get

func (*ProjectHandler) GetCommand

func (h *ProjectHandler) GetCommand(w http.ResponseWriter, r *http.Request)

func (*ProjectHandler) List

func (*ProjectHandler) ListCommands

func (h *ProjectHandler) ListCommands(w http.ResponseWriter, r *http.Request)

func (*ProjectHandler) Reload

func (h *ProjectHandler) Reload(w http.ResponseWriter, r *http.Request)

func (*ProjectHandler) Routes

func (h *ProjectHandler) Routes() chi.Router

func (*ProjectHandler) SetWorkspace

func (h *ProjectHandler) SetWorkspace(w http.ResponseWriter, r *http.Request)

type ProjectReloadResult

type ProjectReloadResult struct {
	Status string   `json:"status"`
	Errors []string `json:"errors,omitempty"`
}

type ProjectRepository

type ProjectRepository interface {
	CreateProject(project *orchestrator.Project) error
	GetProject(id string) (*orchestrator.Project, error)
	ListProjects() ([]*orchestrator.Project, error)
	SetProjectWorkspace(projectID, workspaceID string) error
	ListWorkspaces() ([]*orchestrator.WorkspaceSummary, error)
	DeleteProject(id string) error
}

type ProjectService

type ProjectService interface {
	CreateProject(workDir string) (*orchestrator.Project, error)
	ListProjects(workspaceID string) ([]*orchestrator.Project, error)
	ListWorkspaces() ([]*orchestrator.WorkspaceSummary, error)
	GetProject(id string) (*orchestrator.Project, error)
	SetProjectWorkspace(id, workspaceID string) (*orchestrator.Project, error)
	DeleteProject(id string) error
	ReloadProjects() (*ProjectReloadResult, error)
	// ResolveProjectRef resolves a ref string to one or more matching projects.
	// Priority: id exact match > name exact match > name substring match (case-insensitive).
	// Returns 1 project on unambiguous match, multiple on ambiguous match, StatusError{404} on no match.
	ResolveProjectRef(ref string) ([]*orchestrator.Project, error)
	GetCommand(id, name string) (*CommandResponse, error)
	ListCommands(id string) ([]CommandSummary, error)
}

type ProjectWorkDirLookup

type ProjectWorkDirLookup interface {
	GetProject(id string) (*orchestrator.Project, error)
}

ProjectWorkDirLookup provides read access to a project's working directory.

type ReopenTaskRequest

type ReopenTaskRequest struct {
	Message string `json:"message,omitempty"`
}

type ReplayGateRequest

type ReplayGateRequest struct {
	GateID string
	Status string // optional: override task.Status before replay
}

ReplayGateRequest is the input for gate replay.

type ReplayGateResult

type ReplayGateResult struct {
	Task        *orchestrator.Task        `json:"task"`
	FiredEvents []orchestrator.FiredEvent `json:"fired_events,omitempty"`
}

ReplayGateResult is the output of a gate replay.

type ReplayHookRequest

type ReplayHookRequest struct {
	HookID string
	Status string // optional: override task.Status before replay
}

ReplayHookRequest is the input for hook replay.

type ReplayHookResult

type ReplayHookResult struct {
	Task        *orchestrator.Task        `json:"task"`
	FiredEvents []orchestrator.FiredEvent `json:"fired_events,omitempty"`
}

ReplayHookResult is the output of a hook replay.

type RerunTaskRequest

type RerunTaskRequest struct {
	AutoStart            bool            `json:"auto_start,omitempty"`
	InstructionsOverride json.RawMessage `json:"instructions_override,omitempty"`
}

type SecretHandler

type SecretHandler struct {
	Store SecretStore
}

func (*SecretHandler) Delete

func (h *SecretHandler) Delete(w http.ResponseWriter, r *http.Request)

func (*SecretHandler) GetValue

func (h *SecretHandler) GetValue(w http.ResponseWriter, r *http.Request)

func (*SecretHandler) List

func (h *SecretHandler) List(w http.ResponseWriter, r *http.Request)

func (*SecretHandler) Routes

func (h *SecretHandler) Routes() chi.Router

func (*SecretHandler) Set

type SecretStore

type SecretStore interface {
	List(namespace string) ([]string, error)
	Set(namespace, key, value string) error
	Delete(namespace, key string) error
	Get(namespace, key string) (string, error)
}

type SetProjectWorkspaceRequest

type SetProjectWorkspaceRequest struct {
	WorkspaceID string `json:"workspace_id"`
}

type StatusError

type StatusError struct {
	Code    int
	Message string
}

func (*StatusError) Error

func (e *StatusError) Error() string

type TaskAnswerService

type TaskAnswerService interface {
	AnswerTask(ctx context.Context, taskID, questionID, answer string) error
}

TaskAnswerService records a user reply to a pending Q&A question and transitions the task back to executing.

type TaskAppService

type TaskAppService struct {
	Tasks       TaskStore
	Actions     ActionStore
	Jobs        JobStore
	Meta        MetaStore
	Workflow    WorkflowService
	Projects    ProjectWorkDirLookup
	RuntimesDir string
	Notify      Notifier
}

func (*TaskAppService) AnswerTask

func (s *TaskAppService) AnswerTask(ctx context.Context, taskID, questionID, answer string) error

AnswerTask saves the user's reply and transitions the task awaiting → executing.

func (*TaskAppService) CreateTask

func (s *TaskAppService) CreateTask(req CreateTaskRequest) (*orchestrator.Task, error)

func (*TaskAppService) DeleteTask

func (s *TaskAppService) DeleteTask(id string, force bool) error

func (*TaskAppService) DuplicateTask

func (s *TaskAppService) DuplicateTask(sourceID string, autoStart bool) (*orchestrator.Task, error)

func (*TaskAppService) GetTask

func (s *TaskAppService) GetTask(id string) (*orchestrator.Task, error)

func (*TaskAppService) GetTaskBehaviorCommand

func (s *TaskAppService) GetTaskBehaviorCommand(taskID, name string) (*CommandResponse, error)

func (*TaskAppService) GetTaskDetail

func (s *TaskAppService) GetTaskDetail(id string) (*TaskDetailView, error)

func (*TaskAppService) ImportTasks

func (s *TaskAppService) ImportTasks(reqs []CreateTaskRequest) (*ImportResult, error)

func (*TaskAppService) ListTaskBehaviorCommands

func (s *TaskAppService) ListTaskBehaviorCommands(taskID string) ([]CommandSummary, error)

func (*TaskAppService) ListTasks

func (s *TaskAppService) ListTasks(filter orchestrator.TaskFilter) ([]*orchestrator.Task, error)

func (*TaskAppService) NotifyTask

func (s *TaskAppService) NotifyTask(ctx context.Context, taskID, message, ask, questionID, sessionID, progress string) error

NotifyTask invokes the configured notify command for the given task. Returns 501 when no notifier is wired and ask is empty (notifications disabled in config). When ask is non-empty the task is transitioned to awaiting; the notification is best-effort and skipped if no notifier is configured. questionID identifies the Q&A turn (generated when empty). When progress is non-empty (progress mode), no hook fires and no state transition occurs — only a progress Action is written to the timeline. ask and progress are mutually exclusive.

func (*TaskAppService) RerunTask

func (s *TaskAppService) RerunTask(id string, req RerunTaskRequest) (*orchestrator.Task, error)

func (*TaskAppService) UpdateTask

func (s *TaskAppService) UpdateTask(id string, req UpdateTaskRequest) (*orchestrator.Task, error)

type TaskCommandDispatcher

type TaskCommandDispatcher interface {
	ListTaskBehaviorCommands(taskID string) ([]CommandSummary, error)
	ExecuteTaskBehaviorCommand(ctx context.Context, taskID, commandName string) (*ExecuteCommandResult, error)
}

TaskCommandDispatcher manages task behavior commands: listing and execution. The task ID is appended to the command argv on execution so scripts can reference it as $1.

type TaskDetailView

type TaskDetailView struct {
	Task              *orchestrator.Task
	Actions           []*orchestrator.Action
	Jobs              []*Job
	AvailableActions  []string             `json:"available_actions"`
	Dependents        []*orchestrator.Task `json:"dependents,omitempty"`
	DependsOnResolved []*orchestrator.Task `json:"depends_on_resolved,omitempty"`
	DependsOnTree     []*TaskNode          `json:"depends_on_tree,omitempty"`
	DependentsTree    []*TaskNode          `json:"dependents_tree,omitempty"`
}

type TaskEvent

type TaskEvent struct {
	Kind    string // "action" / "job" / "fired_event" etc.
	Payload any
}

TaskEvent はタスクに関連するイベントを表す。

type TaskEventHub

type TaskEventHub struct {
	// contains filtered or unexported fields
}

TaskEventHub は taskID ごとに複数の subscriber へイベントを配送する pub-sub ハブ。

func NewTaskEventHub

func NewTaskEventHub() *TaskEventHub

NewTaskEventHub は新しい TaskEventHub を返す。

func (*TaskEventHub) Broadcast

func (h *TaskEventHub) Broadcast(taskID string, ev TaskEvent)

Broadcast は taskID の全 subscriber に ev を非ブロッキングで配送する。 チャネルが満杯の subscriber はドロップする(hub 全体を止めない)。

func (*TaskEventHub) Subscribe

func (h *TaskEventHub) Subscribe(ctx context.Context, taskID string) <-chan TaskEvent

Subscribe は taskID のイベントを受け取るチャネルを返す。 ctx がキャンセルされると、チャネルはクローズされ内部からも除去される。

type TaskHandler

type TaskHandler struct {
	Service    TaskService
	Gates      GateService           // optional: enables gate replay/list when set
	Hooks      HookService           // optional: enables hook replay/list when set
	Notifier   TaskNotifyService     // optional: enables POST /{id}/notify when set
	Answerer   TaskAnswerService     // optional: enables POST /{id}/answer when set
	Dispatcher TaskCommandDispatcher // optional: nil causes execute to return 501
}

func (*TaskHandler) Answer

func (h *TaskHandler) Answer(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Create

func (h *TaskHandler) Create(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Delete

func (h *TaskHandler) Delete(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Detail

func (h *TaskHandler) Detail(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Duplicate

func (h *TaskHandler) Duplicate(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) ExecuteTaskCommand

func (h *TaskHandler) ExecuteTaskCommand(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Get

func (h *TaskHandler) Get(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Import

func (h *TaskHandler) Import(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) List

func (h *TaskHandler) List(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) ListGates

func (h *TaskHandler) ListGates(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) ListHooks

func (h *TaskHandler) ListHooks(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) ListTaskCommands

func (h *TaskHandler) ListTaskCommands(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Notify

func (h *TaskHandler) Notify(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Patch

func (h *TaskHandler) Patch(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) ReplayGate

func (h *TaskHandler) ReplayGate(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) ReplayHook

func (h *TaskHandler) ReplayHook(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Rerun

func (h *TaskHandler) Rerun(w http.ResponseWriter, r *http.Request)

func (*TaskHandler) Routes

func (h *TaskHandler) Routes() chi.Router

type TaskNode

type TaskNode struct {
	Task     *orchestrator.Task `json:"task"`
	Children []*TaskNode        `json:"children,omitempty"`
}

TaskNode represents a node in the recursive dependency tree.

type TaskNotifyService

type TaskNotifyService interface {
	NotifyTask(ctx context.Context, taskID, message, ask, questionID, sessionID, progress string) error
}

TaskNotifyService dispatches an agent-driven notification for a task. Wired to *TaskAppService at runtime; left optional on TaskHandler so existing tests do not need to satisfy this interface. ask/questionID/sessionID are optional Q&A fields: when ask is non-empty the task is transitioned to awaiting after the notification is sent. sessionID is stored in the awaiting trait and surfaced as BOID_AGENT_SESSION_ID on the next hook invocation. progress is mutually exclusive with ask: when set, no hook fires and no state transition occurs — only a progress Action is written to the timeline.

type TaskService

type TaskService interface {
	CreateTask(req CreateTaskRequest) (*orchestrator.Task, error)
	ListTasks(filter orchestrator.TaskFilter) ([]*orchestrator.Task, error)
	GetTask(id string) (*orchestrator.Task, error)
	GetTaskDetail(id string) (*TaskDetailView, error)
	UpdateTask(id string, req UpdateTaskRequest) (*orchestrator.Task, error)
	DeleteTask(id string, force bool) error
	ImportTasks(reqs []CreateTaskRequest) (*ImportResult, error)
	DuplicateTask(sourceID string, autoStart bool) (*orchestrator.Task, error)
	RerunTask(id string, req RerunTaskRequest) (*orchestrator.Task, error)
}

type TaskStore

type TaskStore interface {
	CreateTask(task *orchestrator.Task) error
	GetTask(id string) (*orchestrator.Task, error)
	ListTasks(filter orchestrator.TaskFilter) ([]*orchestrator.Task, error)
	UpdateTask(task *orchestrator.Task) error
	DeleteTask(id string) error
	FindTaskByRemote(remoteID, datasourceID string) (*orchestrator.Task, error)
	FindTaskByRef(ref, parentID string) (*orchestrator.Task, error)
	FindDependentTasks(taskID string) ([]*orchestrator.Task, error)
}

type TaskWorkflowService

type TaskWorkflowService struct {
	Tasks       TaskStore
	Jobs        JobStore
	Projects    ProjectRepository
	Tx          Transactor
	Meta        MetaStore
	Coordinator DispatchCoordinator
	Lifecycle   JobLifecycle
	Worktrees   WorktreeCleaner
	Hub         *TaskEventHub
	// contains filtered or unexported fields
}

func (*TaskWorkflowService) ApplyAction

func (*TaskWorkflowService) CompleteJob

func (s *TaskWorkflowService) CompleteJob(_ context.Context, jobID string, req JobDoneRequest) (*Job, error)

func (*TaskWorkflowService) InitDispatch

func (s *TaskWorkflowService) InitDispatch(ctx context.Context)

InitDispatch initialises the lifecycle context used by dispatch-loop goroutines. Must be called before the first action is applied. The returned cancel is stored internally; call Shutdown to invoke it.

func (*TaskWorkflowService) ListGatesForStatus

func (s *TaskWorkflowService) ListGatesForStatus(taskID, status string) ([]orchestrator.Gate, error)

ListGatesForStatus returns gates that match the given status for the task. If status is empty, the task's current status is used.

func (*TaskWorkflowService) ListHooksForStatus

func (s *TaskWorkflowService) ListHooksForStatus(taskID, status string) ([]orchestrator.Hook, error)

ListHooksForStatus returns hooks that match the given status for the task. If status is empty, the task's current status is used.

func (*TaskWorkflowService) ReplayGate

ReplayGate replays a single gate for the given task. If req.Status is non-empty the task's status is overwritten before dispatch (allows recovery from terminal states). Running jobs on the same task cause a 409 Conflict.

func (*TaskWorkflowService) ReplayHook

ReplayHook replays a single hook for the given task. If req.Status is non-empty the task's status is overwritten before dispatch. Running jobs on the same task cause a 409 Conflict.

func (*TaskWorkflowService) Shutdown

func (s *TaskWorkflowService) Shutdown()

Shutdown cancels the dispatch context and blocks until all in-flight dispatch loops have returned. Call this before closing the database.

func (*TaskWorkflowService) TriggerDependents

func (s *TaskWorkflowService) TriggerDependents(ctx context.Context, taskID string)

TriggerDependents は taskID に依存する pending タスクを評価し、 auto_start=true かつ依存条件が満たされた場合に自動 start する。 auto_start=false のタスクは依存解決しても pending のまま残り、 ユーザが手動で start するまで待機する。

type Transactor

type Transactor interface {
	WithinTx(func(TxStore) error) error
}

type TxStore

type TxStore interface {
	TaskStore
	ActionStore
	JobStore
}

type UpdateTaskRequest

type UpdateTaskRequest struct {
	Title            string          `json:"title"`
	Description      string          `json:"description"`
	Payload          json.RawMessage `json:"payload,omitempty"`
	Instructions     json.RawMessage `json:"instructions,omitempty"`
	BaseBranch       *string         `json:"base_branch,omitempty"`
	BranchPrefix     *string         `json:"branch_prefix,omitempty"`
	Worktree         *bool           `json:"worktree,omitempty"`
	DependsOn        []string        `json:"depends_on,omitempty"`
	DependsOnPayload *string         `json:"depends_on_payload,omitempty"`
	ParentID         *string         `json:"parent_id,omitempty"`
	AutoStart        *bool           `json:"auto_start,omitempty"`
}

type WSAttachHandler

type WSAttachHandler struct {
	Subscriber dispatcher.RuntimeSubscriber
	Writer     dispatcher.RuntimeInputWriter
	PublicURL  string
	Registry   *auth.ConnectionRegistry
}

WSAttachHandler handles WebSocket connections for interactive PTY attach. Route: GET /api/jobs/{id}/attach/ws

func (*WSAttachHandler) ServeHTTP

func (h *WSAttachHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type WebAppService

type WebAppService struct {
	Tasks      TaskStore
	Actions    ActionStore
	Jobs       JobStore
	GlobalJobs GlobalJobStore
	Projects   ProjectRepository
	Meta       MetaStore
	Workflow   WorkflowService
	TaskSvc    TaskService
	Gates      GateService
	Hooks      HookService
	Answerer   TaskAnswerService // optional: enables POST /tasks/{id}/answer
}

func (*WebAppService) AnswerTask

func (s *WebAppService) AnswerTask(ctx context.Context, taskID, questionID, answer string) error

func (*WebAppService) ApplyAction

func (s *WebAppService) ApplyAction(taskID string, actionType string) error

func (*WebAppService) CreateTask

func (s *WebAppService) CreateTask(req CreateTaskRequest) (*orchestrator.Task, error)

func (*WebAppService) DeleteTask

func (s *WebAppService) DeleteTask(id string, force bool) error

DeleteTask delegates to the shared TaskService so the web UI uses the same delete semantics as the JSON API and TUI.

func (*WebAppService) DuplicateTask

func (s *WebAppService) DuplicateTask(id string) (string, error)

DuplicateTask delegates to the shared TaskService so the Web UI uses the same duplication semantics as the JSON API: a fresh task is created via CreateTask + resolveBehavior so that Instructions and Payload come from the behavior's DefaultInstruction / DefaultPayload, not from the source task's runtime state. Without this delegation the duplicate inherited the source's runtime payload (claude_code.sessions, awaiting trait) and missing Instructions caused the hook evaluator to skip the agent hook, so no hook fired on Start.

The Web UI button does not auto-start the duplicate; the user clicks Start separately.

func (*WebAppService) GetJob

func (s *WebAppService) GetJob(id string) (*JobWithContext, error)

func (*WebAppService) GetProjectByID

func (s *WebAppService) GetProjectByID(id string) (*orchestrator.Project, error)

func (*WebAppService) GetTaskDetail

func (s *WebAppService) GetTaskDetail(id string) (*TaskDetailView, error)

func (*WebAppService) ListBehaviors

func (s *WebAppService) ListBehaviors() ([]string, error)

func (*WebAppService) ListGatesForStatus

func (s *WebAppService) ListGatesForStatus(taskID, status string) ([]orchestrator.Gate, error)

func (*WebAppService) ListHooksForStatus

func (s *WebAppService) ListHooksForStatus(taskID, status string) ([]orchestrator.Hook, error)

func (*WebAppService) ListJobs

func (s *WebAppService) ListJobs(status string) ([]JobWithContext, error)

func (*WebAppService) ListProjectCommands

func (s *WebAppService) ListProjectCommands(projectID string) ([]CommandSummary, error)

func (*WebAppService) ListProjects

func (s *WebAppService) ListProjects() ([]*orchestrator.Project, error)

func (*WebAppService) ListTaskBehaviorCommands

func (s *WebAppService) ListTaskBehaviorCommands(taskID string) ([]CommandSummary, error)

func (*WebAppService) ListTasks

func (s *WebAppService) ListTasks(filter orchestrator.TaskFilter) ([]*orchestrator.Task, error)

func (*WebAppService) ListWorkspaces

func (s *WebAppService) ListWorkspaces() ([]*orchestrator.WorkspaceSummary, error)

func (*WebAppService) ReopenTask

func (s *WebAppService) ReopenTask(id string, req ReopenTaskRequest) error

func (*WebAppService) ReplayGate

func (s *WebAppService) ReplayGate(ctx context.Context, taskID string, req ReplayGateRequest) (*ReplayGateResult, error)

func (*WebAppService) ReplayHook

func (s *WebAppService) ReplayHook(ctx context.Context, taskID string, req ReplayHookRequest) (*ReplayHookResult, error)

func (*WebAppService) RerunTask

func (s *WebAppService) RerunTask(id string, req RerunTaskRequest) error

func (*WebAppService) UpdateTask

func (s *WebAppService) UpdateTask(id string, req UpdateTaskRequest) error

type WebHandler

type WebHandler struct {
	Service        WebService
	Hub            *TaskEventHub
	Dispatcher     CommandDispatcher
	TaskDispatcher TaskCommandDispatcher
	Registry       *auth.ConnectionRegistry
}

func (*WebHandler) GateReplayList

func (h *WebHandler) GateReplayList(w http.ResponseWriter, r *http.Request)

func (*WebHandler) HookReplayList

func (h *WebHandler) HookReplayList(w http.ResponseWriter, r *http.Request)

func (*WebHandler) JobDetail

func (h *WebHandler) JobDetail(w http.ResponseWriter, r *http.Request)

func (*WebHandler) JobTerminal

func (h *WebHandler) JobTerminal(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostAction

func (h *WebHandler) PostAction(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostAnswer

func (h *WebHandler) PostAnswer(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostDelete

func (h *WebHandler) PostDelete(w http.ResponseWriter, r *http.Request)

PostDelete deletes the task and redirects to the task list. Errors are surfaced via ?error= on the same task page so the user sees the reason (e.g. dependents exist).

func (*WebHandler) PostDuplicate

func (h *WebHandler) PostDuplicate(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostEditDescription

func (h *WebHandler) PostEditDescription(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostGateReplay

func (h *WebHandler) PostGateReplay(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostHookReplay

func (h *WebHandler) PostHookReplay(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostProjectExecuteCommand

func (h *WebHandler) PostProjectExecuteCommand(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostReopen

func (h *WebHandler) PostReopen(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostRerun

func (h *WebHandler) PostRerun(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostTaskCreate

func (h *WebHandler) PostTaskCreate(w http.ResponseWriter, r *http.Request)

func (*WebHandler) PostTaskExecuteCommand

func (h *WebHandler) PostTaskExecuteCommand(w http.ResponseWriter, r *http.Request)

func (*WebHandler) ProjectCommandList

func (h *WebHandler) ProjectCommandList(w http.ResponseWriter, r *http.Request)

func (*WebHandler) QuestionPage

func (h *WebHandler) QuestionPage(w http.ResponseWriter, r *http.Request)

QuestionPage renders the dedicated Q&A turn page at `/tasks/{id}/questions/{question_id}`. The notification deep-link from `boid task notify --ask` lands here. The page shows the question and either an answer form (when this is the active awaiting turn) or the recorded answer (when an answer action exists for the same question_id).

func (*WebHandler) ReopenForm

func (h *WebHandler) ReopenForm(w http.ResponseWriter, r *http.Request)

func (*WebHandler) Routes

func (h *WebHandler) Routes() chi.Router

func (*WebHandler) TaskDetail

func (h *WebHandler) TaskDetail(w http.ResponseWriter, r *http.Request)

func (*WebHandler) TaskDetailFragment

func (h *WebHandler) TaskDetailFragment(w http.ResponseWriter, r *http.Request)

TaskDetailFragment returns a partial HTML fragment for the task detail page. The `kind` query parameter selects which section to render:

  • "timeline": action history section
  • "status": status card + available actions
  • "jobs": jobs section

func (*WebHandler) TaskEvents

func (h *WebHandler) TaskEvents(w http.ResponseWriter, r *http.Request)

TaskEvents streams Server-Sent Events for a specific task. Subscribes to the TaskEventHub and forwards events until the client disconnects or the device is revoked.

func (*WebHandler) TaskList

func (h *WebHandler) TaskList(w http.ResponseWriter, r *http.Request)

func (*WebHandler) TaskNew

func (h *WebHandler) TaskNew(w http.ResponseWriter, r *http.Request)

type WebManagementHandler

type WebManagementHandler struct {
	Pairing   Pairer
	Store     *auth.Store
	PublicURL string
	Registry  *auth.ConnectionRegistry
}

func (*WebManagementHandler) DeleteAllDevices

func (h *WebManagementHandler) DeleteAllDevices(w http.ResponseWriter, r *http.Request)

func (*WebManagementHandler) DeleteDevice

func (h *WebManagementHandler) DeleteDevice(w http.ResponseWriter, r *http.Request)

func (*WebManagementHandler) GetDevices

func (h *WebManagementHandler) GetDevices(w http.ResponseWriter, r *http.Request)

func (*WebManagementHandler) PostPair

func (*WebManagementHandler) Routes

func (h *WebManagementHandler) Routes() chi.Router

type WebService

type WebService interface {
	ListTasks(filter orchestrator.TaskFilter) ([]*orchestrator.Task, error)
	GetTaskDetail(id string) (*TaskDetailView, error)
	ListProjects() ([]*orchestrator.Project, error)
	ListBehaviors() ([]string, error)
	ListWorkspaces() ([]*orchestrator.WorkspaceSummary, error)
	ApplyAction(taskID string, actionType string) error
	DuplicateTask(id string) (string, error)
	DeleteTask(id string, force bool) error
	ListJobs(status string) ([]JobWithContext, error)
	GetJob(id string) (*JobWithContext, error)
	CreateTask(req CreateTaskRequest) (*orchestrator.Task, error)
	UpdateTask(id string, req UpdateTaskRequest) error
	RerunTask(id string, req RerunTaskRequest) error
	ReopenTask(id string, req ReopenTaskRequest) error
	AnswerTask(ctx context.Context, taskID, questionID, answer string) error
	ListGatesForStatus(taskID, status string) ([]orchestrator.Gate, error)
	ReplayGate(ctx context.Context, taskID string, req ReplayGateRequest) (*ReplayGateResult, error)
	ListHooksForStatus(taskID, status string) ([]orchestrator.Hook, error)
	ReplayHook(ctx context.Context, taskID string, req ReplayHookRequest) (*ReplayHookResult, error)
	GetProjectByID(id string) (*orchestrator.Project, error)
	ListProjectCommands(projectID string) ([]CommandSummary, error)
	ListTaskBehaviorCommands(taskID string) ([]CommandSummary, error)
}

type WorkflowService

type WorkflowService interface {
	ApplyAction(ctx context.Context, taskID string, req ApplyActionRequest) (*ActionApplication, error)
	CompleteJob(ctx context.Context, jobID string, req JobDoneRequest) (*Job, error)
	TriggerDependents(ctx context.Context, taskID string)
}

type WorkspaceHandler

type WorkspaceHandler struct {
	Service ProjectService
}

func (*WorkspaceHandler) List

func (*WorkspaceHandler) Routes

func (h *WorkspaceHandler) Routes() chi.Router

type WorktreeCleaner

type WorktreeCleaner interface {
	CleanupForTask(taskID, projectDir, newStatus string) error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL