toc-ocra 0.2.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/LICENSE +21 -0
- package/README.md +70 -0
- package/assets/icon.svg +1 -0
- package/dist/plugin/renderer.css +2 -0
- package/dist/plugin/renderer.css.map +7 -0
- package/dist/plugin/renderer.js +2 -0
- package/dist/plugin/renderer.js.map +7 -0
- package/dist/src/config.d.ts +66 -0
- package/dist/src/config.js +173 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/control/pairing.d.ts +44 -0
- package/dist/src/control/pairing.js +99 -0
- package/dist/src/control/pairing.js.map +1 -0
- package/dist/src/exec/script-runner.d.ts +9 -0
- package/dist/src/exec/script-runner.js +110 -0
- package/dist/src/exec/script-runner.js.map +1 -0
- package/dist/src/health/server.d.ts +74 -0
- package/dist/src/health/server.js +248 -0
- package/dist/src/health/server.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +173 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logging/diagnostic-log.d.ts +16 -0
- package/dist/src/logging/diagnostic-log.js +128 -0
- package/dist/src/logging/diagnostic-log.js.map +1 -0
- package/dist/src/providers/cli/claude.d.ts +2 -0
- package/dist/src/providers/cli/claude.js +48 -0
- package/dist/src/providers/cli/claude.js.map +1 -0
- package/dist/src/providers/cli/codex.d.ts +2 -0
- package/dist/src/providers/cli/codex.js +67 -0
- package/dist/src/providers/cli/codex.js.map +1 -0
- package/dist/src/providers/cli/gemini.d.ts +2 -0
- package/dist/src/providers/cli/gemini.js +30 -0
- package/dist/src/providers/cli/gemini.js.map +1 -0
- package/dist/src/providers/cli/grok.d.ts +2 -0
- package/dist/src/providers/cli/grok.js +29 -0
- package/dist/src/providers/cli/grok.js.map +1 -0
- package/dist/src/providers/cli/opencode.d.ts +2 -0
- package/dist/src/providers/cli/opencode.js +29 -0
- package/dist/src/providers/cli/opencode.js.map +1 -0
- package/dist/src/providers/detection.d.ts +11 -0
- package/dist/src/providers/detection.js +96 -0
- package/dist/src/providers/detection.js.map +1 -0
- package/dist/src/providers/model-catalog-collector.d.ts +22 -0
- package/dist/src/providers/model-catalog-collector.js +66 -0
- package/dist/src/providers/model-catalog-collector.js.map +1 -0
- package/dist/src/providers/model-catalog.d.ts +45 -0
- package/dist/src/providers/model-catalog.js +382 -0
- package/dist/src/providers/model-catalog.js.map +1 -0
- package/dist/src/providers/provider.d.ts +49 -0
- package/dist/src/providers/provider.js +63 -0
- package/dist/src/providers/provider.js.map +1 -0
- package/dist/src/providers/registry.d.ts +31 -0
- package/dist/src/providers/registry.js +60 -0
- package/dist/src/providers/registry.js.map +1 -0
- package/dist/src/runs/orphan-registry.d.ts +24 -0
- package/dist/src/runs/orphan-registry.js +63 -0
- package/dist/src/runs/orphan-registry.js.map +1 -0
- package/dist/src/runs/process-tree.d.ts +21 -0
- package/dist/src/runs/process-tree.js +95 -0
- package/dist/src/runs/process-tree.js.map +1 -0
- package/dist/src/runs/run-supervisor.d.ts +63 -0
- package/dist/src/runs/run-supervisor.js +285 -0
- package/dist/src/runs/run-supervisor.js.map +1 -0
- package/dist/src/runtime/agent-runtime.d.ts +68 -0
- package/dist/src/runtime/agent-runtime.js +340 -0
- package/dist/src/runtime/agent-runtime.js.map +1 -0
- package/dist/src/runtime/agent-service.d.ts +33 -0
- package/dist/src/runtime/agent-service.js +181 -0
- package/dist/src/runtime/agent-service.js.map +1 -0
- package/dist/src/runtime/cli/hydrate-shell-path.d.ts +33 -0
- package/dist/src/runtime/cli/hydrate-shell-path.js +173 -0
- package/dist/src/runtime/cli/hydrate-shell-path.js.map +1 -0
- package/dist/src/session/terminal-line-sanitizer.d.ts +7 -0
- package/dist/src/session/terminal-line-sanitizer.js +21 -0
- package/dist/src/session/terminal-line-sanitizer.js.map +1 -0
- package/dist/src/session/terminal-tail-buffer.d.ts +70 -0
- package/dist/src/session/terminal-tail-buffer.js +149 -0
- package/dist/src/session/terminal-tail-buffer.js.map +1 -0
- package/dist/src/shared/cli-detection-types.d.ts +19 -0
- package/dist/src/shared/cli-detection-types.js +2 -0
- package/dist/src/shared/cli-detection-types.js.map +1 -0
- package/dist/src/shared/node-cli-command-resolution.d.ts +19 -0
- package/dist/src/shared/node-cli-command-resolution.js +173 -0
- package/dist/src/shared/node-cli-command-resolution.js.map +1 -0
- package/dist/src/transport/gateway-client.d.ts +38 -0
- package/dist/src/transport/gateway-client.js +73 -0
- package/dist/src/transport/gateway-client.js.map +1 -0
- package/dist/src/types/protocol.d.ts +172 -0
- package/dist/src/types/protocol.js +55 -0
- package/dist/src/types/protocol.js.map +1 -0
- package/dist/src/workspace/directory-browser.d.ts +17 -0
- package/dist/src/workspace/directory-browser.js +47 -0
- package/dist/src/workspace/directory-browser.js.map +1 -0
- package/dist/src/workspace/workspace-manager.d.ts +41 -0
- package/dist/src/workspace/workspace-manager.js +436 -0
- package/dist/src/workspace/workspace-manager.js.map +1 -0
- package/locales/en.json +66 -0
- package/locales/zh-CN.json +66 -0
- package/package.json +90 -0
- package/scripts/service.mjs +174 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { realpath } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
4
|
+
import { createInterface } from 'node:readline';
|
|
5
|
+
import { resolveHeadlessProvider } from '../providers/registry.js';
|
|
6
|
+
import { sanitizeTerminalLine } from '../session/terminal-line-sanitizer.js';
|
|
7
|
+
import { TerminalTailBuffer } from '../session/terminal-tail-buffer.js';
|
|
8
|
+
import { killProcessTree } from './process-tree.js';
|
|
9
|
+
/**
|
|
10
|
+
* Supervises headless CLI turns. One process per turn:
|
|
11
|
+
*
|
|
12
|
+
* spawn -> report started(pid) -> parse stdout (session id, answer)
|
|
13
|
+
* -> process exits -> report finished(status, final answer)
|
|
14
|
+
*
|
|
15
|
+
* "Done" is the process exit. If the CLI already declared the turn finished
|
|
16
|
+
* but its process lingers, it is stopped after COMPLETION_EXIT_GRACE_MS, so
|
|
17
|
+
* a finished turn can never keep the workstation busy. Stop kills the whole
|
|
18
|
+
* process tree.
|
|
19
|
+
*/
|
|
20
|
+
export const COMPLETION_EXIT_GRACE_MS = 15_000;
|
|
21
|
+
const RECENT_RUN_TTL_MS = 10 * 60_000;
|
|
22
|
+
const MAX_RECENT_RUNS = 100;
|
|
23
|
+
const MAX_ERROR_ROWS = 40;
|
|
24
|
+
export class RunSupervisor {
|
|
25
|
+
config;
|
|
26
|
+
logger;
|
|
27
|
+
reporter;
|
|
28
|
+
orphans;
|
|
29
|
+
active = new Map();
|
|
30
|
+
recent = new Map();
|
|
31
|
+
/** Run ids whose finish report has not been acknowledged yet. */
|
|
32
|
+
unreported = new Set();
|
|
33
|
+
constructor(config, logger, reporter, orphans) {
|
|
34
|
+
this.config = config;
|
|
35
|
+
this.logger = logger;
|
|
36
|
+
this.reporter = reporter;
|
|
37
|
+
this.orphans = orphans;
|
|
38
|
+
}
|
|
39
|
+
get activeCount() {
|
|
40
|
+
return this.active.size;
|
|
41
|
+
}
|
|
42
|
+
/** Runs to list in the heartbeat: still running, or finished but not yet reported. */
|
|
43
|
+
activeRunIds() {
|
|
44
|
+
return [...new Set([...this.active.keys(), ...this.unreported])];
|
|
45
|
+
}
|
|
46
|
+
markReported(runId) {
|
|
47
|
+
this.unreported.delete(runId);
|
|
48
|
+
}
|
|
49
|
+
recentRuns() {
|
|
50
|
+
const running = [...this.active.values()].map((run) => ({ runId: run.runId, workstationId: run.workstationId, status: 'running', at: run.startedAt }));
|
|
51
|
+
const done = [...this.recent.values()].map((run) => ({ runId: run.runId, workstationId: run.workstationId, status: run.status, at: run.finishedAt }));
|
|
52
|
+
return [...running, ...done].sort((a, b) => b.at - a.at).slice(0, 30);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Starts a turn. Refusals (busy workstation, concurrency limit, bad work
|
|
56
|
+
* directory, unknown CLI) are reported as a failed run, never thrown.
|
|
57
|
+
*/
|
|
58
|
+
async start(payload) {
|
|
59
|
+
if (this.active.has(payload.run_id) || this.recent.has(payload.run_id)) {
|
|
60
|
+
this.logger.info('run-duplicate-ignored', { runId: payload.run_id });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const refuse = async (error) => {
|
|
64
|
+
this.logger.warn('run-refused', { runId: payload.run_id, error });
|
|
65
|
+
this.remember({ runId: payload.run_id, workstationId: payload.workstation_id, tail: new TerminalTailBuffer(), finishedAt: Date.now(), status: 'failed' });
|
|
66
|
+
await this.report(payload.run_id, { status: 'failed', error, duration_ms: 0 });
|
|
67
|
+
};
|
|
68
|
+
if ([...this.active.values()].some((run) => run.workstationId === payload.workstation_id)) {
|
|
69
|
+
return refuse('本机该工位已有任务在运行');
|
|
70
|
+
}
|
|
71
|
+
if (this.active.size >= this.config.maxConcurrentRuns) {
|
|
72
|
+
return refuse(`本机同时运行的任务已达上限(${this.config.maxConcurrentRuns})`);
|
|
73
|
+
}
|
|
74
|
+
let provider;
|
|
75
|
+
let workdir;
|
|
76
|
+
try {
|
|
77
|
+
provider = resolveHeadlessProvider(payload.agent_type);
|
|
78
|
+
workdir = await this.validateWorkdir(payload.workdir || this.config.allowedRoots[0]);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
return refuse(errorMessage(error));
|
|
82
|
+
}
|
|
83
|
+
const launch = provider.buildLaunch({
|
|
84
|
+
prompt: payload.prompt,
|
|
85
|
+
sessionId: payload.session_id,
|
|
86
|
+
model: payload.model,
|
|
87
|
+
reasoningEffort: payload.reasoning_effort,
|
|
88
|
+
workdir
|
|
89
|
+
});
|
|
90
|
+
let child;
|
|
91
|
+
try {
|
|
92
|
+
child = spawn(launch.executable, launch.args, {
|
|
93
|
+
cwd: workdir,
|
|
94
|
+
env: launch.env,
|
|
95
|
+
detached: process.platform !== 'win32',
|
|
96
|
+
shell: false,
|
|
97
|
+
windowsHide: true,
|
|
98
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
return refuse(`无法启动 ${provider.id}:${errorMessage(error)}`);
|
|
103
|
+
}
|
|
104
|
+
const run = {
|
|
105
|
+
runId: payload.run_id,
|
|
106
|
+
workstationId: payload.workstation_id,
|
|
107
|
+
agentType: provider.id,
|
|
108
|
+
provider,
|
|
109
|
+
child,
|
|
110
|
+
pid: child.pid ?? 0,
|
|
111
|
+
startedAt: Date.now(),
|
|
112
|
+
sessionId: payload.session_id,
|
|
113
|
+
finalMessage: '',
|
|
114
|
+
turnCompleted: false,
|
|
115
|
+
turnError: '',
|
|
116
|
+
stderr: [],
|
|
117
|
+
cancelRequested: false,
|
|
118
|
+
killedAfterCompletion: false,
|
|
119
|
+
timedOut: false,
|
|
120
|
+
tail: new TerminalTailBuffer(),
|
|
121
|
+
timers: []
|
|
122
|
+
};
|
|
123
|
+
this.active.set(run.runId, run);
|
|
124
|
+
this.unreported.add(run.runId);
|
|
125
|
+
if (run.pid > 1)
|
|
126
|
+
this.orphans?.add({ runId: run.runId, pid: run.pid, executable: launch.executable, startedAt: run.startedAt });
|
|
127
|
+
run.tail.append(`● ${provider.id} 启动于 ${workdir}${payload.session_id ? `(继续会话 ${payload.session_id})` : ''}\n`);
|
|
128
|
+
this.logger.info('run-started', { runId: run.runId, agentType: provider.id, pid: run.pid, resume: Boolean(payload.session_id) });
|
|
129
|
+
let spawnError = '';
|
|
130
|
+
child.once('error', (error) => {
|
|
131
|
+
spawnError = error.message;
|
|
132
|
+
});
|
|
133
|
+
createInterface({ input: child.stdout }).on('line', (line) => this.onStdout(run, line));
|
|
134
|
+
createInterface({ input: child.stderr }).on('line', (line) => {
|
|
135
|
+
const clean = sanitizeTerminalLine(line);
|
|
136
|
+
if (!clean.trim())
|
|
137
|
+
return;
|
|
138
|
+
run.stderr.push(clean);
|
|
139
|
+
if (run.stderr.length > MAX_ERROR_ROWS)
|
|
140
|
+
run.stderr.shift();
|
|
141
|
+
run.tail.append(`${clean}\n`);
|
|
142
|
+
});
|
|
143
|
+
child.once('close', (code, signal) => void this.onExit(run, code, signal, spawnError));
|
|
144
|
+
const maxMs = this.config.maxRunSeconds * 1_000;
|
|
145
|
+
run.timers.push(setTimeout(() => {
|
|
146
|
+
run.timedOut = true;
|
|
147
|
+
run.tail.append(`✗ 超过最长运行时间 ${this.config.maxRunSeconds} 秒,已终止\n`);
|
|
148
|
+
void killProcessTree(run.pid);
|
|
149
|
+
}, maxMs));
|
|
150
|
+
if (run.pid > 0)
|
|
151
|
+
await this.reporter.started(run.runId, { pid: run.pid }).catch((error) => {
|
|
152
|
+
this.logger.warn('run-started-report-failed', { runId: run.runId, error: errorMessage(error) });
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
onStdout(run, rawLine) {
|
|
156
|
+
const line = sanitizeTerminalLine(rawLine);
|
|
157
|
+
const parsed = run.provider.parseLine(line);
|
|
158
|
+
for (const row of parsed.display)
|
|
159
|
+
run.tail.append(`${row}\n`);
|
|
160
|
+
if (parsed.message !== undefined)
|
|
161
|
+
run.finalMessage = parsed.message;
|
|
162
|
+
if (parsed.turnError)
|
|
163
|
+
run.turnError = parsed.turnError;
|
|
164
|
+
if (parsed.sessionId && parsed.sessionId !== run.sessionId) {
|
|
165
|
+
run.sessionId = parsed.sessionId;
|
|
166
|
+
void this.reporter.started(run.runId, { session_id: parsed.sessionId }).catch(() => undefined);
|
|
167
|
+
}
|
|
168
|
+
if ((parsed.turnCompleted || parsed.turnError) && !run.turnCompleted) {
|
|
169
|
+
run.turnCompleted = true;
|
|
170
|
+
// The turn is over; do not let a lingering process hold the workstation.
|
|
171
|
+
run.timers.push(setTimeout(() => {
|
|
172
|
+
if (!this.active.has(run.runId))
|
|
173
|
+
return;
|
|
174
|
+
run.killedAfterCompletion = true;
|
|
175
|
+
run.tail.append('● 本轮已完成但进程未退出,已结束进程\n');
|
|
176
|
+
void killProcessTree(run.pid);
|
|
177
|
+
}, COMPLETION_EXIT_GRACE_MS));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async onExit(run, code, signal, spawnError) {
|
|
181
|
+
for (const timer of run.timers)
|
|
182
|
+
clearTimeout(timer);
|
|
183
|
+
this.active.delete(run.runId);
|
|
184
|
+
this.orphans?.remove(run.runId);
|
|
185
|
+
const durationMs = Date.now() - run.startedAt;
|
|
186
|
+
let report;
|
|
187
|
+
if (run.cancelRequested) {
|
|
188
|
+
report = { status: 'cancelled', duration_ms: durationMs };
|
|
189
|
+
}
|
|
190
|
+
else if (spawnError) {
|
|
191
|
+
report = { status: 'failed', error: `无法启动 ${run.agentType}:${spawnError}`, duration_ms: durationMs };
|
|
192
|
+
}
|
|
193
|
+
else if (run.timedOut) {
|
|
194
|
+
report = { status: 'failed', error: `超过最长运行时间 ${this.config.maxRunSeconds} 秒`, duration_ms: durationMs };
|
|
195
|
+
}
|
|
196
|
+
else if (run.turnError) {
|
|
197
|
+
report = { status: 'failed', error: run.turnError, duration_ms: durationMs };
|
|
198
|
+
}
|
|
199
|
+
else if (code === 0 || run.killedAfterCompletion) {
|
|
200
|
+
report = { status: 'succeeded', duration_ms: durationMs };
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const detail = run.stderr.slice(-8).join('\n').trim();
|
|
204
|
+
report = { status: 'failed', error: detail || `${run.agentType} 异常退出${signal ? `(${signal})` : ''}`, duration_ms: durationMs };
|
|
205
|
+
}
|
|
206
|
+
if (code !== null)
|
|
207
|
+
report.exit_code = code;
|
|
208
|
+
if (run.sessionId)
|
|
209
|
+
report.session_id = run.sessionId;
|
|
210
|
+
if (run.finalMessage)
|
|
211
|
+
report.final_message = run.finalMessage;
|
|
212
|
+
run.tail.append(`● 进程已退出:${report.status}${code !== null ? `(exit ${code})` : ''}\n`);
|
|
213
|
+
this.remember({ runId: run.runId, workstationId: run.workstationId, tail: run.tail, finishedAt: Date.now(), status: report.status });
|
|
214
|
+
this.logger.info('run-finished', { runId: run.runId, status: report.status, code, durationMs });
|
|
215
|
+
await this.report(run.runId, report);
|
|
216
|
+
}
|
|
217
|
+
async report(runId, report) {
|
|
218
|
+
this.unreported.add(runId);
|
|
219
|
+
await this.reporter.finished(runId, report);
|
|
220
|
+
}
|
|
221
|
+
/** Stops a run: the whole process tree, then a `cancelled` report. */
|
|
222
|
+
async cancel(runId) {
|
|
223
|
+
const run = this.active.get(runId);
|
|
224
|
+
if (!run)
|
|
225
|
+
return false;
|
|
226
|
+
run.cancelRequested = true;
|
|
227
|
+
run.tail.append('● 收到停止指令,正在结束进程树\n');
|
|
228
|
+
this.logger.info('run-cancel', { runId, pid: run.pid });
|
|
229
|
+
await killProcessTree(run.pid);
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
tail(query, limit, beforeCursor) {
|
|
233
|
+
const byId = (id) => (id ? this.active.get(id) ?? this.recent.get(id) : undefined);
|
|
234
|
+
const byWorkstation = (id) => {
|
|
235
|
+
if (!id)
|
|
236
|
+
return undefined;
|
|
237
|
+
const live = [...this.active.values()].find((run) => run.workstationId === id);
|
|
238
|
+
if (live)
|
|
239
|
+
return live;
|
|
240
|
+
return [...this.recent.values()].filter((run) => run.workstationId === id).sort((a, b) => b.finishedAt - a.finishedAt)[0];
|
|
241
|
+
};
|
|
242
|
+
const target = byId(query.runId) ?? byWorkstation(query.workstationId);
|
|
243
|
+
if (!target) {
|
|
244
|
+
return { status: 'idle', lines: [], startCursor: 0, nextCursor: 0, oldestCursor: 0, latestCursor: 0, hasMore: false, truncated: false, limited: false, idleMs: undefined };
|
|
245
|
+
}
|
|
246
|
+
const read = target.tail.read(beforeCursor === undefined ? { limit } : { limit, beforeCursor });
|
|
247
|
+
return { ...read, status: this.active.has(target.runId) ? 'running' : 'finished', run_id: target.runId };
|
|
248
|
+
}
|
|
249
|
+
async disposeAll() {
|
|
250
|
+
await Promise.all([...this.active.values()].map((run) => {
|
|
251
|
+
run.cancelRequested = true;
|
|
252
|
+
return killProcessTree(run.pid, 1_000);
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
remember(run) {
|
|
256
|
+
this.recent.set(run.runId, run);
|
|
257
|
+
const cutoff = Date.now() - RECENT_RUN_TTL_MS;
|
|
258
|
+
for (const [id, item] of this.recent) {
|
|
259
|
+
if (item.finishedAt < cutoff || this.recent.size > MAX_RECENT_RUNS)
|
|
260
|
+
this.recent.delete(id);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async validateWorkdir(input) {
|
|
264
|
+
if (!input)
|
|
265
|
+
throw new Error('没有配置允许的工作目录');
|
|
266
|
+
let candidate;
|
|
267
|
+
try {
|
|
268
|
+
candidate = await realpath(isAbsolute(input) ? input : resolve(input));
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
throw new Error(`工作目录不存在:${input}`);
|
|
272
|
+
}
|
|
273
|
+
for (const root of this.config.allowedRoots) {
|
|
274
|
+
const allowed = await realpath(root).catch(() => resolve(root));
|
|
275
|
+
const segment = relative(allowed, candidate);
|
|
276
|
+
if (segment === '' || (!segment.startsWith('..') && !isAbsolute(segment)))
|
|
277
|
+
return candidate;
|
|
278
|
+
}
|
|
279
|
+
throw new Error(`工作目录不在允许范围内:${input}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function errorMessage(error) {
|
|
283
|
+
return error instanceof Error ? error.message : String(error);
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=run-supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-supervisor.js","sourceRoot":"","sources":["../../../src/runs/run-supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AgentConfig } from '../config.js';
|
|
2
|
+
import type { HealthSnapshot } from '../health/server.js';
|
|
3
|
+
import { type DiagnosticLogger } from '../logging/diagnostic-log.js';
|
|
4
|
+
import type { CliDetectionSnapshot } from '../shared/cli-detection-types.js';
|
|
5
|
+
/**
|
|
6
|
+
* The agent's main loop, with no persistent connection:
|
|
7
|
+
* - heartbeat every `heartbeatInterval` seconds (liveness + reconciliation)
|
|
8
|
+
* - long-poll for commands, handling each one concurrently
|
|
9
|
+
* - run reports retried until the server acknowledges them
|
|
10
|
+
*/
|
|
11
|
+
export declare class AgentRuntime {
|
|
12
|
+
private readonly config;
|
|
13
|
+
private readonly version;
|
|
14
|
+
private readonly logger;
|
|
15
|
+
private readonly client;
|
|
16
|
+
private readonly runs;
|
|
17
|
+
private readonly orphans;
|
|
18
|
+
private readonly workspaces;
|
|
19
|
+
private readonly stopController;
|
|
20
|
+
private readonly startedAt;
|
|
21
|
+
private detection?;
|
|
22
|
+
private policy;
|
|
23
|
+
private heartbeatInterval;
|
|
24
|
+
private pollWait;
|
|
25
|
+
private lastHeartbeatOk;
|
|
26
|
+
private lastError;
|
|
27
|
+
/** The server rejected the device token (revoked or unpaired). */
|
|
28
|
+
private unauthorized;
|
|
29
|
+
private readonly ownsLogger;
|
|
30
|
+
private deviceName;
|
|
31
|
+
/** Finish reports not yet acknowledged; retried on every heartbeat. */
|
|
32
|
+
private readonly pendingReports;
|
|
33
|
+
/** Model catalogs of the installed CLIs; re-read in the background. */
|
|
34
|
+
private readonly models;
|
|
35
|
+
private catalogReport;
|
|
36
|
+
private catalogRefresh;
|
|
37
|
+
/** Hash of the catalogs the server has stored (from its heartbeat reply). */
|
|
38
|
+
private serverCatalogHash;
|
|
39
|
+
constructor(config: AgentConfig, version: string, logger?: DiagnosticLogger);
|
|
40
|
+
start(): Promise<void>;
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
/** Current state, for the local dashboard and the plugin. */
|
|
43
|
+
snapshot(): HealthSnapshot & {
|
|
44
|
+
unauthorized: boolean;
|
|
45
|
+
activeRunIds: string[];
|
|
46
|
+
};
|
|
47
|
+
/** Re-detects installed CLIs and pushes the change with the next heartbeat. */
|
|
48
|
+
refreshDetection(): Promise<CliDetectionSnapshot>;
|
|
49
|
+
private heartbeatLoop;
|
|
50
|
+
private heartbeat;
|
|
51
|
+
/** Re-reads catalogs whose sources changed; concurrent calls share one run. */
|
|
52
|
+
private refreshCatalogs;
|
|
53
|
+
private capabilitySummary;
|
|
54
|
+
private noteFailure;
|
|
55
|
+
private pollLoop;
|
|
56
|
+
private handle;
|
|
57
|
+
private execute;
|
|
58
|
+
/**
|
|
59
|
+
* Script / SQL run only when the server policy allows it and the local
|
|
60
|
+
* owner has not switched it off. The policy attached to the command was
|
|
61
|
+
* checked by the server at enqueue time, so it wins over the (up to one
|
|
62
|
+
* heartbeat old) cached copy. New policy fields (read-only SQL,
|
|
63
|
+
* allowlists) are enforced here.
|
|
64
|
+
*/
|
|
65
|
+
private checkPolicy;
|
|
66
|
+
private flushReport;
|
|
67
|
+
private retry;
|
|
68
|
+
}
|