@hilbras/omninode 1.0.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/dist/index.js CHANGED
@@ -987,40 +987,54 @@ function buildRoleRegistry(config) {
987
987
  return registry;
988
988
  }
989
989
 
990
- // src/tasks/store.ts
990
+ // src/persistence/json-file-store.ts
991
991
  import { mkdir, readFile, rename, writeFile } from "fs/promises";
992
992
  import { dirname } from "path";
993
- var FileTaskStore = class {
993
+ var JsonFileStore = class {
994
994
  filePath;
995
- /**
996
- * Read-modify-write operations are serialized: parallel pipeline tasks
997
- * would otherwise race on the JSON file (last writer wins).
998
- */
995
+ schemaVersion;
996
+ onCorrupt;
997
+ log;
999
998
  queue = Promise.resolve();
1000
- constructor(directory = `${process.cwd()}/.omninode`) {
1001
- this.filePath = `${directory}/tasks.json`;
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 });
1002
1004
  }
1003
- async save(task) {
1004
- return this.synchronized(async () => {
1005
- const tasks = await this.load();
1006
- const index = tasks.findIndex((t) => t.id === task.id);
1007
- if (index >= 0) tasks[index] = task;
1008
- else tasks.push(task);
1009
- await this.write(tasks);
1010
- });
1005
+ get path() {
1006
+ return this.filePath;
1011
1007
  }
1012
- async get(id) {
1013
- return this.synchronized(async () => {
1014
- const tasks = await this.load();
1015
- return tasks.find((t) => t.id === id);
1016
- });
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
+ }
1017
1028
  }
1018
- async list(filter = {}) {
1019
- return this.synchronized(async () => {
1020
- const tasks = await this.load();
1021
- 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));
1022
- });
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);
1023
1036
  }
1037
+ /** Serializes an async operation against this file. */
1024
1038
  synchronized(operation) {
1025
1039
  const result = this.queue.then(operation, operation);
1026
1040
  this.queue = result.then(
@@ -1029,21 +1043,37 @@ var FileTaskStore = class {
1029
1043
  );
1030
1044
  return result;
1031
1045
  }
1032
- async load() {
1033
- try {
1034
- const raw = await readFile(this.filePath, "utf8");
1035
- const parsed = JSON.parse(raw);
1036
- return Array.isArray(parsed) ? parsed : [];
1037
- } catch {
1038
- return [];
1039
- }
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
+ });
1040
1054
  }
1041
- async write(tasks) {
1042
- const tmp = `${this.filePath}.tmp`;
1043
- await mkdir(dirname(this.filePath), { recursive: true });
1044
- await writeFile(tmp, `${JSON.stringify(tasks, null, 2)}
1045
- `, "utf8");
1046
- await rename(tmp, this.filePath);
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));
1047
1077
  }
1048
1078
  };
1049
1079
 
@@ -1260,10 +1290,10 @@ var FileAuditLog = class {
1260
1290
  }
1261
1291
  /** Recent events, oldest first; used by the CLI. */
1262
1292
  async recent(limit = 20) {
1263
- const { readFile: readFile6 } = await import("fs/promises");
1293
+ const { readFile: readFile2 } = await import("fs/promises");
1264
1294
  let raw;
1265
1295
  try {
1266
- raw = await readFile6(this.filePath, "utf8");
1296
+ raw = await readFile2(this.filePath, "utf8");
1267
1297
  } catch {
1268
1298
  return [];
1269
1299
  }
@@ -1279,8 +1309,6 @@ var FileAuditLog = class {
1279
1309
  };
1280
1310
 
1281
1311
  // src/memory/local.ts
1282
- import { mkdir as mkdir3, readFile as readFile2, rename as rename2, writeFile as writeFile2 } from "fs/promises";
1283
- import { dirname as dirname3 } from "path";
1284
1312
  var STOPWORDS = /* @__PURE__ */ new Set([
1285
1313
  "the",
1286
1314
  "and",
@@ -1337,29 +1365,24 @@ function relevanceScore(queryKeywords, entry) {
1337
1365
  }
1338
1366
  return overlap * 2 + tagMatches * 1.5;
1339
1367
  }
1340
- var LocalMemoryProvider = class {
1368
+ var LocalMemoryProvider = class extends JsonFileStore {
1341
1369
  name = "local";
1342
- filePath;
1343
- queue = Promise.resolve();
1344
- constructor(directory = `${process.cwd()}/.omninode`) {
1345
- this.filePath = `${directory}/memory.json`;
1370
+ constructor(directory) {
1371
+ super({ ...directory !== void 0 ? { directory } : {}, fileName: "memory.json" });
1346
1372
  }
1347
1373
  async query(query) {
1348
- return this.synchronized(async () => {
1349
- const entries = await this.load();
1350
- const filtered = entries.filter((entry) => query.scope ? entry.scope === query.scope : true).filter(
1351
- (entry) => query.tags && query.tags.length > 0 ? query.tags.every((tag) => (entry.tags ?? []).includes(tag)) : true
1352
- );
1353
- if (!query.text || query.text.trim().length === 0) {
1354
- return filtered.sort((a, b) => (b.updatedAt ?? b.createdAt ?? "").localeCompare(a.updatedAt ?? a.createdAt ?? "")).slice(0, query.limit ?? 10);
1355
- }
1356
- const queryKeywords = keywords(query.text);
1357
- 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);
1358
- });
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);
1359
1383
  }
1360
- async write(entry) {
1361
- return this.synchronized(async () => {
1362
- const entries = await this.load();
1384
+ write(entry) {
1385
+ return this.mutate((entries) => {
1363
1386
  const index = entries.findIndex((e) => e.key === entry.key);
1364
1387
  const stamped = {
1365
1388
  ...entry,
@@ -1368,35 +1391,11 @@ var LocalMemoryProvider = class {
1368
1391
  };
1369
1392
  if (index >= 0) entries[index] = stamped;
1370
1393
  else entries.push(stamped);
1371
- await this.saveAll(entries);
1394
+ return [entries, void 0];
1372
1395
  });
1373
1396
  }
1374
1397
  async count() {
1375
- return (await this.load()).length;
1376
- }
1377
- synchronized(operation) {
1378
- const result = this.queue.then(operation, operation);
1379
- this.queue = result.then(
1380
- () => void 0,
1381
- () => void 0
1382
- );
1383
- return result;
1384
- }
1385
- async load() {
1386
- try {
1387
- const raw = await readFile2(this.filePath, "utf8");
1388
- const parsed = JSON.parse(raw);
1389
- return Array.isArray(parsed) ? parsed : [];
1390
- } catch {
1391
- return [];
1392
- }
1393
- }
1394
- async saveAll(entries) {
1395
- const tmp = `${this.filePath}.tmp`;
1396
- await mkdir3(dirname3(this.filePath), { recursive: true });
1397
- await writeFile2(tmp, `${JSON.stringify(entries, null, 2)}
1398
- `, "utf8");
1399
- await rename2(tmp, this.filePath);
1398
+ return (await this.readAll()).length;
1400
1399
  }
1401
1400
  };
1402
1401
 
@@ -2239,114 +2238,44 @@ function createDefaultChatFn(providers) {
2239
2238
  }
2240
2239
 
2241
2240
  // src/pipelines/store.ts
2242
- import { mkdir as mkdir4, readFile as readFile3, rename as rename3, writeFile as writeFile3 } from "fs/promises";
2243
- import { dirname as dirname4 } from "path";
2244
- var FilePipelineRunStore = class {
2245
- filePath;
2246
- queue = Promise.resolve();
2247
- constructor(directory = `${process.cwd()}/.omninode`) {
2248
- this.filePath = `${directory}/pipelines.json`;
2241
+ var FilePipelineRunStore = class extends JsonFileStore {
2242
+ constructor(directory) {
2243
+ super({ ...directory !== void 0 ? { directory } : {}, fileName: "pipelines.json" });
2249
2244
  }
2250
- async save(run) {
2251
- return this.synchronized(async () => {
2252
- const runs = await this.load();
2245
+ save(run) {
2246
+ return this.mutate((runs) => {
2253
2247
  const index = runs.findIndex((r) => r.id === run.id);
2254
2248
  if (index >= 0) runs[index] = run;
2255
2249
  else runs.push(run);
2256
- await this.write(runs);
2250
+ return [runs, void 0];
2257
2251
  });
2258
2252
  }
2259
2253
  async get(id) {
2260
- return this.synchronized(async () => {
2261
- const runs = await this.load();
2262
- return runs.find((r) => r.id === id);
2263
- });
2254
+ return (await this.readAll()).find((r) => r.id === id);
2264
2255
  }
2265
2256
  async list(filter = {}) {
2266
- return this.synchronized(async () => {
2267
- const runs = await this.load();
2268
- 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 ?? ""));
2269
- });
2270
- }
2271
- synchronized(operation) {
2272
- const result = this.queue.then(operation, operation);
2273
- this.queue = result.then(
2274
- () => void 0,
2275
- () => void 0
2276
- );
2277
- return result;
2278
- }
2279
- async load() {
2280
- try {
2281
- const raw = await readFile3(this.filePath, "utf8");
2282
- const parsed = JSON.parse(raw);
2283
- return Array.isArray(parsed) ? parsed : [];
2284
- } catch {
2285
- return [];
2286
- }
2287
- }
2288
- async write(runs) {
2289
- const tmp = `${this.filePath}.tmp`;
2290
- await mkdir4(dirname4(this.filePath), { recursive: true });
2291
- await writeFile3(tmp, `${JSON.stringify(runs, null, 2)}
2292
- `, "utf8");
2293
- 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 ?? ""));
2294
2258
  }
2295
2259
  };
2296
2260
 
2297
2261
  // src/planner/store.ts
2298
- import { mkdir as mkdir5, readFile as readFile4, rename as rename4, writeFile as writeFile4 } from "fs/promises";
2299
- import { dirname as dirname5 } from "path";
2300
- var FilePlanStore = class {
2301
- filePath;
2302
- queue = Promise.resolve();
2303
- constructor(directory = `${process.cwd()}/.omninode`) {
2304
- this.filePath = `${directory}/plans.json`;
2262
+ var FilePlanStore = class extends JsonFileStore {
2263
+ constructor(directory) {
2264
+ super({ ...directory !== void 0 ? { directory } : {}, fileName: "plans.json" });
2305
2265
  }
2306
- async save(plan) {
2307
- return this.synchronized(async () => {
2308
- const plans = await this.load();
2266
+ save(plan) {
2267
+ return this.mutate((plans) => {
2309
2268
  const index = plans.findIndex((p) => p.id === plan.id);
2310
2269
  if (index >= 0) plans[index] = plan;
2311
2270
  else plans.push(plan);
2312
- await this.write(plans);
2271
+ return [plans, void 0];
2313
2272
  });
2314
2273
  }
2315
2274
  async get(id) {
2316
- return this.synchronized(async () => {
2317
- const plans = await this.load();
2318
- return plans.find((p) => p.id === id);
2319
- });
2275
+ return (await this.readAll()).find((p) => p.id === id);
2320
2276
  }
2321
2277
  async list(filter = {}) {
2322
- return this.synchronized(async () => {
2323
- const plans = await this.load();
2324
- 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));
2325
- });
2326
- }
2327
- synchronized(operation) {
2328
- const result = this.queue.then(operation, operation);
2329
- this.queue = result.then(
2330
- () => void 0,
2331
- () => void 0
2332
- );
2333
- return result;
2334
- }
2335
- async load() {
2336
- try {
2337
- const raw = await readFile4(this.filePath, "utf8");
2338
- const parsed = JSON.parse(raw);
2339
- return Array.isArray(parsed) ? parsed : [];
2340
- } catch {
2341
- return [];
2342
- }
2343
- }
2344
- async write(plans) {
2345
- const tmp = `${this.filePath}.tmp`;
2346
- await mkdir5(dirname5(this.filePath), { recursive: true });
2347
- await writeFile4(tmp, `${JSON.stringify(plans, null, 2)}
2348
- `, "utf8");
2349
- 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));
2350
2279
  }
2351
2280
  };
2352
2281
 
@@ -2582,84 +2511,39 @@ var ReportService = class {
2582
2511
  };
2583
2512
 
2584
2513
  // src/reports/store.ts
2585
- import { mkdir as mkdir6, readFile as readFile5, rename as rename5, writeFile as writeFile5 } from "fs/promises";
2586
- import { dirname as dirname6 } from "path";
2587
- var FileReportStore = class {
2588
- filePath;
2589
- queue = Promise.resolve();
2590
- constructor(directory = `${process.cwd()}/.omninode`) {
2591
- this.filePath = `${directory}/reports.json`;
2514
+ var FileReportStore = class extends JsonFileStore {
2515
+ constructor(directory) {
2516
+ super({ ...directory !== void 0 ? { directory } : {}, fileName: "reports.json" });
2592
2517
  }
2593
2518
  async saveReports(reports) {
2594
- return this.synchronized(async () => {
2595
- const entries = await this.load();
2519
+ await this.mutate((entries) => {
2596
2520
  for (const report of reports) {
2597
- const index = entries.findIndex(
2598
- (e) => e.kind === "report" && e.report.id === report.id
2599
- );
2521
+ const index = entries.findIndex((e) => e.kind === "report" && e.report.id === report.id);
2600
2522
  const entry = { kind: "report", report };
2601
2523
  if (index >= 0) entries[index] = entry;
2602
2524
  else entries.push(entry);
2603
2525
  }
2604
- await this.write(entries);
2526
+ return [entries, void 0];
2605
2527
  });
2606
2528
  }
2607
2529
  async listReports(filter = {}) {
2608
- return this.synchronized(async () => {
2609
- const entries = await this.load();
2610
- 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));
2611
- });
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));
2612
2531
  }
2613
2532
  async saveCombined(combined) {
2614
- return this.synchronized(async () => {
2615
- const entries = await this.load();
2616
- const index = entries.findIndex(
2617
- (e) => e.kind === "combined" && e.combined.id === combined.id
2618
- );
2533
+ await this.mutate((entries) => {
2534
+ const index = entries.findIndex((e) => e.kind === "combined" && e.combined.id === combined.id);
2619
2535
  const entry = { kind: "combined", combined };
2620
2536
  if (index >= 0) entries[index] = entry;
2621
2537
  else entries.push(entry);
2622
- await this.write(entries);
2538
+ return [entries, void 0];
2623
2539
  });
2624
2540
  }
2625
2541
  async getCombined(id) {
2626
- return this.synchronized(async () => {
2627
- const entries = await this.load();
2628
- const found = entries.find((e) => e.kind === "combined" && e.combined.id === id);
2629
- return found?.kind === "combined" ? found.combined : void 0;
2630
- });
2542
+ const found = (await this.readAll()).find((e) => e.kind === "combined" && e.combined.id === id);
2543
+ return found?.kind === "combined" ? found.combined : void 0;
2631
2544
  }
2632
2545
  async listCombined(filter = {}) {
2633
- return this.synchronized(async () => {
2634
- const entries = await this.load();
2635
- return entries.filter((e) => e.kind === "combined").map((e) => e.combined).filter(
2636
- (combined) => filter.pipelineRunId ? combined.pipelineRunId === filter.pipelineRunId : true
2637
- ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
2638
- });
2639
- }
2640
- synchronized(operation) {
2641
- const result = this.queue.then(operation, operation);
2642
- this.queue = result.then(
2643
- () => void 0,
2644
- () => void 0
2645
- );
2646
- return result;
2647
- }
2648
- async load() {
2649
- try {
2650
- const raw = await readFile5(this.filePath, "utf8");
2651
- const parsed = JSON.parse(raw);
2652
- return Array.isArray(parsed) ? parsed : [];
2653
- } catch {
2654
- return [];
2655
- }
2656
- }
2657
- async write(entries) {
2658
- const tmp = `${this.filePath}.tmp`;
2659
- await mkdir6(dirname6(this.filePath), { recursive: true });
2660
- await writeFile5(tmp, `${JSON.stringify(entries, null, 2)}
2661
- `, "utf8");
2662
- 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));
2663
2547
  }
2664
2548
  };
2665
2549
 
@@ -2691,8 +2575,26 @@ function buildPipelineEngine(config, log = logger) {
2691
2575
  });
2692
2576
  }
2693
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
+
2694
2596
  // src/version.ts
2695
- var OMNINODE_VERSION = "1.0.0";
2597
+ var OMNINODE_VERSION = "2.0.0-alpha.1";
2696
2598
  export {
2697
2599
  AgentError,
2698
2600
  AgentRegistry,
@@ -2700,12 +2602,16 @@ export {
2700
2602
  ConsoleLogSink,
2701
2603
  FileAuditLog,
2702
2604
  FilePipelineRunStore,
2605
+ FilePlanStore,
2703
2606
  FileReportStore,
2704
2607
  FileTaskStore,
2608
+ HeuristicPlanner,
2609
+ JsonFileStore,
2705
2610
  LocalMemoryProvider,
2706
2611
  Logger,
2707
2612
  MemoryError,
2708
2613
  MemoryService,
2614
+ ModelPlanner,
2709
2615
  ModelRegistry,
2710
2616
  OMNINODE_VERSION,
2711
2617
  OPENAI_COMPATIBLE_TYPES,
@@ -2716,6 +2622,7 @@ export {
2716
2622
  PipelineError,
2717
2623
  PlannerError,
2718
2624
  ProcessAgent,
2625
+ ProjectStores,
2719
2626
  ProtocolError,
2720
2627
  ProviderError,
2721
2628
  RememberaMemoryProvider,
@@ -2728,7 +2635,10 @@ export {
2728
2635
  appConfigSchema,
2729
2636
  authHeaders,
2730
2637
  buildAgentRegistry,
2638
+ buildChildEnv,
2731
2639
  buildPipelineEngine,
2640
+ buildPlanner,
2641
+ buildPlannerContext,
2732
2642
  buildRoleRegistry,
2733
2643
  composeTaskText,
2734
2644
  createAgent,
@@ -2744,6 +2654,7 @@ export {
2744
2654
  keywords,
2745
2655
  loadConfig,
2746
2656
  logger,
2657
+ parsePlanJson,
2747
2658
  pipelineConfigSchema,
2748
2659
  pipelineStepConfigSchema,
2749
2660
  plannerConfigSchema,