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 +1 -0
- package/dist/config.js +12 -1
- package/dist/index.js +3 -1
- package/dist/tui-history.d.ts +2 -1
- package/dist/tui-history.js +8 -6
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
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
|
|
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");
|
package/dist/tui-history.d.ts
CHANGED
|
@@ -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.
|
package/dist/tui-history.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// tui-history.ts — persisted TUI activity history
|
|
2
|
-
// JSONL file at ~/.aoaoe/tui-history.jsonl with rotation at
|
|
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 =
|
|
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
|
|
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";
|