aoaoe 0.54.0 → 0.55.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/README.md +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +32 -5
- package/dist/index.js +69 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -241,6 +241,7 @@ commands:
|
|
|
241
241
|
status quick daemon health check (is it running? what's it doing?)
|
|
242
242
|
config show the effective resolved config (defaults + file)
|
|
243
243
|
config --validate validate config + check tool availability
|
|
244
|
+
config --diff show only fields that differ from defaults
|
|
244
245
|
notify-test send a test notification to configured webhooks
|
|
245
246
|
task manage tasks and sessions (list, start, stop, new, rm, edit)
|
|
246
247
|
tasks show task progress (from aoaoe.tasks.json)
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AoaoeConfig } from "./types.js";
|
|
2
|
+
export declare const DEFAULTS: AoaoeConfig;
|
|
2
3
|
export declare function findConfigFile(): string | null;
|
|
3
4
|
export declare function configFileExists(): boolean;
|
|
4
5
|
export declare function defaultConfigPath(): string;
|
|
@@ -9,6 +10,11 @@ export declare function warnUnknownKeys(raw: unknown, source: string): void;
|
|
|
9
10
|
export declare function validateConfig(config: AoaoeConfig): void;
|
|
10
11
|
export declare function validateEnvironment(config: AoaoeConfig): Promise<void>;
|
|
11
12
|
export declare function deepMerge(...objects: Record<string, unknown>[]): AoaoeConfig;
|
|
13
|
+
export declare function computeConfigDiff(current: Record<string, unknown>, defaults: Record<string, unknown>, prefix?: string): Array<{
|
|
14
|
+
path: string;
|
|
15
|
+
current: unknown;
|
|
16
|
+
default: unknown;
|
|
17
|
+
}>;
|
|
12
18
|
export declare function parseCliArgs(argv: string[]): {
|
|
13
19
|
overrides: Partial<AoaoeConfig>;
|
|
14
20
|
help: boolean;
|
|
@@ -21,6 +27,7 @@ export declare function parseCliArgs(argv: string[]): {
|
|
|
21
27
|
showStatus: boolean;
|
|
22
28
|
showConfig: boolean;
|
|
23
29
|
configValidate: boolean;
|
|
30
|
+
configDiff: boolean;
|
|
24
31
|
notifyTest: boolean;
|
|
25
32
|
runInit: boolean;
|
|
26
33
|
initForce: boolean;
|
package/dist/config.js
CHANGED
|
@@ -9,7 +9,7 @@ const AOAOE_DIR = join(homedir(), ".aoaoe");
|
|
|
9
9
|
const CONFIG_NAMES = ["aoaoe.config.json", ".aoaoe.json"];
|
|
10
10
|
// search order: ~/.aoaoe/ first (canonical), then cwd (local override for dev)
|
|
11
11
|
const CONFIG_SEARCH_DIRS = [AOAOE_DIR, process.cwd()];
|
|
12
|
-
const DEFAULTS = {
|
|
12
|
+
export const DEFAULTS = {
|
|
13
13
|
reasoner: "opencode",
|
|
14
14
|
pollIntervalMs: 10_000,
|
|
15
15
|
opencode: {
|
|
@@ -259,6 +259,31 @@ export function deepMerge(...objects) {
|
|
|
259
259
|
}
|
|
260
260
|
return result;
|
|
261
261
|
}
|
|
262
|
+
// compute fields that differ between two config objects (flat dot-notation paths)
|
|
263
|
+
// exported for testing
|
|
264
|
+
export function computeConfigDiff(current, defaults, prefix = "") {
|
|
265
|
+
const diffs = [];
|
|
266
|
+
const allKeys = new Set([...Object.keys(current), ...Object.keys(defaults)]);
|
|
267
|
+
for (const key of allKeys) {
|
|
268
|
+
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
269
|
+
const curVal = current[key];
|
|
270
|
+
const defVal = defaults[key];
|
|
271
|
+
// both are plain objects — recurse
|
|
272
|
+
if (curVal && defVal &&
|
|
273
|
+
typeof curVal === "object" && !Array.isArray(curVal) &&
|
|
274
|
+
typeof defVal === "object" && !Array.isArray(defVal)) {
|
|
275
|
+
diffs.push(...computeConfigDiff(curVal, defVal, fullPath));
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
// compare with JSON.stringify for arrays/objects, === for primitives
|
|
279
|
+
const curStr = JSON.stringify(curVal);
|
|
280
|
+
const defStr = JSON.stringify(defVal);
|
|
281
|
+
if (curStr !== defStr) {
|
|
282
|
+
diffs.push({ path: fullPath, current: curVal, default: defVal });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return diffs;
|
|
286
|
+
}
|
|
262
287
|
function log(msg) {
|
|
263
288
|
console.error(`[config] ${msg}`);
|
|
264
289
|
}
|
|
@@ -274,7 +299,7 @@ export function parseCliArgs(argv) {
|
|
|
274
299
|
let initForce = false;
|
|
275
300
|
let runTaskCli = false;
|
|
276
301
|
let registerTitle;
|
|
277
|
-
const defaults = { overrides, help: false, version: false, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: false, configValidate: false, notifyTest: false, runInit: false, initForce: false, runTaskCli: false };
|
|
302
|
+
const defaults = { overrides, help: false, version: false, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: false, configValidate: false, configDiff: false, notifyTest: false, runInit: false, initForce: false, runTaskCli: false };
|
|
278
303
|
// check for subcommand as first non-flag arg
|
|
279
304
|
if (argv[2] === "test-context") {
|
|
280
305
|
return { ...defaults, testContext: true };
|
|
@@ -296,7 +321,8 @@ export function parseCliArgs(argv) {
|
|
|
296
321
|
}
|
|
297
322
|
if (argv[2] === "config") {
|
|
298
323
|
const validate = argv.includes("--validate") || argv.includes("-V");
|
|
299
|
-
|
|
324
|
+
const diff = argv.includes("--diff");
|
|
325
|
+
return { ...defaults, showConfig: true, configValidate: validate, configDiff: diff };
|
|
300
326
|
}
|
|
301
327
|
if (argv[2] === "notify-test") {
|
|
302
328
|
return { ...defaults, notifyTest: true };
|
|
@@ -390,7 +416,7 @@ export function parseCliArgs(argv) {
|
|
|
390
416
|
break;
|
|
391
417
|
}
|
|
392
418
|
}
|
|
393
|
-
return { overrides, help, version, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: false, configValidate: false, notifyTest: false, runInit: false, initForce: false, runTaskCli: false };
|
|
419
|
+
return { overrides, help, version, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: false, configValidate: false, configDiff: false, notifyTest: false, runInit: false, initForce: false, runTaskCli: false };
|
|
394
420
|
}
|
|
395
421
|
export function printHelp() {
|
|
396
422
|
console.log(`aoaoe - autonomous supervisor for agent-of-empires sessions
|
|
@@ -408,7 +434,8 @@ commands:
|
|
|
408
434
|
(none) start the supervisor daemon (interactive TUI)
|
|
409
435
|
status quick daemon health check (is it running? what's it doing?)
|
|
410
436
|
config show the effective resolved config (defaults + file)
|
|
411
|
-
config --validate validate config
|
|
437
|
+
config --validate validate config + check tool availability
|
|
438
|
+
config --diff show only fields that differ from defaults
|
|
412
439
|
notify-test send a test notification to configured webhooks
|
|
413
440
|
task manage tasks and sessions (list, start, stop, new, rm, edit)
|
|
414
441
|
tasks show task progress (from aoaoe.tasks.json)
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loadConfig, validateEnvironment, parseCliArgs, printHelp, configFileExists, findConfigFile } from "./config.js";
|
|
2
|
+
import { loadConfig, validateEnvironment, parseCliArgs, printHelp, configFileExists, findConfigFile, DEFAULTS, computeConfigDiff } 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";
|
|
@@ -28,7 +28,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
28
28
|
const AOAOE_DIR = join(homedir(), ".aoaoe"); // watch dir for wakeable sleep
|
|
29
29
|
const INPUT_FILE = join(AOAOE_DIR, "pending-input.txt"); // file IPC from chat.ts
|
|
30
30
|
async function main() {
|
|
31
|
-
const { overrides, help, version, register, testContext: isTestContext, runTest, showTasks, showHistory, showStatus, showConfig, configValidate, notifyTest, runInit, initForce, runTaskCli: isTaskCli, registerTitle } = parseCliArgs(process.argv);
|
|
31
|
+
const { overrides, help, version, register, testContext: isTestContext, runTest, showTasks, showHistory, showStatus, showConfig, configValidate, configDiff, notifyTest, runInit, initForce, runTaskCli: isTaskCli, registerTitle } = parseCliArgs(process.argv);
|
|
32
32
|
if (help) {
|
|
33
33
|
printHelp();
|
|
34
34
|
process.exit(0);
|
|
@@ -73,11 +73,14 @@ async function main() {
|
|
|
73
73
|
showDaemonStatus();
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
// `aoaoe config` -- show effective resolved config (with optional --validate)
|
|
76
|
+
// `aoaoe config` -- show effective resolved config (with optional --validate or --diff)
|
|
77
77
|
if (showConfig) {
|
|
78
78
|
if (configValidate) {
|
|
79
79
|
await runConfigValidation();
|
|
80
80
|
}
|
|
81
|
+
else if (configDiff) {
|
|
82
|
+
showConfigDiff();
|
|
83
|
+
}
|
|
81
84
|
else {
|
|
82
85
|
showEffectiveConfig();
|
|
83
86
|
}
|
|
@@ -1243,6 +1246,42 @@ function showDaemonStatus() {
|
|
|
1243
1246
|
console.log(` ${statusIcon} ${BOLD}${s.title}${RESET} (${s.tool}) ${s.status}${userTag}${taskTag}`);
|
|
1244
1247
|
}
|
|
1245
1248
|
}
|
|
1249
|
+
// last action from actions.log
|
|
1250
|
+
try {
|
|
1251
|
+
const actionsLogPath = join(homedir(), ".aoaoe", "actions.log");
|
|
1252
|
+
if (existsSync(actionsLogPath)) {
|
|
1253
|
+
const content = readFileSync(actionsLogPath, "utf-8").trim();
|
|
1254
|
+
if (content) {
|
|
1255
|
+
const logLines = content.split("\n").filter((l) => l.trim());
|
|
1256
|
+
// find last non-wait action
|
|
1257
|
+
for (let i = logLines.length - 1; i >= 0; i--) {
|
|
1258
|
+
try {
|
|
1259
|
+
const entry = toActionLogEntry(JSON.parse(logLines[i]));
|
|
1260
|
+
if (!entry || entry.action.action === "wait")
|
|
1261
|
+
continue;
|
|
1262
|
+
const ago = Date.now() - entry.timestamp;
|
|
1263
|
+
const agoStr = ago < 60_000 ? `${Math.floor(ago / 1000)}s ago` :
|
|
1264
|
+
ago < 3_600_000 ? `${Math.floor(ago / 60_000)}m ago` :
|
|
1265
|
+
`${Math.floor(ago / 3_600_000)}h ago`;
|
|
1266
|
+
const icon = entry.success ? `${GREEN}+${RESET}` : `${RED}!${RESET}`;
|
|
1267
|
+
const session = entry.action.session?.slice(0, 8) ?? entry.action.title ?? "";
|
|
1268
|
+
const detail = entry.detail.length > 40 ? entry.detail.slice(0, 37) + "..." : entry.detail;
|
|
1269
|
+
console.log("");
|
|
1270
|
+
console.log(` last action: ${icon} ${entry.action.action} ${session} ${DIM}(${agoStr})${RESET}`);
|
|
1271
|
+
if (detail)
|
|
1272
|
+
console.log(` ${DIM}${detail}${RESET}`);
|
|
1273
|
+
break;
|
|
1274
|
+
}
|
|
1275
|
+
catch {
|
|
1276
|
+
// skip malformed lines
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
catch {
|
|
1283
|
+
// best-effort — actions.log might not exist
|
|
1284
|
+
}
|
|
1246
1285
|
console.log("");
|
|
1247
1286
|
}
|
|
1248
1287
|
// `aoaoe config --validate` -- validate config file, field values, and tool availability
|
|
@@ -1363,6 +1402,33 @@ async function runConfigValidation() {
|
|
|
1363
1402
|
if (failed > 0)
|
|
1364
1403
|
process.exit(1);
|
|
1365
1404
|
}
|
|
1405
|
+
// `aoaoe config --diff` -- show only fields that differ from defaults
|
|
1406
|
+
function showConfigDiff() {
|
|
1407
|
+
const configPath = findConfigFile();
|
|
1408
|
+
const configResult = loadConfig();
|
|
1409
|
+
const { _configPath, ...config } = configResult;
|
|
1410
|
+
const diffs = computeConfigDiff(config, DEFAULTS);
|
|
1411
|
+
console.log("");
|
|
1412
|
+
console.log(" aoaoe — config diff (vs. defaults)");
|
|
1413
|
+
console.log(` ${"─".repeat(50)}`);
|
|
1414
|
+
console.log(` source: ${configPath ?? "defaults (no config file found)"}`);
|
|
1415
|
+
console.log("");
|
|
1416
|
+
if (diffs.length === 0) {
|
|
1417
|
+
console.log(" (no differences — config matches defaults)");
|
|
1418
|
+
}
|
|
1419
|
+
else {
|
|
1420
|
+
for (const d of diffs) {
|
|
1421
|
+
const curStr = d.current === undefined ? `${DIM}(not set)${RESET}` : `${GREEN}${JSON.stringify(d.current)}${RESET}`;
|
|
1422
|
+
const defStr = d.default === undefined ? `${DIM}(not set)${RESET}` : `${DIM}${JSON.stringify(d.default)}${RESET}`;
|
|
1423
|
+
console.log(` ${YELLOW}${d.path}${RESET}`);
|
|
1424
|
+
console.log(` current: ${curStr}`);
|
|
1425
|
+
console.log(` default: ${defStr}`);
|
|
1426
|
+
}
|
|
1427
|
+
console.log("");
|
|
1428
|
+
console.log(` ${diffs.length} field(s) differ from defaults`);
|
|
1429
|
+
}
|
|
1430
|
+
console.log("");
|
|
1431
|
+
}
|
|
1366
1432
|
// `aoaoe config` -- show the effective resolved config (defaults + file + any notes)
|
|
1367
1433
|
function showEffectiveConfig() {
|
|
1368
1434
|
const configPath = findConfigFile();
|