aoaoe 0.1.0

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +250 -0
  3. package/dist/config.d.ts +10 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +149 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/dashboard.d.ts +4 -0
  8. package/dist/dashboard.d.ts.map +1 -0
  9. package/dist/dashboard.js +49 -0
  10. package/dist/dashboard.js.map +1 -0
  11. package/dist/executor.d.ts +26 -0
  12. package/dist/executor.d.ts.map +1 -0
  13. package/dist/executor.js +138 -0
  14. package/dist/executor.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +153 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/poller.d.ts +14 -0
  20. package/dist/poller.d.ts.map +1 -0
  21. package/dist/poller.js +167 -0
  22. package/dist/poller.js.map +1 -0
  23. package/dist/reasoner/claude-code.d.ts +15 -0
  24. package/dist/reasoner/claude-code.d.ts.map +1 -0
  25. package/dist/reasoner/claude-code.js +119 -0
  26. package/dist/reasoner/claude-code.js.map +1 -0
  27. package/dist/reasoner/index.d.ts +5 -0
  28. package/dist/reasoner/index.d.ts.map +1 -0
  29. package/dist/reasoner/index.js +15 -0
  30. package/dist/reasoner/index.js.map +1 -0
  31. package/dist/reasoner/opencode.d.ts +17 -0
  32. package/dist/reasoner/opencode.d.ts.map +1 -0
  33. package/dist/reasoner/opencode.js +193 -0
  34. package/dist/reasoner/opencode.js.map +1 -0
  35. package/dist/reasoner/prompt.d.ts +4 -0
  36. package/dist/reasoner/prompt.d.ts.map +1 -0
  37. package/dist/reasoner/prompt.js +68 -0
  38. package/dist/reasoner/prompt.js.map +1 -0
  39. package/dist/shell.d.ts +8 -0
  40. package/dist/shell.d.ts.map +1 -0
  41. package/dist/shell.js +27 -0
  42. package/dist/shell.js.map +1 -0
  43. package/dist/types.d.ts +85 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Keith Adler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,250 @@
1
+ <p align="center">
2
+ <h1 align="center">Agent of Agent of Empires (aoaoe)</h1>
3
+ <p align="center">
4
+ <a href="https://github.com/Talador12/agent-of-agent-of-empires/releases"><img src="https://img.shields.io/github/v/release/Talador12/agent-of-agent-of-empires" alt="GitHub release"></a>
5
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
6
+ </p>
7
+ </p>
8
+
9
+ An autonomous supervisor that manages [Agent of Empires](https://github.com/njbrake/agent-of-empires) sessions using [OpenCode](https://github.com/anomalyco/opencode) or [Claude Code](https://docs.anthropic.com/en/docs/claude-code) as the reasoning engine.
10
+
11
+ > Built on top of [Agent of Empires (AoE)](https://github.com/njbrake/agent-of-empires) by [Nate Brake](https://x.com/natebrake). AoE is the session manager -- aoaoe is the brain that drives it.
12
+
13
+ ## What is this?
14
+
15
+ [Agent of Empires (AoE)](https://github.com/njbrake/agent-of-empires) manages multiple AI coding agents (Claude Code, OpenCode, Gemini CLI, Codex, etc.) in tmux sessions with git worktrees. It is great at spawning and organizing agents, but someone still needs to watch the tmux panes and intervene when agents get stuck, ask questions, or finish their work.
16
+
17
+ **aoaoe** is that someone -- except it is an LLM. It polls your AoE sessions, reads agent output, decides when to act, and executes without you needing to be there.
18
+
19
+ This is the conductor, not the orchestra. AoE manages the sessions. The agents inside do the coding. aoaoe watches everything and steps in when needed.
20
+
21
+ ## Installation
22
+
23
+ **Prerequisites:**
24
+ - [tmux](https://github.com/tmux/tmux/wiki) (required)
25
+ - [agent-of-empires](https://github.com/njbrake/agent-of-empires) (`aoe` binary on PATH)
26
+ - One of:
27
+ - [OpenCode](https://github.com/anomalyco/opencode) (`opencode` binary on PATH)
28
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude` binary on PATH)
29
+
30
+ ```bash
31
+ # Quick install (Linux & macOS)
32
+ curl -fsSL \
33
+ https://raw.githubusercontent.com/Talador12/agent-of-agent-of-empires/main/scripts/install.sh \
34
+ | bash
35
+
36
+ # Homebrew
37
+ brew install Talador12/tap/aoaoe
38
+
39
+ # npm
40
+ npm install -g aoaoe
41
+
42
+ # Build from source
43
+ git clone https://github.com/Talador12/agent-of-agent-of-empires
44
+ cd agent-of-agent-of-empires && npm install && npm run build
45
+ npm link
46
+ ```
47
+
48
+ ## Quick Start
49
+
50
+ ```bash
51
+ # 1. Make sure you have AoE sessions running
52
+ aoe
53
+
54
+ # 2. Start the supervisor
55
+ aoaoe
56
+
57
+ # 3. Or specify a reasoning backend
58
+ aoaoe --reasoner opencode
59
+ aoaoe --reasoner claude-code
60
+ ```
61
+
62
+ ## How It Works
63
+
64
+ ```
65
+ ┌──────────────────────────────────────────────────────┐
66
+ │ aoaoe daemon │
67
+ │ │
68
+ │ ┌───────────┐ ┌──────────────┐ ┌───────────┐ │
69
+ │ │ Poller │──▶│ Reasoner │──▶│ Executor │ │
70
+ │ │ │ │ ┌──────────┐ │ │ │ │
71
+ │ │ aoe CLI + │ │ │ OpenCode │ │ │ tmux send │ │
72
+ │ │ tmux cap │ │ │ server │ │ │ keys, aoe │ │
73
+ │ │ │ │ ├──────────┤ │ │ CLI cmds │ │
74
+ │ │ │ │ │ Claude │ │ │ │ │
75
+ │ │ │ │ │ Code │ │ │ │ │
76
+ │ │ │ │ └──────────┘ │ │ │ │
77
+ │ └───────────┘ └──────────────┘ └───────────┘ │
78
+ │ │
79
+ │ ┌────────────────────────────────────────────────┐ │
80
+ │ │ Dashboard (optional) │ │
81
+ │ │ opencode web --port 4097 OR plain CLI │ │
82
+ │ └────────────────────────────────────────────────┘ │
83
+ └──────────────────────────────────────────────────────┘
84
+ │ │
85
+ ▼ ▼
86
+ AoE sessions LLM Provider
87
+ (tmux panes) (local or remote)
88
+ ```
89
+
90
+ ### Three Loops
91
+
92
+ **Poller** (every N seconds, configurable):
93
+ - Calls `aoe status --json` to get all session IDs, statuses, and tools
94
+ - For each active session: `tmux capture-pane -t aoe_<name>_<id8> -p -S -100`
95
+ - Diffs against previous capture to detect new output (ignores cursor blinks)
96
+ - Builds an observation payload: `{ sessions: [...], newOutput: {...} }`
97
+
98
+ **Reasoner** (on new observations):
99
+ - Sends observation to the configured LLM backend
100
+ - System prompt defines the supervisor role, policies, and available actions
101
+ - Receives back a structured JSON action decision
102
+ - Backend-agnostic: same observation format and action schema regardless of backend
103
+
104
+ **Executor** (on decisions):
105
+ - `tmux send-keys -t <session> "<text>" Enter` -- inject a prompt into an agent
106
+ - `aoe session start/stop/restart <id>` -- lifecycle management
107
+ - `aoe add <path> -t <title> -c <tool> -y` -- spawn new agents
108
+ - `aoe remove <id>` -- tear down agents
109
+
110
+ ### Supervisor Behavior
111
+
112
+ The LLM supervisor follows these policies:
113
+ - If an agent is stuck or idle too long, nudge it with context or a rephrased task
114
+ - If an agent asks a question and is waiting for input, answer it
115
+ - If an agent finishes its task, acknowledge and optionally assign follow-up work
116
+ - If a session crashes, restart it
117
+ - Do NOT micromanage -- only intervene when there is a clear problem or decision needed
118
+
119
+ ### Available Actions
120
+
121
+ The reasoner returns structured JSON decisions:
122
+
123
+ ```json
124
+ { "action": "send_input", "session": "<id>", "text": "<prompt>" }
125
+ { "action": "start_session", "session": "<id>" }
126
+ { "action": "stop_session", "session": "<id>" }
127
+ { "action": "create_agent", "path": "<dir>", "title": "<name>", "tool": "<agent>" }
128
+ { "action": "remove_agent", "session": "<id>" }
129
+ { "action": "wait" }
130
+ ```
131
+
132
+ ## Reasoning Backends
133
+
134
+ | Backend | Interface | Stateful | Model Flexibility |
135
+ |---------|-----------|----------|-------------------|
136
+ | **OpenCode** | `opencode serve` + `@opencode-ai/sdk` | Yes (long-running session) | Any provider via OpenCode config (Anthropic, OpenAI, Ollama, etc.) |
137
+ | **Claude Code** | `claude --print` subprocess | Via `--resume` | Anthropic models via Claude Code config |
138
+
139
+ ### OpenCode Backend
140
+
141
+ Runs `opencode serve` as a headless HTTP server. Uses the [OpenCode JS SDK](https://opencode.ai/docs/sdk/) to maintain a long-running session with full context. Supports structured JSON output natively. Works with any model provider configured in OpenCode (remote APIs or local models).
142
+
143
+ ### Claude Code Backend
144
+
145
+ Calls `claude --print --output-format json` as a subprocess. System prompt injected via `--append-system-prompt`. Session continuity via `--resume <session_id>`. Uses whatever model is configured in Claude Code (defaults to Anthropic models).
146
+
147
+ ## Configuration
148
+
149
+ `aoaoe.config.json`:
150
+ ```json
151
+ {
152
+ "reasoner": "opencode",
153
+ "pollIntervalMs": 10000,
154
+ "opencode": {
155
+ "port": 4097,
156
+ "model": "anthropic/claude-sonnet-4-20250514"
157
+ },
158
+ "claudeCode": {
159
+ "model": "claude-sonnet-4-20250514",
160
+ "yolo": true,
161
+ "resume": true
162
+ },
163
+ "aoe": {
164
+ "profile": "default"
165
+ },
166
+ "policies": {
167
+ "maxIdleBeforeNudgeMs": 120000,
168
+ "maxErrorsBeforeRestart": 3,
169
+ "autoAnswerPermissions": true
170
+ }
171
+ }
172
+ ```
173
+
174
+ | Field | Description | Default |
175
+ |-------|-------------|---------|
176
+ | `reasoner` | `"opencode"` or `"claude-code"` | `"opencode"` |
177
+ | `pollIntervalMs` | How often to check AoE sessions (ms) | `10000` |
178
+ | `opencode.port` | Port for `opencode serve` | `4097` |
179
+ | `opencode.model` | Model in `provider/model` format | (uses OpenCode default) |
180
+ | `claudeCode.model` | Anthropic model name | (uses Claude Code default) |
181
+ | `claudeCode.yolo` | Skip permissions in Claude Code | `true` |
182
+ | `claudeCode.resume` | Maintain session across calls | `true` |
183
+ | `aoe.profile` | AoE profile to monitor | `"default"` |
184
+ | `policies.maxIdleBeforeNudgeMs` | Nudge idle agents after this long | `120000` |
185
+ | `policies.maxErrorsBeforeRestart` | Restart after N consecutive errors | `3` |
186
+ | `policies.autoAnswerPermissions` | Auto-approve permission prompts | `true` |
187
+
188
+ ## AoE Integration Points
189
+
190
+ | Operation | Command | AoE Source |
191
+ |-----------|---------|------------|
192
+ | List sessions | `aoe list --json` | `cli/list.rs` |
193
+ | Session status | `aoe status --json` | `cli/status.rs` |
194
+ | Session details | `aoe session show <id> --json` | `cli/session.rs` |
195
+ | Capture output | `tmux capture-pane -t aoe_<title>_<id8> -p -S -N` | `tmux/session.rs` |
196
+ | Send input | `tmux send-keys -t aoe_<title>_<id8> "<text>" Enter` | standard tmux |
197
+ | Start/stop | `aoe session start/stop <id>` | `cli/session.rs` |
198
+ | Create agent | `aoe add <path> -t <title> -c <tool> [-w branch] -y` | `cli/add.rs` |
199
+ | Remove agent | `aoe remove <id>` | `cli/remove.rs` |
200
+
201
+ AoE sessions are named `aoe_<sanitized_title>_<first8_of_id>` in tmux. State is stored in `~/.agent-of-empires/profiles/<name>/sessions.json`.
202
+
203
+ ## Tech Stack
204
+
205
+ - **Runtime**: Node.js / TypeScript
206
+ - **LLM (OpenCode)**: `@opencode-ai/sdk` + `opencode serve`
207
+ - **LLM (Claude Code)**: `claude --print --output-format json` subprocess
208
+ - **AoE**: Child process calls to `aoe` CLI + `tmux`
209
+ - **Config**: JSON
210
+
211
+ ## Project Structure
212
+
213
+ ```
214
+ src/
215
+ index.ts # entry point, daemon loop
216
+ config.ts # config loader and validation
217
+ poller.ts # aoe CLI + tmux capture-pane wrapper
218
+ executor.ts # maps action decisions to shell commands
219
+ reasoner/
220
+ index.ts # common Reasoner interface
221
+ opencode.ts # OpenCode SDK backend
222
+ claude-code.ts # Claude Code CLI backend
223
+ types.ts # shared types (SessionSnapshot, Action, etc.)
224
+ ```
225
+
226
+ ## CLI Flags
227
+
228
+ ```
229
+ aoaoe [options]
230
+
231
+ --reasoner <opencode|claude-code> reasoning backend (default: opencode)
232
+ --poll-interval <ms> poll interval in ms (default: 10000)
233
+ --port <number> opencode server port (default: 4097)
234
+ --model <model> model to use
235
+ --profile <name> aoe profile (default: default)
236
+ --dry-run observe + reason but don't execute
237
+ --verbose, -v verbose logging
238
+ ```
239
+
240
+ Action history is persisted to `~/.aoaoe/actions.log` (JSONL format).
241
+
242
+ ## Related Projects
243
+
244
+ - [Agent of Empires](https://github.com/njbrake/agent-of-empires) -- the session manager this project controls
245
+ - [OpenCode](https://github.com/anomalyco/opencode) -- AI coding agent, used as a reasoning backend
246
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) -- Anthropic's CLI agent, used as a reasoning backend
247
+
248
+ ## License
249
+
250
+ MIT License -- see [LICENSE](LICENSE) for details.
@@ -0,0 +1,10 @@
1
+ import type { AoaoeConfig } from "./types.js";
2
+ export declare function loadConfig(overrides?: Partial<AoaoeConfig>): AoaoeConfig;
3
+ export declare function validateEnvironment(config: AoaoeConfig): Promise<void>;
4
+ export declare function parseCliArgs(argv: string[]): {
5
+ overrides: Partial<AoaoeConfig>;
6
+ help: boolean;
7
+ version: boolean;
8
+ };
9
+ export declare function printHelp(): void;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAC;AA2B/D,wBAAgB,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAqBxE;AAGD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E;AAkCD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAC5C,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB,CA2CA;AAED,wBAAgB,SAAS,SAexB"}
package/dist/config.js ADDED
@@ -0,0 +1,149 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ const DEFAULTS = {
4
+ reasoner: "opencode",
5
+ pollIntervalMs: 10_000,
6
+ opencode: {
7
+ port: 4097,
8
+ },
9
+ claudeCode: {
10
+ yolo: true,
11
+ resume: true,
12
+ },
13
+ aoe: {
14
+ profile: "default",
15
+ },
16
+ policies: {
17
+ maxIdleBeforeNudgeMs: 120_000,
18
+ maxErrorsBeforeRestart: 3,
19
+ autoAnswerPermissions: true,
20
+ },
21
+ captureLinesCount: 100,
22
+ verbose: false,
23
+ dryRun: false,
24
+ };
25
+ const CONFIG_NAMES = ["aoaoe.config.json", ".aoaoe.json"];
26
+ export function loadConfig(overrides) {
27
+ let fileConfig = {};
28
+ for (const name of CONFIG_NAMES) {
29
+ const p = resolve(process.cwd(), name);
30
+ if (existsSync(p)) {
31
+ try {
32
+ fileConfig = JSON.parse(readFileSync(p, "utf-8"));
33
+ log(`loaded config from ${p}`);
34
+ }
35
+ catch (e) {
36
+ console.error(`warning: failed to parse ${p}, using defaults`);
37
+ }
38
+ break;
39
+ }
40
+ }
41
+ return deepMerge(DEFAULTS, fileConfig, (overrides ?? {}));
42
+ }
43
+ // validate that required tools are on PATH
44
+ export async function validateEnvironment(config) {
45
+ const missing = [];
46
+ if (!(await which("aoe")))
47
+ missing.push("aoe (agent-of-empires)");
48
+ if (!(await which("tmux")))
49
+ missing.push("tmux");
50
+ if (config.reasoner === "opencode" && !(await which("opencode"))) {
51
+ missing.push("opencode");
52
+ }
53
+ if (config.reasoner === "claude-code" && !(await which("claude"))) {
54
+ missing.push("claude (Claude Code)");
55
+ }
56
+ if (missing.length > 0) {
57
+ throw new Error(`missing required tools: ${missing.join(", ")}`);
58
+ }
59
+ }
60
+ async function which(cmd) {
61
+ const { execFile } = await import("node:child_process");
62
+ const { promisify } = await import("node:util");
63
+ const exec = promisify(execFile);
64
+ try {
65
+ await exec("which", [cmd]);
66
+ return true;
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ function deepMerge(...objects) {
73
+ const result = {};
74
+ for (const obj of objects) {
75
+ for (const [key, val] of Object.entries(obj)) {
76
+ if (val !== undefined && val !== null) {
77
+ if (typeof val === "object" && !Array.isArray(val) && typeof result[key] === "object") {
78
+ result[key] = deepMerge(result[key], val);
79
+ }
80
+ else {
81
+ result[key] = val;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ return result;
87
+ }
88
+ function log(msg) {
89
+ console.error(`[config] ${msg}`);
90
+ }
91
+ export function parseCliArgs(argv) {
92
+ const overrides = {};
93
+ let help = false;
94
+ let version = false;
95
+ for (let i = 2; i < argv.length; i++) {
96
+ const arg = argv[i];
97
+ switch (arg) {
98
+ case "--reasoner":
99
+ overrides.reasoner = argv[++i];
100
+ break;
101
+ case "--poll-interval":
102
+ overrides.pollIntervalMs = parseInt(argv[++i], 10);
103
+ break;
104
+ case "--port":
105
+ overrides.opencode = { ...overrides.opencode, port: parseInt(argv[++i], 10) };
106
+ break;
107
+ case "--model":
108
+ // applies to whichever backend is selected
109
+ overrides.opencode = { ...overrides.opencode, model: argv[++i] };
110
+ overrides.claudeCode = { ...overrides.claudeCode, model: argv[i] };
111
+ break;
112
+ case "--profile":
113
+ overrides.aoe = { profile: argv[++i] };
114
+ break;
115
+ case "--verbose":
116
+ case "-v":
117
+ overrides.verbose = true;
118
+ break;
119
+ case "--dry-run":
120
+ overrides.dryRun = true;
121
+ break;
122
+ case "--help":
123
+ case "-h":
124
+ help = true;
125
+ break;
126
+ case "--version":
127
+ version = true;
128
+ break;
129
+ }
130
+ }
131
+ return { overrides, help, version };
132
+ }
133
+ export function printHelp() {
134
+ console.log(`aoaoe - autonomous supervisor for agent-of-empires sessions
135
+
136
+ usage: aoaoe [options]
137
+
138
+ options:
139
+ --reasoner <opencode|claude-code> reasoning backend (default: opencode)
140
+ --poll-interval <ms> poll interval in ms (default: 10000)
141
+ --port <number> opencode server port (default: 4097)
142
+ --model <model> model to use
143
+ --profile <name> aoe profile (default: default)
144
+ --dry-run observe + reason but don't execute
145
+ --verbose, -v verbose logging
146
+ --help, -h show this help
147
+ --version show version`);
148
+ }
149
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Observation, AoaoeConfig } from "./types.js";
2
+ import type { ActionLogEntry } from "./executor.js";
3
+ export declare function printDashboard(obs: Observation, recentActions: ActionLogEntry[], pollCount: number, config: AoaoeConfig): void;
4
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAYpD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,aAAa,EAAE,cAAc,EAAE,EAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAClB,IAAI,CAyCN"}
@@ -0,0 +1,49 @@
1
+ const STATUS_ICONS = {
2
+ working: "~",
3
+ idle: ".",
4
+ waiting: "?",
5
+ done: "+",
6
+ error: "!",
7
+ stopped: "x",
8
+ };
9
+ // print a compact dashboard summary every dashboardInterval polls
10
+ export function printDashboard(obs, recentActions, pollCount, config) {
11
+ const sep = "-".repeat(72);
12
+ const lines = [];
13
+ lines.push(sep);
14
+ lines.push(` aoaoe dashboard | poll #${pollCount} | ${new Date().toLocaleTimeString()}`);
15
+ if (config.dryRun)
16
+ lines.push(" ** DRY RUN **");
17
+ lines.push(sep);
18
+ // session table
19
+ if (obs.sessions.length === 0) {
20
+ lines.push(" no active sessions");
21
+ }
22
+ else {
23
+ lines.push(" status | tool | title | id");
24
+ lines.push(" " + "-".repeat(68));
25
+ for (const snap of obs.sessions) {
26
+ const s = snap.session;
27
+ const icon = STATUS_ICONS[s.status] ?? "?";
28
+ const tool = s.tool.padEnd(10).slice(0, 10);
29
+ const title = s.title.padEnd(20).slice(0, 20);
30
+ const id = s.id.slice(0, 8);
31
+ lines.push(` ${icon} | ${tool} | ${title} | ${id}`);
32
+ }
33
+ }
34
+ // recent actions (last 5 non-wait)
35
+ const meaningful = recentActions.filter(e => e.action.action !== "wait");
36
+ if (meaningful.length > 0) {
37
+ lines.push("");
38
+ lines.push(" recent actions:");
39
+ for (const entry of meaningful.slice(-5)) {
40
+ const ts = new Date(entry.timestamp).toLocaleTimeString();
41
+ const icon = entry.success ? "+" : "!";
42
+ lines.push(` [${ts}] ${icon} ${entry.action.action}: ${entry.detail}`);
43
+ }
44
+ }
45
+ lines.push(sep);
46
+ lines.push("");
47
+ console.error(lines.join("\n"));
48
+ }
49
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { Action, AoaoeConfig, SessionSnapshot } from "./types.js";
2
+ export declare class Executor {
3
+ private config;
4
+ private actionLog;
5
+ private recentActions;
6
+ constructor(config: AoaoeConfig);
7
+ execute(actions: Action[], snapshots: SessionSnapshot[]): Promise<ActionLogEntry[]>;
8
+ private executeOne;
9
+ private sendInput;
10
+ private startSession;
11
+ private stopSession;
12
+ private createAgent;
13
+ private removeAgent;
14
+ private resolveTmuxName;
15
+ private isRateLimited;
16
+ private markAction;
17
+ private logAction;
18
+ getRecentLog(n?: number): ActionLogEntry[];
19
+ }
20
+ export interface ActionLogEntry {
21
+ timestamp: number;
22
+ action: Action;
23
+ success: boolean;
24
+ detail: string;
25
+ }
26
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKvE,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,aAAa,CAAkC;gBAE3C,MAAM,EAAE,WAAW;IAMzB,OAAO,CACX,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,cAAc,EAAE,CAAC;YAoBd,UAAU;YA4BV,SAAS;YAmCT,YAAY;YAWZ,WAAW;YAWX,WAAW;YAeX,WAAW;IAWzB,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,SAAS;IAwBjB,YAAY,CAAC,CAAC,SAAK,GAAG,cAAc,EAAE;CAGvC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB"}