@hilbras/omninode 0.10.0 → 2.0.0-alpha.1
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 +46 -7
- package/dist/cli/index.js +271 -254
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +192 -31
- package/dist/index.js +233 -233
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -130,6 +130,7 @@ var agentConfigSchema = z.object({
|
|
|
130
130
|
env: z.record(z.string()).optional(),
|
|
131
131
|
input_mode: z.enum(["stdin", "arg", "protocol"]).default("stdin"),
|
|
132
132
|
timeout_ms: z.number().int().positive().optional(),
|
|
133
|
+
inherit_env: z.boolean().optional(),
|
|
133
134
|
metadata: z.record(z.unknown()).optional()
|
|
134
135
|
}).strict();
|
|
135
136
|
var roleConfigSchema = z.object({
|
|
@@ -303,6 +304,7 @@ function toAgentConfig(raw) {
|
|
|
303
304
|
env: raw.env,
|
|
304
305
|
inputMode: raw.input_mode,
|
|
305
306
|
timeoutMs: raw.timeout_ms,
|
|
307
|
+
inheritEnv: raw.inherit_env,
|
|
306
308
|
metadata: raw.metadata
|
|
307
309
|
};
|
|
308
310
|
}
|
|
@@ -664,6 +666,17 @@ var ModelRegistry = class {
|
|
|
664
666
|
import { spawn } from "child_process";
|
|
665
667
|
var DEFAULT_TIMEOUT_MS2 = 6e5;
|
|
666
668
|
var KILL_GRACE_MS = 5e3;
|
|
669
|
+
function buildChildEnv(config) {
|
|
670
|
+
const configured = config.env ?? {};
|
|
671
|
+
if (config.inheritEnv !== false) {
|
|
672
|
+
return { ...process.env, ...configured };
|
|
673
|
+
}
|
|
674
|
+
return {
|
|
675
|
+
PATH: process.env.PATH ?? "",
|
|
676
|
+
HOME: process.env.HOME ?? "",
|
|
677
|
+
...configured
|
|
678
|
+
};
|
|
679
|
+
}
|
|
667
680
|
function composeTaskText(input) {
|
|
668
681
|
const sections = [`# Objective
|
|
669
682
|
${input.objective}`];
|
|
@@ -730,7 +743,7 @@ var ProcessAgent = class {
|
|
|
730
743
|
[...this.config.args ?? [], ...mode === "arg" ? [composeTaskText(input)] : []],
|
|
731
744
|
{
|
|
732
745
|
cwd: this.config.cwd,
|
|
733
|
-
env:
|
|
746
|
+
env: buildChildEnv(this.config),
|
|
734
747
|
stdio: ["pipe", "pipe", "pipe"]
|
|
735
748
|
}
|
|
736
749
|
);
|
|
@@ -974,40 +987,54 @@ function buildRoleRegistry(config) {
|
|
|
974
987
|
return registry;
|
|
975
988
|
}
|
|
976
989
|
|
|
977
|
-
// src/
|
|
990
|
+
// src/persistence/json-file-store.ts
|
|
978
991
|
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
979
992
|
import { dirname } from "path";
|
|
980
|
-
var
|
|
993
|
+
var JsonFileStore = class {
|
|
981
994
|
filePath;
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
*/
|
|
995
|
+
schemaVersion;
|
|
996
|
+
onCorrupt;
|
|
997
|
+
log;
|
|
986
998
|
queue = Promise.resolve();
|
|
987
|
-
constructor(
|
|
988
|
-
this.filePath = `${directory}
|
|
999
|
+
constructor(options) {
|
|
1000
|
+
this.filePath = `${options.directory ?? `${process.cwd()}/.omninode`}/${options.fileName}`;
|
|
1001
|
+
this.schemaVersion = options.schemaVersion ?? 1;
|
|
1002
|
+
this.onCorrupt = options.onCorrupt;
|
|
1003
|
+
this.log = logger.child({ component: "persistence", file: options.fileName });
|
|
989
1004
|
}
|
|
990
|
-
|
|
991
|
-
return this.
|
|
992
|
-
const tasks = await this.load();
|
|
993
|
-
const index = tasks.findIndex((t) => t.id === task.id);
|
|
994
|
-
if (index >= 0) tasks[index] = task;
|
|
995
|
-
else tasks.push(task);
|
|
996
|
-
await this.write(tasks);
|
|
997
|
-
});
|
|
1005
|
+
get path() {
|
|
1006
|
+
return this.filePath;
|
|
998
1007
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1008
|
+
/** All items, or [] when missing/corrupt. */
|
|
1009
|
+
async readAll() {
|
|
1010
|
+
let raw;
|
|
1011
|
+
try {
|
|
1012
|
+
raw = await readFile(this.filePath, "utf8");
|
|
1013
|
+
} catch {
|
|
1014
|
+
return [];
|
|
1015
|
+
}
|
|
1016
|
+
try {
|
|
1017
|
+
const parsed = JSON.parse(raw);
|
|
1018
|
+
if (Array.isArray(parsed)) return parsed;
|
|
1019
|
+
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.items)) {
|
|
1020
|
+
return parsed.items;
|
|
1021
|
+
}
|
|
1022
|
+
throw new Error("persisted file has an unrecognized shape");
|
|
1023
|
+
} catch (error) {
|
|
1024
|
+
this.log.warn(`Treating ${this.filePath} as empty \u2014 it could not be parsed.`);
|
|
1025
|
+
this.onCorrupt?.(this.filePath, error);
|
|
1026
|
+
return [];
|
|
1027
|
+
}
|
|
1004
1028
|
}
|
|
1005
|
-
async
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
}
|
|
1029
|
+
async writeAll(items) {
|
|
1030
|
+
const document = { schemaVersion: this.schemaVersion, items };
|
|
1031
|
+
const tmp = `${this.filePath}.tmp`;
|
|
1032
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
1033
|
+
await writeFile(tmp, `${JSON.stringify(document, null, 2)}
|
|
1034
|
+
`, "utf8");
|
|
1035
|
+
await rename(tmp, this.filePath);
|
|
1010
1036
|
}
|
|
1037
|
+
/** Serializes an async operation against this file. */
|
|
1011
1038
|
synchronized(operation) {
|
|
1012
1039
|
const result = this.queue.then(operation, operation);
|
|
1013
1040
|
this.queue = result.then(
|
|
@@ -1016,21 +1043,37 @@ var FileTaskStore = class {
|
|
|
1016
1043
|
);
|
|
1017
1044
|
return result;
|
|
1018
1045
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
return
|
|
1026
|
-
}
|
|
1046
|
+
/** Read-modify-write helper: applies `mutate` to the current items. */
|
|
1047
|
+
async mutate(mutate) {
|
|
1048
|
+
return this.synchronized(async () => {
|
|
1049
|
+
const items = await this.readAll();
|
|
1050
|
+
const [next, result] = await mutate(items);
|
|
1051
|
+
await this.writeAll(next);
|
|
1052
|
+
return result;
|
|
1053
|
+
});
|
|
1027
1054
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
// src/tasks/store.ts
|
|
1058
|
+
var FileTaskStore = class extends JsonFileStore {
|
|
1059
|
+
constructor(directory) {
|
|
1060
|
+
super({ ...directory !== void 0 ? { directory } : {}, fileName: "tasks.json" });
|
|
1061
|
+
}
|
|
1062
|
+
save(task) {
|
|
1063
|
+
return this.mutate((tasks) => {
|
|
1064
|
+
const index = tasks.findIndex((t) => t.id === task.id);
|
|
1065
|
+
if (index >= 0) tasks[index] = task;
|
|
1066
|
+
else tasks.push(task);
|
|
1067
|
+
return [tasks, void 0];
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
async get(id) {
|
|
1071
|
+
const tasks = await this.readAll();
|
|
1072
|
+
return tasks.find((t) => t.id === id);
|
|
1073
|
+
}
|
|
1074
|
+
async list(filter = {}) {
|
|
1075
|
+
const tasks = await this.readAll();
|
|
1076
|
+
return tasks.filter((task) => filter.status ? task.status === filter.status : true).filter((task) => filter.project ? task.project === filter.project : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
1034
1077
|
}
|
|
1035
1078
|
};
|
|
1036
1079
|
|
|
@@ -1085,6 +1128,7 @@ var TaskEngine = class {
|
|
|
1085
1128
|
};
|
|
1086
1129
|
await this.options.store.save(task);
|
|
1087
1130
|
this.log.info(`Created task ${task.id}.`);
|
|
1131
|
+
await this.audit("task.created", task.id, { objective: task.objective, project: task.project });
|
|
1088
1132
|
return task;
|
|
1089
1133
|
}
|
|
1090
1134
|
async queue(id) {
|
|
@@ -1176,6 +1220,7 @@ var TaskEngine = class {
|
|
|
1176
1220
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1177
1221
|
};
|
|
1178
1222
|
await this.options.store.save(reset);
|
|
1223
|
+
await this.audit("task.retry", id, { from: task.status });
|
|
1179
1224
|
this.log.info(`Task ${id} reset for retry.`);
|
|
1180
1225
|
return reset;
|
|
1181
1226
|
}
|
|
@@ -1204,16 +1249,66 @@ var TaskEngine = class {
|
|
|
1204
1249
|
...extra.result !== void 0 ? { result: { ...task.result, ...extra.result } } : {}
|
|
1205
1250
|
};
|
|
1206
1251
|
await this.options.store.save(updated);
|
|
1252
|
+
await this.audit(`task.${to === "queued" ? "queued" : to}`, updated.id, {
|
|
1253
|
+
from: task.status
|
|
1254
|
+
});
|
|
1207
1255
|
return updated;
|
|
1208
1256
|
}
|
|
1257
|
+
async audit(action, id, detail) {
|
|
1258
|
+
await this.options.audit?.record({
|
|
1259
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1260
|
+
action,
|
|
1261
|
+
id,
|
|
1262
|
+
...detail !== void 0 ? { detail } : {}
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1209
1265
|
};
|
|
1210
1266
|
function generateTaskId() {
|
|
1211
1267
|
return `task-${Date.now().toString(36)}-${randomBytes(3).toString("hex")}`;
|
|
1212
1268
|
}
|
|
1213
1269
|
|
|
1214
|
-
// src/
|
|
1215
|
-
import { mkdir as mkdir2
|
|
1270
|
+
// src/audit/index.ts
|
|
1271
|
+
import { appendFile, mkdir as mkdir2 } from "fs/promises";
|
|
1216
1272
|
import { dirname as dirname2 } from "path";
|
|
1273
|
+
var FileAuditLog = class {
|
|
1274
|
+
filePath;
|
|
1275
|
+
log;
|
|
1276
|
+
constructor(directory = `${process.cwd()}/.omninode`, log = logger) {
|
|
1277
|
+
this.filePath = `${directory}/audit.jsonl`;
|
|
1278
|
+
this.log = log.child({ component: "audit" });
|
|
1279
|
+
}
|
|
1280
|
+
async record(event) {
|
|
1281
|
+
try {
|
|
1282
|
+
await mkdir2(dirname2(this.filePath), { recursive: true });
|
|
1283
|
+
await appendFile(this.filePath, `${JSON.stringify(event)}
|
|
1284
|
+
`, "utf8");
|
|
1285
|
+
} catch (error) {
|
|
1286
|
+
this.log.warn(
|
|
1287
|
+
`Audit write failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
/** Recent events, oldest first; used by the CLI. */
|
|
1292
|
+
async recent(limit = 20) {
|
|
1293
|
+
const { readFile: readFile2 } = await import("fs/promises");
|
|
1294
|
+
let raw;
|
|
1295
|
+
try {
|
|
1296
|
+
raw = await readFile2(this.filePath, "utf8");
|
|
1297
|
+
} catch {
|
|
1298
|
+
return [];
|
|
1299
|
+
}
|
|
1300
|
+
const events = raw.split("\n").filter((line) => line.length > 0).map((line) => {
|
|
1301
|
+
try {
|
|
1302
|
+
return JSON.parse(line);
|
|
1303
|
+
} catch {
|
|
1304
|
+
return void 0;
|
|
1305
|
+
}
|
|
1306
|
+
}).filter((event) => event !== void 0);
|
|
1307
|
+
return events.slice(-limit);
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
|
|
1311
|
+
// src/memory/local.ts
|
|
1217
1312
|
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
1218
1313
|
"the",
|
|
1219
1314
|
"and",
|
|
@@ -1270,29 +1365,24 @@ function relevanceScore(queryKeywords, entry) {
|
|
|
1270
1365
|
}
|
|
1271
1366
|
return overlap * 2 + tagMatches * 1.5;
|
|
1272
1367
|
}
|
|
1273
|
-
var LocalMemoryProvider = class {
|
|
1368
|
+
var LocalMemoryProvider = class extends JsonFileStore {
|
|
1274
1369
|
name = "local";
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
constructor(directory = `${process.cwd()}/.omninode`) {
|
|
1278
|
-
this.filePath = `${directory}/memory.json`;
|
|
1370
|
+
constructor(directory) {
|
|
1371
|
+
super({ ...directory !== void 0 ? { directory } : {}, fileName: "memory.json" });
|
|
1279
1372
|
}
|
|
1280
1373
|
async query(query) {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
return filtered.map((entry) => ({ entry, score: relevanceScore(queryKeywords, entry) })).filter(({ score }) => score > 0).sort((a, b) => b.score - a.score).slice(0, query.limit ?? 10).map(({ entry }) => entry);
|
|
1291
|
-
});
|
|
1374
|
+
const entries = await this.readAll();
|
|
1375
|
+
const filtered = entries.filter((entry) => query.scope ? entry.scope === query.scope : true).filter(
|
|
1376
|
+
(entry) => query.tags && query.tags.length > 0 ? query.tags.every((tag) => (entry.tags ?? []).includes(tag)) : true
|
|
1377
|
+
);
|
|
1378
|
+
if (!query.text || query.text.trim().length === 0) {
|
|
1379
|
+
return filtered.sort((a, b) => (b.updatedAt ?? b.createdAt ?? "").localeCompare(a.updatedAt ?? a.createdAt ?? "")).slice(0, query.limit ?? 10);
|
|
1380
|
+
}
|
|
1381
|
+
const queryKeywords = keywords(query.text);
|
|
1382
|
+
return filtered.map((entry) => ({ entry, score: relevanceScore(queryKeywords, entry) })).filter(({ score }) => score > 0).sort((a, b) => b.score - a.score).slice(0, query.limit ?? 10).map(({ entry }) => entry);
|
|
1292
1383
|
}
|
|
1293
|
-
|
|
1294
|
-
return this.
|
|
1295
|
-
const entries = await this.load();
|
|
1384
|
+
write(entry) {
|
|
1385
|
+
return this.mutate((entries) => {
|
|
1296
1386
|
const index = entries.findIndex((e) => e.key === entry.key);
|
|
1297
1387
|
const stamped = {
|
|
1298
1388
|
...entry,
|
|
@@ -1301,35 +1391,11 @@ var LocalMemoryProvider = class {
|
|
|
1301
1391
|
};
|
|
1302
1392
|
if (index >= 0) entries[index] = stamped;
|
|
1303
1393
|
else entries.push(stamped);
|
|
1304
|
-
|
|
1394
|
+
return [entries, void 0];
|
|
1305
1395
|
});
|
|
1306
1396
|
}
|
|
1307
1397
|
async count() {
|
|
1308
|
-
return (await this.
|
|
1309
|
-
}
|
|
1310
|
-
synchronized(operation) {
|
|
1311
|
-
const result = this.queue.then(operation, operation);
|
|
1312
|
-
this.queue = result.then(
|
|
1313
|
-
() => void 0,
|
|
1314
|
-
() => void 0
|
|
1315
|
-
);
|
|
1316
|
-
return result;
|
|
1317
|
-
}
|
|
1318
|
-
async load() {
|
|
1319
|
-
try {
|
|
1320
|
-
const raw = await readFile2(this.filePath, "utf8");
|
|
1321
|
-
const parsed = JSON.parse(raw);
|
|
1322
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
1323
|
-
} catch {
|
|
1324
|
-
return [];
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
async saveAll(entries) {
|
|
1328
|
-
const tmp = `${this.filePath}.tmp`;
|
|
1329
|
-
await mkdir2(dirname2(this.filePath), { recursive: true });
|
|
1330
|
-
await writeFile2(tmp, `${JSON.stringify(entries, null, 2)}
|
|
1331
|
-
`, "utf8");
|
|
1332
|
-
await rename2(tmp, this.filePath);
|
|
1398
|
+
return (await this.readAll()).length;
|
|
1333
1399
|
}
|
|
1334
1400
|
};
|
|
1335
1401
|
|
|
@@ -1511,6 +1577,7 @@ function createTaskEngine(config, log = logger, directory) {
|
|
|
1511
1577
|
roles,
|
|
1512
1578
|
store: new FileTaskStore(directory),
|
|
1513
1579
|
...config.project.memory !== void 0 ? { memory: new MemoryService(createMemoryProvider(config.project.memory), log) } : {},
|
|
1580
|
+
audit: new FileAuditLog(),
|
|
1514
1581
|
log
|
|
1515
1582
|
});
|
|
1516
1583
|
}
|
|
@@ -1862,6 +1929,12 @@ var PipelineEngine = class {
|
|
|
1862
1929
|
};
|
|
1863
1930
|
await this.options.store.save(run);
|
|
1864
1931
|
this.log.info(`Running pipeline ${def.id} as ${run.id}.`);
|
|
1932
|
+
await this.options.audit?.record({
|
|
1933
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1934
|
+
action: "pipeline.run.started",
|
|
1935
|
+
id: run.id,
|
|
1936
|
+
detail: { pipeline: def.id, objective }
|
|
1937
|
+
});
|
|
1865
1938
|
const deps = this.effectiveDependencies(def);
|
|
1866
1939
|
const outcomes = /* @__PURE__ */ new Map();
|
|
1867
1940
|
const pending = new Set(def.steps.map((s) => s.id));
|
|
@@ -1952,6 +2025,12 @@ ${contribution}`);
|
|
|
1952
2025
|
};
|
|
1953
2026
|
await this.options.store.save(finished);
|
|
1954
2027
|
this.log.info(`Pipeline ${def.id} finished: ${finalStatus}.`);
|
|
2028
|
+
await this.options.audit?.record({
|
|
2029
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2030
|
+
action: "pipeline.run.finished",
|
|
2031
|
+
id: run.id,
|
|
2032
|
+
detail: { pipeline: def.id, status: finalStatus }
|
|
2033
|
+
});
|
|
1955
2034
|
return finished;
|
|
1956
2035
|
}
|
|
1957
2036
|
async get(runId) {
|
|
@@ -2096,6 +2175,12 @@ ${contribution}`);
|
|
|
2096
2175
|
};
|
|
2097
2176
|
}
|
|
2098
2177
|
await this.options.plans?.save(plan);
|
|
2178
|
+
await this.options.audit?.record({
|
|
2179
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2180
|
+
action: "plan.generated",
|
|
2181
|
+
id: plan.id,
|
|
2182
|
+
detail: { generatedBy: plan.generatedBy, steps: plan.steps.length }
|
|
2183
|
+
});
|
|
2099
2184
|
return {
|
|
2100
2185
|
status: "completed",
|
|
2101
2186
|
summary: plan.summary,
|
|
@@ -2153,114 +2238,44 @@ function createDefaultChatFn(providers) {
|
|
|
2153
2238
|
}
|
|
2154
2239
|
|
|
2155
2240
|
// src/pipelines/store.ts
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
filePath;
|
|
2160
|
-
queue = Promise.resolve();
|
|
2161
|
-
constructor(directory = `${process.cwd()}/.omninode`) {
|
|
2162
|
-
this.filePath = `${directory}/pipelines.json`;
|
|
2241
|
+
var FilePipelineRunStore = class extends JsonFileStore {
|
|
2242
|
+
constructor(directory) {
|
|
2243
|
+
super({ ...directory !== void 0 ? { directory } : {}, fileName: "pipelines.json" });
|
|
2163
2244
|
}
|
|
2164
|
-
|
|
2165
|
-
return this.
|
|
2166
|
-
const runs = await this.load();
|
|
2245
|
+
save(run) {
|
|
2246
|
+
return this.mutate((runs) => {
|
|
2167
2247
|
const index = runs.findIndex((r) => r.id === run.id);
|
|
2168
2248
|
if (index >= 0) runs[index] = run;
|
|
2169
2249
|
else runs.push(run);
|
|
2170
|
-
|
|
2250
|
+
return [runs, void 0];
|
|
2171
2251
|
});
|
|
2172
2252
|
}
|
|
2173
2253
|
async get(id) {
|
|
2174
|
-
return this.
|
|
2175
|
-
const runs = await this.load();
|
|
2176
|
-
return runs.find((r) => r.id === id);
|
|
2177
|
-
});
|
|
2254
|
+
return (await this.readAll()).find((r) => r.id === id);
|
|
2178
2255
|
}
|
|
2179
2256
|
async list(filter = {}) {
|
|
2180
|
-
return this.
|
|
2181
|
-
const runs = await this.load();
|
|
2182
|
-
return runs.filter((run) => filter.pipelineId ? run.pipelineId === filter.pipelineId : true).filter((run) => filter.status ? run.status === filter.status : true).sort((a, b) => (a.startedAt ?? "").localeCompare(b.startedAt ?? ""));
|
|
2183
|
-
});
|
|
2184
|
-
}
|
|
2185
|
-
synchronized(operation) {
|
|
2186
|
-
const result = this.queue.then(operation, operation);
|
|
2187
|
-
this.queue = result.then(
|
|
2188
|
-
() => void 0,
|
|
2189
|
-
() => void 0
|
|
2190
|
-
);
|
|
2191
|
-
return result;
|
|
2192
|
-
}
|
|
2193
|
-
async load() {
|
|
2194
|
-
try {
|
|
2195
|
-
const raw = await readFile3(this.filePath, "utf8");
|
|
2196
|
-
const parsed = JSON.parse(raw);
|
|
2197
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
2198
|
-
} catch {
|
|
2199
|
-
return [];
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
async write(runs) {
|
|
2203
|
-
const tmp = `${this.filePath}.tmp`;
|
|
2204
|
-
await mkdir3(dirname3(this.filePath), { recursive: true });
|
|
2205
|
-
await writeFile3(tmp, `${JSON.stringify(runs, null, 2)}
|
|
2206
|
-
`, "utf8");
|
|
2207
|
-
await rename3(tmp, this.filePath);
|
|
2257
|
+
return (await this.readAll()).filter((run) => filter.pipelineId ? run.pipelineId === filter.pipelineId : true).filter((run) => filter.status ? run.status === filter.status : true).sort((a, b) => (a.startedAt ?? "").localeCompare(b.startedAt ?? ""));
|
|
2208
2258
|
}
|
|
2209
2259
|
};
|
|
2210
2260
|
|
|
2211
2261
|
// src/planner/store.ts
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
filePath;
|
|
2216
|
-
queue = Promise.resolve();
|
|
2217
|
-
constructor(directory = `${process.cwd()}/.omninode`) {
|
|
2218
|
-
this.filePath = `${directory}/plans.json`;
|
|
2262
|
+
var FilePlanStore = class extends JsonFileStore {
|
|
2263
|
+
constructor(directory) {
|
|
2264
|
+
super({ ...directory !== void 0 ? { directory } : {}, fileName: "plans.json" });
|
|
2219
2265
|
}
|
|
2220
|
-
|
|
2221
|
-
return this.
|
|
2222
|
-
const plans = await this.load();
|
|
2266
|
+
save(plan) {
|
|
2267
|
+
return this.mutate((plans) => {
|
|
2223
2268
|
const index = plans.findIndex((p) => p.id === plan.id);
|
|
2224
2269
|
if (index >= 0) plans[index] = plan;
|
|
2225
2270
|
else plans.push(plan);
|
|
2226
|
-
|
|
2271
|
+
return [plans, void 0];
|
|
2227
2272
|
});
|
|
2228
2273
|
}
|
|
2229
2274
|
async get(id) {
|
|
2230
|
-
return this.
|
|
2231
|
-
const plans = await this.load();
|
|
2232
|
-
return plans.find((p) => p.id === id);
|
|
2233
|
-
});
|
|
2275
|
+
return (await this.readAll()).find((p) => p.id === id);
|
|
2234
2276
|
}
|
|
2235
2277
|
async list(filter = {}) {
|
|
2236
|
-
return this.
|
|
2237
|
-
const plans = await this.load();
|
|
2238
|
-
return plans.filter((plan) => filter.pipelineRunId ? plan.pipelineRunId === filter.pipelineRunId : true).filter((plan) => filter.taskId ? plan.taskId === filter.taskId : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2239
|
-
});
|
|
2240
|
-
}
|
|
2241
|
-
synchronized(operation) {
|
|
2242
|
-
const result = this.queue.then(operation, operation);
|
|
2243
|
-
this.queue = result.then(
|
|
2244
|
-
() => void 0,
|
|
2245
|
-
() => void 0
|
|
2246
|
-
);
|
|
2247
|
-
return result;
|
|
2248
|
-
}
|
|
2249
|
-
async load() {
|
|
2250
|
-
try {
|
|
2251
|
-
const raw = await readFile4(this.filePath, "utf8");
|
|
2252
|
-
const parsed = JSON.parse(raw);
|
|
2253
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
2254
|
-
} catch {
|
|
2255
|
-
return [];
|
|
2256
|
-
}
|
|
2257
|
-
}
|
|
2258
|
-
async write(plans) {
|
|
2259
|
-
const tmp = `${this.filePath}.tmp`;
|
|
2260
|
-
await mkdir4(dirname4(this.filePath), { recursive: true });
|
|
2261
|
-
await writeFile4(tmp, `${JSON.stringify(plans, null, 2)}
|
|
2262
|
-
`, "utf8");
|
|
2263
|
-
await rename4(tmp, this.filePath);
|
|
2278
|
+
return (await this.readAll()).filter((plan) => filter.pipelineRunId ? plan.pipelineRunId === filter.pipelineRunId : true).filter((plan) => filter.taskId ? plan.taskId === filter.taskId : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2264
2279
|
}
|
|
2265
2280
|
};
|
|
2266
2281
|
|
|
@@ -2496,84 +2511,39 @@ var ReportService = class {
|
|
|
2496
2511
|
};
|
|
2497
2512
|
|
|
2498
2513
|
// src/reports/store.ts
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
filePath;
|
|
2503
|
-
queue = Promise.resolve();
|
|
2504
|
-
constructor(directory = `${process.cwd()}/.omninode`) {
|
|
2505
|
-
this.filePath = `${directory}/reports.json`;
|
|
2514
|
+
var FileReportStore = class extends JsonFileStore {
|
|
2515
|
+
constructor(directory) {
|
|
2516
|
+
super({ ...directory !== void 0 ? { directory } : {}, fileName: "reports.json" });
|
|
2506
2517
|
}
|
|
2507
2518
|
async saveReports(reports) {
|
|
2508
|
-
|
|
2509
|
-
const entries = await this.load();
|
|
2519
|
+
await this.mutate((entries) => {
|
|
2510
2520
|
for (const report of reports) {
|
|
2511
|
-
const index = entries.findIndex(
|
|
2512
|
-
(e) => e.kind === "report" && e.report.id === report.id
|
|
2513
|
-
);
|
|
2521
|
+
const index = entries.findIndex((e) => e.kind === "report" && e.report.id === report.id);
|
|
2514
2522
|
const entry = { kind: "report", report };
|
|
2515
2523
|
if (index >= 0) entries[index] = entry;
|
|
2516
2524
|
else entries.push(entry);
|
|
2517
2525
|
}
|
|
2518
|
-
|
|
2526
|
+
return [entries, void 0];
|
|
2519
2527
|
});
|
|
2520
2528
|
}
|
|
2521
2529
|
async listReports(filter = {}) {
|
|
2522
|
-
return this.
|
|
2523
|
-
const entries = await this.load();
|
|
2524
|
-
return entries.filter((e) => e.kind === "report").map((e) => e.report).filter((report) => filter.taskId ? report.taskId === filter.taskId : true).filter((report) => filter.agent ? report.agent === filter.agent : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2525
|
-
});
|
|
2530
|
+
return (await this.readAll()).filter((e) => e.kind === "report").map((e) => e.report).filter((report) => filter.taskId ? report.taskId === filter.taskId : true).filter((report) => filter.agent ? report.agent === filter.agent : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2526
2531
|
}
|
|
2527
2532
|
async saveCombined(combined) {
|
|
2528
|
-
|
|
2529
|
-
const
|
|
2530
|
-
const index = entries.findIndex(
|
|
2531
|
-
(e) => e.kind === "combined" && e.combined.id === combined.id
|
|
2532
|
-
);
|
|
2533
|
+
await this.mutate((entries) => {
|
|
2534
|
+
const index = entries.findIndex((e) => e.kind === "combined" && e.combined.id === combined.id);
|
|
2533
2535
|
const entry = { kind: "combined", combined };
|
|
2534
2536
|
if (index >= 0) entries[index] = entry;
|
|
2535
2537
|
else entries.push(entry);
|
|
2536
|
-
|
|
2538
|
+
return [entries, void 0];
|
|
2537
2539
|
});
|
|
2538
2540
|
}
|
|
2539
2541
|
async getCombined(id) {
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
const found = entries.find((e) => e.kind === "combined" && e.combined.id === id);
|
|
2543
|
-
return found?.kind === "combined" ? found.combined : void 0;
|
|
2544
|
-
});
|
|
2542
|
+
const found = (await this.readAll()).find((e) => e.kind === "combined" && e.combined.id === id);
|
|
2543
|
+
return found?.kind === "combined" ? found.combined : void 0;
|
|
2545
2544
|
}
|
|
2546
2545
|
async listCombined(filter = {}) {
|
|
2547
|
-
return this.
|
|
2548
|
-
const entries = await this.load();
|
|
2549
|
-
return entries.filter((e) => e.kind === "combined").map((e) => e.combined).filter(
|
|
2550
|
-
(combined) => filter.pipelineRunId ? combined.pipelineRunId === filter.pipelineRunId : true
|
|
2551
|
-
).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2552
|
-
});
|
|
2553
|
-
}
|
|
2554
|
-
synchronized(operation) {
|
|
2555
|
-
const result = this.queue.then(operation, operation);
|
|
2556
|
-
this.queue = result.then(
|
|
2557
|
-
() => void 0,
|
|
2558
|
-
() => void 0
|
|
2559
|
-
);
|
|
2560
|
-
return result;
|
|
2561
|
-
}
|
|
2562
|
-
async load() {
|
|
2563
|
-
try {
|
|
2564
|
-
const raw = await readFile5(this.filePath, "utf8");
|
|
2565
|
-
const parsed = JSON.parse(raw);
|
|
2566
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
2567
|
-
} catch {
|
|
2568
|
-
return [];
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
async write(entries) {
|
|
2572
|
-
const tmp = `${this.filePath}.tmp`;
|
|
2573
|
-
await mkdir5(dirname5(this.filePath), { recursive: true });
|
|
2574
|
-
await writeFile5(tmp, `${JSON.stringify(entries, null, 2)}
|
|
2575
|
-
`, "utf8");
|
|
2576
|
-
await rename5(tmp, this.filePath);
|
|
2546
|
+
return (await this.readAll()).filter((e) => e.kind === "combined").map((e) => e.combined).filter((combined) => filter.pipelineRunId ? combined.pipelineRunId === filter.pipelineRunId : true).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2577
2547
|
}
|
|
2578
2548
|
};
|
|
2579
2549
|
|
|
@@ -2587,6 +2557,7 @@ function buildPipelineEngine(config, log = logger) {
|
|
|
2587
2557
|
roles,
|
|
2588
2558
|
store: new FileTaskStore(),
|
|
2589
2559
|
...config.project.memory !== void 0 ? { memory: new MemoryService(createMemoryProvider(config.project.memory), log) } : {},
|
|
2560
|
+
audit: new FileAuditLog(),
|
|
2590
2561
|
log
|
|
2591
2562
|
});
|
|
2592
2563
|
return new PipelineEngine({
|
|
@@ -2599,24 +2570,48 @@ function buildPipelineEngine(config, log = logger) {
|
|
|
2599
2570
|
...config.project.planner !== void 0 ? { planner: buildPlanner(config.project.planner, chat, log) } : {},
|
|
2600
2571
|
plans: new FilePlanStore(),
|
|
2601
2572
|
reports: new ReportService(new FileReportStore(), log),
|
|
2573
|
+
audit: new FileAuditLog(),
|
|
2602
2574
|
log
|
|
2603
2575
|
});
|
|
2604
2576
|
}
|
|
2605
2577
|
|
|
2578
|
+
// src/persistence/index.ts
|
|
2579
|
+
var ProjectStores = class {
|
|
2580
|
+
tasks;
|
|
2581
|
+
pipelineRuns;
|
|
2582
|
+
reports;
|
|
2583
|
+
plans;
|
|
2584
|
+
memory;
|
|
2585
|
+
audit;
|
|
2586
|
+
constructor(directory = `${process.cwd()}/.omninode`) {
|
|
2587
|
+
this.tasks = new FileTaskStore(directory);
|
|
2588
|
+
this.pipelineRuns = new FilePipelineRunStore(directory);
|
|
2589
|
+
this.reports = new FileReportStore(directory);
|
|
2590
|
+
this.plans = new FilePlanStore(directory);
|
|
2591
|
+
this.memory = new LocalMemoryProvider(directory);
|
|
2592
|
+
this.audit = new FileAuditLog(directory);
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
|
|
2606
2596
|
// src/version.ts
|
|
2607
|
-
var OMNINODE_VERSION = "0.
|
|
2597
|
+
var OMNINODE_VERSION = "2.0.0-alpha.1";
|
|
2608
2598
|
export {
|
|
2609
2599
|
AgentError,
|
|
2610
2600
|
AgentRegistry,
|
|
2611
2601
|
ConfigError,
|
|
2612
2602
|
ConsoleLogSink,
|
|
2603
|
+
FileAuditLog,
|
|
2613
2604
|
FilePipelineRunStore,
|
|
2605
|
+
FilePlanStore,
|
|
2614
2606
|
FileReportStore,
|
|
2615
2607
|
FileTaskStore,
|
|
2608
|
+
HeuristicPlanner,
|
|
2609
|
+
JsonFileStore,
|
|
2616
2610
|
LocalMemoryProvider,
|
|
2617
2611
|
Logger,
|
|
2618
2612
|
MemoryError,
|
|
2619
2613
|
MemoryService,
|
|
2614
|
+
ModelPlanner,
|
|
2620
2615
|
ModelRegistry,
|
|
2621
2616
|
OMNINODE_VERSION,
|
|
2622
2617
|
OPENAI_COMPATIBLE_TYPES,
|
|
@@ -2627,6 +2622,7 @@ export {
|
|
|
2627
2622
|
PipelineError,
|
|
2628
2623
|
PlannerError,
|
|
2629
2624
|
ProcessAgent,
|
|
2625
|
+
ProjectStores,
|
|
2630
2626
|
ProtocolError,
|
|
2631
2627
|
ProviderError,
|
|
2632
2628
|
RememberaMemoryProvider,
|
|
@@ -2639,7 +2635,10 @@ export {
|
|
|
2639
2635
|
appConfigSchema,
|
|
2640
2636
|
authHeaders,
|
|
2641
2637
|
buildAgentRegistry,
|
|
2638
|
+
buildChildEnv,
|
|
2642
2639
|
buildPipelineEngine,
|
|
2640
|
+
buildPlanner,
|
|
2641
|
+
buildPlannerContext,
|
|
2643
2642
|
buildRoleRegistry,
|
|
2644
2643
|
composeTaskText,
|
|
2645
2644
|
createAgent,
|
|
@@ -2655,6 +2654,7 @@ export {
|
|
|
2655
2654
|
keywords,
|
|
2656
2655
|
loadConfig,
|
|
2657
2656
|
logger,
|
|
2657
|
+
parsePlanJson,
|
|
2658
2658
|
pipelineConfigSchema,
|
|
2659
2659
|
pipelineStepConfigSchema,
|
|
2660
2660
|
plannerConfigSchema,
|