doer-agent 0.4.9 → 0.5.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/dist/agent-daemon-rpc.js
CHANGED
|
@@ -105,13 +105,7 @@ function normalizeLogEvent(value) {
|
|
|
105
105
|
}
|
|
106
106
|
const row = value;
|
|
107
107
|
const ts = typeof row.ts === "string" ? row.ts.trim() : "";
|
|
108
|
-
const type = row.type === "start" ||
|
|
109
|
-
row.type === "stdout" ||
|
|
110
|
-
row.type === "stderr" ||
|
|
111
|
-
row.type === "heartbeat" ||
|
|
112
|
-
row.type === "exit" ||
|
|
113
|
-
row.type === "signal" ||
|
|
114
|
-
row.type === "error"
|
|
108
|
+
const type = row.type === "start" || row.type === "stdout" || row.type === "stderr" || row.type === "exit" || row.type === "signal" || row.type === "error"
|
|
115
109
|
? row.type
|
|
116
110
|
: null;
|
|
117
111
|
if (!ts || !type) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { appendFile, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
const DEFAULT_HEARTBEAT_MS = 15_000;
|
|
4
3
|
function readRequiredEnv(name) {
|
|
5
4
|
const value = process.env[name]?.trim() || "";
|
|
6
5
|
if (!value) {
|
|
@@ -8,17 +7,6 @@ function readRequiredEnv(name) {
|
|
|
8
7
|
}
|
|
9
8
|
return value;
|
|
10
9
|
}
|
|
11
|
-
function readHeartbeatIntervalMs() {
|
|
12
|
-
const raw = process.env.DOER_DAEMON_HEARTBEAT_MS?.trim();
|
|
13
|
-
if (!raw) {
|
|
14
|
-
return DEFAULT_HEARTBEAT_MS;
|
|
15
|
-
}
|
|
16
|
-
const numeric = Number(raw);
|
|
17
|
-
if (!Number.isFinite(numeric) || numeric < 1_000) {
|
|
18
|
-
return DEFAULT_HEARTBEAT_MS;
|
|
19
|
-
}
|
|
20
|
-
return Math.floor(numeric);
|
|
21
|
-
}
|
|
22
10
|
async function readState(statePath) {
|
|
23
11
|
const raw = await readFile(statePath, "utf8");
|
|
24
12
|
return JSON.parse(raw);
|
|
@@ -37,14 +25,13 @@ async function appendEvent(eventsPath, event) {
|
|
|
37
25
|
};
|
|
38
26
|
await appendFile(eventsPath, `${JSON.stringify(row)}\n`, "utf8");
|
|
39
27
|
}
|
|
40
|
-
function attachLineLogger(stream, type, eventsPath, pid
|
|
28
|
+
function attachLineLogger(stream, type, eventsPath, pid) {
|
|
41
29
|
if (!stream) {
|
|
42
30
|
return;
|
|
43
31
|
}
|
|
44
32
|
stream.setEncoding("utf8");
|
|
45
33
|
let pending = "";
|
|
46
34
|
stream.on("data", (chunk) => {
|
|
47
|
-
onActivity?.();
|
|
48
35
|
pending += chunk;
|
|
49
36
|
const lines = pending.split(/\r\n|\n|\r/);
|
|
50
37
|
pending = lines.pop() ?? "";
|
|
@@ -74,7 +61,6 @@ async function main() {
|
|
|
74
61
|
const command = readRequiredEnv("DOER_DAEMON_COMMAND");
|
|
75
62
|
const cwd = readRequiredEnv("DOER_DAEMON_CWD");
|
|
76
63
|
const shellPath = readRequiredEnv("DOER_DAEMON_SHELL_PATH");
|
|
77
|
-
const heartbeatIntervalMs = readHeartbeatIntervalMs();
|
|
78
64
|
const childEnv = { ...process.env };
|
|
79
65
|
delete childEnv.DOER_DAEMON_STATE_PATH;
|
|
80
66
|
delete childEnv.DOER_DAEMON_EVENTS_PATH;
|
|
@@ -108,28 +94,8 @@ async function main() {
|
|
|
108
94
|
type: "start",
|
|
109
95
|
pid: child.pid,
|
|
110
96
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
lastActivityAt = Date.now();
|
|
114
|
-
};
|
|
115
|
-
attachLineLogger(child.stdout, "stdout", eventsPath, child.pid, markActivity);
|
|
116
|
-
attachLineLogger(child.stderr, "stderr", eventsPath, child.pid, markActivity);
|
|
117
|
-
const heartbeatTimer = setInterval(() => {
|
|
118
|
-
if (child.exitCode !== null || child.killed) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
const idleMs = Date.now() - lastActivityAt;
|
|
122
|
-
if (idleMs < heartbeatIntervalMs) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
lastActivityAt = Date.now();
|
|
126
|
-
void appendEvent(eventsPath, {
|
|
127
|
-
type: "heartbeat",
|
|
128
|
-
pid: child.pid,
|
|
129
|
-
text: `[doer-daemon] heartbeat: process still running without new output for ${Math.max(1, Math.round(idleMs / 1000))}s`,
|
|
130
|
-
});
|
|
131
|
-
}, heartbeatIntervalMs);
|
|
132
|
-
heartbeatTimer.unref?.();
|
|
97
|
+
attachLineLogger(child.stdout, "stdout", eventsPath, child.pid);
|
|
98
|
+
attachLineLogger(child.stderr, "stderr", eventsPath, child.pid);
|
|
133
99
|
const forwardSignal = (signal) => {
|
|
134
100
|
if (child.exitCode !== null || child.killed) {
|
|
135
101
|
return;
|
|
@@ -156,7 +122,6 @@ async function main() {
|
|
|
156
122
|
child.once("error", reject);
|
|
157
123
|
child.once("exit", async (code, signal) => {
|
|
158
124
|
try {
|
|
159
|
-
clearInterval(heartbeatTimer);
|
|
160
125
|
const latest = await readState(statePath);
|
|
161
126
|
await writeState(statePath, {
|
|
162
127
|
...latest,
|
|
@@ -175,7 +140,6 @@ async function main() {
|
|
|
175
140
|
resolve();
|
|
176
141
|
}
|
|
177
142
|
catch (error) {
|
|
178
|
-
clearInterval(heartbeatTimer);
|
|
179
143
|
reject(error);
|
|
180
144
|
}
|
|
181
145
|
});
|