Documentation
¶
Overview ¶
Package agents implements the VORTEX agent runtime (build plan M10): a supervised, message-passing system of autonomous sub-agents coordinated by a single user-facing coordinator. This file defines the core types — agent state machine, configuration, inter-agent message envelope, the Agent interface, and an embeddable BaseAgent that the coordinator and spawned sub-agents build upon.
Index ¶
- Constants
- Variables
- func RegisterBuiltins(registry *ToolRegistry, sandboxDir string, allowedCommands []string, bus *Bus, ...) error
- func RegisterLocalTools(registry *ToolRegistry, cfg LocalFSConfig) error
- type AIGateway
- type Agent
- type AgentConfig
- type AgentMessage
- type AgentState
- type ApprovalError
- type ApprovalFunc
- type ApprovalRequest
- type AuditLogger
- type BaseAgent
- func (a *BaseAgent) Config() AgentConfig
- func (a *BaseAgent) Name() string
- func (a *BaseAgent) Receive() <-chan AgentMessage
- func (a *BaseAgent) Send(msg AgentMessage) error
- func (a *BaseAgent) Start(ctx context.Context) error
- func (a *BaseAgent) State() AgentState
- func (a *BaseAgent) Stop() error
- func (a *BaseAgent) Supervise(ctx context.Context) (err error)
- func (a *BaseAgent) TransitionState(from, to AgentState) error
- type BuildAppFunc
- type Bus
- type BusStats
- type Coordinator
- func (c *Coordinator) ActiveAgents() []string
- func (c *Coordinator) ApproveAction(session string, approved bool) (transcript string, matched bool)
- func (c *Coordinator) ClearSession(sessionID string)
- func (c *Coordinator) ExecuteLocalTool(ctx context.Context, session, name string, params map[string]any, ...) (any, error)
- func (c *Coordinator) ExecuteLocalToolSync(name string, params map[string]any) (string, error)
- func (c *Coordinator) HandleMessage(_ context.Context, userMsg, sessionID string) (string, error)
- func (c *Coordinator) HasPendingApproval(session string) bool
- func (c *Coordinator) ListSessions() []SessionInfo
- func (c *Coordinator) Reap(name string)
- func (c *Coordinator) RunTool(ctx context.Context, name string, params map[string]any) (any, error)
- func (c *Coordinator) SessionHistory(sessionID string) []MemoryMessage
- func (c *Coordinator) SetMemoryStore(s *MemoryStore)
- func (c *Coordinator) SpawnAgent(_ context.Context, cfg AgentConfig, tools []string) (Agent, error)
- func (c *Coordinator) WorkingDir() string
- type CoordinatorConfig
- type CreateProjectTool
- type DevOpsFunc
- type Diagnostic
- type EditFileTool
- type FindFilesTool
- type GitAddTool
- type GitCommitTool
- type GitDiffTool
- type GitStatusTool
- type HTTPGetTool
- type Intent
- type LSPClient
- func (c *LSPClient) Close() error
- func (c *LSPClient) Definition(file string, line, col int) (*Location, error)
- func (c *LSPClient) Diagnostics(file string) ([]Diagnostic, error)
- func (c *LSPClient) Hover(file string, line, col int) (string, error)
- func (c *LSPClient) References(file string, line, col int) ([]Location, error)
- type LSPConfig
- type LSPDiagnosticsTool
- type ListDirectoryTool
- type LocalFSConfig
- type Location
- type Memory
- type MemoryMessage
- type MemoryStats
- type MemoryStore
- func (m *MemoryStore) AppendMessage(sessionID, role, content string, tools []string) error
- func (m *MemoryStore) Close() error
- func (m *MemoryStore) DeleteSession(id string) error
- func (m *MemoryStore) ListSessions() ([]SessionInfo, error)
- func (m *MemoryStore) MigrateJSONDir(dir string) (int, error)
- func (m *MemoryStore) NewSession() (string, error)
- func (m *MemoryStore) Recent(sessionID string, n int) ([]MemoryMessage, error)
- func (m *MemoryStore) SearchMessages(query string) ([]SearchResult, error)
- func (m *MemoryStore) Stats() MemoryStats
- type OrchestrateFunc
- type PipelineFunc
- type ReadFileTool
- type ReadLocalFileTool
- type ResearchFunc
- type RunCommandTool
- type RunTerminalTool
- type Runtime
- func (r *Runtime) Approve(sessionID string, approved bool) (string, bool)
- func (r *Runtime) Coordinator() *Coordinator
- func (r *Runtime) ListSessions() []SessionInfo
- func (r *Runtime) SessionHistory(sessionID string) []MemoryMessage
- func (r *Runtime) Start(_ context.Context) error
- func (r *Runtime) Stats() RuntimeStats
- func (r *Runtime) Stop(ctx context.Context) error
- func (r *Runtime) Submit(ctx context.Context, userMsg, sessionID string) (<-chan string, error)
- type RuntimeConfig
- type RuntimeStats
- type SandboxedToolRegistry
- func (s *SandboxedToolRegistry) Execute(ctx context.Context, name string, params map[string]any) (any, error)
- func (s *SandboxedToolRegistry) ExecuteApproved(ctx context.Context, name string, params map[string]any) (any, error)
- func (s *SandboxedToolRegistry) Get(name string) (Tool, error)
- func (s *SandboxedToolRegistry) List() []string
- func (s *SandboxedToolRegistry) SandboxDir() string
- func (s *SandboxedToolRegistry) WithAudit(log AuditLogger, actor string) *SandboxedToolRegistry
- type SearchFilesTool
- type SearchResult
- type SendMessageTool
- type SessionInfo
- type SessionState
- type StubAIGateway
- type Tool
- type ToolRegistry
- type UndoTool
- type VortexAPITool
- type WriteFileTool
- type WriteLocalFileTool
Constants ¶
const ( TypePersistent = "persistent" TypeTask = "task" )
Agent type constants.
const ( MsgTaskBrief = "task_brief" MsgResult = "result" MsgError = "error" MsgStatus = "status" )
Message type constants.
Variables ¶
var ( // ErrBusFull is returned when a recipient's inbox is full; sends are // non-blocking so a slow agent never stalls the sender. ErrBusFull = errors.New("agents: recipient inbox full") // ErrAgentNotFound is returned when routing to an unregistered agent. ErrAgentNotFound = errors.New("agents: agent not found") // ErrAlreadyRegistered is returned when registering a duplicate name. ErrAlreadyRegistered = errors.New("agents: agent already registered") )
Package-level sentinel errors shared by the agent runtime and the message bus (defined here so File 1 — agent.go — compiles independently of bus.go).
var DefaultAllowedCommands = []string{
"go", "flutter", "git", "tar", "unzip",
}
DefaultAllowedCommands is the whitelist used when none is supplied.
Interpreters and package managers (python3, npm, pip3) are deliberately EXCLUDED: they execute arbitrary code from a single flag (python3 -c, npm run, pip3 install <pkg-with-setup.py>), so name-based whitelisting gives no real containment without an OS-level sandbox. The remaining binaries still need per-argument validation (see validateArgs) because even they have code-exec flags (git core.sshCommand, tar --to-command, go -exec).
var DefaultLSPServers = map[string][]string{
"go": {"gopls"},
"python": {"pylsp"},
"typescript": {"typescript-language-server", "--stdio"},
"rust": {"rust-analyzer"},
}
DefaultLSPServers maps a language to its conventional server command.
var ErrApprovalRequired = errors.New("agents: command requires human approval")
ErrApprovalRequired is returned by RunCommandTool when RequireApproval is set. It carries the full command so a human-in-the-loop approver can review it.
var ErrDangerousAction = fmt.Errorf("agents: action blocked (catastrophic system destruction)")
ErrDangerousAction is returned when an action matches a catastrophic, always-blocked pattern (e.g. rm -rf /, a fork bomb, formatting a disk, or writing into a Windows system directory). These are refused EVEN WITH user approval — they are non-recoverable system destruction, not normal edits. There is no path/working-directory confinement: the approval gate is the security control (the Claude Code model). Any other path is allowed once the user approves the action.
var ErrRuntimeStopped = errors.New("agents: runtime is stopped")
ErrRuntimeStopped is returned by Submit after the runtime has been stopped.
var ErrSSRFBlocked = errors.New("agents: SSRF target blocked")
ErrSSRFBlocked is returned when http_get is asked to reach a private, loopback, link-local, or cloud-metadata address (SSRF prevention).
var ErrSandboxEscape = fmt.Errorf("%w: path escapes sandbox boundary", ErrSandboxViolation)
ErrSandboxEscape is returned specifically when a filesystem path escapes the sandbox boundary, either lexically (../) or via a symlink pointing outside. It wraps ErrSandboxViolation so existing errors.Is(err, ErrSandboxViolation) checks continue to hold.
var ErrSandboxViolation = errors.New("agents: sandbox violation")
ErrSandboxViolation is returned when a tool's parameters would escape its permitted sandbox (path outside the sandbox dir, disallowed command, etc.).
var ErrTooManyRequests = errors.New("agents: too many concurrent submissions")
ErrTooManyRequests is returned by Submit when the concurrency cap is reached.
var ErrToolNotFound = errors.New("agents: tool not found")
ErrToolNotFound is returned when looking up an unregistered tool.
Functions ¶
func RegisterBuiltins ¶
func RegisterBuiltins(registry *ToolRegistry, sandboxDir string, allowedCommands []string, bus *Bus, apiBaseURL, agentName string) error
RegisterBuiltins populates registry with the built-in tools bound to the given sandbox dir, command whitelist, bus, and management API base URL. It is a convenience for wiring (used by the runtime and start.go).
func RegisterLocalTools ¶
func RegisterLocalTools(registry *ToolRegistry, cfg LocalFSConfig) error
RegisterLocalTools registers the local filesystem + terminal tools (real machine access, approval-gated) into registry, bound to cfg. These provide list_directory/read_file (read-only) and write_file/edit_file/run_terminal/ create_project (approval-required). When mixed with RegisterBuiltins, register local tools into a separate registry to avoid read_file/write_file name collisions — the wiring (start.go) chooses one set.
Types ¶
type AIGateway ¶
type AIGateway interface {
Complete(ctx context.Context, prompt string, systemPrompt string) (string, error)
}
AIGateway is the interface the coordinator uses to reach a language model. It is implemented by the messaging AI gateway (M11); for M10 a stub suffices.
type Agent ¶
type Agent interface {
Name() string
State() AgentState
Start(ctx context.Context) error
Stop() error
Send(msg AgentMessage) error
Receive() <-chan AgentMessage
}
Agent is the behaviour every agent (coordinator and sub-agents) implements.
type AgentConfig ¶
type AgentConfig struct {
Name string
Type string // "persistent" | "task"
Description string
MaxRetries int // default 3 (applied by NewBaseAgent if <= 0)
Timeout time.Duration // 0 = no timeout
}
AgentConfig configures a single agent.
type AgentMessage ¶
type AgentMessage struct {
ID string
FromAgent string
ToAgent string
Type string // "task_brief" | "result" | "error" | "status"
Payload any
Timestamp time.Time
}
AgentMessage is the typed envelope passed between agents over the bus.
type AgentState ¶
type AgentState string
AgentState is the lifecycle state of an agent. Agents move through these states under the supervision of the runtime; TransitionState enforces the legal edges of the state machine.
const ( // StateIdle is the initial (and, for persistent agents, the resting) state. StateIdle AgentState = "idle" // StateRunning means the agent is actively processing work. StateRunning AgentState = "running" // StateWaiting means the agent is blocked awaiting a message or result. StateWaiting AgentState = "waiting" // StateError means the agent failed; it may retry back to Idle. StateError AgentState = "error" // StateComplete means the agent finished its task. Terminal for task // agents; persistent agents may return to Idle. StateComplete AgentState = "complete" )
type ApprovalError ¶
type ApprovalError struct {
Request ApprovalRequest
}
ApprovalError wraps ErrApprovalRequired with the command details.
func (*ApprovalError) Unwrap ¶
func (e *ApprovalError) Unwrap() error
Unwrap lets errors.Is(err, ErrApprovalRequired) succeed.
type ApprovalFunc ¶
type ApprovalFunc func(ctx context.Context, req ApprovalRequest) bool
ApprovalFunc requests human approval for an action (e.g. a run_command). It returns true if approved, false if rejected or timed out. The messaging layer supplies the real implementation (Telegram approve/reject buttons); when nil, approval-gated actions are denied by default (fail safe).
type ApprovalRequest ¶
type ApprovalRequest struct {
Command string
Args []string
// Richer fields for the local FS / terminal tools (M-agent local access).
Tool string // e.g. "write_file", "run_terminal"
Description string // one-line human summary
Preview string // diff / content / command preview to show
Params map[string]any // the parameters to re-run with on approval
}
ApprovalRequest describes an action awaiting human approval. It is the value wrapped by an *ApprovalError so callers (the coordinator/approver) can render a preview and decide. Command/Args describe a run_command; Tool/Description/ Preview describe the richer local-filesystem and terminal tools.
type AuditLogger ¶
type AuditLogger interface {
Append(ctx context.Context, actor, action, resource string, detail map[string]any) error
}
AuditLogger is the subset of the audit log the sandbox uses to record tool executions. It is satisfied by *audit.Log.
type BaseAgent ¶
type BaseAgent struct {
// contains filtered or unexported fields
}
BaseAgent is an embeddable implementation of Agent. It owns the state machine and the buffered inbound message channel, and provides a supervised run wrapper that recovers from panics and drives the agent to StateError.
Embedders typically override the work performed inside Start by supplying a run function via NewBaseAgentFunc, or by embedding BaseAgent and providing their own Start that calls Supervise.
func NewBaseAgent ¶
func NewBaseAgent(cfg AgentConfig) *BaseAgent
NewBaseAgent constructs a BaseAgent in StateIdle with a buffered inbox.
func NewBaseAgentFunc ¶
func NewBaseAgentFunc(cfg AgentConfig, run func(ctx context.Context) error) *BaseAgent
NewBaseAgentFunc is like NewBaseAgent but attaches a unit of work run by Start under panic supervision.
func (*BaseAgent) Config ¶
func (a *BaseAgent) Config() AgentConfig
Config returns a copy of the agent's configuration.
func (*BaseAgent) Receive ¶
func (a *BaseAgent) Receive() <-chan AgentMessage
Receive returns the agent's inbound message channel.
func (*BaseAgent) Send ¶
func (a *BaseAgent) Send(msg AgentMessage) error
Send places a message on the agent's inbox. It is non-blocking: a full inbox returns ErrBusFull rather than blocking the sender.
func (*BaseAgent) Start ¶
Start drives the agent through its work under panic supervision. It marks the agent Running, executes the run function (if any), and transitions to Complete on success or Error on failure/panic.
func (*BaseAgent) State ¶
func (a *BaseAgent) State() AgentState
State returns the agent's current lifecycle state.
func (*BaseAgent) Stop ¶
Stop transitions the agent back to Idle and is safe to call from any state.
func (*BaseAgent) Supervise ¶
Supervise runs the agent's work function, recovering from panics and driving the agent to StateError if one occurs. It is exported so embedders that provide a custom Start can reuse the supervision behaviour.
func (*BaseAgent) TransitionState ¶
func (a *BaseAgent) TransitionState(from, to AgentState) error
TransitionState moves the agent from `from` to `to`, returning an error if the current state is not `from` or the edge is illegal. The Complete → Idle edge is permitted only for persistent agents (task agents treat Complete as terminal).
type BuildAppFunc ¶
BuildAppFunc handles a BUILD_APP request, returning a user-facing reply (e.g. a job id). VORTEX Forge (M13) supplies the implementation via start.go; the coordinator stays decoupled from the forge package (which imports agents) to avoid an import cycle. When nil, BUILD_APP returns a not-implemented stub.
type Bus ¶
type Bus struct {
// contains filtered or unexported fields
}
Bus is a typed, in-process message bus that routes AgentMessages between registered agents. Routing is non-blocking: delivery to a full inbox is dropped (counted in stats) rather than blocking the sender, so one slow agent cannot stall the whole runtime.
func (*Bus) Broadcast ¶
func (b *Bus) Broadcast(msg AgentMessage)
Broadcast sends msg to every registered agent except the sender (msg.FromAgent). Delivery is non-blocking per recipient: a full inbox is dropped and counted, never blocking other recipients.
func (*Bus) Register ¶
Register adds an agent under its name. It returns ErrAlreadyRegistered if the name is already taken.
func (*Bus) Send ¶
func (b *Bus) Send(msg AgentMessage) error
Send routes msg to the inbox of msg.ToAgent. It returns ErrAgentNotFound if the recipient is not registered, or ErrBusFull if its inbox is full. A successful send increments MessagesSent; a full inbox increments MessagesDropped.
func (*Bus) Unregister ¶
Unregister removes an agent by name. It is a no-op if the name is unknown.
type Coordinator ¶
type Coordinator struct {
*BaseAgent
// contains filtered or unexported fields
}
Coordinator is the single user-facing agent. It classifies user messages, routes them to the appropriate mode handler, and supervises spawned sub-agents. It implements Agent via an embedded BaseAgent.
func NewCoordinator ¶
func NewCoordinator(cfg CoordinatorConfig) (*Coordinator, error)
NewCoordinator constructs a coordinator. It requires a Bus and an AIGateway.
func (*Coordinator) ActiveAgents ¶
func (c *Coordinator) ActiveAgents() []string
ActiveAgents returns the names of currently active sub-agents.
func (*Coordinator) ApproveAction ¶
func (c *Coordinator) ApproveAction(session string, approved bool) (transcript string, matched bool)
ApproveAction resolves a pending TUI approval for a session and, on approval, EXECUTES the stashed action — returning a transcript of the result (the original Submit already returned the preview, so the work happens here). matched is false when no action was pending for the session.
func (*Coordinator) ClearSession ¶
func (c *Coordinator) ClearSession(sessionID string)
ClearSession drops a session's state (called when its job completes/fails).
func (*Coordinator) ExecuteLocalTool ¶
func (c *Coordinator) ExecuteLocalTool(ctx context.Context, session, name string, params map[string]any, emit func(string)) (any, error)
ExecuteLocalTool runs a local FS/terminal tool, streaming human-readable progress lines via emit (each becomes a chat message). Read-only tools run immediately; mutating tools that return an *ApprovalError are routed for approval — via the Approval callback if set, otherwise via a session-keyed pending request resolved by ApproveAction (the TUI [Y]/[N]). If NEITHER an approver nor a pending resolver can grant approval, the action is DENIED (fail-safe — never auto-executed).
func (*Coordinator) ExecuteLocalToolSync ¶
ExecuteLocalToolSync runs a read-only local tool and returns its transcript as a string (for non-streaming callers like the Telegram /ls command). It is only intended for tools that don't require approval.
func (*Coordinator) HandleMessage ¶
HandleMessage is the main entry point for a user message. It classifies the intent via the AI gateway and routes to the matching handler. For M10, the BUILD_APP/RESEARCH/DEVOPS/DATA handlers are stubs; GENERAL_QUESTION is answered directly and UNKNOWN returns a clarifying question.
func (*Coordinator) HasPendingApproval ¶
func (c *Coordinator) HasPendingApproval(session string) bool
HasPendingApproval reports whether a session has an action awaiting approval.
func (*Coordinator) ListSessions ¶
func (c *Coordinator) ListSessions() []SessionInfo
ListSessions returns stored conversation sessions (newest first), or nil when no memory backend is configured.
func (*Coordinator) Reap ¶
func (c *Coordinator) Reap(name string)
Reap removes a sub-agent that has reached a terminal state from the active set and unregisters it from the bus.
func (*Coordinator) RunTool ¶
RunTool executes a named tool through the sandboxed registry, handling the human-in-the-loop approval flow: if the tool returns an *ApprovalError, the coordinator asks the configured ApprovalFunc; on approval it re-runs the action with approval granted, and on rejection (or a nil ApprovalFunc) it returns an error without executing. Tools that don't require approval run directly.
func (*Coordinator) SessionHistory ¶
func (c *Coordinator) SessionHistory(sessionID string) []MemoryMessage
SessionHistory returns the persisted messages for a session.
func (*Coordinator) SetMemoryStore ¶ added in v0.3.0
func (c *Coordinator) SetMemoryStore(s *MemoryStore)
SetMemoryStore wires the SQLite conversation store, making it the persistence backend for this coordinator. Pass nil to use the legacy JSON store.
func (*Coordinator) SpawnAgent ¶
func (c *Coordinator) SpawnAgent(_ context.Context, cfg AgentConfig, tools []string) (Agent, error)
SpawnAgent creates a sub-agent restricted to the named tools, registers it on the bus, and tracks it as active. It returns an error if MaxAgents would be exceeded.
func (*Coordinator) WorkingDir ¶
func (c *Coordinator) WorkingDir() string
WorkingDir returns the directory the agent resolves relative paths against.
type CoordinatorConfig ¶
type CoordinatorConfig struct {
Bus *Bus
Tools *SandboxedToolRegistry
LocalTools *ToolRegistry // local FS + terminal tools (real machine access)
AIGateway AIGateway
MaxAgents int // concurrent sub-agent limit (default 8)
Approval ApprovalFunc // human-in-the-loop approval; nil = deny gated actions
BuildApp BuildAppFunc // BUILD_APP handler (VORTEX Forge); nil = stub
Research ResearchFunc // RESEARCH handler (M15 research agent); nil = stub
DevOps DevOpsFunc // DEVOPS handler (M16 devops agent); nil = stub
Pipeline PipelineFunc // DATA_PIPELINE handler (M17 pipeline agent); nil = stub
Orchestrate OrchestrateFunc // ORCHESTRATE handler (M18 multi-agent); nil = stub
// SessionClarifying reports whether the most recent build for a session is
// awaiting clarifying answers (forge JobClarify state). Optional.
SessionClarifying func(sessionID string) bool
// SessionPending reports whether the most recent build for a session is
// non-terminal (queued/running/clarifying). Used so a follow-up message is
// treated as an answer while the (async) build is still in flight — even
// before it reaches needs_clarification. Optional.
SessionPending func(sessionID string) bool
// MemoryStore, when set, persists per-session conversation history under this
// directory and passes recent context to the AI. Optional.
MemoryStore string
WorkingDir string // directory relative paths resolve against
}
CoordinatorConfig configures the user-facing coordinator agent.
type CreateProjectTool ¶
type CreateProjectTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
CreateProjectTool scaffolds a project (approval required).
func (CreateProjectTool) Description ¶
func (CreateProjectTool) Description() string
Description returns a human-readable summary.
type DevOpsFunc ¶ added in v0.3.0
DevOpsFunc handles a DEVOPS request (SSH/Docker/Nginx server management), returning a user-facing reply. The M16 devops agent supplies it via start.go. When nil, DEVOPS returns a not-implemented stub.
type Diagnostic ¶ added in v0.3.0
type Diagnostic struct {
File string `json:"file"`
Line int `json:"line"` // 1-based
Col int `json:"col"` // 1-based
Severity string `json:"severity"` // "error" | "warning" | "info" | "hint"
Message string `json:"message"`
}
Diagnostic is one error/warning reported by the language server.
type EditFileTool ¶
type EditFileTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
EditFileTool replaces an exact string in a real file. Requires approval.
func (EditFileTool) Description ¶
func (EditFileTool) Description() string
Description returns a human-readable summary.
type FindFilesTool ¶
type FindFilesTool struct {
// contains filtered or unexported fields
}
FindFilesTool finds files by name/glob. Read-only, no approval.
func (FindFilesTool) Description ¶
func (FindFilesTool) Description() string
Description returns a human-readable summary.
type GitAddTool ¶
type GitAddTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
GitAddTool stages files. Requires approval.
func (GitAddTool) Description ¶
func (GitAddTool) Description() string
Description returns a human-readable summary.
type GitCommitTool ¶
type GitCommitTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
GitCommitTool stages + commits. Requires approval.
func (GitCommitTool) Description ¶
func (GitCommitTool) Description() string
Description returns a human-readable summary.
type GitDiffTool ¶
type GitDiffTool struct {
// contains filtered or unexported fields
}
GitDiffTool shows the working-tree diff. Read-only, no approval.
func (GitDiffTool) Description ¶
func (GitDiffTool) Description() string
Description returns a human-readable summary.
type GitStatusTool ¶
type GitStatusTool struct {
// contains filtered or unexported fields
}
GitStatusTool reports the repo status. Read-only, no approval.
func (GitStatusTool) Description ¶
func (GitStatusTool) Description() string
Description returns a human-readable summary.
type HTTPGetTool ¶
type HTTPGetTool struct {
Client *http.Client
// AllowedHosts, when non-empty, restricts requests to URLs whose hostname
// exactly matches one of these entries (in addition to the IP checks).
AllowedHosts []string
}
HTTPGetTool performs an HTTP(S) GET request with SSRF protection.
func (HTTPGetTool) Description ¶
func (HTTPGetTool) Description() string
Description returns a human-readable summary.
type Intent ¶
type Intent string
Intent is the classification of a user message.
const ( IntentBuildApp Intent = "BUILD_APP" IntentLocalFile Intent = "LOCAL_FILE" IntentResearch Intent = "RESEARCH" IntentDevOpsCheck Intent = "DEVOPS_CHECK" IntentDataPipeline Intent = "DATA_PIPELINE" IntentOrchestrate Intent = "ORCHESTRATE" IntentGeneralQuestion Intent = "GENERAL_QUESTION" IntentUnknown Intent = "UNKNOWN" )
Intent classifications produced by the coordinator.
type LSPClient ¶ added in v0.3.0
type LSPClient struct {
// contains filtered or unexported fields
}
LSPClient is a JSON-RPC client to a language server subprocess.
func NewLSPClient ¶ added in v0.3.0
NewLSPClient starts the language server for cfg and performs the LSP initialize handshake. If the server binary is not on PATH it returns (nil, nil) — LSP is an optional enhancement, not a hard dependency. The caller owns Close.
func (*LSPClient) Definition ¶ added in v0.3.0
Definition returns the definition location of the symbol at (line, col).
func (*LSPClient) Diagnostics ¶ added in v0.3.0
func (c *LSPClient) Diagnostics(file string) ([]Diagnostic, error)
Diagnostics opens file in the server and returns the diagnostics it reports. It waits briefly for the server's asynchronous publishDiagnostics.
type LSPConfig ¶ added in v0.3.0
type LSPConfig struct {
Language string // "go" | "python" | "typescript" | "rust"
ServerCmd []string // e.g. ["gopls"]; ServerCmd[0] is the binary
WorkDir string // workspace root
}
LSPConfig configures an LSP client for one language/workspace.
type LSPDiagnosticsTool ¶ added in v0.3.0
type LSPDiagnosticsTool struct {
// WorkDir is the workspace root passed to the language server.
WorkDir string
// contains filtered or unexported fields
}
LSPDiagnosticsTool exposes language-server diagnostics (errors/warnings) for a file as an agent tool (build plan M20). It is read-only, so it needs no approval. The tool lazily starts one LSP client per language and reuses it; when the language server is not installed it returns an empty, non-error result so the agent degrades gracefully.
func (*LSPDiagnosticsTool) Close ¶ added in v0.3.0
func (t *LSPDiagnosticsTool) Close()
Close shuts down all started LSP clients.
func (*LSPDiagnosticsTool) Description ¶ added in v0.3.0
func (*LSPDiagnosticsTool) Description() string
Description returns a human-readable summary.
func (*LSPDiagnosticsTool) Execute ¶ added in v0.3.0
Execute runs diagnostics on params["file"]. It returns a structured result with the diagnostics list and a count.
func (*LSPDiagnosticsTool) Name ¶ added in v0.3.0
func (*LSPDiagnosticsTool) Name() string
Name returns the tool name.
type ListDirectoryTool ¶
type ListDirectoryTool struct {
// contains filtered or unexported fields
}
ListDirectoryTool lists a directory's entries. Read-only, no approval.
func (ListDirectoryTool) Description ¶
func (ListDirectoryTool) Description() string
Description returns a human-readable summary.
type LocalFSConfig ¶
type LocalFSConfig struct {
// Root is the base for resolving relative paths (default: os.Getwd). It does
// NOT restrict where files may be written; absolute paths anywhere are
// allowed once the user approves the action.
Root string
// RequireApproval gates mutating tools (default true via NewLocalTools).
RequireApproval bool
}
LocalFSConfig configures the local FS/terminal tools. There is NO path confinement — the approval gate is the security model. Root is informational only: it is the base for resolving *relative* paths (defaults to the process working directory) and is shown in the TUI top bar.
type Memory ¶
type Memory struct {
SessionID string `json:"session_id"`
Messages []MemoryMessage `json:"messages"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// contains filtered or unexported fields
}
Memory is a per-session conversation history persisted to disk under storePath/<sessionID>.json.
func NewMemory ¶
NewMemory creates an in-memory conversation bound to a store directory. Call Load to populate it from disk, or Append + Save to persist.
func (*Memory) List ¶
func (m *Memory) List() []SessionInfo
List returns all stored sessions (newest first), reading summaries from disk.
func (*Memory) Recent ¶
func (m *Memory) Recent(n int) []MemoryMessage
Recent returns the last n messages (for AI context). n<=0 returns all.
type MemoryMessage ¶
type MemoryMessage struct {
Role string `json:"role"` // "user" | "agent" | "system"
Content string `json:"content"`
Timestamp time.Time `json:"timestamp"`
ToolCalls []string `json:"tool_calls,omitempty"`
}
MemoryMessage is one persisted turn in a conversation.
type MemoryStats ¶ added in v0.3.0
type MemoryStats struct {
TotalSessions int `json:"total_sessions"`
TotalMessages int `json:"total_messages"`
DBSizeMB float64 `json:"db_size_mb"`
}
MemoryStats summarises the store for the dashboard/CLI.
type MemoryStore ¶ added in v0.3.0
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore persists agent conversations in a single SQLite database (build plan M20), replacing the one-JSON-file-per-session layout. SQLite gives indexed queries, full-text search across all messages, and O(1) session listing instead of the O(n) directory scan the JSON store needed (production audit L2). It is safe for concurrent use — the database/sql pool serialises writes and SQLite is opened in WAL mode for concurrent reads.
func NewMemoryStore ¶ added in v0.3.0
func NewMemoryStore(dbPath string) (*MemoryStore, error)
NewMemoryStore opens (creating if needed) a SQLite-backed conversation store at dbPath, applying the schema and enabling WAL + foreign keys.
func (*MemoryStore) AppendMessage ¶ added in v0.3.0
func (m *MemoryStore) AppendMessage(sessionID, role, content string, tools []string) error
AppendMessage adds a message to a session, creating the session if needed and updating its summary (first user message) and updated_at.
func (*MemoryStore) Close ¶ added in v0.3.0
func (m *MemoryStore) Close() error
Close closes the underlying database.
func (*MemoryStore) DeleteSession ¶ added in v0.3.0
func (m *MemoryStore) DeleteSession(id string) error
DeleteSession removes a session and its messages (cascade).
func (*MemoryStore) ListSessions ¶ added in v0.3.0
func (m *MemoryStore) ListSessions() ([]SessionInfo, error)
ListSessions returns all sessions, newest-updated first.
func (*MemoryStore) MigrateJSONDir ¶ added in v0.3.0
func (m *MemoryStore) MigrateJSONDir(dir string) (int, error)
MigrateJSONDir imports legacy <sessionID>.json conversation files from dir into the store, skipping sessions that already exist. It returns the number of sessions imported. A missing/empty dir imports nothing (not an error), so it is safe to call on every startup.
func (*MemoryStore) NewSession ¶ added in v0.3.0
func (m *MemoryStore) NewSession() (string, error)
NewSession creates a session row with a generated ID and returns it.
func (*MemoryStore) Recent ¶ added in v0.3.0
func (m *MemoryStore) Recent(sessionID string, n int) ([]MemoryMessage, error)
Recent returns the last n messages for a session in chronological order. n<=0 returns all.
func (*MemoryStore) SearchMessages ¶ added in v0.3.0
func (m *MemoryStore) SearchMessages(query string) ([]SearchResult, error)
SearchMessages runs a full-text search across all message content and returns matching messages (with their session) newest-first, capped at 100.
func (*MemoryStore) Stats ¶ added in v0.3.0
func (m *MemoryStore) Stats() MemoryStats
Stats returns aggregate counts and the database file size.
type OrchestrateFunc ¶ added in v0.3.0
type OrchestrateFunc func(ctx context.Context, goal string, progressFn func(string)) (string, error)
OrchestrateFunc handles a multi-agent goal (M18): decompose into tasks and run them across specialized agents, returning a summary. Supplied via start.go. When nil, orchestration returns a not-implemented stub.
type PipelineFunc ¶ added in v0.3.0
PipelineFunc handles a DATA_PIPELINE request (analyze data → chart → report), returning a user-facing reply. The M17 pipeline agent supplies it via start.go. When nil, DATA_PIPELINE returns a not-implemented stub.
type ReadFileTool ¶
type ReadFileTool struct{ SandboxDir string }
ReadFileTool reads a file inside the agent's sandbox.
func (ReadFileTool) Description ¶
func (ReadFileTool) Description() string
Description returns a human-readable summary.
type ReadLocalFileTool ¶
type ReadLocalFileTool struct {
// contains filtered or unexported fields
}
ReadLocalFileTool reads a real file. Read-only, no approval.
func (ReadLocalFileTool) Description ¶
func (ReadLocalFileTool) Description() string
Description returns a human-readable summary.
type ResearchFunc ¶ added in v0.3.0
ResearchFunc handles a RESEARCH request, returning a user-facing reply. The M15 research agent supplies the implementation via start.go (keeping the coordinator decoupled from the research package). progressFn streams step updates. When nil, RESEARCH returns a not-implemented stub.
type RunCommandTool ¶
type RunCommandTool struct {
SandboxDir string
AllowedCommands []string
// RequireApproval, when true, makes Execute return an *ApprovalError
// instead of running — the coordinator routes this to a human approver
// (M10.7). It defaults to true via NewRunCommandTool until an OS-level
// sandbox makes unattended execution safe.
RequireApproval bool
}
RunCommandTool runs a whitelisted command in the sandbox directory.
func NewRunCommandTool ¶
func NewRunCommandTool(sandboxDir string, allowed []string) RunCommandTool
NewRunCommandTool builds a RunCommandTool with RequireApproval defaulted to true (safe by default). Callers that have an OS sandbox can clear it.
func (RunCommandTool) Description ¶
func (RunCommandTool) Description() string
Description returns a human-readable summary.
type RunTerminalTool ¶
type RunTerminalTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
RunTerminalTool runs an arbitrary command (approval required, guardrailed).
func (RunTerminalTool) Description ¶
func (RunTerminalTool) Description() string
Description returns a human-readable summary.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime supervises the coordinator and the message bus, exposing a simple Submit API for delivering user messages and receiving streamed responses.
func NewRuntime ¶
func NewRuntime(cfg RuntimeConfig) (*Runtime, error)
NewRuntime constructs a runtime. It requires a Bus and a Coordinator.
func (*Runtime) Approve ¶
Approve resolves a pending tool-action approval for a session, delegating to the coordinator. It returns the result transcript (executed on approval) and whether a pending action matched.
func (*Runtime) Coordinator ¶
func (r *Runtime) Coordinator() *Coordinator
Coordinator returns the runtime's coordinator (for wiring local-tool calls).
func (*Runtime) ListSessions ¶
func (r *Runtime) ListSessions() []SessionInfo
ListSessions returns stored conversation sessions (newest first).
func (*Runtime) SessionHistory ¶
func (r *Runtime) SessionHistory(sessionID string) []MemoryMessage
SessionHistory returns the persisted messages for a session.
func (*Runtime) Start ¶
Start registers the coordinator on the bus, ensures the sandbox base exists, and marks the runtime ready. It is idempotent.
func (*Runtime) Stats ¶
func (r *Runtime) Stats() RuntimeStats
Stats returns a snapshot of runtime activity.
func (*Runtime) Stop ¶
Stop rejects new Submits, cancels the runtime context so in-flight HandleMessage calls unwind, and waits (up to ctx's deadline) for those goroutines to drain before unregistering agents. Sub-agents are unregistered first, the coordinator last.
type RuntimeConfig ¶
type RuntimeConfig struct {
Bus *Bus
Coordinator *Coordinator
MaxAgents int
MaxConcurrent int // max simultaneous in-flight Submits (default 5)
SandboxBase string // base directory for per-agent sandboxes
Logger *slog.Logger // optional; defaults to slog.Default()
}
RuntimeConfig configures the persistent agent runtime supervisor.
type RuntimeStats ¶
RuntimeStats is a snapshot of runtime activity.
type SandboxedToolRegistry ¶
type SandboxedToolRegistry struct {
// contains filtered or unexported fields
}
SandboxedToolRegistry wraps a ToolRegistry, enforcing per-tool restrictions (sandbox dir, command whitelist, bus) and recording every execution to the audit log when one is configured.
func NewSandboxedRegistry ¶
func NewSandboxedRegistry(registry *ToolRegistry, sandboxDir string, allowedCommands []string, bus *Bus) *SandboxedToolRegistry
NewSandboxedRegistry constructs a sandboxed registry over the given base registry. The built-in stateful tools (file, command, message) are re-registered with the sandbox restrictions bound in.
func (*SandboxedToolRegistry) Execute ¶
func (s *SandboxedToolRegistry) Execute(ctx context.Context, name string, params map[string]any) (any, error)
Execute looks up and runs a tool, recording the execution (and its outcome) to the audit log when configured. Restrictions are enforced by the tools themselves, which the registry binds to this sandbox.
func (*SandboxedToolRegistry) ExecuteApproved ¶
func (s *SandboxedToolRegistry) ExecuteApproved(ctx context.Context, name string, params map[string]any) (any, error)
ExecuteApproved runs a tool with the human-approval gate disabled. It is called only after an approver has granted permission for an action that returned an *ApprovalError. For a RunCommandTool this re-runs the same command with RequireApproval cleared; other tools execute normally. The execution is audit-logged as an approved action.
func (*SandboxedToolRegistry) Get ¶
func (s *SandboxedToolRegistry) Get(name string) (Tool, error)
Get returns the named tool from the underlying registry.
func (*SandboxedToolRegistry) List ¶
func (s *SandboxedToolRegistry) List() []string
List returns the available tool names.
func (*SandboxedToolRegistry) SandboxDir ¶
func (s *SandboxedToolRegistry) SandboxDir() string
SandboxDir returns the configured sandbox directory.
func (*SandboxedToolRegistry) WithAudit ¶
func (s *SandboxedToolRegistry) WithAudit(log AuditLogger, actor string) *SandboxedToolRegistry
WithAudit sets the audit logger and actor used to record executions.
type SearchFilesTool ¶
type SearchFilesTool struct {
// contains filtered or unexported fields
}
SearchFilesTool searches file contents for a pattern. Read-only, no approval.
func (SearchFilesTool) Description ¶
func (SearchFilesTool) Description() string
Description returns a human-readable summary.
type SearchResult ¶ added in v0.3.0
type SearchResult struct {
SessionID string `json:"session_id"`
Message MemoryMessage `json:"message"`
}
SearchResult is one full-text search hit.
type SendMessageTool ¶
SendMessageTool sends a message to another agent over the bus.
func (SendMessageTool) Description ¶
func (SendMessageTool) Description() string
Description returns a human-readable summary.
type SessionInfo ¶
type SessionInfo struct {
SessionID string `json:"session_id"`
Summary string `json:"summary"`
UpdatedAt time.Time `json:"updated_at"`
}
SessionInfo describes a stored session for listings.
type SessionState ¶
type SessionState struct {
OriginalRequest string // the first build message in this session
AwaitingClarification bool // forge asked questions; next msg is an answer
Answers []string // accumulated clarification answers
LastActivity time.Time // for idle cleanup
}
SessionState tracks per-conversation context so a multi-turn build (with clarifying questions) continues the SAME job instead of restarting.
type StubAIGateway ¶
type StubAIGateway struct {
// IntentReply, if set, is returned verbatim for intent-classification
// prompts (tests use this to drive routing).
IntentReply string
// AnswerReply is returned for direct-answer completions.
AnswerReply string
}
StubAIGateway is a fixed-response AIGateway used until the real gateway is wired in (M11). It echoes a canned reply and, for intent classification, returns GENERAL_QUESTION so the coordinator answers directly.
type Tool ¶
type Tool interface {
Name() string
Description() string
Execute(ctx context.Context, params map[string]any) (any, error)
}
Tool is a single, declared, enumerable action an agent may perform. Every agent action goes through a Tool: no tool means no action (the permission model is allow-list only).
func NewLocalTools ¶
func NewLocalTools(cfg LocalFSConfig) []Tool
NewLocalTools returns the local FS + terminal tools bound to cfg, with approval REQUIRED on all mutating tools.
type ToolRegistry ¶
type ToolRegistry struct {
// contains filtered or unexported fields
}
ToolRegistry holds the set of tools available to agents.
func NewToolRegistry ¶
func NewToolRegistry() *ToolRegistry
NewToolRegistry constructs an empty tool registry.
func (*ToolRegistry) Get ¶
func (r *ToolRegistry) Get(name string) (Tool, error)
Get returns the named tool or ErrToolNotFound.
func (*ToolRegistry) List ¶
func (r *ToolRegistry) List() []string
List returns the names of all registered tools.
func (*ToolRegistry) Register ¶
func (r *ToolRegistry) Register(tool Tool) error
Register adds a tool. It returns an error if the name is already taken.
type UndoTool ¶
type UndoTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
UndoTool restores the most recent file backup for a session. Requires approval (it overwrites the current file).
func (UndoTool) Description ¶
Description returns a human-readable summary.
type VortexAPITool ¶
type VortexAPITool struct {
BaseURL string // e.g. http://127.0.0.1:9090
Client *http.Client
}
VortexAPITool calls the VORTEX management API. Only /api/* paths are allowed, excluding the agent and control-plane paths in vortexAPIDeniedPaths.
func (VortexAPITool) Description ¶
func (VortexAPITool) Description() string
Description returns a human-readable summary.
type WriteFileTool ¶
type WriteFileTool struct{ SandboxDir string }
WriteFileTool writes content to a file inside the agent's sandbox.
func (WriteFileTool) Description ¶
func (WriteFileTool) Description() string
Description returns a human-readable summary.
type WriteLocalFileTool ¶
type WriteLocalFileTool struct {
RequireApproval bool
// contains filtered or unexported fields
}
WriteLocalFileTool writes a real file. Requires approval.
func (WriteLocalFileTool) Description ¶
func (WriteLocalFileTool) Description() string
Description returns a human-readable summary.
func (WriteLocalFileTool) Execute ¶
Execute writes params["path"] with params["content"], optionally creating parent dirs (params["create_dirs"]). Returns an *ApprovalError when approval is required.
func (WriteLocalFileTool) Name ¶
func (WriteLocalFileTool) Name() string
Name returns the tool name.