@mobrienv/autoloop 0.1.2
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 +145 -0
- package/bin/autoloop +2 -0
- package/dist/backend/index.d.ts +10 -0
- package/dist/backend/index.js +59 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/run-command.d.ts +7 -0
- package/dist/backend/run-command.js +50 -0
- package/dist/backend/run-command.js.map +1 -0
- package/dist/backend/run-mock.d.ts +1 -0
- package/dist/backend/run-mock.js +6 -0
- package/dist/backend/run-mock.js.map +1 -0
- package/dist/backend/run-pi.d.ts +5 -0
- package/dist/backend/run-pi.js +5 -0
- package/dist/backend/run-pi.js.map +1 -0
- package/dist/backend/types.d.ts +21 -0
- package/dist/backend/types.js +2 -0
- package/dist/backend/types.js.map +1 -0
- package/dist/chains/budget.d.ts +7 -0
- package/dist/chains/budget.js +42 -0
- package/dist/chains/budget.js.map +1 -0
- package/dist/chains/load.d.ts +12 -0
- package/dist/chains/load.js +80 -0
- package/dist/chains/load.js.map +1 -0
- package/dist/chains/render.d.ts +2 -0
- package/dist/chains/render.js +46 -0
- package/dist/chains/render.js.map +1 -0
- package/dist/chains/run.d.ts +17 -0
- package/dist/chains/run.js +175 -0
- package/dist/chains/run.js.map +1 -0
- package/dist/chains/types.d.ts +37 -0
- package/dist/chains/types.js +2 -0
- package/dist/chains/types.js.map +1 -0
- package/dist/chains.d.ts +5 -0
- package/dist/chains.js +5 -0
- package/dist/chains.js.map +1 -0
- package/dist/commands/chain.d.ts +1 -0
- package/dist/commands/chain.js +51 -0
- package/dist/commands/chain.js.map +1 -0
- package/dist/commands/inspect.d.ts +1 -0
- package/dist/commands/inspect.js +95 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +12 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/loops.d.ts +1 -0
- package/dist/commands/loops.js +72 -0
- package/dist/commands/loops.js.map +1 -0
- package/dist/commands/memory.d.ts +1 -0
- package/dist/commands/memory.js +65 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/pi-adapter.d.ts +1 -0
- package/dist/commands/pi-adapter.js +6 -0
- package/dist/commands/pi-adapter.js.map +1 -0
- package/dist/commands/run.d.ts +1 -0
- package/dist/commands/run.js +185 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.js +169 -0
- package/dist/config.js.map +1 -0
- package/dist/events/decode.d.ts +2 -0
- package/dist/events/decode.js +45 -0
- package/dist/events/decode.js.map +1 -0
- package/dist/events/encode.d.ts +2 -0
- package/dist/events/encode.js +33 -0
- package/dist/events/encode.js.map +1 -0
- package/dist/events/guards.d.ts +5 -0
- package/dist/events/guards.js +42 -0
- package/dist/events/guards.js.map +1 -0
- package/dist/events/types.d.ts +25 -0
- package/dist/events/types.js +2 -0
- package/dist/events/types.js.map +1 -0
- package/dist/harness/config-helpers.d.ts +24 -0
- package/dist/harness/config-helpers.js +231 -0
- package/dist/harness/config-helpers.js.map +1 -0
- package/dist/harness/coordination.d.ts +1 -0
- package/dist/harness/coordination.js +127 -0
- package/dist/harness/coordination.js.map +1 -0
- package/dist/harness/display.d.ts +20 -0
- package/dist/harness/display.js +130 -0
- package/dist/harness/display.js.map +1 -0
- package/dist/harness/emit.d.ts +15 -0
- package/dist/harness/emit.js +220 -0
- package/dist/harness/emit.js.map +1 -0
- package/dist/harness/index.d.ts +13 -0
- package/dist/harness/index.js +124 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/iteration.d.ts +4 -0
- package/dist/harness/iteration.js +129 -0
- package/dist/harness/iteration.js.map +1 -0
- package/dist/harness/journal.d.ts +13 -0
- package/dist/harness/journal.js +106 -0
- package/dist/harness/journal.js.map +1 -0
- package/dist/harness/metareview.d.ts +4 -0
- package/dist/harness/metareview.js +33 -0
- package/dist/harness/metareview.js.map +1 -0
- package/dist/harness/metrics.d.ts +12 -0
- package/dist/harness/metrics.js +180 -0
- package/dist/harness/metrics.js.map +1 -0
- package/dist/harness/parallel.d.ts +37 -0
- package/dist/harness/parallel.js +158 -0
- package/dist/harness/parallel.js.map +1 -0
- package/dist/harness/prompt.d.ts +35 -0
- package/dist/harness/prompt.js +328 -0
- package/dist/harness/prompt.js.map +1 -0
- package/dist/harness/scratchpad.d.ts +2 -0
- package/dist/harness/scratchpad.js +65 -0
- package/dist/harness/scratchpad.js.map +1 -0
- package/dist/harness/stop.d.ts +5 -0
- package/dist/harness/stop.js +63 -0
- package/dist/harness/stop.js.map +1 -0
- package/dist/harness/tools.d.ts +3 -0
- package/dist/harness/tools.js +39 -0
- package/dist/harness/tools.js.map +1 -0
- package/dist/harness/types.d.ts +81 -0
- package/dist/harness/types.js +2 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/wave/finalize-wave.d.ts +9 -0
- package/dist/harness/wave/finalize-wave.js +60 -0
- package/dist/harness/wave/finalize-wave.js.map +1 -0
- package/dist/harness/wave/launch-branches.d.ts +6 -0
- package/dist/harness/wave/launch-branches.js +218 -0
- package/dist/harness/wave/launch-branches.js.map +1 -0
- package/dist/harness/wave/parse-objectives.d.ts +3 -0
- package/dist/harness/wave/parse-objectives.js +29 -0
- package/dist/harness/wave/parse-objectives.js.map +1 -0
- package/dist/harness/wave/types.d.ts +43 -0
- package/dist/harness/wave/types.js +2 -0
- package/dist/harness/wave/types.js.map +1 -0
- package/dist/harness/wave.d.ts +6 -0
- package/dist/harness/wave.js +98 -0
- package/dist/harness/wave.js.map +1 -0
- package/dist/json.d.ts +8 -0
- package/dist/json.js +80 -0
- package/dist/json.js.map +1 -0
- package/dist/loops/health.d.ts +14 -0
- package/dist/loops/health.js +104 -0
- package/dist/loops/health.js.map +1 -0
- package/dist/loops/list.d.ts +6 -0
- package/dist/loops/list.js +21 -0
- package/dist/loops/list.js.map +1 -0
- package/dist/loops/render.d.ts +18 -0
- package/dist/loops/render.js +87 -0
- package/dist/loops/render.js.map +1 -0
- package/dist/loops/show.d.ts +8 -0
- package/dist/loops/show.js +31 -0
- package/dist/loops/show.js.map +1 -0
- package/dist/loops/watch.d.ts +8 -0
- package/dist/loops/watch.js +77 -0
- package/dist/loops/watch.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +101 -0
- package/dist/main.js.map +1 -0
- package/dist/markdown.d.ts +10 -0
- package/dist/markdown.js +66 -0
- package/dist/markdown.js.map +1 -0
- package/dist/memory-render.d.ts +6 -0
- package/dist/memory-render.js +81 -0
- package/dist/memory-render.js.map +1 -0
- package/dist/memory.d.ts +23 -0
- package/dist/memory.js +314 -0
- package/dist/memory.js.map +1 -0
- package/dist/pi-adapter.d.ts +1 -0
- package/dist/pi-adapter.js +220 -0
- package/dist/pi-adapter.js.map +1 -0
- package/dist/registry/derive.d.ts +8 -0
- package/dist/registry/derive.js +81 -0
- package/dist/registry/derive.js.map +1 -0
- package/dist/registry/harness.d.ts +7 -0
- package/dist/registry/harness.js +57 -0
- package/dist/registry/harness.js.map +1 -0
- package/dist/registry/index.d.ts +5 -0
- package/dist/registry/index.js +5 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/read.d.ts +11 -0
- package/dist/registry/read.js +50 -0
- package/dist/registry/read.js.map +1 -0
- package/dist/registry/rebuild.d.ts +5 -0
- package/dist/registry/rebuild.js +19 -0
- package/dist/registry/rebuild.js.map +1 -0
- package/dist/registry/types.d.ts +19 -0
- package/dist/registry/types.js +2 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/registry/update.d.ts +2 -0
- package/dist/registry/update.js +7 -0
- package/dist/registry/update.js.map +1 -0
- package/dist/testing/mock-backend.d.ts +11 -0
- package/dist/testing/mock-backend.js +76 -0
- package/dist/testing/mock-backend.js.map +1 -0
- package/dist/topology.d.ts +25 -0
- package/dist/topology.js +188 -0
- package/dist/topology.js.map +1 -0
- package/dist/usage.d.ts +8 -0
- package/dist/usage.js +114 -0
- package/dist/usage.js.map +1 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.js +79 -0
- package/dist/utils.js.map +1 -0
- package/package.json +52 -0
- package/presets/autocode/README.md +81 -0
- package/presets/autocode/autoloops.toml +22 -0
- package/presets/autocode/harness.md +19 -0
- package/presets/autocode/miniloops.toml +22 -0
- package/presets/autocode/roles/build.md +33 -0
- package/presets/autocode/roles/critic.md +40 -0
- package/presets/autocode/roles/finalizer.md +43 -0
- package/presets/autocode/roles/planner.md +40 -0
- package/presets/autocode/topology.toml +32 -0
- package/presets/autodoc/README.md +42 -0
- package/presets/autodoc/autoloops.toml +21 -0
- package/presets/autodoc/harness.md +19 -0
- package/presets/autodoc/miniloops.toml +21 -0
- package/presets/autodoc/roles/auditor.md +39 -0
- package/presets/autodoc/roles/checker.md +43 -0
- package/presets/autodoc/roles/publisher.md +51 -0
- package/presets/autodoc/roles/writer.md +37 -0
- package/presets/autodoc/topology.toml +31 -0
- package/presets/autofix/README.md +56 -0
- package/presets/autofix/autoloops.toml +21 -0
- package/presets/autofix/harness.md +24 -0
- package/presets/autofix/miniloops.toml +21 -0
- package/presets/autofix/roles/closer.md +48 -0
- package/presets/autofix/roles/diagnoser.md +42 -0
- package/presets/autofix/roles/fixer.md +28 -0
- package/presets/autofix/roles/verifier.md +31 -0
- package/presets/autofix/topology.toml +33 -0
- package/presets/autoideas/README.md +73 -0
- package/presets/autoideas/autoloops.toml +18 -0
- package/presets/autoideas/harness.md +31 -0
- package/presets/autoideas/miniloops.toml +18 -0
- package/presets/autoideas/roles/analyst.md +32 -0
- package/presets/autoideas/roles/reviewer.md +36 -0
- package/presets/autoideas/roles/scanner.md +26 -0
- package/presets/autoideas/roles/synthesizer.md +48 -0
- package/presets/autoideas/topology.toml +32 -0
- package/presets/autoperf/README.md +56 -0
- package/presets/autoperf/autoloops.toml +21 -0
- package/presets/autoperf/harness.md +21 -0
- package/presets/autoperf/miniloops.toml +21 -0
- package/presets/autoperf/roles/judge.md +38 -0
- package/presets/autoperf/roles/measurer.md +36 -0
- package/presets/autoperf/roles/optimizer.md +35 -0
- package/presets/autoperf/roles/profiler.md +38 -0
- package/presets/autoperf/topology.toml +32 -0
- package/presets/autoqa/README.md +76 -0
- package/presets/autoqa/autoloops.toml +21 -0
- package/presets/autoqa/harness.md +30 -0
- package/presets/autoqa/miniloops.toml +21 -0
- package/presets/autoqa/roles/executor.md +43 -0
- package/presets/autoqa/roles/inspector.md +45 -0
- package/presets/autoqa/roles/planner.md +55 -0
- package/presets/autoqa/roles/reporter.md +74 -0
- package/presets/autoqa/topology.toml +31 -0
- package/presets/autoresearch/README.md +63 -0
- package/presets/autoresearch/autoloops.toml +18 -0
- package/presets/autoresearch/harness.md +28 -0
- package/presets/autoresearch/miniloops.toml +18 -0
- package/presets/autoresearch/roles/benchmarker.md +34 -0
- package/presets/autoresearch/roles/evaluator.md +33 -0
- package/presets/autoresearch/roles/implementer.md +26 -0
- package/presets/autoresearch/roles/strategist.md +43 -0
- package/presets/autoresearch/topology.toml +31 -0
- package/presets/autoreview/README.md +51 -0
- package/presets/autoreview/autoloops.toml +21 -0
- package/presets/autoreview/harness.md +20 -0
- package/presets/autoreview/miniloops.toml +21 -0
- package/presets/autoreview/roles/checker.md +36 -0
- package/presets/autoreview/roles/reader.md +33 -0
- package/presets/autoreview/roles/suggester.md +26 -0
- package/presets/autoreview/roles/summarizer.md +57 -0
- package/presets/autoreview/topology.toml +31 -0
- package/presets/autosec/README.md +51 -0
- package/presets/autosec/autoloops.toml +21 -0
- package/presets/autosec/harness.md +20 -0
- package/presets/autosec/miniloops.toml +21 -0
- package/presets/autosec/roles/analyst.md +38 -0
- package/presets/autosec/roles/hardener.md +36 -0
- package/presets/autosec/roles/reporter.md +63 -0
- package/presets/autosec/roles/scanner.md +38 -0
- package/presets/autosec/topology.toml +31 -0
- package/presets/autosimplify/README.md +83 -0
- package/presets/autosimplify/autoloops.toml +22 -0
- package/presets/autosimplify/harness.md +25 -0
- package/presets/autosimplify/miniloops.toml +22 -0
- package/presets/autosimplify/roles/reviewer.md +38 -0
- package/presets/autosimplify/roles/scoper.md +42 -0
- package/presets/autosimplify/roles/simplifier.md +51 -0
- package/presets/autosimplify/roles/verifier.md +40 -0
- package/presets/autosimplify/topology.toml +32 -0
- package/presets/autospec/README.md +84 -0
- package/presets/autospec/autoloops.toml +21 -0
- package/presets/autospec/harness.md +23 -0
- package/presets/autospec/miniloops.toml +21 -0
- package/presets/autospec/roles/clarifier.md +38 -0
- package/presets/autospec/roles/critic.md +41 -0
- package/presets/autospec/roles/designer.md +37 -0
- package/presets/autospec/roles/planner.md +38 -0
- package/presets/autospec/roles/researcher.md +33 -0
- package/presets/autospec/topology.toml +38 -0
- package/presets/autotest/README.md +55 -0
- package/presets/autotest/autoloops.toml +21 -0
- package/presets/autotest/harness.md +21 -0
- package/presets/autotest/miniloops.toml +21 -0
- package/presets/autotest/roles/assessor.md +57 -0
- package/presets/autotest/roles/runner.md +31 -0
- package/presets/autotest/roles/surveyor.md +39 -0
- package/presets/autotest/roles/writer.md +37 -0
- package/presets/autotest/topology.toml +32 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RegistryStatus, RunRecord } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Derive run records from raw journal lines.
|
|
4
|
+
* Each `loop.start` creates a new record; subsequent events update it.
|
|
5
|
+
* Returns one record per run_id, reflecting the final known state.
|
|
6
|
+
*/
|
|
7
|
+
export declare function deriveRunRecords(lines: string[]): RunRecord[];
|
|
8
|
+
export declare function stopReasonToStatus(reason: string): RegistryStatus;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { decodeEvent } from "../events/decode.js";
|
|
2
|
+
import { normalizeBackendLabel } from "../backend/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Derive run records from raw journal lines.
|
|
5
|
+
* Each `loop.start` creates a new record; subsequent events update it.
|
|
6
|
+
* Returns one record per run_id, reflecting the final known state.
|
|
7
|
+
*/
|
|
8
|
+
export function deriveRunRecords(lines) {
|
|
9
|
+
const runs = new Map();
|
|
10
|
+
for (const line of lines) {
|
|
11
|
+
const event = decodeEvent(line);
|
|
12
|
+
if (!event)
|
|
13
|
+
continue;
|
|
14
|
+
const runId = event.run;
|
|
15
|
+
if (!runId)
|
|
16
|
+
continue;
|
|
17
|
+
const topic = String(event.topic);
|
|
18
|
+
if (topic === "loop.start" && event.shape === "fields") {
|
|
19
|
+
const f = event.fields;
|
|
20
|
+
runs.set(runId, {
|
|
21
|
+
run_id: runId,
|
|
22
|
+
status: "running",
|
|
23
|
+
preset: f.preset ?? "",
|
|
24
|
+
objective: f.objective ?? "",
|
|
25
|
+
trigger: f.trigger ?? "",
|
|
26
|
+
project_dir: f.project_dir ?? "",
|
|
27
|
+
work_dir: f.work_dir ?? "",
|
|
28
|
+
state_dir: "",
|
|
29
|
+
journal_file: "",
|
|
30
|
+
parent_run_id: f.parent_run_id ?? "",
|
|
31
|
+
backend: normalizeBackendLabel(f.backend ?? ""),
|
|
32
|
+
created_at: f.created_at ?? "",
|
|
33
|
+
updated_at: f.created_at ?? "",
|
|
34
|
+
iteration: 0,
|
|
35
|
+
stop_reason: "",
|
|
36
|
+
latest_event: topic,
|
|
37
|
+
});
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const record = runs.get(runId);
|
|
41
|
+
if (!record)
|
|
42
|
+
continue;
|
|
43
|
+
if (topic === "iteration.finish") {
|
|
44
|
+
const iter = event.iteration ? parseInt(event.iteration, 10) : record.iteration;
|
|
45
|
+
record.iteration = Number.isNaN(iter) ? record.iteration : iter;
|
|
46
|
+
record.updated_at = record.created_at;
|
|
47
|
+
record.latest_event = topic;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (topic === "loop.complete") {
|
|
51
|
+
record.status = "completed";
|
|
52
|
+
record.stop_reason = fieldValue(event, "reason");
|
|
53
|
+
record.updated_at = record.created_at;
|
|
54
|
+
record.latest_event = topic;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (topic === "loop.stop") {
|
|
58
|
+
record.status = stopReasonToStatus(fieldValue(event, "reason"));
|
|
59
|
+
record.stop_reason = fieldValue(event, "reason");
|
|
60
|
+
record.updated_at = record.created_at;
|
|
61
|
+
record.latest_event = topic;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Array.from(runs.values());
|
|
66
|
+
}
|
|
67
|
+
function fieldValue(event, key) {
|
|
68
|
+
if (!event)
|
|
69
|
+
return "";
|
|
70
|
+
if (event.shape === "fields")
|
|
71
|
+
return event.fields[key] ?? "";
|
|
72
|
+
return "";
|
|
73
|
+
}
|
|
74
|
+
export function stopReasonToStatus(reason) {
|
|
75
|
+
if (reason === "backend_failed")
|
|
76
|
+
return "failed";
|
|
77
|
+
if (reason === "backend_timeout")
|
|
78
|
+
return "timed_out";
|
|
79
|
+
return "stopped";
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=derive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.js","sourceRoot":"","sources":["../../src/registry/derive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LoopContext } from "../harness/types.js";
|
|
2
|
+
import type { RegistryStatus } from "./types.js";
|
|
3
|
+
export declare function registryStart(loop: LoopContext): void;
|
|
4
|
+
export declare function registryProgress(loop: LoopContext, iteration: number): void;
|
|
5
|
+
export declare function registryTerminal(loop: LoopContext, iteration: number, status: RegistryStatus, stopReason: string, latestEvent: string): void;
|
|
6
|
+
export declare function registryComplete(loop: LoopContext, iteration: number, reason: string): void;
|
|
7
|
+
export declare function registryStop(loop: LoopContext, iteration: number, reason: string): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { normalizeBackendLabel } from "../backend/index.js";
|
|
2
|
+
import { appendRegistryEntry } from "./update.js";
|
|
3
|
+
import { getRun } from "./read.js";
|
|
4
|
+
import { stopReasonToStatus } from "./derive.js";
|
|
5
|
+
function registryPath(loop) {
|
|
6
|
+
return loop.paths.registryFile;
|
|
7
|
+
}
|
|
8
|
+
function baseRecord(loop) {
|
|
9
|
+
return {
|
|
10
|
+
run_id: loop.runtime.runId,
|
|
11
|
+
status: "running",
|
|
12
|
+
preset: loop.launch.preset,
|
|
13
|
+
objective: loop.objective,
|
|
14
|
+
trigger: loop.launch.trigger,
|
|
15
|
+
project_dir: loop.paths.projectDir,
|
|
16
|
+
work_dir: loop.paths.workDir,
|
|
17
|
+
state_dir: loop.paths.stateDir,
|
|
18
|
+
journal_file: loop.paths.journalFile,
|
|
19
|
+
parent_run_id: loop.launch.parentRunId,
|
|
20
|
+
backend: normalizeBackendLabel(loop.backend.command),
|
|
21
|
+
created_at: loop.launch.createdAt,
|
|
22
|
+
updated_at: new Date().toISOString(),
|
|
23
|
+
iteration: 0,
|
|
24
|
+
stop_reason: "",
|
|
25
|
+
latest_event: "loop.start",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function registryStart(loop) {
|
|
29
|
+
appendRegistryEntry(registryPath(loop), baseRecord(loop));
|
|
30
|
+
}
|
|
31
|
+
export function registryProgress(loop, iteration) {
|
|
32
|
+
const path = registryPath(loop);
|
|
33
|
+
const existing = getRun(path, loop.runtime.runId);
|
|
34
|
+
const record = existing ? { ...existing } : baseRecord(loop);
|
|
35
|
+
record.iteration = iteration;
|
|
36
|
+
record.updated_at = new Date().toISOString();
|
|
37
|
+
record.latest_event = "iteration.finish";
|
|
38
|
+
appendRegistryEntry(path, record);
|
|
39
|
+
}
|
|
40
|
+
export function registryTerminal(loop, iteration, status, stopReason, latestEvent) {
|
|
41
|
+
const path = registryPath(loop);
|
|
42
|
+
const existing = getRun(path, loop.runtime.runId);
|
|
43
|
+
const record = existing ? { ...existing } : baseRecord(loop);
|
|
44
|
+
record.status = status;
|
|
45
|
+
record.iteration = iteration;
|
|
46
|
+
record.stop_reason = stopReason;
|
|
47
|
+
record.updated_at = new Date().toISOString();
|
|
48
|
+
record.latest_event = latestEvent;
|
|
49
|
+
appendRegistryEntry(path, record);
|
|
50
|
+
}
|
|
51
|
+
export function registryComplete(loop, iteration, reason) {
|
|
52
|
+
registryTerminal(loop, iteration, "completed", reason, "loop.complete");
|
|
53
|
+
}
|
|
54
|
+
export function registryStop(loop, iteration, reason) {
|
|
55
|
+
registryTerminal(loop, iteration, stopReasonToStatus(reason), reason, "loop.stop");
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/registry/harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { RegistryStatus, RunRecord } from "./types.js";
|
|
2
|
+
export { deriveRunRecords, stopReasonToStatus } from "./derive.js";
|
|
3
|
+
export { readRegistry, getRun, activeRuns, recentRuns, findRunByPrefix } from "./read.js";
|
|
4
|
+
export { appendRegistryEntry } from "./update.js";
|
|
5
|
+
export { rebuildRegistry } from "./rebuild.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { deriveRunRecords, stopReasonToStatus } from "./derive.js";
|
|
2
|
+
export { readRegistry, getRun, activeRuns, recentRuns, findRunByPrefix } from "./read.js";
|
|
3
|
+
export { appendRegistryEntry } from "./update.js";
|
|
4
|
+
export { rebuildRegistry } from "./rebuild.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RunRecord } from "./types.js";
|
|
2
|
+
export declare function readRegistry(path: string): RunRecord[];
|
|
3
|
+
export declare function getRun(path: string, runId: string): RunRecord | undefined;
|
|
4
|
+
export declare function activeRuns(path: string): RunRecord[];
|
|
5
|
+
export declare function recentRuns(path: string, limit: number): RunRecord[];
|
|
6
|
+
/**
|
|
7
|
+
* Find a run by exact or prefix match.
|
|
8
|
+
* Returns the matched record, or an array of candidates if ambiguous.
|
|
9
|
+
* Returns undefined if no match.
|
|
10
|
+
*/
|
|
11
|
+
export declare function findRunByPrefix(path: string, partial: string): RunRecord | RunRecord[] | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
export function readRegistry(path) {
|
|
3
|
+
if (!existsSync(path))
|
|
4
|
+
return [];
|
|
5
|
+
const text = readFileSync(path, "utf-8");
|
|
6
|
+
const entries = new Map();
|
|
7
|
+
for (const line of text.split("\n")) {
|
|
8
|
+
const trimmed = line.trim();
|
|
9
|
+
if (!trimmed)
|
|
10
|
+
continue;
|
|
11
|
+
try {
|
|
12
|
+
const record = JSON.parse(trimmed);
|
|
13
|
+
if (record.run_id)
|
|
14
|
+
entries.set(record.run_id, record);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// skip malformed lines
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return Array.from(entries.values());
|
|
21
|
+
}
|
|
22
|
+
export function getRun(path, runId) {
|
|
23
|
+
return readRegistry(path).find((r) => r.run_id === runId);
|
|
24
|
+
}
|
|
25
|
+
export function activeRuns(path) {
|
|
26
|
+
return readRegistry(path).filter((r) => r.status === "running");
|
|
27
|
+
}
|
|
28
|
+
export function recentRuns(path, limit) {
|
|
29
|
+
const all = readRegistry(path);
|
|
30
|
+
all.sort((a, b) => b.updated_at.localeCompare(a.updated_at));
|
|
31
|
+
return all.slice(0, limit);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Find a run by exact or prefix match.
|
|
35
|
+
* Returns the matched record, or an array of candidates if ambiguous.
|
|
36
|
+
* Returns undefined if no match.
|
|
37
|
+
*/
|
|
38
|
+
export function findRunByPrefix(path, partial) {
|
|
39
|
+
const all = readRegistry(path);
|
|
40
|
+
const exact = all.find((r) => r.run_id === partial);
|
|
41
|
+
if (exact)
|
|
42
|
+
return exact;
|
|
43
|
+
const matches = all.filter((r) => r.run_id.startsWith(partial));
|
|
44
|
+
if (matches.length === 1)
|
|
45
|
+
return matches[0];
|
|
46
|
+
if (matches.length > 1)
|
|
47
|
+
return matches;
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/registry/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGnD,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;YAChD,IAAI,MAAM,CAAC,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,KAAa;IAChD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAa;IACpD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7D,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;IACpD,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IACvC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { readFileSync, existsSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { deriveRunRecords } from "./derive.js";
|
|
5
|
+
/**
|
|
6
|
+
* Rebuild the registry JSONL from the canonical journal.
|
|
7
|
+
* Overwrites the registry file with derived state.
|
|
8
|
+
*/
|
|
9
|
+
export function rebuildRegistry(journalPath, registryPath) {
|
|
10
|
+
if (!existsSync(journalPath))
|
|
11
|
+
return;
|
|
12
|
+
const text = readFileSync(journalPath, "utf-8");
|
|
13
|
+
const lines = text.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
14
|
+
const records = deriveRunRecords(lines);
|
|
15
|
+
mkdirSync(dirname(registryPath), { recursive: true });
|
|
16
|
+
const content = records.map((r) => JSON.stringify(r)).join("\n") + (records.length > 0 ? "\n" : "");
|
|
17
|
+
writeFileSync(registryPath, content, "utf-8");
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=rebuild.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild.js","sourceRoot":"","sources":["../../src/registry/rebuild.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,YAAoB;IACvE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpG,aAAa,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type RegistryStatus = "running" | "completed" | "failed" | "timed_out" | "stopped";
|
|
2
|
+
export interface RunRecord {
|
|
3
|
+
run_id: string;
|
|
4
|
+
status: RegistryStatus;
|
|
5
|
+
preset: string;
|
|
6
|
+
objective: string;
|
|
7
|
+
trigger: string;
|
|
8
|
+
project_dir: string;
|
|
9
|
+
work_dir: string;
|
|
10
|
+
state_dir: string;
|
|
11
|
+
journal_file: string;
|
|
12
|
+
parent_run_id: string;
|
|
13
|
+
backend: string;
|
|
14
|
+
created_at: string;
|
|
15
|
+
updated_at: string;
|
|
16
|
+
iteration: number;
|
|
17
|
+
stop_reason: string;
|
|
18
|
+
latest_event: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
export function appendRegistryEntry(path, record) {
|
|
4
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
5
|
+
appendFileSync(path, JSON.stringify(record) + "\n", "utf-8");
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/registry/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,MAAiB;IACjE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic mock backend for autoloop integration tests.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node dist/testing/mock-backend.js [fixture-path] [prompt]
|
|
7
|
+
*
|
|
8
|
+
* Reads MOCK_FIXTURE_PATH to find a JSON fixture describing the output,
|
|
9
|
+
* or accepts a fixture path as the first positional argument.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic mock backend for autoloop integration tests.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node dist/testing/mock-backend.js [fixture-path] [prompt]
|
|
7
|
+
*
|
|
8
|
+
* Reads MOCK_FIXTURE_PATH to find a JSON fixture describing the output,
|
|
9
|
+
* or accepts a fixture path as the first positional argument.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { execFileSync } from "node:child_process";
|
|
13
|
+
import { dirname, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
function fixturePathFromArgs() {
|
|
16
|
+
return process.argv[2] ?? "";
|
|
17
|
+
}
|
|
18
|
+
function loadFixture() {
|
|
19
|
+
const fixturePath = process.env["MOCK_FIXTURE_PATH"] || fixturePathFromArgs();
|
|
20
|
+
if (!fixturePath) {
|
|
21
|
+
process.stderr.write("mock-backend: fixture path missing (set MOCK_FIXTURE_PATH or pass a fixture path argument)\n");
|
|
22
|
+
process.exit(2);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const raw = readFileSync(fixturePath, "utf-8");
|
|
26
|
+
const parsed = JSON.parse(raw);
|
|
27
|
+
return {
|
|
28
|
+
output: parsed.output ?? "",
|
|
29
|
+
exit_code: parsed.exit_code ?? 0,
|
|
30
|
+
delay_ms: parsed.delay_ms ?? 0,
|
|
31
|
+
emit_event: parsed.emit_event,
|
|
32
|
+
emit_payload: parsed.emit_payload,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
process.stderr.write(`mock-backend: failed to load fixture: ${err}\n`);
|
|
37
|
+
process.exit(2);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function emitEvent(event, payload) {
|
|
41
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
42
|
+
const distDir = dirname(dirname(currentFile));
|
|
43
|
+
const mainEntry = resolve(distDir, "main.js");
|
|
44
|
+
try {
|
|
45
|
+
execFileSync(process.execPath, [mainEntry, "emit", event, payload], {
|
|
46
|
+
encoding: "utf-8",
|
|
47
|
+
timeout: 5_000,
|
|
48
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
49
|
+
env: process.env,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
process.stderr.write(`mock-backend: emit failed: ${err}\n`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function sleep(ms) {
|
|
57
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
58
|
+
}
|
|
59
|
+
async function main() {
|
|
60
|
+
const fixture = loadFixture();
|
|
61
|
+
if (fixture.delay_ms > 0) {
|
|
62
|
+
await sleep(fixture.delay_ms);
|
|
63
|
+
}
|
|
64
|
+
if (fixture.emit_event) {
|
|
65
|
+
emitEvent(fixture.emit_event, fixture.emit_payload ?? "");
|
|
66
|
+
}
|
|
67
|
+
if (fixture.output) {
|
|
68
|
+
process.stdout.write(fixture.output);
|
|
69
|
+
}
|
|
70
|
+
process.exitCode = fixture.exit_code;
|
|
71
|
+
}
|
|
72
|
+
main().catch((err) => {
|
|
73
|
+
process.stderr.write(`mock-backend: unexpected error: ${err}\n`);
|
|
74
|
+
process.exitCode = 2;
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=mock-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-backend.js","sourceRoot":"","sources":["../../src/testing/mock-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface Role {
|
|
2
|
+
id: string;
|
|
3
|
+
prompt: string;
|
|
4
|
+
promptFile: string;
|
|
5
|
+
emits: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface Topology {
|
|
8
|
+
name: string;
|
|
9
|
+
completion: string;
|
|
10
|
+
roles: Role[];
|
|
11
|
+
handoff: Record<string, string[]>;
|
|
12
|
+
handoffKeys: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function eventMatchesAny(topic: string, patterns: string[]): boolean;
|
|
15
|
+
export declare function getRoleIds(topology: Topology): string[];
|
|
16
|
+
export declare function allEmittedEvents(topology: Topology): string[];
|
|
17
|
+
export declare function handoffKeys(topology: Topology): string[];
|
|
18
|
+
export declare function handoffTargetIds(topology: Topology): string[];
|
|
19
|
+
export declare function loadTopology(projectDir: string): Topology;
|
|
20
|
+
export declare function completionEvent(topology: Topology, fallback: string): string;
|
|
21
|
+
export declare function suggestedRoles(topology: Topology, recentEvent: string): string[];
|
|
22
|
+
export declare function allowedEvents(topology: Topology, recentEvent: string): string[];
|
|
23
|
+
export declare function roleCount(topology: Topology): number;
|
|
24
|
+
export declare function render(topology: Topology, recentEvent: string): string;
|
|
25
|
+
export declare function renderWithContext(topology: Topology, recentEvent: string, suggested: string[], allowed: string[]): string;
|
package/dist/topology.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import TOML from "@iarna/toml";
|
|
4
|
+
import { listContains, listText, lineSep } from "./utils.js";
|
|
5
|
+
export function eventMatchesAny(topic, patterns) {
|
|
6
|
+
for (const pattern of patterns) {
|
|
7
|
+
if (eventMatchesPattern(topic, pattern))
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
export function getRoleIds(topology) {
|
|
13
|
+
return topology.roles.map((r) => r.id);
|
|
14
|
+
}
|
|
15
|
+
export function allEmittedEvents(topology) {
|
|
16
|
+
const all = [];
|
|
17
|
+
for (const role of topology.roles) {
|
|
18
|
+
for (const e of role.emits) {
|
|
19
|
+
if (!all.includes(e))
|
|
20
|
+
all.push(e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return all;
|
|
24
|
+
}
|
|
25
|
+
export function handoffKeys(topology) {
|
|
26
|
+
return topology.handoffKeys;
|
|
27
|
+
}
|
|
28
|
+
export function handoffTargetIds(topology) {
|
|
29
|
+
const all = [];
|
|
30
|
+
for (const key of topology.handoffKeys) {
|
|
31
|
+
for (const target of topology.handoff[key] ?? []) {
|
|
32
|
+
if (!all.includes(target))
|
|
33
|
+
all.push(target);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return all;
|
|
37
|
+
}
|
|
38
|
+
export function loadTopology(projectDir) {
|
|
39
|
+
const path = join(projectDir, "topology.toml");
|
|
40
|
+
if (!existsSync(path))
|
|
41
|
+
return defaultTopology();
|
|
42
|
+
return loadExisting(path, projectDir);
|
|
43
|
+
}
|
|
44
|
+
export function completionEvent(topology, fallback) {
|
|
45
|
+
return topology.completion || fallback;
|
|
46
|
+
}
|
|
47
|
+
export function suggestedRoles(topology, recentEvent) {
|
|
48
|
+
const roles = collectMatchingRoles(topology, recentEvent);
|
|
49
|
+
if (roles.length === 0)
|
|
50
|
+
return getRoleIds(topology);
|
|
51
|
+
return roles;
|
|
52
|
+
}
|
|
53
|
+
export function allowedEvents(topology, recentEvent) {
|
|
54
|
+
const roleIds = suggestedRoles(topology, recentEvent);
|
|
55
|
+
return collectEventsForRoles(topology.roles, roleIds);
|
|
56
|
+
}
|
|
57
|
+
export function roleCount(topology) {
|
|
58
|
+
return topology.roles.length;
|
|
59
|
+
}
|
|
60
|
+
export function render(topology, recentEvent) {
|
|
61
|
+
if (topology.roles.length === 0)
|
|
62
|
+
return "";
|
|
63
|
+
const suggested = suggestedRoles(topology, recentEvent);
|
|
64
|
+
const allowed = allowedEvents(topology, recentEvent);
|
|
65
|
+
return renderWithContext(topology, recentEvent, suggested, allowed);
|
|
66
|
+
}
|
|
67
|
+
export function renderWithContext(topology, recentEvent, suggested, allowed) {
|
|
68
|
+
if (topology.roles.length === 0)
|
|
69
|
+
return "";
|
|
70
|
+
return ("Topology (advisory):\n" +
|
|
71
|
+
"Recent routing event: " + recentEvent + "\n" +
|
|
72
|
+
"Suggested next roles: " + listText(suggested) + "\n" +
|
|
73
|
+
"Allowed next events: " + listText(allowed) + "\n\n" +
|
|
74
|
+
"Role deck:\n" +
|
|
75
|
+
renderRoles(topology.roles));
|
|
76
|
+
}
|
|
77
|
+
function defaultTopology() {
|
|
78
|
+
return { name: "", completion: "", roles: [], handoff: {}, handoffKeys: [] };
|
|
79
|
+
}
|
|
80
|
+
function loadExisting(path, projectDir) {
|
|
81
|
+
const text = readFileSync(path, "utf-8");
|
|
82
|
+
const parsed = TOML.parse(text);
|
|
83
|
+
return buildTopology(parsed, projectDir);
|
|
84
|
+
}
|
|
85
|
+
function buildTopology(parsed, projectDir) {
|
|
86
|
+
const name = typeof parsed.name === "string" ? parsed.name : "";
|
|
87
|
+
const completion = typeof parsed.completion === "string" ? parsed.completion : "";
|
|
88
|
+
const rawRoles = (parsed.role ?? []);
|
|
89
|
+
const roles = rawRoles
|
|
90
|
+
.filter((r) => typeof r.id === "string" && r.id !== "")
|
|
91
|
+
.map((r) => {
|
|
92
|
+
const role = {
|
|
93
|
+
id: r.id,
|
|
94
|
+
prompt: typeof r.prompt === "string" ? r.prompt : "",
|
|
95
|
+
promptFile: typeof r.prompt_file === "string" ? r.prompt_file : "",
|
|
96
|
+
emits: Array.isArray(r.emits) ? r.emits.map(String) : [],
|
|
97
|
+
};
|
|
98
|
+
return { ...role, prompt: rolePrompt(role, projectDir) };
|
|
99
|
+
});
|
|
100
|
+
const rawHandoff = (parsed.handoff ?? {});
|
|
101
|
+
const handoff = {};
|
|
102
|
+
const handoffKeys = [];
|
|
103
|
+
for (const [key, value] of Object.entries(rawHandoff)) {
|
|
104
|
+
handoff[key] = Array.isArray(value) ? value.map(String) : [String(value)];
|
|
105
|
+
handoffKeys.push(key);
|
|
106
|
+
}
|
|
107
|
+
return { name, completion, roles, handoff, handoffKeys };
|
|
108
|
+
}
|
|
109
|
+
function rolePrompt(role, projectDir) {
|
|
110
|
+
if (role.prompt)
|
|
111
|
+
return role.prompt;
|
|
112
|
+
if (!role.promptFile)
|
|
113
|
+
return "";
|
|
114
|
+
return readPromptFile(projectDir, role.promptFile);
|
|
115
|
+
}
|
|
116
|
+
function readPromptFile(projectDir, promptFile) {
|
|
117
|
+
const fullPath = join(projectDir, promptFile);
|
|
118
|
+
if (!existsSync(fullPath))
|
|
119
|
+
return "";
|
|
120
|
+
return readFileSync(fullPath, "utf-8");
|
|
121
|
+
}
|
|
122
|
+
function collectMatchingRoles(topology, event) {
|
|
123
|
+
const acc = [];
|
|
124
|
+
for (const key of topology.handoffKeys) {
|
|
125
|
+
if (eventMatchesPattern(event, key)) {
|
|
126
|
+
for (const roleId of topology.handoff[key] ?? []) {
|
|
127
|
+
if (!acc.includes(roleId))
|
|
128
|
+
acc.push(roleId);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return acc;
|
|
133
|
+
}
|
|
134
|
+
function collectEventsForRoles(roles, roleIds) {
|
|
135
|
+
const acc = [];
|
|
136
|
+
for (const role of roles) {
|
|
137
|
+
if (listContains(roleIds, role.id)) {
|
|
138
|
+
for (const e of role.emits) {
|
|
139
|
+
if (!acc.includes(e))
|
|
140
|
+
acc.push(e);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return acc;
|
|
145
|
+
}
|
|
146
|
+
function eventMatchesPattern(topic, pattern) {
|
|
147
|
+
if (isRegexPattern(pattern)) {
|
|
148
|
+
return regexMatch(topic, stripRegexDelimiters(pattern));
|
|
149
|
+
}
|
|
150
|
+
return topic === pattern;
|
|
151
|
+
}
|
|
152
|
+
function isRegexPattern(value) {
|
|
153
|
+
return value.length >= 3 && value.startsWith("/") && value.endsWith("/");
|
|
154
|
+
}
|
|
155
|
+
function stripRegexDelimiters(value) {
|
|
156
|
+
return value.slice(1, -1);
|
|
157
|
+
}
|
|
158
|
+
function regexMatch(topic, pattern) {
|
|
159
|
+
try {
|
|
160
|
+
const re = new RegExp("^" + pattern + "$");
|
|
161
|
+
return re.test(topic);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function renderRoles(roles) {
|
|
168
|
+
let result = "";
|
|
169
|
+
for (const role of roles) {
|
|
170
|
+
result +=
|
|
171
|
+
"- role `" + role.id + "`\n" +
|
|
172
|
+
" emits: " + listText(role.emits) + "\n" +
|
|
173
|
+
" prompt: " + promptSummary(role.prompt) + "\n";
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
function promptSummary(prompt) {
|
|
178
|
+
if (!prompt)
|
|
179
|
+
return "(none)";
|
|
180
|
+
const lines = prompt.split(lineSep());
|
|
181
|
+
for (const line of lines) {
|
|
182
|
+
const trimmed = line.trim();
|
|
183
|
+
if (trimmed !== "")
|
|
184
|
+
return trimmed;
|
|
185
|
+
}
|
|
186
|
+
return "(none)";
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=topology.js.map
|