aoaoe 0.50.0 → 0.51.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.
- package/dist/chat.js +10 -4
- package/dist/config.d.ts +2 -0
- package/dist/config.js +10 -2
- package/dist/console.js +5 -2
- package/dist/context.js +4 -2
- package/dist/executor.js +5 -2
- package/dist/index.js +88 -3
- package/dist/init.js +4 -2
- package/dist/poller.js +7 -3
- package/package.json +1 -1
package/dist/chat.js
CHANGED
|
@@ -53,8 +53,9 @@ function main() {
|
|
|
53
53
|
lastSize = currSize;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
catch {
|
|
56
|
+
catch (e) {
|
|
57
57
|
// file may be truncated or removed — reset so we pick up from start of new file
|
|
58
|
+
console.error(`[chat] conversation log read failed: ${e}`);
|
|
58
59
|
lastSize = 0;
|
|
59
60
|
}
|
|
60
61
|
};
|
|
@@ -341,7 +342,8 @@ async function captureTmuxPane(tmuxName) {
|
|
|
341
342
|
const result = await exec("tmux", ["capture-pane", "-t", tmuxName, "-p", "-S", "-100"], 5_000);
|
|
342
343
|
return result.exitCode === 0 ? result.stdout : null;
|
|
343
344
|
}
|
|
344
|
-
catch {
|
|
345
|
+
catch (e) {
|
|
346
|
+
console.error(`[chat] tmux capture-pane failed for ${tmuxName}: ${e}`);
|
|
345
347
|
return null;
|
|
346
348
|
}
|
|
347
349
|
}
|
|
@@ -437,7 +439,9 @@ function appendToInput(msg) {
|
|
|
437
439
|
try {
|
|
438
440
|
appendFileSync(INPUT_FILE, msg + "\n");
|
|
439
441
|
}
|
|
440
|
-
catch {
|
|
442
|
+
catch (e) {
|
|
443
|
+
console.error(`[chat] pending-input write failed: ${e}`);
|
|
444
|
+
}
|
|
441
445
|
}
|
|
442
446
|
function replayLog() {
|
|
443
447
|
if (!existsSync(CONVO_LOG))
|
|
@@ -449,7 +453,9 @@ function replayLog() {
|
|
|
449
453
|
console.log(`${DIM}--- end of history ---${RESET}\n`);
|
|
450
454
|
}
|
|
451
455
|
}
|
|
452
|
-
catch {
|
|
456
|
+
catch (e) {
|
|
457
|
+
console.error(`[chat] conversation log replay failed: ${e}`);
|
|
458
|
+
}
|
|
453
459
|
}
|
|
454
460
|
export function colorize(text) {
|
|
455
461
|
// first pass: colorize tick separator lines (──── tick #N ────)
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -245,7 +245,7 @@ export function parseCliArgs(argv) {
|
|
|
245
245
|
let initForce = false;
|
|
246
246
|
let runTaskCli = false;
|
|
247
247
|
let registerTitle;
|
|
248
|
-
const defaults = { overrides, help: false, version: false, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, runInit: false, initForce: false, runTaskCli: false };
|
|
248
|
+
const defaults = { overrides, help: false, version: false, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: false, runInit: false, initForce: false, runTaskCli: false };
|
|
249
249
|
// check for subcommand as first non-flag arg
|
|
250
250
|
if (argv[2] === "test-context") {
|
|
251
251
|
return { ...defaults, testContext: true };
|
|
@@ -262,6 +262,12 @@ export function parseCliArgs(argv) {
|
|
|
262
262
|
if (argv[2] === "history") {
|
|
263
263
|
return { ...defaults, showHistory: true };
|
|
264
264
|
}
|
|
265
|
+
if (argv[2] === "status") {
|
|
266
|
+
return { ...defaults, showStatus: true };
|
|
267
|
+
}
|
|
268
|
+
if (argv[2] === "config") {
|
|
269
|
+
return { ...defaults, showConfig: true };
|
|
270
|
+
}
|
|
265
271
|
if (argv[2] === "init") {
|
|
266
272
|
const force = argv.includes("--force") || argv.includes("-f");
|
|
267
273
|
return { ...defaults, runInit: true, initForce: force };
|
|
@@ -351,7 +357,7 @@ export function parseCliArgs(argv) {
|
|
|
351
357
|
break;
|
|
352
358
|
}
|
|
353
359
|
}
|
|
354
|
-
return { overrides, help, version, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, runInit: false, initForce: false, runTaskCli: false };
|
|
360
|
+
return { overrides, help, version, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: false, runInit: false, initForce: false, runTaskCli: false };
|
|
355
361
|
}
|
|
356
362
|
export function printHelp() {
|
|
357
363
|
console.log(`aoaoe - autonomous supervisor for agent-of-empires sessions
|
|
@@ -367,6 +373,8 @@ getting started:
|
|
|
367
373
|
commands:
|
|
368
374
|
init detect tools + sessions, import history, generate config
|
|
369
375
|
(none) start the supervisor daemon (interactive TUI)
|
|
376
|
+
status quick daemon health check (is it running? what's it doing?)
|
|
377
|
+
config show the effective resolved config (defaults + file)
|
|
370
378
|
task manage tasks and sessions (list, start, stop, new, rm, edit)
|
|
371
379
|
tasks show task progress (from aoaoe.tasks.json)
|
|
372
380
|
history review recent actions (from ~/.aoaoe/actions.log)
|
package/dist/console.js
CHANGED
|
@@ -91,7 +91,8 @@ export class ReasonerConsole {
|
|
|
91
91
|
const st = statSync(INPUT_FILE);
|
|
92
92
|
return st.size > 0;
|
|
93
93
|
}
|
|
94
|
-
catch {
|
|
94
|
+
catch (e) {
|
|
95
|
+
console.error(`[console] pending-input size check failed: ${e}`);
|
|
95
96
|
return false;
|
|
96
97
|
}
|
|
97
98
|
}
|
|
@@ -133,7 +134,9 @@ export class ReasonerConsole {
|
|
|
133
134
|
try {
|
|
134
135
|
appendFileSync(CONVO_LOG, line + "\n");
|
|
135
136
|
}
|
|
136
|
-
catch {
|
|
137
|
+
catch (e) {
|
|
138
|
+
console.error(`[console] conversation log write failed: ${e}`);
|
|
139
|
+
}
|
|
137
140
|
// in inline mode, also print colorized output to stderr
|
|
138
141
|
if (this.inlineMode) {
|
|
139
142
|
process.stderr.write(colorizeConsoleLine(line) + "\n");
|
package/dist/context.js
CHANGED
|
@@ -78,7 +78,8 @@ export function readContextFile(filePath) {
|
|
|
78
78
|
evictCache();
|
|
79
79
|
return content;
|
|
80
80
|
}
|
|
81
|
-
catch {
|
|
81
|
+
catch (e) {
|
|
82
|
+
console.error(`[context] context file read failed for ${filePath}: ${e}`);
|
|
82
83
|
return "";
|
|
83
84
|
}
|
|
84
85
|
}
|
|
@@ -109,8 +110,9 @@ export function discoverContextFiles(dir) {
|
|
|
109
110
|
seenInodes.add(inodeKey);
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
|
-
catch {
|
|
113
|
+
catch (e) {
|
|
113
114
|
// stat failed — still add by path to avoid silently dropping
|
|
115
|
+
console.error(`[context] inode de-dup stat failed for ${resolved}: ${e}`);
|
|
114
116
|
}
|
|
115
117
|
seenPaths.add(resolved);
|
|
116
118
|
found.push(filePath);
|
package/dist/executor.js
CHANGED
|
@@ -164,7 +164,8 @@ export class Executor {
|
|
|
164
164
|
return this.logAction({ action: "create_agent", path, title, tool }, false, `path is not a directory: ${path}`);
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
catch {
|
|
167
|
+
catch (e) {
|
|
168
|
+
console.error(`[executor] statSync failed for create_agent path ${path}: ${e}`);
|
|
168
169
|
return this.logAction({ action: "create_agent", path, title, tool }, false, `cannot stat path: ${path}`);
|
|
169
170
|
}
|
|
170
171
|
// validate tool name
|
|
@@ -281,7 +282,9 @@ export class Executor {
|
|
|
281
282
|
this.rotateLogIfNeeded();
|
|
282
283
|
appendFileSync(LOG_FILE, JSON.stringify(entry) + "\n");
|
|
283
284
|
}
|
|
284
|
-
catch {
|
|
285
|
+
catch (e) {
|
|
286
|
+
console.error(`[executor] action log write failed: ${e}`);
|
|
287
|
+
} // best-effort, don't crash the daemon
|
|
285
288
|
}
|
|
286
289
|
return entry;
|
|
287
290
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loadConfig, validateEnvironment, parseCliArgs, printHelp, configFileExists } from "./config.js";
|
|
2
|
+
import { loadConfig, validateEnvironment, parseCliArgs, printHelp, configFileExists, findConfigFile } from "./config.js";
|
|
3
3
|
import { Poller, computeTmuxName } from "./poller.js";
|
|
4
4
|
import { createReasoner } from "./reasoner/index.js";
|
|
5
5
|
import { Executor } from "./executor.js";
|
|
6
6
|
import { printDashboard } from "./dashboard.js";
|
|
7
7
|
import { InputReader } from "./input.js";
|
|
8
8
|
import { ReasonerConsole } from "./console.js";
|
|
9
|
-
import { writeState, buildSessionStates, checkInterrupt, clearInterrupt, cleanupState, acquireLock } from "./daemon-state.js";
|
|
9
|
+
import { writeState, buildSessionStates, checkInterrupt, clearInterrupt, cleanupState, acquireLock, readState } from "./daemon-state.js";
|
|
10
10
|
import { formatSessionSummaries, formatActionDetail, formatPlainEnglishAction, narrateObservation, summarizeRecentActions, friendlyError } from "./console.js";
|
|
11
11
|
import { loadGlobalContext, resolveProjectDirWithSource, discoverContextFiles, loadSessionContext } from "./context.js";
|
|
12
12
|
import { tick as loopTick } from "./loop.js";
|
|
@@ -16,6 +16,7 @@ import { classifyMessages, formatUserMessages, buildReceipts, shouldSkipSleep, h
|
|
|
16
16
|
import { TaskManager, loadTaskDefinitions, loadTaskState, formatTaskTable } from "./task-manager.js";
|
|
17
17
|
import { runTaskCli, handleTaskSlashCommand } from "./task-cli.js";
|
|
18
18
|
import { TUI } from "./tui.js";
|
|
19
|
+
import { isDaemonRunningFromState } from "./chat.js";
|
|
19
20
|
import { actionSession, actionDetail } from "./types.js";
|
|
20
21
|
import { YELLOW, GREEN, DIM, BOLD, RED, RESET } from "./colors.js";
|
|
21
22
|
import { readFileSync, existsSync, statSync, mkdirSync, writeFileSync, chmodSync } from "node:fs";
|
|
@@ -26,7 +27,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
26
27
|
const AOAOE_DIR = join(homedir(), ".aoaoe"); // watch dir for wakeable sleep
|
|
27
28
|
const INPUT_FILE = join(AOAOE_DIR, "pending-input.txt"); // file IPC from chat.ts
|
|
28
29
|
async function main() {
|
|
29
|
-
const { overrides, help, version, register, testContext: isTestContext, runTest, showTasks, showHistory, runInit, initForce, runTaskCli: isTaskCli, registerTitle } = parseCliArgs(process.argv);
|
|
30
|
+
const { overrides, help, version, register, testContext: isTestContext, runTest, showTasks, showHistory, showStatus, showConfig, runInit, initForce, runTaskCli: isTaskCli, registerTitle } = parseCliArgs(process.argv);
|
|
30
31
|
if (help) {
|
|
31
32
|
printHelp();
|
|
32
33
|
process.exit(0);
|
|
@@ -66,6 +67,16 @@ async function main() {
|
|
|
66
67
|
await showActionHistory();
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
70
|
+
// `aoaoe status` -- quick one-shot daemon health check
|
|
71
|
+
if (showStatus) {
|
|
72
|
+
showDaemonStatus();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// `aoaoe config` -- show effective resolved config
|
|
76
|
+
if (showConfig) {
|
|
77
|
+
showEffectiveConfig();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
69
80
|
// `aoaoe task` -- task management CLI
|
|
70
81
|
if (isTaskCli) {
|
|
71
82
|
await runTaskCli(process.argv);
|
|
@@ -1101,6 +1112,80 @@ async function runIntegrationTest() {
|
|
|
1101
1112
|
// the integration test is a self-contained script that runs main() on import
|
|
1102
1113
|
await import(testModule);
|
|
1103
1114
|
}
|
|
1115
|
+
// `aoaoe status` -- quick one-shot health check: is the daemon running? what's it doing?
|
|
1116
|
+
function showDaemonStatus() {
|
|
1117
|
+
const state = readState();
|
|
1118
|
+
const running = isDaemonRunningFromState(state);
|
|
1119
|
+
const pkg = readPkgVersion();
|
|
1120
|
+
console.log("");
|
|
1121
|
+
console.log(` aoaoe${pkg ? ` v${pkg}` : ""} — daemon status`);
|
|
1122
|
+
console.log(` ${"─".repeat(50)}`);
|
|
1123
|
+
if (!running || !state) {
|
|
1124
|
+
console.log(` ${RED}●${RESET} daemon is ${BOLD}not running${RESET}`);
|
|
1125
|
+
const configPath = findConfigFile();
|
|
1126
|
+
console.log(` config: ${configPath ?? "none found (run 'aoaoe init')"}`);
|
|
1127
|
+
console.log("");
|
|
1128
|
+
console.log(" start with: aoaoe");
|
|
1129
|
+
console.log(" or observe: aoaoe --observe");
|
|
1130
|
+
console.log("");
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
// daemon is running — show details
|
|
1134
|
+
const elapsed = Date.now() - state.phaseStartedAt;
|
|
1135
|
+
const elapsedStr = elapsed < 60_000 ? `${Math.floor(elapsed / 1000)}s` : `${Math.floor(elapsed / 60_000)}m`;
|
|
1136
|
+
const phaseIcon = state.phase === "sleeping" ? `${DIM}○${RESET}` :
|
|
1137
|
+
state.phase === "reasoning" ? `${YELLOW}●${RESET}` :
|
|
1138
|
+
state.phase === "executing" ? `${GREEN}●${RESET}` :
|
|
1139
|
+
state.phase === "polling" ? `${YELLOW}○${RESET}` :
|
|
1140
|
+
`${RED}●${RESET}`;
|
|
1141
|
+
console.log(` ${GREEN}●${RESET} daemon is ${BOLD}running${RESET} (poll #${state.pollCount})`);
|
|
1142
|
+
console.log(` ${phaseIcon} phase: ${state.phase} (${elapsedStr})`);
|
|
1143
|
+
if (state.paused)
|
|
1144
|
+
console.log(` ${YELLOW}${BOLD} PAUSED${RESET}`);
|
|
1145
|
+
console.log(` poll interval: ${state.pollIntervalMs / 1000}s`);
|
|
1146
|
+
if (state.nextTickAt > Date.now()) {
|
|
1147
|
+
const countdown = Math.ceil((state.nextTickAt - Date.now()) / 1000);
|
|
1148
|
+
console.log(` next tick: ${countdown}s`);
|
|
1149
|
+
}
|
|
1150
|
+
console.log("");
|
|
1151
|
+
// sessions
|
|
1152
|
+
if (state.sessions.length === 0) {
|
|
1153
|
+
console.log(" no active sessions");
|
|
1154
|
+
}
|
|
1155
|
+
else {
|
|
1156
|
+
console.log(` ${state.sessions.length} session(s):`);
|
|
1157
|
+
for (const s of state.sessions) {
|
|
1158
|
+
const statusIcon = s.status === "working" || s.status === "running" ? `${GREEN}●${RESET}` :
|
|
1159
|
+
s.status === "idle" ? `${DIM}○${RESET}` :
|
|
1160
|
+
s.status === "error" ? `${RED}●${RESET}` :
|
|
1161
|
+
s.status === "done" ? `${GREEN}✓${RESET}` :
|
|
1162
|
+
`${DIM}?${RESET}`;
|
|
1163
|
+
const userTag = s.userActive ? ` ${DIM}(user active)${RESET}` : "";
|
|
1164
|
+
const taskTag = s.currentTask ? ` — ${DIM}${s.currentTask.slice(0, 50)}${RESET}` : "";
|
|
1165
|
+
console.log(` ${statusIcon} ${BOLD}${s.title}${RESET} (${s.tool}) ${s.status}${userTag}${taskTag}`);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
console.log("");
|
|
1169
|
+
}
|
|
1170
|
+
// `aoaoe config` -- show the effective resolved config (defaults + file + any notes)
|
|
1171
|
+
function showEffectiveConfig() {
|
|
1172
|
+
const configPath = findConfigFile();
|
|
1173
|
+
const configResult = loadConfig();
|
|
1174
|
+
// strip _configPath from output
|
|
1175
|
+
const { _configPath, ...config } = configResult;
|
|
1176
|
+
console.log("");
|
|
1177
|
+
console.log(" aoaoe — effective config");
|
|
1178
|
+
console.log(` ${"─".repeat(50)}`);
|
|
1179
|
+
console.log(` source: ${configPath ?? "defaults (no config file found)"}`);
|
|
1180
|
+
console.log("");
|
|
1181
|
+
console.log(JSON.stringify(config, null, 2));
|
|
1182
|
+
console.log("");
|
|
1183
|
+
// helpful notes
|
|
1184
|
+
if (!configPath) {
|
|
1185
|
+
console.log(` ${DIM}create a config: aoaoe init${RESET}`);
|
|
1186
|
+
console.log("");
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1104
1189
|
main().catch((err) => {
|
|
1105
1190
|
console.error(`fatal: ${err}`);
|
|
1106
1191
|
process.exit(1);
|
package/dist/init.js
CHANGED
|
@@ -60,7 +60,8 @@ async function discoverSessions() {
|
|
|
60
60
|
.filter((r) => r.status === "fulfilled")
|
|
61
61
|
.map((r) => r.value);
|
|
62
62
|
}
|
|
63
|
-
catch {
|
|
63
|
+
catch (e) {
|
|
64
|
+
console.error(`[init] failed to parse session list: ${e}`);
|
|
64
65
|
return [];
|
|
65
66
|
}
|
|
66
67
|
}
|
|
@@ -72,7 +73,8 @@ async function getSessionStatus(id) {
|
|
|
72
73
|
const data = JSON.parse(result.stdout);
|
|
73
74
|
return toSessionStatus(data.status);
|
|
74
75
|
}
|
|
75
|
-
catch {
|
|
76
|
+
catch (e) {
|
|
77
|
+
console.error(`[init] failed to parse session status for ${id}: ${e}`);
|
|
76
78
|
return "unknown";
|
|
77
79
|
}
|
|
78
80
|
}
|
package/dist/poller.js
CHANGED
|
@@ -115,7 +115,8 @@ export class Poller {
|
|
|
115
115
|
const data = JSON.parse(result.stdout);
|
|
116
116
|
return toSessionStatus(data.status);
|
|
117
117
|
}
|
|
118
|
-
catch {
|
|
118
|
+
catch (e) {
|
|
119
|
+
console.error(`[poller] failed to parse session status for ${id}: ${e}`);
|
|
119
120
|
return "unknown";
|
|
120
121
|
}
|
|
121
122
|
}
|
|
@@ -232,7 +233,8 @@ export async function listAoeSessionsShared(timeoutMs = 10_000) {
|
|
|
232
233
|
const parsed = JSON.parse(result.stdout);
|
|
233
234
|
raw = Array.isArray(parsed) ? parsed : [];
|
|
234
235
|
}
|
|
235
|
-
catch {
|
|
236
|
+
catch (e) {
|
|
237
|
+
console.error(`[poller] failed to parse session list: ${e}`);
|
|
236
238
|
return [];
|
|
237
239
|
}
|
|
238
240
|
const results = await Promise.allSettled(raw.map(async (s) => {
|
|
@@ -245,7 +247,9 @@ export async function listAoeSessionsShared(timeoutMs = 10_000) {
|
|
|
245
247
|
status = JSON.parse(showResult.stdout).status ?? "unknown";
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
|
-
catch {
|
|
250
|
+
catch (e) {
|
|
251
|
+
console.error(`[poller] failed to parse session show for ${id}: ${e}`);
|
|
252
|
+
}
|
|
249
253
|
return { id, title, tool: s.tool ?? "", status, tmuxName: computeTmuxName(id, title) };
|
|
250
254
|
}));
|
|
251
255
|
return results
|