teapot-coding-agent 0.15.6 → 0.15.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +248 -0
- package/README.md +238 -245
- package/package.json +1 -1
- package/public/assets/{index-mKmKGRRj.css → index-CL7BIo-z.css} +1 -1
- package/public/assets/index-CXOcSpYs.js +28 -0
- package/public/assets/index-CXOcSpYs.js.map +1 -0
- package/public/assets/{shiki-BxccsPX4.js → shiki-C5KwscN-.js} +2 -2
- package/public/assets/{shiki-BxccsPX4.js.map → shiki-C5KwscN-.js.map} +1 -1
- package/public/index.html +2 -2
- package/public/assets/index-19jhnt7X.js +0 -28
- package/public/assets/index-19jhnt7X.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,301 +1,294 @@
|
|
|
1
1
|
# teapot 🫖
|
|
2
2
|
|
|
3
|
-
A lightweight harness for running
|
|
4
|
-
and lighter than existing harnesses. No TUI. One small web server, a browser
|
|
5
|
-
tab, and any number of long-running agents.
|
|
6
|
-
|
|
7
|
-
## Design principles
|
|
8
|
-
|
|
9
|
-
- **TypeScript + Node.js**, small runtime dependency set (`hono`, `openai`,
|
|
10
|
-
`@hono/node-server`, `ws`, `zod`, `@mozilla/readability` + `happy-dom` for
|
|
11
|
-
`read_url`). Frontend-only libraries (SolidJS, xterm.js, shiki) are
|
|
12
|
-
devDependencies — they're compiled into the static bundle under `public/`
|
|
13
|
-
and never touch the server's runtime install.
|
|
14
|
-
- **Idle cost ≈ 0**: no polling loops; everything is event-driven or driven by
|
|
15
|
-
one 15-second scheduler tick. Verified: master sits at ~0% CPU when idle.
|
|
16
|
-
- **No TUI** — Discord-style chat UI built with **SolidJS + Vite**
|
|
17
|
-
(`frontend/`, built to `public/`): agents as channels, events flowing as chat
|
|
18
|
-
messages, tool calls as compact embeds. Markdown is rendered by a hand-written,
|
|
19
|
-
XSS-safe renderer (`frontend/md.js`)
|
|
20
|
-
- **Integrated terminal** — humans get an interactive shell (xterm.js over
|
|
21
|
-
WebSocket) inside the selected agent's workspace: inspect what the agent
|
|
22
|
-
did, run tests, fix things alongside it. Zero native dependencies — the PTY
|
|
23
|
-
comes from util-linux `script` when available (colors, line editing,
|
|
24
|
-
ctrl+c), with a plain-pipe fallback elsewhere.
|
|
25
|
-
- **Human-readable persistence** — append-only JSONL event logs you can read
|
|
26
|
-
with `cat` / `jq`; goal & memory as plain Markdown files in git
|
|
27
|
-
|
|
28
|
-
## Quick start
|
|
29
|
-
|
|
30
|
-
Requires Node.js **>= 24** (TypeScript is executed natively in dev mode).
|
|
31
|
-
|
|
32
|
-
### Install globally from npm
|
|
3
|
+
**A lightweight harness for running multiple autonomous AI coding agents in parallel, from your browser.**
|
|
33
4
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# open http://localhost:7788 — the first-run wizard walks you through
|
|
38
|
-
# provider → API key → model → first agent (writes config.json for you)
|
|
39
|
-
```
|
|
5
|
+
> Try it in 5 minutes → [Quick start](#-quick-start) · Details live in the [Reference](#-reference) section
|
|
6
|
+
|
|
7
|
+
[日本語版はこちら](README.ja.md)
|
|
40
8
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🚀 Quick start
|
|
12
|
+
|
|
13
|
+
### 1. Install
|
|
14
|
+
|
|
15
|
+
Requires Node.js **24+**.
|
|
46
16
|
|
|
47
17
|
```sh
|
|
48
|
-
|
|
49
|
-
teapot --port 8080 # CLI flags: --port/-p, --config/-c
|
|
50
|
-
teapot ~/my-config.json # explicit config path
|
|
51
|
-
TEAPOT_PORT=8080 teapot # env overrides work as usual
|
|
18
|
+
npm install -g teapot-coding-agent
|
|
52
19
|
```
|
|
53
20
|
|
|
54
|
-
###
|
|
21
|
+
### 2. Write a config file
|
|
55
22
|
|
|
56
23
|
```sh
|
|
57
|
-
pnpm install
|
|
58
24
|
mkdir -p ~/.config/teapot-coding-agent
|
|
59
|
-
|
|
60
|
-
pnpm dev # or: pnpm build && pnpm start
|
|
61
|
-
# open http://localhost:7788
|
|
25
|
+
nano ~/.config/teapot-coding-agent/config.json
|
|
62
26
|
```
|
|
63
27
|
|
|
64
|
-
|
|
65
|
-
`~/.config/teapot-coding-agent/config.json` → `./teapot.config.json` (legacy).
|
|
66
|
-
Data (event logs) goes to `~/.local/share/teapot-coding-agent` by default.
|
|
67
|
-
Env overrides: `TEAPOT_PORT`, `TEAPOT_API_KEY`, `TEAPOT_BASE_URL`,
|
|
68
|
-
`TEAPOT_MODEL`, `TEAPOT_CONFIG_DIR`, `TEAPOT_DATA_DIR`.
|
|
28
|
+
**Minimal setup** (OpenRouter — other providers below):
|
|
69
29
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Agents are matched to named OpenAI-compatible providers:
|
|
73
|
-
|
|
74
|
-
```jsonc
|
|
30
|
+
```json
|
|
75
31
|
{
|
|
76
32
|
"providers": {
|
|
77
|
-
"openrouter": {
|
|
78
|
-
|
|
79
|
-
|
|
33
|
+
"openrouter": {
|
|
34
|
+
"baseUrl": "https://openrouter.ai/api/v1",
|
|
35
|
+
"apiKey": "sk-or-your-key",
|
|
36
|
+
"model": "anthropic/claude-sonnet-4"
|
|
37
|
+
}
|
|
80
38
|
},
|
|
81
39
|
"defaultProvider": "openrouter",
|
|
82
40
|
"agents": [
|
|
83
|
-
{ "id": "
|
|
84
|
-
{ "id": "beta", "workspace": "workspaces/beta", "provider": "local" }, // local model
|
|
85
|
-
{ "id": "gamma", "workspace": "workspaces/gamma", "provider": "openrouter",
|
|
86
|
-
"model": "anthropic/claude-sonnet-4" } // per-agent model
|
|
41
|
+
{ "id": "main", "workspace": "/home/you/my-project" }
|
|
87
42
|
]
|
|
88
43
|
}
|
|
89
44
|
```
|
|
90
45
|
|
|
91
|
-
|
|
92
|
-
first-run wizard and the settings modal ship quick-add presets for OpenRouter,
|
|
93
|
-
OrcaRouter, OpenAI and a local llama.cpp server.
|
|
46
|
+
Prefer copying a template? Grab [`teapot.config.example.json`](teapot.config.example.json).
|
|
94
47
|
|
|
95
|
-
|
|
96
|
-
automatically carry `HTTP-Referer` / `X-OpenRouter-Title` /
|
|
97
|
-
`X-OpenRouter-Categories: programming-app`, so teapot's usage shows up in
|
|
98
|
-
OpenRouter's public rankings & analytics — no config needed. Other providers
|
|
99
|
-
receive no extra headers.
|
|
100
|
-
|
|
101
|
-
## Architecture
|
|
48
|
+
### 3. Run
|
|
102
49
|
|
|
50
|
+
```sh
|
|
51
|
+
teapot
|
|
103
52
|
```
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
53
|
+
|
|
54
|
+
→ Open **http://localhost:7788**. That's it.
|
|
55
|
+
|
|
56
|
+
### 4. Use it
|
|
57
|
+
|
|
58
|
+
- Click `#main` in the left panel
|
|
59
|
+
- Type an instruction in the composer (e.g. "Fix this bug and make the tests pass")
|
|
60
|
+
- The agent reads/writes files, runs bash, and works on its own
|
|
61
|
+
|
|
62
|
+
| Action | How |
|
|
63
|
+
|---|---|
|
|
64
|
+
| Terminal | `t` |
|
|
65
|
+
| Right panel (goal/progress/runtime) | `d` |
|
|
66
|
+
| Command list | type `/` in the composer |
|
|
67
|
+
| Interrupt the agent | `Esc` |
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 🤔 What is this?
|
|
72
|
+
|
|
73
|
+
One line: **a server that hosts several autonomous coding agents over any OpenAI-compatible API, operated from a browser.**
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
├─ agent: android ── ~/projects/android-app
|
|
77
|
+
├─ agent: kernel ── ~/projects/kernel
|
|
78
|
+
└─ agent: web ── ~/projects/film-sims-web
|
|
108
79
|
```
|
|
109
80
|
|
|
110
|
-
- **
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
- **LLM** (`src/agent/llm.ts`): official `openai` npm client against any
|
|
128
|
-
OpenAI-compatible endpoint (OpenRouter, OrcaRouter, vLLM, llama.cpp server...). Model is config,
|
|
129
|
-
never hard-coded.
|
|
130
|
-
- **Tools** (`src/agent/tools.ts`): provider-agnostic JSON-schema function specs —
|
|
131
|
-
file work via `read_file` (numbered lines, grep-style `pattern` mode, negative
|
|
132
|
-
offsets), `write_file`, `edit_file` (unique replacement, `replace_all`,
|
|
133
|
-
whitespace-tolerant fallbacks with recovery hints), `apply_patch`
|
|
134
|
-
(Codex-style multi-file add/update/rename/delete patches, validated
|
|
135
|
-
atomically before writing) and `list_dir`; `bash` for git/builds/tests and
|
|
136
|
-
quick bulk transforms; `read_url` fetches a web page's readable content
|
|
137
|
-
(Mozilla Readability + happy-dom); plus meta tools `finish` / `ask_user` /
|
|
138
|
-
`report_progress` / `get_goal` / `set_goal` / `get_todo` / `set_todo` /
|
|
139
|
-
`read_memory` / `set_memory` / `get_feedback` / `add_feedback` /
|
|
140
|
-
`record_decision` / `get_decisions` / `list_skills`. Paths are confined to
|
|
141
|
-
the workspace (symlink-aware); bash runs detached in its own process group
|
|
142
|
-
and the whole group is SIGKILLed on timeout or shutdown.
|
|
143
|
-
- **Sub-agents** — an agent can `spawn_agent({task, context, persona?})` to
|
|
144
|
-
delegate work: `context:"fork"` starts the child with a byte-exact copy of
|
|
145
|
-
the parent's conversation prefix (provider prefix caches stay warm; stored
|
|
146
|
-
as a reference header in the child's log — parent history is never copied),
|
|
147
|
-
`"none"` starts fresh. Parents steer children via `message_agent`, check on
|
|
148
|
-
them with `list_children`, and can bulk-stop them (`stop_children`,
|
|
149
|
-
descendants included). Children mirror their activity into the parent's
|
|
150
|
-
timeline tagged `@<id>`, and their finish/error reports are delivered back
|
|
151
|
-
automatically. Nesting depth is capped by `maxSpawnDepth` (default 3).
|
|
152
|
-
Default personas: reviewer/tester/researcher/implementer (+ read-only
|
|
153
|
-
enforcement for researcher/reviewer), plus `@mention` spawning from the
|
|
154
|
-
composer.
|
|
155
|
-
- **Cache-friendly prompt design** — the system prompt is byte-identical on
|
|
156
|
-
every turn; session state (goal, memory, skills) is fetched via tools, never
|
|
157
|
-
injected. Combined with the append-only message history this keeps provider
|
|
158
|
-
prefix caches hot, so long sessions pay incremental input prices instead of
|
|
159
|
-
re-sending full context every turn.
|
|
160
|
-
- **Session storage** — everything teapot manages lives under
|
|
161
|
-
`<dataDir>/sessions/<sid>/` (`chat.jsonl`, `goal.md`, `todo.md`,
|
|
162
|
-
`memory.md`, `feedback.md`, `decisions.md`), so agent workspaces stay
|
|
163
|
-
clean. Each incarnation gets a fresh `<agentId>-<uuid>` directory (no
|
|
164
|
-
history leaks across projects); restarts reuse the latest one. Legacy
|
|
165
|
-
layouts are migrated automatically.
|
|
166
|
-
- **Goal / knowledge** — goal + memory are harness-managed and read/written
|
|
167
|
-
through tools (`get_goal` / `set_goal` / `read_memory` / `set_memory`);
|
|
168
|
-
`AGENTS.md` is optional project knowledge in the workspace root that agents
|
|
169
|
-
are told to read at session start. Nothing is seeded into your project.
|
|
170
|
-
- **Decisions & feedback** — `record_decision(decision, rationale,
|
|
171
|
-
alternatives?)` keeps the *why* behind choices in `decisions.md`
|
|
172
|
-
(compaction forgets reasoning, this file doesn't); corrections become
|
|
173
|
-
durable rules via `add_feedback(rule)` with repetition counts.
|
|
174
|
-
- **Task list** — `todo.md` in the session dir, editable by BOTH sides:
|
|
175
|
-
humans write it from the web UI (✅ tasks panel) or
|
|
176
|
-
`POST /api/agents/:id/todo {text, notify?}`, the agent reads and updates it
|
|
177
|
-
via `get_todo` / `set_todo`. Saving with notify queues a harness prompt so
|
|
178
|
-
the agent picks up changes at the next turn boundary.
|
|
179
|
-
|
|
180
|
-
### Web UI
|
|
181
|
-
|
|
182
|
-
- **Sessions as channels** — chat feed with live-streamed LLM output (💭
|
|
183
|
-
reasoning collapsible), tool calls/results as expandable embeds, progress
|
|
184
|
-
reports and state changes as dividers
|
|
185
|
-
- **Deep links** — every session has a URL (`http://localhost:7788/session/<id>`);
|
|
186
|
-
the last open session is remembered
|
|
187
|
-
- **Details panel** (`d`) — session info, model switcher (provider select +
|
|
188
|
-
OpenAI-compatible `GET /models` autocomplete; applies to the running
|
|
189
|
-
session from the next turn), controls, goal editor, progress, runtime stats
|
|
190
|
-
- **Terminal** (`t`) — interactive shell in the agent's workspace for humans,
|
|
191
|
-
rendered with xterm.js over WebSocket
|
|
192
|
-
- **Keyboard** — `↑`/`↓` switch sessions · `/` focus composer · `t` terminal ·
|
|
193
|
-
`d` panel · `esc` interrupt a running agent
|
|
194
|
-
- Realtime updates flow over WebSocket (`/api/ws`) with auto-reconnect
|
|
195
|
-
|
|
196
|
-
### Agent Skills
|
|
197
|
-
|
|
198
|
-
Skills are reusable playbooks the agent loads on demand — and writes itself,
|
|
199
|
-
so hard-won procedure knowledge survives sessions:
|
|
81
|
+
Each agent owns its own workspace and runs in parallel as a channel in a Discord-style UI. teapot is **not** a wrapper around Claude Code or Codex CLI — it implements its own agent loop (read_file / edit_file / apply_patch / bash / read_url / memory / skills).
|
|
82
|
+
|
|
83
|
+
### When would I use it?
|
|
84
|
+
|
|
85
|
+
- Long-running self-directed tasks like *"triage every bug in this repo and fix them until tests pass"*
|
|
86
|
+
- **Different models per project** — heavy work on Sonnet, code review on a local Qwen
|
|
87
|
+
- Watch progress, goals and task lists in the browser while you do something else
|
|
88
|
+
|
|
89
|
+
### How does it compare to CLI tools?
|
|
90
|
+
|
|
91
|
+
| | teapot | Claude Code & similar CLIs |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Form | resident server + web UI | interactive terminal |
|
|
94
|
+
| Multiple agents | ✅ parallel | usually one session |
|
|
95
|
+
| Mixed models | ✅ per agent | fixed |
|
|
96
|
+
| Long-running work | ✅ auto-restores from JSONL logs | manual session juggling |
|
|
97
|
+
| Scheduled tasks (cron) | ✅ 15-second tick | ❌ |
|
|
200
98
|
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 🔧 Features
|
|
102
|
+
|
|
103
|
+
<details>
|
|
104
|
+
<summary><b>Goals & autonomous loop</b></summary>
|
|
105
|
+
|
|
106
|
+
Set a goal and auto-continue keeps deciding whether to keep working after each round. Optionally attach a **verification contract** — when the agent calls `finish`, an independent auditor LLM checks the contract before "done" counts:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
goal: "Add account deletion to the auth module"
|
|
110
|
+
verify: "npm test passes with zero failures / README documents the endpoint"
|
|
111
|
+
↓ on finish
|
|
112
|
+
independent audit → approved ⇒ done · changes-required ⇒ gaps queued back to the worker
|
|
201
113
|
```
|
|
202
|
-
|
|
203
|
-
|
|
114
|
+
|
|
115
|
+
</details>
|
|
116
|
+
|
|
117
|
+
<details>
|
|
118
|
+
<summary><b>Sub-agents</b></summary>
|
|
119
|
+
|
|
120
|
+
Spawn sub-agents with `@persona <task>` mentions. Children can fork the parent conversation by reference, so provider prefix caches stay warm. `wait_children` parks the parent until a child settles; its report lands in the parent's timeline. Nesting cap via `maxSpawnDepth` (default 3).
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
<details>
|
|
125
|
+
<summary><b>Memory / task list / skills</b></summary>
|
|
126
|
+
|
|
127
|
+
- **memory.md** — durable notes per session (set_memory / get_memory)
|
|
128
|
+
- **todo.md** — checklist shared with the operator; supports surgical per-item updates
|
|
129
|
+
- **skills** — reusable playbooks stored globally (`~/.config/teapot-coding-agent/skills/`) or per workspace; workspace versions shadow global ones
|
|
130
|
+
|
|
131
|
+
</details>
|
|
132
|
+
|
|
133
|
+
<details>
|
|
134
|
+
<summary><b>Scheduled tasks (cron)</b></summary>
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{ "tasks": [{ "id": "nightly", "agent": "main",
|
|
138
|
+
"schedule": "0 3 * * *", "prompt": "Check git status and test results, report anything broken" }] }
|
|
204
139
|
```
|
|
205
140
|
|
|
206
|
-
|
|
141
|
+
</details>
|
|
142
|
+
|
|
143
|
+
<details>
|
|
144
|
+
<summary><b>Integrated terminal</b></summary>
|
|
145
|
+
|
|
146
|
+
Press `t` for an interactive shell inside the selected agent's workspace (xterm.js over WebSocket). The PTY comes from util-linux `script` when available, with a plain-pipe fallback — zero native dependencies.
|
|
147
|
+
|
|
148
|
+
</details>
|
|
149
|
+
|
|
150
|
+
<details>
|
|
151
|
+
<summary><b>File tree with previews & editing</b></summary>
|
|
152
|
+
|
|
153
|
+
Browse the workspace from 🗂 files in the right panel: shiki syntax highlighting for code, rendered preview for Markdown, inline playback for images/video/audio, and in-place text editing that saves back to disk (409 on write conflicts).
|
|
154
|
+
|
|
155
|
+
</details>
|
|
156
|
+
|
|
157
|
+
<details>
|
|
158
|
+
<summary><b>Context management</b></summary>
|
|
159
|
+
|
|
160
|
+
Past a token budget (default: 75% of the model's window, or 96k if unknown), older turns are summarized by the LLM so work continues. Goals, memory and skills live in separate files, so context survives restarts and next-day resumes.
|
|
161
|
+
|
|
162
|
+
</details>
|
|
163
|
+
|
|
207
164
|
---
|
|
208
|
-
|
|
209
|
-
|
|
165
|
+
|
|
166
|
+
## ⚠️ Security (please read)
|
|
167
|
+
|
|
168
|
+
Agents can run `bash` and rewrite files — including `rm` and `npm install`.
|
|
169
|
+
|
|
170
|
+
- Designed to run under a **dedicated Linux user**
|
|
171
|
+
- `git commit` before handing over a repo you care about
|
|
172
|
+
- File operations outside the workspace are rejected (`safeJoin`)
|
|
173
|
+
- teapot listens on localhost only by default. If you expose it, set **both** `--host 0.0.0.0` and an API token (`TEAPOT_API_TOKEN` env or config `password`):
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
TEAPOT_API_TOKEN=mysecret teapot --host 0.0.0.0 --port 7788
|
|
177
|
+
```
|
|
178
|
+
|
|
210
179
|
---
|
|
211
180
|
|
|
212
|
-
|
|
213
|
-
|
|
181
|
+
<a id="-reference"></a>
|
|
182
|
+
## 📖 Reference
|
|
183
|
+
|
|
184
|
+
<details>
|
|
185
|
+
<summary><b>Config reference</b></summary>
|
|
186
|
+
|
|
187
|
+
| Key | Default | Meaning |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `port` | 7788 | listen port (env `TEAPOT_PORT`, CLI `--port/-p`) |
|
|
190
|
+
| `host` | 127.0.0.1 | bind address (env `TEAPOT_HOST`, CLI `--host`; `0.0.0.0` exposes to LAN) |
|
|
191
|
+
| `dataDir` | `~/.local/share/teapot-coding-agent` | session logs etc. (env `TEAPOT_DATA_DIR`) |
|
|
192
|
+
| `providers.<name>` | — | `{ baseUrl, apiKey, model? }` OpenAI-compatible endpoint |
|
|
193
|
+
| `defaultProvider` | — | used when an agent doesn't specify one |
|
|
194
|
+
| `agents[].id` | required | URL key / display name |
|
|
195
|
+
| `agents[].workspace` | required | working directory |
|
|
196
|
+
| `agents[].provider` / `model` | inherited | per-agent overrides |
|
|
197
|
+
| `agents[].contextWindowTokens` | auto-inferred | model's real window (drives gauge + compaction) |
|
|
198
|
+
| `agents[].readOnly` | false | true blocks mutating tools |
|
|
199
|
+
| `agents[].autoContinue` | true | keep looping toward an active goal |
|
|
200
|
+
| `contextTokenBudget` | derived | compaction threshold in raw tokens; null/unset = 75% derivation (recommended) |
|
|
201
|
+
| `maxSpawnDepth` | 3 | sub-agent nesting limit |
|
|
202
|
+
| `password` | — | API auth (env `TEAPOT_API_TOKEN` wins) |
|
|
203
|
+
| `tasks[]` | — | cron tasks `{ id, agent, schedule, prompt }` |
|
|
204
|
+
|
|
205
|
+
Lookup order: CLI arg → `$TEAPOT_CONFIG` → `~/.config/teapot-coding-agent/config.json` → `./teapot.config.json`
|
|
206
|
+
|
|
207
|
+
</details>
|
|
208
|
+
|
|
209
|
+
<details>
|
|
210
|
+
<summary><b>Mixing providers</b></summary>
|
|
211
|
+
|
|
212
|
+
```jsonc
|
|
213
|
+
{
|
|
214
|
+
"providers": {
|
|
215
|
+
"openrouter": { "baseUrl": "https://openrouter.ai/api/v1", "apiKey": "sk-or-..." },
|
|
216
|
+
"local": { "baseUrl": "http://localhost:8080/v1", "apiKey": "llama.cpp" }
|
|
217
|
+
},
|
|
218
|
+
"defaultProvider": "openrouter",
|
|
219
|
+
"agents": [
|
|
220
|
+
{ "id": "coder", "workspace": "~/proj", "model": "anthropic/claude-sonnet-4" },
|
|
221
|
+
{ "id": "reviewer", "workspace": "~/proj", "provider": "local" }
|
|
222
|
+
]
|
|
223
|
+
}
|
|
214
224
|
```
|
|
215
225
|
|
|
216
|
-
-
|
|
217
|
-
|
|
218
|
-
- The agent calls `load_skill(name)` when a task matches and follows it.
|
|
219
|
-
- The agent calls `save_skill(name, description, content, files?)` to distill a
|
|
220
|
-
reusable procedure — `files` bundles helper scripts next to `SKILL.md`
|
|
221
|
-
(made executable automatically), and `load_skill` lists them as runnable
|
|
222
|
-
workspace paths. Available from the next turn, forever.
|
|
223
|
-
- Bundled skill: [`skills/qa-adversarial`](skills/qa-adversarial/SKILL.md) —
|
|
224
|
-
seven adversarial QA personas. Copy it into
|
|
225
|
-
`~/.config/teapot-coding-agent/skills/` (global) or a workspace's
|
|
226
|
-
`skills/` folder to enable it.
|
|
226
|
+
Anything OpenAI-compatible works: OpenRouter / OpenAI / Ollama / vLLM / llama.cpp.
|
|
227
|
+
Requests to openrouter.ai automatically carry app-attribution headers.
|
|
227
228
|
|
|
228
|
-
|
|
229
|
+
Model context windows are inferred from `/v1/models` at startup and drive the runtime gauge plus the derived compaction budget (manual override supported).
|
|
229
230
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
</details>
|
|
232
|
+
|
|
233
|
+
<details>
|
|
234
|
+
<summary><b>HTTP API</b></summary>
|
|
233
235
|
|
|
234
|
-
```json
|
|
235
|
-
{"v":1,"id":"e27","seq":27,"ts":"…","agent":"alpha","session":"alpha-9f3c21ab",
|
|
236
|
-
"branch":"br032sl","parent":"e26","type":"fork",
|
|
237
|
-
"data":{"fromSession":"alpha-9f3c21ab","fromBranch":"br0","fromEvent":"e26","newBranch":"br032sl"}}
|
|
238
236
|
```
|
|
237
|
+
GET /api/agents list
|
|
238
|
+
POST /api/agents create { workspace, id?, provider?, model?, start? }
|
|
239
|
+
GET /api/agents/:id/events?limit=300 events ( ?before=<id> pages upward )
|
|
240
|
+
GET /api/agents/:id/branches branch list
|
|
241
|
+
GET /api/agents/:id/file?path= fetch text file
|
|
242
|
+
PUT /api/agents/:id/file?path= save { content, baseContent? } (409 on conflict)
|
|
243
|
+
GET /api/agents/:id/raw?path= raw media bytes
|
|
244
|
+
GET /api/agents/:id/tree file tree
|
|
245
|
+
POST /api/agents/:id/prompt send { text, start? } → { promptId }
|
|
246
|
+
POST /api/agents/:id/prompt/cancel withdraw { promptId } (409 once delivered)
|
|
247
|
+
POST /api/agents/:id/goal { text?, status?, verify? }
|
|
248
|
+
POST /api/agents/:id/start|stop|fork|load
|
|
249
|
+
DELETE /api/agents/:id remove (logs kept)
|
|
250
|
+
GET /api/metrics RSS / heap / loadavg
|
|
251
|
+
WS /api/ws live event stream
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
All API routes honor optional bearer auth.
|
|
239
255
|
|
|
240
|
-
|
|
241
|
-
- a `fork` event records exactly where the new branch split off
|
|
242
|
-
- reconstruct any conversation: filter `branch === X` (or walk `parent` links
|
|
243
|
-
backwards across the fork point)
|
|
244
|
-
- event types: `session_start, fork, prompt, system_note, message, tool_call,
|
|
245
|
-
tool_result, state, progress, error, usage, goal`
|
|
246
|
-
- torn trailing lines are ignored on read → crash-safe append-only log
|
|
256
|
+
</details>
|
|
247
257
|
|
|
248
|
-
|
|
258
|
+
<details>
|
|
259
|
+
<summary><b>Session log (JSONL) format</b></summary>
|
|
249
260
|
|
|
250
|
-
|
|
261
|
+
Append-only JSONL you can read with `cat`/`jq`:
|
|
251
262
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
263
|
+
```jsonl
|
|
264
|
+
{"v":1,"id":"e1","type":"prompt","data":{"source":"user","text":"..."}}
|
|
265
|
+
{"v":1,"id":"e2","type":"tool_call","data":{"callId":"…","name":"bash","argsRaw":"…"}}
|
|
266
|
+
{"v":1,"id":"e3","type":"tool_result","data":{"callId":"…","ok":true,"durationMs":117}}
|
|
267
|
+
{"v":1,"id":"e4","type":"message","data":{"role":"assistant","content":"…"}}
|
|
268
|
+
```
|
|
256
269
|
|
|
257
|
-
|
|
270
|
+
Each event links to its parent, forks share the branch point, and `goal.md` / `memory.md` / `todo.md` live beside `chat.jsonl` under `sessions/<agent>-<uuid>/`.
|
|
258
271
|
|
|
259
|
-
|
|
260
|
-
master tick. Tasks run as prompts on **forked branches** by default so periodic
|
|
261
|
-
chatter never disturbs an agent's main line of work.
|
|
272
|
+
</details>
|
|
262
273
|
|
|
263
|
-
|
|
274
|
+
<details>
|
|
275
|
+
<summary><b>Development (from a checkout)</b></summary>
|
|
264
276
|
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
POST /api/agents/:id/goal {text, notify?} or {status}
|
|
272
|
-
POST /api/agents/:id/fork {} → new branch, same session log
|
|
273
|
-
POST /api/agents/:id/edit-prompt {eventId, text, tail: "discard"|"summarize"} → fork & resend
|
|
274
|
-
GET /api/agents/:id/events?limit&branch&session
|
|
275
|
-
GET /api/agents/:id/branches
|
|
276
|
-
GET /api/tasks scheduled tasks with computed next-fire times
|
|
277
|
-
GET /api/metrics master rss/heap/load + per-agent stats
|
|
278
|
-
GET /api/events SSE updates (push, no polling)
|
|
279
|
-
GET /brew 418 I'm a teapot (RFC 2324)
|
|
277
|
+
```sh
|
|
278
|
+
pnpm install
|
|
279
|
+
pnpm dev # run TypeScript natively
|
|
280
|
+
pnpm dev-web # Vite HMR (separate terminal)
|
|
281
|
+
pnpm test # node --test
|
|
282
|
+
pnpm build # tsc + vite build → dist/ + public/
|
|
280
283
|
```
|
|
281
284
|
|
|
282
|
-
|
|
285
|
+
Layout: `src/master.ts` (boot/cron/config) · `src/agent/` (loop/tools) ·
|
|
286
|
+
`src/server/api.ts` (Hono REST+WS) · `frontend/` (SolidJS) · `test/` (node:test)
|
|
283
287
|
|
|
284
|
-
|
|
285
|
-
subprocesses run in killable process groups with hard timeouts, and resource
|
|
286
|
-
limits (RLIMIT_* / cgroups) have a natural insertion point in
|
|
287
|
-
`src/agent/tools.ts:runShell`.
|
|
288
|
+
</details>
|
|
288
289
|
|
|
289
|
-
|
|
290
|
-
expose it beyond localhost, set `TEAPOT_API_TOKEN=<secret>` (env wins) or a
|
|
291
|
-
`password` field in the config — every `/api/*`
|
|
292
|
-
route then requires `Authorization: Bearer <secret>` (WebSocket handshakes
|
|
293
|
-
accept `?token=<secret>`). In the web UI, open
|
|
294
|
-
`http://host:7788/#token=<secret>` once; the token is stored locally and
|
|
295
|
-
attached automatically. The master survives agent crashes by
|
|
296
|
-
construction: agent errors never escape their own loop, and global handlers
|
|
297
|
-
keep the process alive.
|
|
290
|
+
---
|
|
298
291
|
|
|
299
292
|
## License
|
|
300
293
|
|
|
301
|
-
AGPL-3.0-or-later
|
|
294
|
+
AGPL-3.0-or-later — [LICENSE](LICENSE)
|