aoaoe 0.61.0 → 0.62.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 CHANGED
@@ -342,6 +342,7 @@ Config lives at `~/.aoaoe/aoaoe.config.json` (canonical, written by `aoaoe init`
342
342
  | `notifications.slackWebhookUrl` | Slack incoming webhook URL (block kit format) | (none) |
343
343
  | `notifications.events` | Filter which events fire (omit to send all). Valid: `session_error`, `session_done`, `action_executed`, `action_failed`, `daemon_started`, `daemon_stopped` | (all) |
344
344
  | `notifications.maxRetries` | Retry failed webhook deliveries with exponential backoff (1s, 2s, 4s, ...) | `0` (no retry) |
345
+ | `tuiHistoryRetentionDays` | How many days of TUI history to replay on startup (1-365) | `7` |
345
346
 
346
347
  Also reads `.aoaoe.json` as an alternative config filename.
347
348
 
package/dist/config.js CHANGED
@@ -83,7 +83,7 @@ export function loadConfig(overrides) {
83
83
  const KNOWN_KEYS = {
84
84
  reasoner: true, pollIntervalMs: true, captureLinesCount: true,
85
85
  verbose: true, dryRun: true, observe: true, confirm: true,
86
- contextFiles: true, sessionDirs: true, protectedSessions: true, healthPort: true,
86
+ contextFiles: true, sessionDirs: true, protectedSessions: true, healthPort: true, tuiHistoryRetentionDays: true,
87
87
  opencode: new Set(["port", "model"]),
88
88
  claudeCode: new Set(["model", "yolo", "resume"]),
89
89
  aoe: new Set(["profile"]),
@@ -133,6 +133,13 @@ export function validateConfig(config) {
133
133
  errors.push(`healthPort must be 1-65535, got ${config.healthPort}`);
134
134
  }
135
135
  }
136
+ // tuiHistoryRetentionDays: must be a positive integer, 1-365
137
+ if (config.tuiHistoryRetentionDays !== undefined) {
138
+ const d = config.tuiHistoryRetentionDays;
139
+ if (typeof d !== "number" || !isFinite(d) || !Number.isInteger(d) || d < 1 || d > 365) {
140
+ errors.push(`tuiHistoryRetentionDays must be an integer 1-365, got ${d}`);
141
+ }
142
+ }
136
143
  if (typeof config.policies?.maxErrorsBeforeRestart !== "number" || config.policies.maxErrorsBeforeRestart < 1) {
137
144
  errors.push(`policies.maxErrorsBeforeRestart must be >= 1, got ${config.policies?.maxErrorsBeforeRestart}`);
138
145
  }
@@ -540,6 +547,7 @@ example config:
540
547
  "other-repo": "/path/to/other-repo"
541
548
  },
542
549
  "healthPort": 4098,
550
+ "tuiHistoryRetentionDays": 7,
543
551
  "notifications": {
544
552
  "webhookUrl": "https://example.com/webhook",
545
553
  "slackWebhookUrl": "https://hooks.slack.com/services/T.../B.../xxx",
@@ -552,6 +560,9 @@ example config:
552
560
  aoaoe loads AGENTS.md, claude.md, and other AI instruction files
553
561
  from each project directory to give the reasoner per-session context.
554
562
 
563
+ tuiHistoryRetentionDays controls how many days of TUI history to replay
564
+ on daemon startup (default: 7, range: 1-365). History file rotates at 50MB.
565
+
555
566
  notifications sends webhook alerts for daemon events. Both webhookUrl
556
567
  and slackWebhookUrl are optional. events filters which events fire
557
568
  (omit to send all). maxRetries enables exponential backoff retry on
package/dist/index.js CHANGED
@@ -232,7 +232,9 @@ async function main() {
232
232
  // start TUI (alternate screen buffer) after input is ready
233
233
  if (tui) {
234
234
  // replay persisted history from previous runs before entering alt screen
235
- const history = loadTuiHistory();
235
+ const retentionDays = config.tuiHistoryRetentionDays ?? 7;
236
+ const retentionMs = retentionDays * 24 * 60 * 60 * 1000;
237
+ const history = loadTuiHistory(200, undefined, retentionMs);
236
238
  if (history.length > 0)
237
239
  tui.replayHistory(history);
238
240
  tui.start(pkg || "dev");
@@ -14,9 +14,10 @@ export declare function appendHistoryEntry(entry: HistoryEntry, filePath?: strin
14
14
  /**
15
15
  * Load recent TUI history entries from the JSONL file.
16
16
  * Returns the last `maxEntries` entries (default 200), newest last.
17
+ * Filters out entries older than `maxAgeMs` (default: 7 days).
17
18
  * Returns empty array if the file doesn't exist or is unreadable.
18
19
  */
19
- export declare function loadTuiHistory(maxEntries?: number, filePath?: string): HistoryEntry[];
20
+ export declare function loadTuiHistory(maxEntries?: number, filePath?: string, maxAgeMs?: number): HistoryEntry[];
20
21
  /**
21
22
  * Rotate the history file if it exceeds the size threshold.
22
23
  * Renames current file to .old (overwriting any previous .old) and starts fresh.
@@ -1,5 +1,5 @@
1
1
  // tui-history.ts — persisted TUI activity history
2
- // JSONL file at ~/.aoaoe/tui-history.jsonl with rotation at 500KB.
2
+ // JSONL file at ~/.aoaoe/tui-history.jsonl with rotation at 50MB.
3
3
  // pure exported functions for testability — no classes, no singletons.
4
4
  import { appendFileSync, readFileSync, renameSync, statSync, mkdirSync, existsSync } from "node:fs";
5
5
  import { join } from "node:path";
@@ -7,7 +7,7 @@ import { homedir } from "node:os";
7
7
  const AOAOE_DIR = join(homedir(), ".aoaoe");
8
8
  const HISTORY_FILE = join(AOAOE_DIR, "tui-history.jsonl");
9
9
  const HISTORY_OLD = join(AOAOE_DIR, "tui-history.jsonl.old");
10
- const MAX_FILE_SIZE = 500 * 1024; // 500KB rotation threshold
10
+ const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB rotation threshold
11
11
  /**
12
12
  * Append a single history entry to the JSONL file.
13
13
  * Fire-and-forget — errors are silently swallowed so they never block the TUI.
@@ -29,27 +29,29 @@ export function appendHistoryEntry(entry, filePath = HISTORY_FILE, maxSize = MAX
29
29
  /**
30
30
  * Load recent TUI history entries from the JSONL file.
31
31
  * Returns the last `maxEntries` entries (default 200), newest last.
32
+ * Filters out entries older than `maxAgeMs` (default: 7 days).
32
33
  * Returns empty array if the file doesn't exist or is unreadable.
33
34
  */
34
- export function loadTuiHistory(maxEntries = 200, filePath = HISTORY_FILE) {
35
+ export function loadTuiHistory(maxEntries = 200, filePath = HISTORY_FILE, maxAgeMs = 7 * 24 * 60 * 60 * 1000) {
35
36
  try {
36
37
  if (!existsSync(filePath))
37
38
  return [];
38
39
  const content = readFileSync(filePath, "utf-8");
39
40
  const lines = content.split("\n").filter((l) => l.trim());
40
- const recent = lines.slice(-maxEntries);
41
+ const cutoff = Date.now() - maxAgeMs;
42
+ const recent = lines.slice(-maxEntries * 2); // read extra to compensate for age filtering
41
43
  const entries = [];
42
44
  for (const line of recent) {
43
45
  try {
44
46
  const parsed = JSON.parse(line);
45
- if (isValidEntry(parsed))
47
+ if (isValidEntry(parsed) && parsed.ts >= cutoff)
46
48
  entries.push(parsed);
47
49
  }
48
50
  catch {
49
51
  // skip malformed lines
50
52
  }
51
53
  }
52
- return entries;
54
+ return entries.slice(-maxEntries);
53
55
  }
54
56
  catch {
55
57
  return [];
package/dist/types.d.ts CHANGED
@@ -122,6 +122,7 @@ export interface AoaoeConfig {
122
122
  maxRetries?: number;
123
123
  };
124
124
  healthPort?: number;
125
+ tuiHistoryRetentionDays?: number;
125
126
  }
126
127
  export type NotificationEvent = "session_error" | "session_done" | "action_executed" | "action_failed" | "daemon_started" | "daemon_stopped";
127
128
  export type DaemonPhase = "sleeping" | "polling" | "reasoning" | "executing" | "interrupted";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aoaoe",
3
- "version": "0.61.0",
3
+ "version": "0.62.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",