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 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
@@ -18,6 +18,8 @@ export declare function parseCliArgs(argv: string[]): {
18
18
  runTest: boolean;
19
19
  showTasks: boolean;
20
20
  showHistory: boolean;
21
+ showStatus: boolean;
22
+ showConfig: boolean;
21
23
  runInit: boolean;
22
24
  initForce: boolean;
23
25
  runTaskCli: boolean;
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 { } // best-effort, don't crash the daemon
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aoaoe",
3
- "version": "0.50.0",
3
+ "version": "0.51.0",
4
4
  "description": "Autonomous supervisor for agent-of-empires sessions using OpenCode or Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",