174 lines
10 KiB
Markdown
174 lines
10 KiB
Markdown
# AGENTS.md
|
|
Project-level context for AI agents working in this repository.
|
|
|
|
> **⚠️ IMPORTANT: All work must be done in THIS source directory (`~/src/ollie/`).**
|
|
> Never edit files under `~/.config/ollie/` — that is an install target.
|
|
> Changes made there are overwritten on the next `just install-data`.
|
|
> Edit source files here, then run `just` to build and install.
|
|
|
|
## Project Overview
|
|
Ollie is an AI agent runtime inspired by Plan 9: agent state and behaviors are exposed as files in a 9P namespace. Orchestration, scheduling, and UIs are external — shell scripts, editors, web apps. The core is minimal; capabilities come from composing scripts.
|
|
## Repository Layout
|
|
Monorepo with Git submodules. Each submodule has its own Go module (except `el` which is Elisp and `kde` which is C++/Qt).
|
|
```
|
|
ollie/ ← you are here
|
|
├── virtfs/ (Go module) Virtual filesystem EDSL (FsNodeDecl, BuildTree, Tree)
|
|
├── toolsrv/ (Go) Tool server client library (Conn, Dial)
|
|
├── cmd/
|
|
│ ├── olliesrv/ (Go) 9P server binary
|
|
│ │ └── internal/
|
|
│ │ ├── fs/ 9P namespace (everything in spec.go)
|
|
│ │ │ ├── spec.go Single source of truth — entire namespace + handlers
|
|
│ │ │ └── support.go Shared utilities (streamChat, stripMarkers, dispatch)
|
|
│ │ ├── agent/ Agent loop, history, hooks
|
|
│ │ ├── session/ Session lifecycle, persistence
|
|
│ │ ├── backend/ LLM backends (ollama, openai, anthropic, etc.)
|
|
│ │ └── bypass/ Sandbox bypass broker
|
|
│ ├── toolsrv/ (Go) Tool server binary (sandboxed execution)
|
|
│ │ └── internal/
|
|
│ │ ├── fs/ toolsrv 9P namespace (spec.go)
|
|
│ │ └── sandbox/ Landlock enforcement
|
|
│ ├── ollie-9p/ (Go) CLI client for the 9P namespace
|
|
│ └── ollie-remote/ (Go) Remote execution agent
|
|
├── tools/ (Go) Tool implementations:
|
|
│ └── lsp/ LSP bridge + cmd/ binaries
|
|
├── kde/ (C++/Qt6) KDE integration: GUI, Kate plugin, KRunner, tray
|
|
├── contrib/elisp (Elisp) Emacs frontend (ellie.el)
|
|
├── data/agents/ Agent config JSONs (loaded at runtime)
|
|
├── data/prompts/ System prompt templates (markdown)
|
|
├── data/tools/ Tool executables + .meta sidecar files
|
|
├── data/skills/ Domain knowledge modules (markdown)
|
|
├── sandbox/ Landlock sandbox config YAML
|
|
├── doc/ Architecture docs, usage guide
|
|
├── contrib/ Community scripts
|
|
└── experiments/ Trial notes
|
|
```
|
|
### Canonical source for prompts/tools/skills
|
|
|
|
> **⛔ DO NOT edit `~/.config/ollie/` directly — it is an install target. All changes go in this repo.**
|
|
|
|
Prompt and tool files live in `data/`. The `just install-data` target copies them to `~/.config/ollie/`.
|
|
| Location | Purpose | Deployed by |
|
|
|----------|---------|-------------|
|
|
| `data/prompts/`, `data/tools/` | Canonical source for all prompts, tools, and skills | `just install-data` |
|
|
| `data/skills/` | Domain knowledge modules (markdown) | `just install-data` |
|
|
| `kde/` | KDE-specific tool scripts (`gui_*`) | `just install-kde` |
|
|
## Build System
|
|
```bash
|
|
# Build and install everything:
|
|
just
|
|
# Individual build targets:
|
|
just ninep # olliesrv + ollie-9p
|
|
just toolsrv # tool server binary
|
|
just core # core Go packages
|
|
just kde # KDE integration (cmake with ~/.local prefix)
|
|
just lsp-tools # LSP tool binaries
|
|
# Install targets:
|
|
just install-data # agents, prompts, tools, skills → ~/.config/ollie/
|
|
just install-el # ellie.el → ~/.config/emacs/ellie/
|
|
# Test:
|
|
just test # run all tests
|
|
just test-core # core Go tests
|
|
just test-9p # 9p integration tests
|
|
# Lifecycle:
|
|
just uninstall # remove all installed files
|
|
just clean # remove build artifacts
|
|
```
|
|
Requires [just](https://github.com/casey/just): `cargo install just`
|
|
## Testing
|
|
```bash
|
|
# All Go tests (excludes cmd/ollie-remote which needs just to build):
|
|
go test $(go list ./... | grep -v cmd/ollie-remote)
|
|
# KDE has integration test scripts:
|
|
cd kde && ./test-e2e.sh
|
|
# ollie-remote requires the just build pipeline to resolve embedded deps:
|
|
just ollie-remote
|
|
just test
|
|
# or individually:
|
|
just test-remote
|
|
```
|
|
|
|
**Note on `cmd/ollie-remote`**: This package uses `//go:embed sandbox/default.yaml` and `//go:embed all:tools`. The embedded files are not in the source tree — `just ollie-remote` copies them in before building then cleans up. Running `go test ./...` will fail on this package. Use `just test-remote` or `go test $(go list ./... | grep -v cmd/ollie-remote)` instead.
|
|
## Language & Conventions
|
|
|
|
- **Go** (root module): Go 1.25+, standard library preferred, minimal dependencies.
|
|
- **C++20/Qt6/KF6** (kde): CMake build, dual Qt5/Qt6 support where noted.
|
|
- **Elisp** (el): single file `ellie.el`.
|
|
- **Tool scripts**: Python 3, Bash, or compiled binaries. Must be executable. Metadata lives in a `.meta` sidecar JSON file (see `data/tools/*.meta`).
|
|
### Code style
|
|
- Go: `gofmt`, short variable names, error returns (no panics), table-driven tests.
|
|
- Tool scripts: emit structured output (`STATUS=ok`, `STATUS=error`). Image/LSP tools return JSON content blocks.
|
|
- Prompts: markdown, concise, example-driven. Follow the pattern in existing `tools-*.md` files.
|
|
## Architecture (key concepts)
|
|
1. **One integration surface**: 9P filesystem. Sessions at `session/{sname}/agent/{aname}/`. All control via `ctl` (rdwr: write command, read response). Tools, skills, memory on physical filesystem via env vars.
|
|
2. **Two-process model**: Each session runs an `olliesrv` (the 9P namespace, agent loop, backends) and a per-session `toolsrv` (sandboxed tool execution). They communicate over a Unix socket using 9P. The toolsrv is spawned by olliesrv at session creation and has its own namespace (`/proc/new`, `/ctl`, `/tools`, etc.).
|
|
3. **Agent loop** (`cmd/olliesrv/internal/agent/loop.go`): Streaming LLM call → parse tool calls → dispatch to toolsrv → loop until no more tool calls or max steps.
|
|
4. **Tool dispatch**: ALL tools (including `reasoning_think`, `file_read`, `shell`) execute through the per-session toolsrv. The agent holds a `*toolsrv.Conn` (9P client) and calls `CallTool(name, args)` which writes to `proc/new` and reads the result. Tool registry is per-agent, keyed by agent ID in the protocol.
|
|
5. **Sandbox** (`cmd/toolsrv/internal/sandbox/`): Landlock-based. Config in `sandbox/*.yaml` defines filesystem access per profile. Escape via bypass broker (`cmd/olliesrv/internal/bypass/`).
|
|
6. **Backends** (`cmd/olliesrv/internal/backend/`): Ollama, OpenAI-compatible, Anthropic, Copilot, Kiro, Gemini. Selectable per-session.
|
|
7. **Prompts assembled at runtime**: Agent JSON `prompt` array specifies which prompt files to concatenate. The base system prompt is embedded in the binary and always prepended.
|
|
8. **9P namespace declared via virtfs EDSL**: The entire filesystem is a single recursive `FsNodeDecl` tree in `cmd/olliesrv/internal/fs/spec.go`, built by `virtfs.BuildTree()`. Every handler is an inline closure — no indirection. Same pattern in `cmd/toolsrv/internal/fs/spec.go`.
|
|
## Key Files
|
|
| What | Where |
|
|
|------|-------|
|
|
| 9P namespace (olliesrv) | `cmd/olliesrv/internal/fs/spec.go` |
|
|
| 9P namespace (toolsrv) | `cmd/toolsrv/internal/fs/spec.go` |
|
|
| virtfs EDSL | `virtfs/decl.go`, `virtfs/builder.go` |
|
|
| Agent loop | `cmd/olliesrv/internal/agent/loop.go` |
|
|
| Tool server binary | `cmd/toolsrv/` |
|
|
| Tool server client | `toolsrv/client9p.go` |
|
|
| Remote execution | `cmd/ollie-remote/` |
|
|
| Sandbox enforcement | `cmd/toolsrv/internal/sandbox/` |
|
|
| Session management | `cmd/olliesrv/internal/session/` |
|
|
| System prompt template | Embedded in binary (`cmd/olliesrv/internal/prompts/`) |
|
|
| Agent configs | `data/agents/*.json` |
|
|
| KDE GUI | `kde/gui/` |
|
|
| Kate plugin | `kde/kate/` |
|
|
## Environment
|
|
Config lives in `~/.config/ollie/env`. Key variables:
|
|
- `OLLIE_BACKEND` — default backend (ollama, openai, anthropic, copilot, kiro)
|
|
- `OLLIE_MODEL` — default model
|
|
- Tools live at `$XDG_CONFIG_HOME/ollie/tools` (default: `~/.config/ollie/tools`)
|
|
- Memory lives at `$XDG_CONFIG_HOME/ollie/memory` (default: `~/.config/ollie/memory`)
|
|
## Adding a new tool
|
|
|
|
### Script-based tool (Python/Bash)
|
|
1. Create an executable script in `data/tools/<name>`
|
|
2. Create `data/tools/<name>.meta` with JSON metadata:
|
|
```json
|
|
{"description":"...","prompt":"...","args":{...},"tier":"hot","readOnly":false}
|
|
```
|
|
3. Run `just install-data` to install
|
|
|
|
### Compiled tool (Go)
|
|
1. Create a package under `tools/<family>/cmd/<name>/main.go`
|
|
- Read JSON args from stdin, write result to stdout, exit 0/1
|
|
- Share library code in `tools/<family>/` (e.g. `tools/lsp/`)
|
|
2. Create `<name>.meta` alongside `main.go` in the same `cmd/<name>/` directory (same format as above)
|
|
3. Add a build target in the justfile that compiles to `{{cfg}}/tools/<name>` **and** installs the `.meta` file alongside it
|
|
4. Run `just` to build and install
|
|
|
|
The `.meta` file lives with the code that produces the tool, not in `data/tools/`. See the `lsp-tools` just target for the canonical pattern.
|
|
|
|
Both paths produce the same result: an executable + `.meta` in `$XDG_CONFIG_HOME/ollie/tools`.
|
|
The registry doesn't distinguish between scripts and binaries.
|
|
## Adding a new prompt
|
|
1. Write the markdown file in `data/prompts/`
|
|
2. If it should be loaded by default, reference it in `data/agents/default.json`
|
|
3. Run `just install-data` to install
|
|
## Submodule workflow
|
|
The only remaining submodule is `kde/`. For KDE:
|
|
```bash
|
|
# Update KDE submodule:
|
|
git submodule update --remote --merge kde
|
|
# Work in the KDE submodule:
|
|
cd kde
|
|
# ... make changes, commit ...
|
|
git push
|
|
cd ..
|
|
git add kde
|
|
git commit -m "update kde submodule"
|
|
```
|
|
Each submodule has its own remote at `ssh://lkn@lneely.de:44220/lkn/ollie-{name}.git`.
|
|
When cloning, use `--recurse-submodules` or run `git submodule update --init --recursive`.
|