aoaoe 0.48.0 → 0.50.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/config.d.ts CHANGED
@@ -2,7 +2,10 @@ import type { AoaoeConfig } from "./types.js";
2
2
  export declare function findConfigFile(): string | null;
3
3
  export declare function configFileExists(): boolean;
4
4
  export declare function defaultConfigPath(): string;
5
- export declare function loadConfig(overrides?: Partial<AoaoeConfig>): AoaoeConfig;
5
+ export declare function loadConfig(overrides?: Partial<AoaoeConfig>): AoaoeConfig & {
6
+ _configPath?: string;
7
+ };
8
+ export declare function warnUnknownKeys(raw: unknown, source: string): void;
6
9
  export declare function validateConfig(config: AoaoeConfig): void;
7
10
  export declare function validateEnvironment(config: AoaoeConfig): Promise<void>;
8
11
  export declare function deepMerge(...objects: Record<string, unknown>[]): AoaoeConfig;
package/dist/config.js CHANGED
@@ -61,16 +61,56 @@ export function loadConfig(overrides) {
61
61
  const found = findConfigFile();
62
62
  if (found) {
63
63
  try {
64
- fileConfig = JSON.parse(readFileSync(found, "utf-8"));
64
+ const raw = JSON.parse(readFileSync(found, "utf-8"));
65
+ warnUnknownKeys(raw, found);
66
+ fileConfig = raw;
65
67
  log(`loaded config from ${found}`);
66
68
  }
67
69
  catch (e) {
68
- console.error(`warning: failed to parse ${found}, using defaults`);
70
+ if (e instanceof SyntaxError) {
71
+ console.error(`warning: failed to parse ${found}, using defaults`);
72
+ }
73
+ else {
74
+ throw e; // re-throw validation errors from warnUnknownKeys
75
+ }
69
76
  }
70
77
  }
71
78
  const config = deepMerge(DEFAULTS, fileConfig, (overrides ?? {}));
72
79
  validateConfig(config);
73
- return config;
80
+ return { ...config, _configPath: found ?? undefined };
81
+ }
82
+ // known top-level and nested config keys — used to warn on typos
83
+ const KNOWN_KEYS = {
84
+ reasoner: true, pollIntervalMs: true, captureLinesCount: true,
85
+ verbose: true, dryRun: true, observe: true, confirm: true,
86
+ contextFiles: true, sessionDirs: true, protectedSessions: true,
87
+ opencode: new Set(["port", "model"]),
88
+ claudeCode: new Set(["model", "yolo", "resume"]),
89
+ aoe: new Set(["profile"]),
90
+ policies: new Set([
91
+ "maxIdleBeforeNudgeMs", "maxErrorsBeforeRestart", "autoAnswerPermissions",
92
+ "actionCooldownMs", "userActivityThresholdMs", "allowDestructive",
93
+ ]),
94
+ };
95
+ export function warnUnknownKeys(raw, source) {
96
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
97
+ return;
98
+ const obj = raw;
99
+ for (const key of Object.keys(obj)) {
100
+ if (!(key in KNOWN_KEYS)) {
101
+ console.error(`warning: unknown config key "${key}" in ${source} (typo?)`);
102
+ continue;
103
+ }
104
+ // check nested keys for known sub-objects
105
+ const schema = KNOWN_KEYS[key];
106
+ if (schema instanceof Set && obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) {
107
+ for (const subKey of Object.keys(obj[key])) {
108
+ if (!schema.has(subKey)) {
109
+ console.error(`warning: unknown config key "${key}.${subKey}" in ${source} (typo?)`);
110
+ }
111
+ }
112
+ }
113
+ }
74
114
  }
75
115
  // validate config values to catch bad configs at startup rather than runtime
76
116
  export function validateConfig(config) {
package/dist/index.js CHANGED
@@ -92,7 +92,9 @@ async function main() {
92
92
  console.error("");
93
93
  }
94
94
  }
95
- const config = loadConfig(overrides);
95
+ const configResult = loadConfig(overrides);
96
+ const configPath = configResult._configPath;
97
+ const config = configResult; // strip _configPath from type for downstream
96
98
  // acquire daemon lock — prevent two daemons from running simultaneously
97
99
  const lock = acquireLock();
98
100
  if (!lock.acquired) {
@@ -112,6 +114,7 @@ async function main() {
112
114
  console.error("");
113
115
  console.error(" aoaoe" + (pkg ? ` v${pkg}` : "") + " — autonomous supervisor");
114
116
  console.error(` reasoner: ${config.reasoner} | poll: ${config.pollIntervalMs / 1000}s`);
117
+ console.error(` config: ${configPath ?? "defaults (no config file found)"}`);
115
118
  if (config.observe)
116
119
  console.error(" OBSERVE MODE — watching only, no AI, no actions");
117
120
  else if (config.confirm)
@@ -210,6 +213,7 @@ async function main() {
210
213
  tui.log("system", `The AI supervisor is watching your agents and will help when needed.`);
211
214
  }
212
215
  tui.log("system", "");
216
+ tui.log("system", `config: ${configPath ?? "using defaults (no config file found)"}`);
213
217
  tui.log("system", "Type a message to talk to the AI, or use /help for commands.");
214
218
  tui.log("system", "Press ESC twice to interrupt the AI mid-thought.");
215
219
  tui.log("system", "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aoaoe",
3
- "version": "0.48.0",
3
+ "version": "0.50.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",