harnery 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +2 -0
- package/dist/commands/supervisor.d.ts +4 -0
- package/dist/commands/supervisor.d.ts.map +1 -0
- package/dist/commands/supervisor.js +446 -0
- package/dist/core/supervisor/index.d.ts +4 -0
- package/dist/core/supervisor/index.d.ts.map +1 -0
- package/dist/core/supervisor/index.js +3 -0
- package/dist/core/supervisor/read.d.ts +4 -0
- package/dist/core/supervisor/read.d.ts.map +1 -0
- package/dist/core/supervisor/read.js +2 -0
- package/dist/core/supervisor/runner.d.ts +34 -0
- package/dist/core/supervisor/runner.d.ts.map +1 -0
- package/dist/core/supervisor/runner.js +198 -0
- package/dist/core/supervisor/service-read.d.ts +6 -0
- package/dist/core/supervisor/service-read.d.ts.map +1 -0
- package/dist/core/supervisor/service-read.js +127 -0
- package/dist/core/supervisor/service.d.ts +114 -0
- package/dist/core/supervisor/service.d.ts.map +1 -0
- package/dist/core/supervisor/service.js +699 -0
- package/dist/core/supervisor/state.d.ts +69 -0
- package/dist/core/supervisor/state.d.ts.map +1 -0
- package/dist/core/supervisor/state.js +413 -0
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +21 -8
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +1 -0
- package/dist/core/workflow/run-state.d.ts +2 -0
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +12 -0
- package/dist/core/workflow/specialists.d.ts +7 -0
- package/dist/core/workflow/specialists.d.ts.map +1 -0
- package/dist/core/workflow/specialists.js +78 -0
- package/dist/core/workflow/types.d.ts +17 -0
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/lib/tunnel/gate.d.ts.map +1 -1
- package/dist/lib/tunnel/gate.js +6 -1
- package/package.json +11 -1
- package/src/commander.ts +2 -0
- package/src/commands/supervisor.ts +575 -0
- package/src/core/supervisor/index.ts +51 -0
- package/src/core/supervisor/read.ts +29 -0
- package/src/core/supervisor/runner.ts +278 -0
- package/src/core/supervisor/service-read.ts +144 -0
- package/src/core/supervisor/service.ts +920 -0
- package/src/core/supervisor/state.ts +552 -0
- package/src/core/workflow/engine.ts +21 -8
- package/src/core/workflow/index.ts +1 -0
- package/src/core/workflow/proof.ts +1 -0
- package/src/core/workflow/run-state.ts +17 -0
- package/src/core/workflow/specialists.ts +97 -0
- package/src/core/workflow/types.ts +18 -0
- package/src/lib/tunnel/gate.ts +7 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { acceptWorkItem, reconcileWorkItem, runWorkItem, } from "../work/index.js";
|
|
3
|
+
import { acquireSupervisorLease, readSupervisorIgnoringLease, } from "./state.js";
|
|
4
|
+
export async function runSupervisor(input) {
|
|
5
|
+
const coordRoot = resolve(input.coordRoot);
|
|
6
|
+
const mode = input.mode ?? "run";
|
|
7
|
+
const actor = input.actor?.trim() || `supervisor:${input.goalId}`;
|
|
8
|
+
const log = input.onLog ?? (() => undefined);
|
|
9
|
+
const startedAt = new Date().toISOString();
|
|
10
|
+
const startedMs = Date.now();
|
|
11
|
+
const release = acquireSupervisorLease(coordRoot, input.goalId);
|
|
12
|
+
let cycles = 0;
|
|
13
|
+
let dispatches = 0;
|
|
14
|
+
let acceptances = 0;
|
|
15
|
+
const outcomes = [];
|
|
16
|
+
try {
|
|
17
|
+
const initial = readSupervisorIgnoringLease(coordRoot, input.goalId);
|
|
18
|
+
const cycleLimit = mode === "tick" ? 1 : initial.intent.limits.max_cycles;
|
|
19
|
+
const deadline = startedMs + initial.intent.limits.max_runtime_ms;
|
|
20
|
+
while (cycles < cycleLimit) {
|
|
21
|
+
cycles++;
|
|
22
|
+
let record = refreshGraph(coordRoot, input.goalId, actor);
|
|
23
|
+
log(`[${record.intent.title}] cycle ${cycles}: ${record.projection.state}; ` +
|
|
24
|
+
`${record.projection.ready_work.length} ready, ${record.projection.attention_work.length} attention`);
|
|
25
|
+
if (record.projection.state === "succeeded") {
|
|
26
|
+
return report("succeeded", record.projection.reason, record);
|
|
27
|
+
}
|
|
28
|
+
if (Date.now() >= deadline) {
|
|
29
|
+
return report("budget_exhausted", "supervisor wall-time limit reached", record);
|
|
30
|
+
}
|
|
31
|
+
const before = graphFingerprint(record);
|
|
32
|
+
let changed = false;
|
|
33
|
+
if (record.intent.automation.accept_passing_proof) {
|
|
34
|
+
for (const work of record.work) {
|
|
35
|
+
if (work.projection.state !== "in_review")
|
|
36
|
+
continue;
|
|
37
|
+
acceptWorkItem(coordRoot, work.intent.id, {
|
|
38
|
+
actor,
|
|
39
|
+
reason: "passing proof accepted by frozen supervisor policy",
|
|
40
|
+
});
|
|
41
|
+
acceptances++;
|
|
42
|
+
changed = true;
|
|
43
|
+
log(`[${record.intent.title}] accepted ${work.intent.id} from passing proof`);
|
|
44
|
+
}
|
|
45
|
+
if (changed)
|
|
46
|
+
record = refreshGraph(coordRoot, input.goalId, actor);
|
|
47
|
+
if (record.projection.state === "succeeded") {
|
|
48
|
+
return report("succeeded", record.projection.reason, record);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const candidates = selectCandidates(record);
|
|
52
|
+
const selected = selectWithinAttemptBudget(record, candidates).slice(0, record.intent.limits.max_parallel_work);
|
|
53
|
+
if (selected.length > 0 && Date.now() < deadline) {
|
|
54
|
+
const settled = await Promise.all(selected.map(async (candidate) => {
|
|
55
|
+
dispatches++;
|
|
56
|
+
log(`[${record.intent.title}] ${candidate.action} ${candidate.record.intent.id}`);
|
|
57
|
+
try {
|
|
58
|
+
const result = await runWorkItem({
|
|
59
|
+
coordRoot,
|
|
60
|
+
workId: candidate.record.intent.id,
|
|
61
|
+
retry: candidate.action === "retry",
|
|
62
|
+
actor,
|
|
63
|
+
engine: {
|
|
64
|
+
...input.engine,
|
|
65
|
+
specialists: record.intent.specialists,
|
|
66
|
+
maxAgents: record.intent.limits.max_agents_per_work,
|
|
67
|
+
concurrency: record.intent.limits.agent_concurrency,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
work_id: candidate.record.intent.id,
|
|
72
|
+
action: candidate.action,
|
|
73
|
+
status: "completed",
|
|
74
|
+
run_id: result.runId,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
const latest = reconcileWorkItem(coordRoot, candidate.record.intent.id, actor);
|
|
79
|
+
return {
|
|
80
|
+
work_id: candidate.record.intent.id,
|
|
81
|
+
action: candidate.action,
|
|
82
|
+
status: latest.projection.state === "awaiting_approval" ? "parked" : "failed",
|
|
83
|
+
run_id: latest.projection.latest_run_id,
|
|
84
|
+
error: boundedError(error.message),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}));
|
|
88
|
+
outcomes.push(...settled);
|
|
89
|
+
changed = true;
|
|
90
|
+
}
|
|
91
|
+
record = refreshGraph(coordRoot, input.goalId, actor);
|
|
92
|
+
const after = graphFingerprint(record);
|
|
93
|
+
if (record.projection.state === "succeeded") {
|
|
94
|
+
return report("succeeded", record.projection.reason, record);
|
|
95
|
+
}
|
|
96
|
+
if (mode === "tick") {
|
|
97
|
+
return report(before === after ? "no_progress" : "tick_complete", before === after
|
|
98
|
+
? "the tick found no legal progress action"
|
|
99
|
+
: "one bounded supervisor cycle completed", record);
|
|
100
|
+
}
|
|
101
|
+
if (Date.now() >= deadline) {
|
|
102
|
+
return report("budget_exhausted", "supervisor wall-time limit reached", record);
|
|
103
|
+
}
|
|
104
|
+
if (record.projection.state === "budget_exhausted") {
|
|
105
|
+
return report("budget_exhausted", record.projection.reason, record);
|
|
106
|
+
}
|
|
107
|
+
if (selected.length === 0 && !changed) {
|
|
108
|
+
return report(stopForProjection(record.projection), record.projection.reason, record);
|
|
109
|
+
}
|
|
110
|
+
if (selected.length === 0 && record.projection.state !== "ready") {
|
|
111
|
+
return report(stopForProjection(record.projection), record.projection.reason, record);
|
|
112
|
+
}
|
|
113
|
+
if (before === after) {
|
|
114
|
+
return report("no_progress", "a supervisor cycle produced no durable state change", record);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const final = refreshGraph(coordRoot, input.goalId, actor);
|
|
118
|
+
return report("budget_exhausted", `supervisor cycle limit reached (${cycleLimit})`, final);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
release();
|
|
122
|
+
}
|
|
123
|
+
function report(stopReason, reason, record) {
|
|
124
|
+
const endedAt = new Date().toISOString();
|
|
125
|
+
return {
|
|
126
|
+
goal_id: input.goalId,
|
|
127
|
+
mode,
|
|
128
|
+
stop_reason: stopReason,
|
|
129
|
+
reason,
|
|
130
|
+
started_at: startedAt,
|
|
131
|
+
ended_at: endedAt,
|
|
132
|
+
duration_ms: Date.now() - startedMs,
|
|
133
|
+
cycles,
|
|
134
|
+
dispatches,
|
|
135
|
+
acceptances,
|
|
136
|
+
outcomes,
|
|
137
|
+
projection: record.projection,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function refreshGraph(coordRoot, goalId, actor) {
|
|
142
|
+
const before = readSupervisorIgnoringLease(coordRoot, goalId);
|
|
143
|
+
for (const work of before.work)
|
|
144
|
+
reconcileWorkItem(coordRoot, work.intent.id, actor);
|
|
145
|
+
return readSupervisorIgnoringLease(coordRoot, goalId);
|
|
146
|
+
}
|
|
147
|
+
function selectCandidates(record) {
|
|
148
|
+
const candidates = [];
|
|
149
|
+
for (const work of record.work) {
|
|
150
|
+
if (work.projection.state === "ready") {
|
|
151
|
+
candidates.push({ record: work, action: "run", consumesAttempt: true });
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (work.projection.state === "awaiting_approval" &&
|
|
155
|
+
work.projection.next_action === "resume" &&
|
|
156
|
+
record.intent.automation.resume_approved) {
|
|
157
|
+
candidates.push({ record: work, action: "resume", consumesAttempt: false });
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (work.projection.state === "blocked" &&
|
|
161
|
+
work.projection.next_action === "retry" &&
|
|
162
|
+
record.intent.automation.retry_blocked) {
|
|
163
|
+
candidates.push({ record: work, action: "retry", consumesAttempt: true });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return candidates;
|
|
167
|
+
}
|
|
168
|
+
function selectWithinAttemptBudget(record, candidates) {
|
|
169
|
+
let remaining = record.projection.attempts_remaining;
|
|
170
|
+
return candidates.filter((candidate) => {
|
|
171
|
+
if (!candidate.consumesAttempt)
|
|
172
|
+
return true;
|
|
173
|
+
if (remaining <= 0)
|
|
174
|
+
return false;
|
|
175
|
+
remaining--;
|
|
176
|
+
return true;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function graphFingerprint(record) {
|
|
180
|
+
return JSON.stringify(record.work.map((work) => [
|
|
181
|
+
work.intent.id,
|
|
182
|
+
work.projection.state,
|
|
183
|
+
work.projection.next_action,
|
|
184
|
+
work.projection.attempts_used,
|
|
185
|
+
work.events.length,
|
|
186
|
+
]));
|
|
187
|
+
}
|
|
188
|
+
function stopForProjection(projection) {
|
|
189
|
+
if (projection.state === "budget_exhausted")
|
|
190
|
+
return "budget_exhausted";
|
|
191
|
+
if (projection.state === "blocked")
|
|
192
|
+
return "blocked";
|
|
193
|
+
return "awaiting_attention";
|
|
194
|
+
}
|
|
195
|
+
function boundedError(message) {
|
|
196
|
+
const normalized = message.replace(/\s+/g, " ").trim();
|
|
197
|
+
return normalized.length > 2_000 ? `${normalized.slice(0, 1_999)}…` : normalized;
|
|
198
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SupervisorServiceConfig, SupervisorServiceRuntime, SupervisorServiceStatus } from "./service.js";
|
|
2
|
+
export declare function readSupervisorServiceConfig(coordRootRaw: string): SupervisorServiceConfig;
|
|
3
|
+
export declare function readSupervisorServiceRuntime(coordRootRaw: string): SupervisorServiceRuntime | undefined;
|
|
4
|
+
export declare function readSupervisorServiceStatus(coordRootRaw: string): SupervisorServiceStatus;
|
|
5
|
+
export declare function supervisorServiceLogPath(coordRoot: string): string;
|
|
6
|
+
//# sourceMappingURL=service-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-read.d.ts","sourceRoot":"","sources":["../../../src/core/supervisor/service-read.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EAExB,MAAM,cAAc,CAAC;AAMtB,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,uBAAuB,CA0BzF;AAED,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,GACnB,wBAAwB,GAAG,SAAS,CAgBtC;AAED,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,uBAAuB,CAkBzF;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAElE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
const MAX_FILE_BYTES = 512 * 1024;
|
|
5
|
+
const MAX_GOALS = 100;
|
|
6
|
+
const FOREIGN_STATUS_STALE_MS = 30_000;
|
|
7
|
+
export function readSupervisorServiceConfig(coordRootRaw) {
|
|
8
|
+
const coordRoot = resolve(coordRootRaw);
|
|
9
|
+
const config = readBoundedJson(join(serviceDir(coordRoot), "config.json"), "supervisor service configuration");
|
|
10
|
+
if (config.schema_version !== 1 ||
|
|
11
|
+
!validTimestamp(config.created_at) ||
|
|
12
|
+
!Array.isArray(config.goal_ids) ||
|
|
13
|
+
config.goal_ids.length < 1 ||
|
|
14
|
+
config.goal_ids.length > MAX_GOALS ||
|
|
15
|
+
config.goal_ids.some((goalId) => typeof goalId !== "string" || !goalId.trim()) ||
|
|
16
|
+
!positive(config.wake_interval_ms) ||
|
|
17
|
+
!positive(config.heartbeat_interval_ms) ||
|
|
18
|
+
!positive(config.error_backoff_base_ms) ||
|
|
19
|
+
!positive(config.error_backoff_max_ms) ||
|
|
20
|
+
config.error_backoff_max_ms < config.error_backoff_base_ms ||
|
|
21
|
+
!config.engine ||
|
|
22
|
+
typeof config.engine !== "object" ||
|
|
23
|
+
typeof config.engine.subscription_only !== "boolean" ||
|
|
24
|
+
typeof config.engine.allow_api_billing !== "boolean") {
|
|
25
|
+
throw new Error("supervisor service configuration has an unsupported schema");
|
|
26
|
+
}
|
|
27
|
+
return config;
|
|
28
|
+
}
|
|
29
|
+
export function readSupervisorServiceRuntime(coordRootRaw) {
|
|
30
|
+
const coordRoot = resolve(coordRootRaw);
|
|
31
|
+
const path = join(serviceDir(coordRoot), "runtime.json");
|
|
32
|
+
if (!existsSync(path))
|
|
33
|
+
return undefined;
|
|
34
|
+
const runtime = readBoundedJson(path, "supervisor service runtime");
|
|
35
|
+
if (runtime.schema_version !== 1 ||
|
|
36
|
+
!validTimestamp(runtime.config_created_at) ||
|
|
37
|
+
!validTimestamp(runtime.updated_at) ||
|
|
38
|
+
!runtime.goals ||
|
|
39
|
+
typeof runtime.goals !== "object" ||
|
|
40
|
+
Array.isArray(runtime.goals)) {
|
|
41
|
+
throw new Error("supervisor service runtime has an unsupported schema");
|
|
42
|
+
}
|
|
43
|
+
return runtime;
|
|
44
|
+
}
|
|
45
|
+
export function readSupervisorServiceStatus(coordRootRaw) {
|
|
46
|
+
const coordRoot = resolve(coordRootRaw);
|
|
47
|
+
const record = readStatusRecord(coordRoot);
|
|
48
|
+
let config;
|
|
49
|
+
let runtime;
|
|
50
|
+
try {
|
|
51
|
+
config = readSupervisorServiceConfig(coordRoot);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Unconfigured or corrupt service state is represented without throwing.
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
runtime = readSupervisorServiceRuntime(coordRoot);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Runtime is recoverable and must not make the dashboard unreadable.
|
|
61
|
+
}
|
|
62
|
+
if (!record)
|
|
63
|
+
return { running: false, stale: false, config, runtime };
|
|
64
|
+
const running = statusOwnerIsLive(record);
|
|
65
|
+
return { running, stale: !running && record.state !== "stopped", record, config, runtime };
|
|
66
|
+
}
|
|
67
|
+
export function supervisorServiceLogPath(coordRoot) {
|
|
68
|
+
return join(serviceDir(resolve(coordRoot)), "service.log");
|
|
69
|
+
}
|
|
70
|
+
function readStatusRecord(coordRoot) {
|
|
71
|
+
const path = join(serviceDir(coordRoot), "status.json");
|
|
72
|
+
if (!existsSync(path))
|
|
73
|
+
return undefined;
|
|
74
|
+
try {
|
|
75
|
+
const value = readBoundedJson(path, "supervisor service status");
|
|
76
|
+
if (value.schema_version !== 1 ||
|
|
77
|
+
!Number.isSafeInteger(value.pid) ||
|
|
78
|
+
value.pid < 1 ||
|
|
79
|
+
typeof value.host !== "string" ||
|
|
80
|
+
typeof value.nonce !== "string" ||
|
|
81
|
+
!validTimestamp(value.started_at) ||
|
|
82
|
+
!validTimestamp(value.heartbeat_at)) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function statusOwnerIsLive(record) {
|
|
92
|
+
if (record.state === "stopped")
|
|
93
|
+
return false;
|
|
94
|
+
if (record.host === hostname()) {
|
|
95
|
+
try {
|
|
96
|
+
process.kill(record.pid, 0);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return error.code === "EPERM";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const age = Date.now() - Date.parse(record.heartbeat_at);
|
|
104
|
+
return Number.isFinite(age) && age < FOREIGN_STATUS_STALE_MS;
|
|
105
|
+
}
|
|
106
|
+
function readBoundedJson(path, label) {
|
|
107
|
+
if (!existsSync(path))
|
|
108
|
+
throw new Error(`${label} does not exist`);
|
|
109
|
+
const size = statSync(path).size;
|
|
110
|
+
if (size <= 0 || size > MAX_FILE_BYTES)
|
|
111
|
+
throw new Error(`${label} has invalid size ${size}`);
|
|
112
|
+
try {
|
|
113
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
throw new Error(`cannot parse ${label}: ${error.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function serviceDir(coordRoot) {
|
|
120
|
+
return join(coordRoot, ".harnery", "supervisor-service");
|
|
121
|
+
}
|
|
122
|
+
function positive(value) {
|
|
123
|
+
return Number.isSafeInteger(value) && value > 0;
|
|
124
|
+
}
|
|
125
|
+
function validTimestamp(value) {
|
|
126
|
+
return typeof value === "string" && value.length <= 40 && Number.isFinite(Date.parse(value));
|
|
127
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { type NormalizedPolicy, type PolicyIsolation } from "../policy/index.js";
|
|
2
|
+
import type { RunWorkItemInput } from "../work/index.js";
|
|
3
|
+
import { type SupervisorRunReport, type SupervisorStopReason } from "./runner.js";
|
|
4
|
+
import { type SupervisorRecord } from "./state.js";
|
|
5
|
+
export declare const SUPERVISOR_SERVICE_CONFIG_SCHEMA_VERSION: 1;
|
|
6
|
+
export declare const SUPERVISOR_SERVICE_RUNTIME_SCHEMA_VERSION: 1;
|
|
7
|
+
export declare const SUPERVISOR_SERVICE_STATUS_SCHEMA_VERSION: 1;
|
|
8
|
+
export interface SupervisorServiceEngineConfig {
|
|
9
|
+
default_harness?: string;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
subscription_only: boolean;
|
|
12
|
+
allow_api_billing: boolean;
|
|
13
|
+
policy?: NormalizedPolicy;
|
|
14
|
+
isolation?: PolicyIsolation;
|
|
15
|
+
approval_addressee?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SupervisorServiceConfig {
|
|
18
|
+
schema_version: typeof SUPERVISOR_SERVICE_CONFIG_SCHEMA_VERSION;
|
|
19
|
+
goal_ids: string[];
|
|
20
|
+
wake_interval_ms: number;
|
|
21
|
+
heartbeat_interval_ms: number;
|
|
22
|
+
error_backoff_base_ms: number;
|
|
23
|
+
error_backoff_max_ms: number;
|
|
24
|
+
engine: SupervisorServiceEngineConfig;
|
|
25
|
+
created_at: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ConfigureSupervisorServiceInput {
|
|
28
|
+
coordRoot: string;
|
|
29
|
+
goalIds: readonly string[];
|
|
30
|
+
wakeIntervalMs?: number;
|
|
31
|
+
heartbeatIntervalMs?: number;
|
|
32
|
+
errorBackoffBaseMs?: number;
|
|
33
|
+
errorBackoffMaxMs?: number;
|
|
34
|
+
engine?: Partial<SupervisorServiceEngineConfig>;
|
|
35
|
+
}
|
|
36
|
+
export type SupervisorServiceGoalState = "idle" | "backoff" | "awaiting_change";
|
|
37
|
+
export interface SupervisorServiceGoalRuntime {
|
|
38
|
+
state: SupervisorServiceGoalState;
|
|
39
|
+
consecutive_errors: number;
|
|
40
|
+
observed_fingerprint?: string;
|
|
41
|
+
next_wake_at?: string;
|
|
42
|
+
last_tick_at?: string;
|
|
43
|
+
last_stop_reason?: SupervisorStopReason;
|
|
44
|
+
last_error?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface SupervisorServiceRuntime {
|
|
47
|
+
schema_version: typeof SUPERVISOR_SERVICE_RUNTIME_SCHEMA_VERSION;
|
|
48
|
+
config_created_at: string;
|
|
49
|
+
updated_at: string;
|
|
50
|
+
goals: Record<string, SupervisorServiceGoalRuntime>;
|
|
51
|
+
}
|
|
52
|
+
export type SupervisorServiceProcessState = "starting" | "running" | "stopping" | "stopped";
|
|
53
|
+
export interface SupervisorServiceStatusRecord {
|
|
54
|
+
schema_version: typeof SUPERVISOR_SERVICE_STATUS_SCHEMA_VERSION;
|
|
55
|
+
pid: number;
|
|
56
|
+
host: string;
|
|
57
|
+
nonce: string;
|
|
58
|
+
state: SupervisorServiceProcessState;
|
|
59
|
+
started_at: string;
|
|
60
|
+
heartbeat_at: string;
|
|
61
|
+
config_created_at: string;
|
|
62
|
+
sweep_count: number;
|
|
63
|
+
active_goal_id?: string;
|
|
64
|
+
last_sweep_at?: string;
|
|
65
|
+
next_wake_at?: string;
|
|
66
|
+
last_error?: string;
|
|
67
|
+
stopped_at?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface SupervisorServiceStatus {
|
|
70
|
+
running: boolean;
|
|
71
|
+
stale: boolean;
|
|
72
|
+
record?: SupervisorServiceStatusRecord;
|
|
73
|
+
config?: SupervisorServiceConfig;
|
|
74
|
+
runtime?: SupervisorServiceRuntime;
|
|
75
|
+
}
|
|
76
|
+
export interface SupervisorServiceSweepOutcome {
|
|
77
|
+
goal_id: string;
|
|
78
|
+
action: "tick" | "skip" | "backoff";
|
|
79
|
+
reason: string;
|
|
80
|
+
stop_reason?: SupervisorStopReason;
|
|
81
|
+
next_wake_at?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface SupervisorServiceSweepReport {
|
|
84
|
+
started_at: string;
|
|
85
|
+
ended_at: string;
|
|
86
|
+
outcomes: SupervisorServiceSweepOutcome[];
|
|
87
|
+
}
|
|
88
|
+
export interface RunSupervisorServiceSweepInput {
|
|
89
|
+
coordRoot: string;
|
|
90
|
+
config: SupervisorServiceConfig;
|
|
91
|
+
engine?: Omit<RunWorkItemInput["engine"], "maxAgents" | "concurrency" | "specialists">;
|
|
92
|
+
actor?: string;
|
|
93
|
+
now?: () => number;
|
|
94
|
+
readGoal?: (coordRoot: string, goalId: string) => SupervisorRecord;
|
|
95
|
+
runGoal?: (goalId: string) => Promise<SupervisorRunReport>;
|
|
96
|
+
onGoalStart?: (goalId: string) => void;
|
|
97
|
+
}
|
|
98
|
+
export interface RunSupervisorServiceDaemonInput {
|
|
99
|
+
coordRoot: string;
|
|
100
|
+
engine: Omit<RunWorkItemInput["engine"], "maxAgents" | "concurrency" | "specialists">;
|
|
101
|
+
actor?: string;
|
|
102
|
+
maxSweeps?: number;
|
|
103
|
+
onLog?: (line: string) => void;
|
|
104
|
+
}
|
|
105
|
+
export declare function configureSupervisorService(input: ConfigureSupervisorServiceInput): SupervisorServiceConfig;
|
|
106
|
+
export declare function readSupervisorServiceConfig(coordRootRaw: string): SupervisorServiceConfig;
|
|
107
|
+
export declare function readSupervisorServiceRuntime(coordRootRaw: string): SupervisorServiceRuntime | undefined;
|
|
108
|
+
export declare function readSupervisorServiceStatus(coordRootRaw: string): SupervisorServiceStatus;
|
|
109
|
+
export declare function spawnSupervisorService(coordRootRaw: string): Promise<SupervisorServiceStatus>;
|
|
110
|
+
export declare function requestSupervisorServiceStop(coordRootRaw: string): SupervisorServiceStatus;
|
|
111
|
+
export declare function runSupervisorServiceSweep(input: RunSupervisorServiceSweepInput): Promise<SupervisorServiceSweepReport>;
|
|
112
|
+
export declare function runSupervisorServiceDaemon(input: RunSupervisorServiceDaemonInput): Promise<SupervisorServiceStatusRecord>;
|
|
113
|
+
export declare function supervisorServiceLogPath(coordRoot: string): string;
|
|
114
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/core/supervisor/service.ts"],"names":[],"mappings":"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"}
|