Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI

on:
push:
branches: [master, main]
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Install build deps (CGO sqlite)
run: sudo apt-get update && sudo apt-get install -y gcc libc6-dev

- name: Download dependencies
run: make deps

- name: Vet
run: make vet

- name: Test
run: make test

- name: Build
run: make build
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ bin/
*.dll
*.so
*.dylib
octa-agentd
octa-agent
/octa-agentd
/octa-agent

# Test binary, built with `go test -c`
*.test
Expand Down Expand Up @@ -35,6 +35,7 @@ Thumbs.db
*.db
*.sqlite
*.sqlite3
config.yaml
data/
logs/
tmp/
Expand Down
87 changes: 87 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# AGENTS.md

This file provides guidance to WARP (warp.dev) when working with code in this repository.

## Core development commands

### Setup and build
- `make deps` — download and tidy Go modules.
- `make build` — build both binaries into `bin/` (`octa-agentd`, `octa-agent`).
- `make build-daemon` / `make build-cli` — build one binary.
- `make install` — install both binaries via `go install`.

### Run locally
- `./bin/octa-agentd` — start daemon (polls and processes queued goals).
- `./bin/octa-agentd --browser-port 8765` — start daemon with browser automation enabled on a specific port.
- `./bin/octa-agent init` — create `~/.config/octaai/config.yaml`.
- `./bin/octa-agent goal "<description>"` — submit a goal.
- `./bin/octa-agent status` — list goal states and progress.
- `./bin/octa-agent logs <goal-id>` — inspect execution logs and task outcomes.
- `./bin/octa-agent approvals` / `approve <id>` / `deny <id>` — handle human approval gates.

### Test, lint, and validation
- `make test` — run all tests (`go test -v ./...`).
- `make test-coverage` — run tests with coverage report (`coverage.out`, `coverage.html`).
- `go test -v ./pkg/workflow -run TestName` — run a single test in one package.
- `make lint` — run `golangci-lint run` (requires `golangci-lint` installed).
- `make fmt` and `make vet` — baseline formatting and static checks.

## High-level architecture

### Runtime shape (daemon + CLI + state store)
- `cmd/octa-agent/main.go`: CLI for creating goals, checking status/logs, and resolving approvals.
- `cmd/octa-agentd/main.go`: long-running daemon that loads config/LLM/tools, polls goals every 5 seconds, resumes interrupted `EXECUTING`/`EVALUATING` goals, and processes goals concurrently.
- `pkg/storage/sqlite.go`: central persistence layer — tables: `goals`, `tasks`, `execution_steps`, `logs`, `checkpoints`, `approvals`. SQLite is the source of truth for resumability. Default path: `~/.config/octaai/state.db`.

### Goal state machine
Goals move through: `IDLE → PLANNING → EXECUTING → EVALUATING → COMPLETED / FAILED`, with optional states `RETRYING` (recoverable failure triggers replanning), `WAITING_FOR_APPROVAL` (permission gate), and `BLOCKED`. Valid transitions are enforced by `engine.CanTransition()` in `pkg/engine/state.go`.

### Goal execution pipeline
- `pkg/agent/agent.go`: thin wrapper around the engine.
- `pkg/engine/engine.go`: drives the state machine loop (default: 50 max loops, 500ms pause per loop):
1. Planner creates 1–2 template tasks (project setup + LLM-driven execution task); the LLM chooses concrete tool calls per step inside `executeLLMTask`.
2. Engine runs ready tasks respecting dependencies; parallel up to `MaxParallel=3` when enabled.
3. Every tool call produces a persisted `ExecutionStep` record (pending → running → completed/failed) with retry count bounded by `engine.max_retries` (default 3).
4. Evaluator chain runs after each step; can signal retry or fatal failure.
5. On recoverable failure with `EnableReplan=true`, `replan.go` adds one corrective task.
- `pkg/engine/runner.go`: executes tool calls with per-step timeout (default 5 min) + permission checks + optional Docker isolation (argv-safe).
- `pkg/engine/checkpoint.go`: checkpoints saved during execution; daemon resumes interrupted goals on restart.

### Evaluator chain
`pkg/evaluator/evaluator.go` runs four evaluators in sequence per step:
1. **ToolResultEvaluator** — basic success/failure from `ToolResult.Success`.
2. **BuildResultEvaluator** — detects compile/build error patterns in command output.
3. **TestResultEvaluator** — detects test failure patterns.
4. **GoalCompletionEvaluator** — heuristic check based on step outcomes (not a separate LLM call).

Each returns one of: `success`, `partial_success`, `retry_required`, `fatal_failure` (defined in `pkg/execution/types.go`).

### Planner
`pkg/planner/planner.go` uses a lightweight template planner (1–2 tasks) with an LLM yes/no project-name prompt. Actual tool selection happens per-step in the engine. `pkg/workflow` provides DAG validation utilities used in tests only.

### Extensibility and tool loading
- `pkg/plugin/registry.go` + `pkg/plugin/builtin.go`: plugin system wires capability groups into tool registry at daemon startup.
- Default plugins: `coding` (filesystem, command, git), `devops` (ssh, http), `browser` (only when `--browser-port` is passed).
- Adding a new tool: implement `tools.Tool` interface (Name/Schema/Execute), register it in the relevant plugin's `Load()`, and add a `CheckTool` case in `pkg/permission/manager.go`.

### Safety, approvals, and isolation
- `pkg/permission/manager.go`: enforces policy for all six tools — `Allow`, `Deny`, or `RequireApproval`. Command `cwd`, git paths, HTTP URLs (SSRF guard), browser domains, and SSH always gated.
- `pkg/approval/service.go`: persists pending approvals; resolved interactively via `octa-agent approve/deny <id>`.
- `pkg/isolation/docker.go`: wraps tool args for Docker execution when `isolation.require_docker_for` lists the tool type.

### LLM providers
Configured via `llm.provider` in config. Supported values: `ollama` (default, no API key needed), `openai`, `claude`. The provider interface (`pkg/llm/provider.go`) exposes `Complete(ctx, messages)` — all planners and evaluators go through this single interface.

### Memory
- `pkg/memory/manager.go`: appends facts learned during execution to a per-goal store.
- `pkg/memory/semantic.go`: vector-based retrieval providing relevant past facts to the planner as context, improving replanning quality.

### Configuration that affects behavior
- Primary config: `~/.config/octaai/config.yaml` (created by `octa-agent init`).
- Key sections in `pkg/config/config.go`:
- `llm`: provider / model / base_url / api_key / temperature / max_tokens
- `safety`: allow_paths, allow_http_hosts, deny_commands, require_confirmation_for
- `engine`: max_loops, max_retries, enable_replan, enable_parallel
- `isolation`: enabled, docker (image/network/memory/cpu limits), require_docker_for
- `browser`: enabled, port, token, browser_domains
- `storage`: type, path (defaults to `~/.config/octaai/state.db`)
28 changes: 28 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Contributing to OctaAI

Thank you for contributing. This project is a Go CLI + daemon agent for autonomous goal execution.

## Development setup

```bash
make deps
make build
make test
```

## Code style

- Run `make fmt` and `make vet` before opening a PR.
- Keep changes focused; match existing package layout and naming.
- Add tests for safety-critical behavior (`pkg/permission`, `pkg/tools`).

## Pull requests

1. Fork and create a feature branch.
2. Ensure `make test` passes locally.
3. Describe behavior changes and security impact when touching tools or permissions.
4. Do not commit personal `config.yaml` files or SQLite databases.

## Reporting security issues

See [SECURITY.md](SECURITY.md). Do not open public issues for exploitable vulnerabilities.
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM golang:1.23-bookworm AS builder

RUN apt-get update && apt-get install -y gcc libc6-dev && rm -rf /var/lib/apt/lists/*

WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download

COPY . .
ENV CGO_ENABLED=1
RUN make build

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y ca-certificates git openssh-client && rm -rf /var/lib/apt/lists/*

COPY --from=builder /src/bin/octa-agentd /usr/local/bin/octa-agentd
COPY --from=builder /src/bin/octa-agent /usr/local/bin/octa-agent

RUN useradd -m -u 1000 octa
USER octa
WORKDIR /home/octa

ENV HOME=/home/octa
VOLUME ["/home/octa/.config/octaai"]

ENTRYPOINT ["octa-agentd"]
36 changes: 36 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Security Policy

OctaAI executes shell commands, filesystem operations, SSH, HTTP requests, and browser automation based on LLM output. Treat it as a privileged local agent.

## Supported versions

Security fixes are applied on the `master` branch.

## Reporting a vulnerability

Please report security issues privately to the repository maintainer rather than opening a public GitHub issue.

Include:

- Description of the vulnerability and impact
- Steps to reproduce
- Suggested fix (if any)

## Security configuration

Review `config.example.yaml` before running the daemon:

- `safety.allow_paths` — filesystem and command `cwd` boundaries
- `safety.deny_commands` — blocked shell command patterns (normalized matching)
- `safety.require_confirmation_for` — commands requiring human approval
- `safety.allow_http_hosts` — optional HTTP host allowlist for `http` and `git clone`
- `browser.token` — required WebSocket token when browser automation is enabled
- `browser.browser_domains` — allowed navigation domains for the browser tool
- `ssh.known_hosts_file` — required for SSH host-key verification

## Threat model notes

- The permission manager gates all six built-in tools.
- Docker isolation is opt-in and should be validated before relying on it in production.
- Browser WebSocket connections require a token and restricted origins.
- HTTP tool requests block private/link-local addresses by default (SSRF mitigation).
Loading
Loading