aoaoe 0.53.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 +2 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +33 -4
- package/dist/index.js +204 -9
- package/dist/types.d.ts +12 -0
- package/dist/types.js +27 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -240,6 +240,8 @@ commands:
|
|
|
240
240
|
init detect tools + sessions, import history, generate config
|
|
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
|
+
config --validate validate config + check tool availability
|
|
244
|
+
config --diff show only fields that differ from defaults
|
|
243
245
|
notify-test send a test notification to configured webhooks
|
|
244
246
|
task manage tasks and sessions (list, start, stop, new, rm, edit)
|
|
245
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;
|
|
@@ -20,6 +26,8 @@ export declare function parseCliArgs(argv: string[]): {
|
|
|
20
26
|
showHistory: boolean;
|
|
21
27
|
showStatus: boolean;
|
|
22
28
|
showConfig: boolean;
|
|
29
|
+
configValidate: boolean;
|
|
30
|
+
configDiff: boolean;
|
|
23
31
|
notifyTest: boolean;
|
|
24
32
|
runInit: boolean;
|
|
25
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, 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 };
|
|
@@ -295,7 +320,9 @@ export function parseCliArgs(argv) {
|
|
|
295
320
|
return { ...defaults, showStatus: true };
|
|
296
321
|
}
|
|
297
322
|
if (argv[2] === "config") {
|
|
298
|
-
|
|
323
|
+
const validate = argv.includes("--validate") || argv.includes("-V");
|
|
324
|
+
const diff = argv.includes("--diff");
|
|
325
|
+
return { ...defaults, showConfig: true, configValidate: validate, configDiff: diff };
|
|
299
326
|
}
|
|
300
327
|
if (argv[2] === "notify-test") {
|
|
301
328
|
return { ...defaults, notifyTest: true };
|
|
@@ -389,7 +416,7 @@ export function parseCliArgs(argv) {
|
|
|
389
416
|
break;
|
|
390
417
|
}
|
|
391
418
|
}
|
|
392
|
-
return { overrides, help, version, register: false, testContext: false, runTest: false, showTasks: false, showHistory: false, showStatus: false, showConfig: 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 };
|
|
393
420
|
}
|
|
394
421
|
export function printHelp() {
|
|
395
422
|
console.log(`aoaoe - autonomous supervisor for agent-of-empires sessions
|
|
@@ -407,6 +434,8 @@ commands:
|
|
|
407
434
|
(none) start the supervisor daemon (interactive TUI)
|
|
408
435
|
status quick daemon health check (is it running? what's it doing?)
|
|
409
436
|
config show the effective resolved config (defaults + file)
|
|
437
|
+
config --validate validate config + check tool availability
|
|
438
|
+
config --diff show only fields that differ from defaults
|
|
410
439
|
notify-test send a test notification to configured webhooks
|
|
411
440
|
task manage tasks and sessions (list, start, stop, new, rm, edit)
|
|
412
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";
|
|
@@ -18,7 +18,7 @@ import { runTaskCli, handleTaskSlashCommand } from "./task-cli.js";
|
|
|
18
18
|
import { TUI } from "./tui.js";
|
|
19
19
|
import { isDaemonRunningFromState } from "./chat.js";
|
|
20
20
|
import { sendNotification, sendTestNotification } from "./notify.js";
|
|
21
|
-
import { actionSession, actionDetail } from "./types.js";
|
|
21
|
+
import { actionSession, actionDetail, toActionLogEntry } from "./types.js";
|
|
22
22
|
import { YELLOW, GREEN, DIM, BOLD, RED, RESET } from "./colors.js";
|
|
23
23
|
import { readFileSync, existsSync, statSync, mkdirSync, writeFileSync, chmodSync } from "node:fs";
|
|
24
24
|
import { resolve, dirname, join } from "node:path";
|
|
@@ -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, 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,9 +73,17 @@ async function main() {
|
|
|
73
73
|
showDaemonStatus();
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
// `aoaoe config` -- show effective resolved config
|
|
76
|
+
// `aoaoe config` -- show effective resolved config (with optional --validate or --diff)
|
|
77
77
|
if (showConfig) {
|
|
78
|
-
|
|
78
|
+
if (configValidate) {
|
|
79
|
+
await runConfigValidation();
|
|
80
|
+
}
|
|
81
|
+
else if (configDiff) {
|
|
82
|
+
showConfigDiff();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
showEffectiveConfig();
|
|
86
|
+
}
|
|
79
87
|
return;
|
|
80
88
|
}
|
|
81
89
|
// `aoaoe notify-test` -- send a test notification to configured webhooks
|
|
@@ -1136,7 +1144,9 @@ async function showActionHistory() {
|
|
|
1136
1144
|
console.log(` ${"─".repeat(70)}`);
|
|
1137
1145
|
for (const line of recent) {
|
|
1138
1146
|
try {
|
|
1139
|
-
const entry = JSON.parse(line);
|
|
1147
|
+
const entry = toActionLogEntry(JSON.parse(line));
|
|
1148
|
+
if (!entry)
|
|
1149
|
+
continue; // skip malformed lines
|
|
1140
1150
|
const time = new Date(entry.timestamp).toLocaleTimeString();
|
|
1141
1151
|
const date = new Date(entry.timestamp).toLocaleDateString();
|
|
1142
1152
|
const icon = entry.success ? `${GREEN}+${RESET}` : `${RED}!${RESET}`;
|
|
@@ -1146,7 +1156,7 @@ async function showActionHistory() {
|
|
|
1146
1156
|
console.log(` ${icon} ${DIM}${date} ${time}${RESET} ${YELLOW}${actionName.padEnd(16)}${RESET} ${session.padEnd(10)} ${detail}`);
|
|
1147
1157
|
}
|
|
1148
1158
|
catch {
|
|
1149
|
-
// skip
|
|
1159
|
+
// skip unparseable JSON lines
|
|
1150
1160
|
}
|
|
1151
1161
|
}
|
|
1152
1162
|
console.log(` ${"─".repeat(70)}`);
|
|
@@ -1155,14 +1165,18 @@ async function showActionHistory() {
|
|
|
1155
1165
|
const actionCounts = new Map();
|
|
1156
1166
|
for (const line of lines) {
|
|
1157
1167
|
try {
|
|
1158
|
-
const e = JSON.parse(line);
|
|
1168
|
+
const e = toActionLogEntry(JSON.parse(line));
|
|
1169
|
+
if (!e)
|
|
1170
|
+
continue;
|
|
1159
1171
|
if (e.success)
|
|
1160
1172
|
successes++;
|
|
1161
1173
|
else
|
|
1162
1174
|
failures++;
|
|
1163
1175
|
actionCounts.set(e.action.action, (actionCounts.get(e.action.action) ?? 0) + 1);
|
|
1164
1176
|
}
|
|
1165
|
-
catch {
|
|
1177
|
+
catch {
|
|
1178
|
+
// skip unparseable JSON lines
|
|
1179
|
+
}
|
|
1166
1180
|
}
|
|
1167
1181
|
const breakdown = [...actionCounts.entries()].sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}: ${v}`).join(", ");
|
|
1168
1182
|
console.log(` total: ${lines.length} actions (${GREEN}${successes} ok${RESET}, ${RED}${failures} failed${RESET})`);
|
|
@@ -1232,6 +1246,187 @@ function showDaemonStatus() {
|
|
|
1232
1246
|
console.log(` ${statusIcon} ${BOLD}${s.title}${RESET} (${s.tool}) ${s.status}${userTag}${taskTag}`);
|
|
1233
1247
|
}
|
|
1234
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
|
+
}
|
|
1285
|
+
console.log("");
|
|
1286
|
+
}
|
|
1287
|
+
// `aoaoe config --validate` -- validate config file, field values, and tool availability
|
|
1288
|
+
async function runConfigValidation() {
|
|
1289
|
+
const configPath = findConfigFile();
|
|
1290
|
+
let checks = 0;
|
|
1291
|
+
let passed = 0;
|
|
1292
|
+
let warnings = 0;
|
|
1293
|
+
console.log("");
|
|
1294
|
+
console.log(" aoaoe — config validation");
|
|
1295
|
+
console.log(` ${"─".repeat(50)}`);
|
|
1296
|
+
// 1. config file exists
|
|
1297
|
+
checks++;
|
|
1298
|
+
if (configPath) {
|
|
1299
|
+
console.log(` ${GREEN}✓${RESET} config file found: ${configPath}`);
|
|
1300
|
+
passed++;
|
|
1301
|
+
}
|
|
1302
|
+
else {
|
|
1303
|
+
console.log(` ${YELLOW}!${RESET} no config file found (using defaults)`);
|
|
1304
|
+
console.log(` ${DIM}run 'aoaoe init' to create one${RESET}`);
|
|
1305
|
+
warnings++;
|
|
1306
|
+
}
|
|
1307
|
+
// 2. config parses + validates
|
|
1308
|
+
checks++;
|
|
1309
|
+
let config;
|
|
1310
|
+
try {
|
|
1311
|
+
const configResult = loadConfig();
|
|
1312
|
+
config = configResult;
|
|
1313
|
+
console.log(` ${GREEN}✓${RESET} config valid (all field values OK)`);
|
|
1314
|
+
passed++;
|
|
1315
|
+
}
|
|
1316
|
+
catch (err) {
|
|
1317
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1318
|
+
console.log(` ${RED}✗${RESET} config validation failed:`);
|
|
1319
|
+
for (const line of msg.split("\n")) {
|
|
1320
|
+
console.log(` ${line}`);
|
|
1321
|
+
}
|
|
1322
|
+
console.log("");
|
|
1323
|
+
console.log(` ${passed}/${checks} checks passed, fix config errors and retry`);
|
|
1324
|
+
console.log("");
|
|
1325
|
+
process.exit(1);
|
|
1326
|
+
return; // unreachable, but satisfies TypeScript
|
|
1327
|
+
}
|
|
1328
|
+
// 3. required tools on PATH
|
|
1329
|
+
const tools = [
|
|
1330
|
+
{ name: "aoe", label: "agent-of-empires CLI" },
|
|
1331
|
+
{ name: "tmux", label: "terminal multiplexer" },
|
|
1332
|
+
];
|
|
1333
|
+
if (config.reasoner === "opencode") {
|
|
1334
|
+
tools.push({ name: "opencode", label: "OpenCode CLI" });
|
|
1335
|
+
}
|
|
1336
|
+
else if (config.reasoner === "claude-code") {
|
|
1337
|
+
tools.push({ name: "claude", label: "Claude Code CLI" });
|
|
1338
|
+
}
|
|
1339
|
+
for (const tool of tools) {
|
|
1340
|
+
checks++;
|
|
1341
|
+
try {
|
|
1342
|
+
const { execFile: execFileCb } = await import("node:child_process");
|
|
1343
|
+
const { promisify } = await import("node:util");
|
|
1344
|
+
const execFileAsync = promisify(execFileCb);
|
|
1345
|
+
await execFileAsync("which", [tool.name]);
|
|
1346
|
+
console.log(` ${GREEN}✓${RESET} ${tool.name} found on PATH (${tool.label})`);
|
|
1347
|
+
passed++;
|
|
1348
|
+
}
|
|
1349
|
+
catch {
|
|
1350
|
+
console.log(` ${RED}✗${RESET} ${tool.name} not found on PATH (${tool.label})`);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
// 4. notifications config check
|
|
1354
|
+
checks++;
|
|
1355
|
+
if (config.notifications) {
|
|
1356
|
+
const hasWebhook = !!config.notifications.webhookUrl;
|
|
1357
|
+
const hasSlack = !!config.notifications.slackWebhookUrl;
|
|
1358
|
+
if (hasWebhook || hasSlack) {
|
|
1359
|
+
const targets = [hasWebhook && "webhook", hasSlack && "Slack"].filter(Boolean).join(" + ");
|
|
1360
|
+
console.log(` ${GREEN}✓${RESET} notifications configured (${targets})`);
|
|
1361
|
+
console.log(` ${DIM}run 'aoaoe notify-test' to verify delivery${RESET}`);
|
|
1362
|
+
passed++;
|
|
1363
|
+
}
|
|
1364
|
+
else {
|
|
1365
|
+
console.log(` ${YELLOW}!${RESET} notifications block exists but no webhook URLs configured`);
|
|
1366
|
+
warnings++;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
else {
|
|
1370
|
+
console.log(` ${DIM}○${RESET} notifications not configured (optional)`);
|
|
1371
|
+
passed++; // not configured is fine — it's optional
|
|
1372
|
+
}
|
|
1373
|
+
// 5. sessionDirs validation — check that mapped dirs exist
|
|
1374
|
+
if (config.sessionDirs && Object.keys(config.sessionDirs).length > 0) {
|
|
1375
|
+
const basePath = process.cwd();
|
|
1376
|
+
for (const [title, dir] of Object.entries(config.sessionDirs)) {
|
|
1377
|
+
checks++;
|
|
1378
|
+
const resolved = dir.startsWith("/") ? dir : resolve(basePath, dir);
|
|
1379
|
+
if (existsSync(resolved)) {
|
|
1380
|
+
console.log(` ${GREEN}✓${RESET} sessionDirs.${title} → ${resolved}`);
|
|
1381
|
+
passed++;
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
console.log(` ${YELLOW}!${RESET} sessionDirs.${title} → ${resolved} (not found)`);
|
|
1385
|
+
warnings++;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
// summary
|
|
1390
|
+
const failed = checks - passed - warnings;
|
|
1391
|
+
console.log("");
|
|
1392
|
+
if (failed === 0 && warnings === 0) {
|
|
1393
|
+
console.log(` ${GREEN}${BOLD}all ${checks} checks passed${RESET}`);
|
|
1394
|
+
}
|
|
1395
|
+
else if (failed === 0) {
|
|
1396
|
+
console.log(` ${passed}/${checks} passed, ${YELLOW}${warnings} warning(s)${RESET}`);
|
|
1397
|
+
}
|
|
1398
|
+
else {
|
|
1399
|
+
console.log(` ${passed}/${checks} passed, ${RED}${failed} failed${RESET}${warnings > 0 ? `, ${YELLOW}${warnings} warning(s)${RESET}` : ""}`);
|
|
1400
|
+
}
|
|
1401
|
+
console.log("");
|
|
1402
|
+
if (failed > 0)
|
|
1403
|
+
process.exit(1);
|
|
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
|
+
}
|
|
1235
1430
|
console.log("");
|
|
1236
1431
|
}
|
|
1237
1432
|
// `aoaoe config` -- show the effective resolved config (defaults + file + any notes)
|
package/dist/types.d.ts
CHANGED
|
@@ -175,4 +175,16 @@ export declare function toAoeSessionList(raw: unknown): Array<{
|
|
|
175
175
|
title: string;
|
|
176
176
|
}>;
|
|
177
177
|
export declare function toReasonerBackend(raw: string): ReasonerBackend;
|
|
178
|
+
export interface ActionLogEntry {
|
|
179
|
+
timestamp: number;
|
|
180
|
+
action: {
|
|
181
|
+
action: string;
|
|
182
|
+
session?: string;
|
|
183
|
+
text?: string;
|
|
184
|
+
title?: string;
|
|
185
|
+
};
|
|
186
|
+
success: boolean;
|
|
187
|
+
detail: string;
|
|
188
|
+
}
|
|
189
|
+
export declare function toActionLogEntry(raw: unknown): ActionLogEntry | null;
|
|
178
190
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
CHANGED
|
@@ -112,4 +112,31 @@ export function toReasonerBackend(raw) {
|
|
|
112
112
|
return raw;
|
|
113
113
|
throw new Error(`--reasoner must be "opencode" or "claude-code", got "${raw}"`);
|
|
114
114
|
}
|
|
115
|
+
export function toActionLogEntry(raw) {
|
|
116
|
+
if (!raw || typeof raw !== "object")
|
|
117
|
+
return null;
|
|
118
|
+
const obj = raw;
|
|
119
|
+
if (typeof obj.timestamp !== "number")
|
|
120
|
+
return null;
|
|
121
|
+
if (typeof obj.success !== "boolean")
|
|
122
|
+
return null;
|
|
123
|
+
if (typeof obj.detail !== "string")
|
|
124
|
+
obj.detail = "";
|
|
125
|
+
if (!obj.action || typeof obj.action !== "object")
|
|
126
|
+
return null;
|
|
127
|
+
const action = obj.action;
|
|
128
|
+
if (typeof action.action !== "string")
|
|
129
|
+
return null;
|
|
130
|
+
return {
|
|
131
|
+
timestamp: obj.timestamp,
|
|
132
|
+
action: {
|
|
133
|
+
action: action.action,
|
|
134
|
+
session: typeof action.session === "string" ? action.session : undefined,
|
|
135
|
+
text: typeof action.text === "string" ? action.text : undefined,
|
|
136
|
+
title: typeof action.title === "string" ? action.title : undefined,
|
|
137
|
+
},
|
|
138
|
+
success: obj.success,
|
|
139
|
+
detail: typeof obj.detail === "string" ? obj.detail : "",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
115
142
|
//# sourceMappingURL=types.js.map
|