aoaoe 0.47.0 → 0.48.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/colors.d.ts +0 -4
- package/dist/colors.js +0 -4
- package/dist/config.js +2 -1
- package/dist/daemon-state.js +2 -1
- package/dist/index.js +2 -0
- package/dist/init.js +4 -1
- package/dist/prompt-watcher.js +1 -1
- package/dist/reasoner/opencode.js +3 -1
- package/dist/reasoner/prompt.js +1 -1
- package/dist/task-cli.js +2 -1
- package/dist/task-manager.js +11 -7
- package/dist/types.d.ts +7 -0
- package/dist/types.js +75 -0
- package/package.json +1 -1
package/dist/colors.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export declare const RESET = "\u001B[0m";
|
|
2
2
|
export declare const BOLD = "\u001B[1m";
|
|
3
3
|
export declare const DIM = "\u001B[2m";
|
|
4
|
-
export declare const ITALIC = "\u001B[3m";
|
|
5
4
|
export declare const RED = "\u001B[31m";
|
|
6
5
|
export declare const GREEN = "\u001B[32m";
|
|
7
6
|
export declare const YELLOW = "\u001B[33m";
|
|
@@ -15,9 +14,6 @@ export declare const ROSE = "\u001B[38;5;204m";
|
|
|
15
14
|
export declare const LIME = "\u001B[38;5;114m";
|
|
16
15
|
export declare const SKY = "\u001B[38;5;117m";
|
|
17
16
|
export declare const BG_DARK = "\u001B[48;5;236m";
|
|
18
|
-
export declare const BG_DARKER = "\u001B[48;5;234m";
|
|
19
|
-
export declare const BG_PANEL = "\u001B[48;5;237m";
|
|
20
|
-
export declare const BG_HIGHLIGHT = "\u001B[48;5;238m";
|
|
21
17
|
export declare const BOX: {
|
|
22
18
|
readonly tl: "┌";
|
|
23
19
|
readonly tr: "┐";
|
package/dist/colors.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
export const RESET = "\x1b[0m";
|
|
4
4
|
export const BOLD = "\x1b[1m";
|
|
5
5
|
export const DIM = "\x1b[2m";
|
|
6
|
-
export const ITALIC = "\x1b[3m";
|
|
7
6
|
export const RED = "\x1b[31m";
|
|
8
7
|
export const GREEN = "\x1b[32m";
|
|
9
8
|
export const YELLOW = "\x1b[33m";
|
|
@@ -20,9 +19,6 @@ export const LIME = "\x1b[38;5;114m"; // fresh green for success/working
|
|
|
20
19
|
export const SKY = "\x1b[38;5;117m"; // light blue for reasoning
|
|
21
20
|
// background variants (256-color)
|
|
22
21
|
export const BG_DARK = "\x1b[48;5;236m"; // dark gray for header bar
|
|
23
|
-
export const BG_DARKER = "\x1b[48;5;234m"; // near-black for contrast panels
|
|
24
|
-
export const BG_PANEL = "\x1b[48;5;237m"; // subtle panel background
|
|
25
|
-
export const BG_HIGHLIGHT = "\x1b[48;5;238m"; // highlight row
|
|
26
22
|
// box-drawing characters — Unicode block elements
|
|
27
23
|
export const BOX = {
|
|
28
24
|
tl: "┌", tr: "┐", bl: "└", br: "┘",
|
package/dist/config.js
CHANGED
|
@@ -3,6 +3,7 @@ import { resolve, join } from "node:path";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { execFile as execFileCb } from "node:child_process";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
|
+
import { toReasonerBackend } from "./types.js";
|
|
6
7
|
const execFileAsync = promisify(execFileCb);
|
|
7
8
|
const AOAOE_DIR = join(homedir(), ".aoaoe");
|
|
8
9
|
const CONFIG_NAMES = ["aoaoe.config.json", ".aoaoe.json"];
|
|
@@ -250,7 +251,7 @@ export function parseCliArgs(argv) {
|
|
|
250
251
|
const arg = argv[i];
|
|
251
252
|
switch (arg) {
|
|
252
253
|
case "--reasoner":
|
|
253
|
-
overrides.reasoner = nextArg(i, arg);
|
|
254
|
+
overrides.reasoner = toReasonerBackend(nextArg(i, arg));
|
|
254
255
|
i++;
|
|
255
256
|
break;
|
|
256
257
|
case "--poll-interval": {
|
package/dist/daemon-state.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { writeFileSync, readFileSync, existsSync, unlinkSync, mkdirSync, renameSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
|
+
import { toDaemonState } from "./types.js";
|
|
7
8
|
import { parseTasks, formatTaskList } from "./task-parser.js";
|
|
8
9
|
const AOAOE_DIR = join(homedir(), ".aoaoe");
|
|
9
10
|
const STATE_FILE = join(AOAOE_DIR, "daemon-state.json");
|
|
@@ -122,7 +123,7 @@ export function readState() {
|
|
|
122
123
|
try {
|
|
123
124
|
if (!existsSync(STATE_FILE))
|
|
124
125
|
return null;
|
|
125
|
-
return JSON.parse(readFileSync(STATE_FILE, "utf-8"));
|
|
126
|
+
return toDaemonState(JSON.parse(readFileSync(STATE_FILE, "utf-8")));
|
|
126
127
|
}
|
|
127
128
|
catch {
|
|
128
129
|
return null;
|
package/dist/index.js
CHANGED
|
@@ -467,6 +467,8 @@ async function main() {
|
|
|
467
467
|
else {
|
|
468
468
|
// ── normal mode: full tick ─────────────────────────────────────────
|
|
469
469
|
const activeTaskContext = taskManager ? taskManager.tasks.filter((t) => t.status !== "completed") : undefined;
|
|
470
|
+
if (!reasoner || !executor)
|
|
471
|
+
throw new Error("reasoner/executor unexpectedly null in normal mode");
|
|
470
472
|
const { interrupted, decisionsThisTick, actionsOk, actionsFail } = await daemonTick(config, poller, reasoner, executor, reasonerConsole, pollCount, policyStates, userMessage, forceDashboard, activeTaskContext, taskManager, tui);
|
|
471
473
|
totalDecisions += decisionsThisTick;
|
|
472
474
|
totalActionsExecuted += actionsOk;
|
package/dist/init.js
CHANGED
|
@@ -36,7 +36,10 @@ async function discoverSessions() {
|
|
|
36
36
|
if (result.exitCode !== 0)
|
|
37
37
|
return [];
|
|
38
38
|
try {
|
|
39
|
-
const
|
|
39
|
+
const parsed = JSON.parse(result.stdout);
|
|
40
|
+
if (!Array.isArray(parsed))
|
|
41
|
+
return [];
|
|
42
|
+
const raw = parsed;
|
|
40
43
|
// fetch status for each session in parallel (allSettled so one failure doesn't kill all)
|
|
41
44
|
const results = await Promise.allSettled(raw.map(async (r) => {
|
|
42
45
|
const id = String(r.id ?? "");
|
package/dist/prompt-watcher.js
CHANGED
|
@@ -80,6 +80,8 @@ export class OpencodeReasoner {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
async decideViaSDK(prompt, signal) {
|
|
83
|
+
if (!this.client)
|
|
84
|
+
throw new Error("decideViaSDK called without a connected client");
|
|
83
85
|
const client = this.client;
|
|
84
86
|
// create session on first call, after rotation, or after error reset
|
|
85
87
|
if (!this.sessionId) {
|
|
@@ -281,7 +283,7 @@ class OpencodeClient {
|
|
|
281
283
|
// extract text from assistant response parts
|
|
282
284
|
const textParts = (data.parts ?? [])
|
|
283
285
|
.filter((p) => p.type === "text" && p.text)
|
|
284
|
-
.map((p) => p.text);
|
|
286
|
+
.map((p) => p.text ?? "");
|
|
285
287
|
return textParts.join("\n");
|
|
286
288
|
}
|
|
287
289
|
}
|
package/dist/reasoner/prompt.js
CHANGED
|
@@ -160,7 +160,7 @@ export function formatObservation(obs) {
|
|
|
160
160
|
parts.push("Project context for sessions:");
|
|
161
161
|
let contextBudget = 50_000; // max bytes for all project context combined
|
|
162
162
|
for (const snap of sortedContextSessions) {
|
|
163
|
-
const ctx = snap.projectContext;
|
|
163
|
+
const ctx = snap.projectContext ?? "";
|
|
164
164
|
const ctxBytes = Buffer.byteLength(ctx, "utf-8");
|
|
165
165
|
if (ctxBytes > contextBudget) {
|
|
166
166
|
// truncate this context to fit remaining budget
|
package/dist/task-cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { exec } from "./shell.js";
|
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { resolve, basename } from "node:path";
|
|
6
6
|
import { loadTaskState, saveTaskState, formatTaskTable } from "./task-manager.js";
|
|
7
|
+
import { toAoeSessionList } from "./types.js";
|
|
7
8
|
import { BOLD, DIM, GREEN, YELLOW, RED, RESET } from "./colors.js";
|
|
8
9
|
// resolve a fuzzy reference to a task: match by title, repo basename, or session ID prefix
|
|
9
10
|
export function resolveTask(ref, tasks) {
|
|
@@ -112,7 +113,7 @@ export async function taskNew(title, path, tool = "opencode") {
|
|
|
112
113
|
let sessionId;
|
|
113
114
|
if (listResult.exitCode === 0) {
|
|
114
115
|
try {
|
|
115
|
-
const sessions = JSON.parse(listResult.stdout);
|
|
116
|
+
const sessions = toAoeSessionList(JSON.parse(listResult.stdout));
|
|
116
117
|
const found = sessions.find((s) => s.title.toLowerCase() === lower);
|
|
117
118
|
sessionId = found?.id;
|
|
118
119
|
}
|
package/dist/task-manager.js
CHANGED
|
@@ -5,6 +5,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from "
|
|
|
5
5
|
import { join, resolve, basename } from "node:path";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { exec } from "./shell.js";
|
|
8
|
+
import { toTaskState, toAoeSessionList } from "./types.js";
|
|
8
9
|
import { RESET, BOLD, DIM, GREEN, YELLOW, RED, CYAN } from "./colors.js";
|
|
9
10
|
const AOAOE_DIR = join(homedir(), ".aoaoe");
|
|
10
11
|
const STATE_FILE = join(AOAOE_DIR, "task-state.json");
|
|
@@ -84,8 +85,9 @@ export function loadTaskState() {
|
|
|
84
85
|
const raw = JSON.parse(readFileSync(STATE_FILE, "utf-8"));
|
|
85
86
|
if (raw && typeof raw.tasks === "object") {
|
|
86
87
|
for (const [repo, state] of Object.entries(raw.tasks)) {
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
const validated = toTaskState(state);
|
|
89
|
+
if (validated) {
|
|
90
|
+
map.set(repo, validated);
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
}
|
|
@@ -138,10 +140,12 @@ export class TaskManager {
|
|
|
138
140
|
else {
|
|
139
141
|
// update goal/tool if definition changed (don't reset progress)
|
|
140
142
|
const existing = this.states.get(def.repo);
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
if (existing) {
|
|
144
|
+
if (def.goal)
|
|
145
|
+
existing.goal = def.goal;
|
|
146
|
+
if (def.tool)
|
|
147
|
+
existing.tool = def.tool;
|
|
148
|
+
}
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
this.save();
|
|
@@ -201,7 +205,7 @@ export class TaskManager {
|
|
|
201
205
|
const refreshResult = await exec("aoe", ["list", "--json"]);
|
|
202
206
|
if (refreshResult.exitCode === 0) {
|
|
203
207
|
try {
|
|
204
|
-
const refreshed = JSON.parse(refreshResult.stdout);
|
|
208
|
+
const refreshed = toAoeSessionList(JSON.parse(refreshResult.stdout));
|
|
205
209
|
const newSession = refreshed.find((s) => s.title.toLowerCase() === task.sessionTitle.toLowerCase());
|
|
206
210
|
if (newSession) {
|
|
207
211
|
task.sessionId = newSession.id;
|
package/dist/types.d.ts
CHANGED
|
@@ -162,4 +162,11 @@ export interface TaskState {
|
|
|
162
162
|
completedAt?: number;
|
|
163
163
|
progress: TaskProgress[];
|
|
164
164
|
}
|
|
165
|
+
export declare function toTaskState(raw: unknown): TaskState | null;
|
|
166
|
+
export declare function toDaemonState(raw: unknown): DaemonState | null;
|
|
167
|
+
export declare function toAoeSessionList(raw: unknown): Array<{
|
|
168
|
+
id: string;
|
|
169
|
+
title: string;
|
|
170
|
+
}>;
|
|
171
|
+
export declare function toReasonerBackend(raw: string): ReasonerBackend;
|
|
165
172
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
CHANGED
|
@@ -37,4 +37,79 @@ export function actionDetail(action) {
|
|
|
37
37
|
return undefined;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
+
const VALID_TASK_STATUSES = new Set(["pending", "active", "completed", "paused", "failed"]);
|
|
41
|
+
// validate an unknown value (e.g. from JSON.parse) as a TaskState, returning null if invalid
|
|
42
|
+
export function toTaskState(raw) {
|
|
43
|
+
if (!raw || typeof raw !== "object")
|
|
44
|
+
return null;
|
|
45
|
+
const r = raw;
|
|
46
|
+
if (typeof r.repo !== "string" || !r.repo)
|
|
47
|
+
return null;
|
|
48
|
+
if (typeof r.sessionTitle !== "string")
|
|
49
|
+
return null;
|
|
50
|
+
if (typeof r.tool !== "string")
|
|
51
|
+
return null;
|
|
52
|
+
if (typeof r.goal !== "string")
|
|
53
|
+
return null;
|
|
54
|
+
if (typeof r.status !== "string" || !VALID_TASK_STATUSES.has(r.status))
|
|
55
|
+
return null;
|
|
56
|
+
if (!Array.isArray(r.progress))
|
|
57
|
+
return null;
|
|
58
|
+
return {
|
|
59
|
+
repo: r.repo,
|
|
60
|
+
sessionTitle: r.sessionTitle,
|
|
61
|
+
tool: r.tool,
|
|
62
|
+
goal: r.goal,
|
|
63
|
+
status: r.status,
|
|
64
|
+
sessionId: typeof r.sessionId === "string" ? r.sessionId : undefined,
|
|
65
|
+
createdAt: typeof r.createdAt === "number" ? r.createdAt : undefined,
|
|
66
|
+
lastProgressAt: typeof r.lastProgressAt === "number" ? r.lastProgressAt : undefined,
|
|
67
|
+
completedAt: typeof r.completedAt === "number" ? r.completedAt : undefined,
|
|
68
|
+
progress: r.progress.filter((p) => !!p && typeof p === "object" &&
|
|
69
|
+
typeof p.at === "number" &&
|
|
70
|
+
typeof p.summary === "string"),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// validate an unknown value as a DaemonState, returning null if invalid
|
|
74
|
+
export function toDaemonState(raw) {
|
|
75
|
+
if (!raw || typeof raw !== "object")
|
|
76
|
+
return null;
|
|
77
|
+
const r = raw;
|
|
78
|
+
if (typeof r.tickStartedAt !== "number")
|
|
79
|
+
return null;
|
|
80
|
+
if (typeof r.nextTickAt !== "number")
|
|
81
|
+
return null;
|
|
82
|
+
if (typeof r.pollIntervalMs !== "number")
|
|
83
|
+
return null;
|
|
84
|
+
if (typeof r.phase !== "string")
|
|
85
|
+
return null;
|
|
86
|
+
if (typeof r.phaseStartedAt !== "number")
|
|
87
|
+
return null;
|
|
88
|
+
if (typeof r.pollCount !== "number")
|
|
89
|
+
return null;
|
|
90
|
+
if (typeof r.paused !== "boolean")
|
|
91
|
+
return null;
|
|
92
|
+
if (typeof r.sessionCount !== "number")
|
|
93
|
+
return null;
|
|
94
|
+
if (typeof r.changeCount !== "number")
|
|
95
|
+
return null;
|
|
96
|
+
if (!Array.isArray(r.sessions))
|
|
97
|
+
return null;
|
|
98
|
+
return raw;
|
|
99
|
+
}
|
|
100
|
+
// validate an unknown array as an AoE session list (from `aoe list --json`)
|
|
101
|
+
export function toAoeSessionList(raw) {
|
|
102
|
+
if (!Array.isArray(raw))
|
|
103
|
+
return [];
|
|
104
|
+
return raw.filter((item) => !!item && typeof item === "object" &&
|
|
105
|
+
typeof item.id === "string" &&
|
|
106
|
+
typeof item.title === "string");
|
|
107
|
+
}
|
|
108
|
+
// validate a string as a ReasonerBackend, throwing on invalid input
|
|
109
|
+
const VALID_REASONER_BACKENDS = new Set(["opencode", "claude-code"]);
|
|
110
|
+
export function toReasonerBackend(raw) {
|
|
111
|
+
if (VALID_REASONER_BACKENDS.has(raw))
|
|
112
|
+
return raw;
|
|
113
|
+
throw new Error(`--reasoner must be "opencode" or "claude-code", got "${raw}"`);
|
|
114
|
+
}
|
|
40
115
|
//# sourceMappingURL=types.js.map
|