@agentteams/runner 0.0.79 → 0.0.80-dev.189
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/config.js +16 -1
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +12 -2
- package/dist/config.test.js.map +1 -1
- package/dist/executable.js +25 -5
- package/dist/executable.js.map +1 -1
- package/dist/executable.test.js +12 -0
- package/dist/executable.test.js.map +1 -1
- package/dist/handlers/trigger-handler.d.ts +2 -0
- package/dist/handlers/trigger-handler.js +11 -0
- package/dist/handlers/trigger-handler.js.map +1 -1
- package/dist/handlers/trigger-handler.test.js +112 -11
- package/dist/handlers/trigger-handler.test.js.map +1 -1
- package/dist/poller.test.js +2 -1
- package/dist/poller.test.js.map +1 -1
- package/dist/runners/codex.d.ts +1 -0
- package/dist/runners/codex.js +34 -7
- package/dist/runners/codex.js.map +1 -1
- package/dist/runners/codex.test.js +37 -1
- package/dist/runners/codex.test.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/utils/power-save-blocker.d.ts +20 -0
- package/dist/utils/power-save-blocker.js +155 -0
- package/dist/utils/power-save-blocker.js.map +1 -0
- package/dist/utils/power-save-blocker.test.d.ts +1 -0
- package/dist/utils/power-save-blocker.test.js +170 -0
- package/dist/utils/power-save-blocker.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
2
|
+
import { platform as osPlatform } from "node:os";
|
|
3
|
+
import { logger } from "../logger.js";
|
|
4
|
+
// launchd 환경에서는 PATH가 비어 있을 수 있으므로 macOS 시스템 바이너리는 절대 경로로 호출한다.
|
|
5
|
+
const CAFFEINATE_PATH = "/usr/bin/caffeinate";
|
|
6
|
+
const PMSET_PATH = "/usr/bin/pmset";
|
|
7
|
+
// -i: 시스템 idle 절전 방지, -m: 디스크 idle 절전 방지, -s: 시스템 절전 방지(AC 전원에서만 유효)
|
|
8
|
+
const DEFAULT_CAFFEINATE_ARGS = ["-i", "-m", "-s"];
|
|
9
|
+
// 실행 도중 배터리로 전환되는 경우를 감지하기 위한 전원 상태 재확인 주기
|
|
10
|
+
const DEFAULT_POWER_RECHECK_INTERVAL_MS = 30_000;
|
|
11
|
+
// `pmset -g batt`의 첫 줄은 "Now drawing from 'AC Power'" 또는 "Now drawing from 'Battery Power'" 형태다.
|
|
12
|
+
export const parsePowerSource = (output) => {
|
|
13
|
+
const match = output.match(/Now drawing from '([^']+)'/i);
|
|
14
|
+
if (!match) {
|
|
15
|
+
return "UNKNOWN";
|
|
16
|
+
}
|
|
17
|
+
const source = match[1].toLowerCase();
|
|
18
|
+
if (source.includes("ac")) {
|
|
19
|
+
return "AC";
|
|
20
|
+
}
|
|
21
|
+
if (source.includes("battery")) {
|
|
22
|
+
return "BATTERY";
|
|
23
|
+
}
|
|
24
|
+
return "UNKNOWN";
|
|
25
|
+
};
|
|
26
|
+
const noopRelease = () => { };
|
|
27
|
+
export const createPowerSaveBlocker = (deps = {}) => {
|
|
28
|
+
const platform = deps.platform ?? osPlatform;
|
|
29
|
+
const spawnFn = deps.spawn ?? spawn;
|
|
30
|
+
const execFileSyncFn = deps.execFileSync ?? execFileSync;
|
|
31
|
+
const log = deps.logger ?? logger;
|
|
32
|
+
const setIntervalFn = deps.setInterval ?? global.setInterval;
|
|
33
|
+
const clearIntervalFn = deps.clearInterval ?? global.clearInterval;
|
|
34
|
+
const recheckIntervalMs = deps.recheckIntervalMs ?? DEFAULT_POWER_RECHECK_INTERVAL_MS;
|
|
35
|
+
const caffeinateArgs = deps.caffeinateArgs ?? DEFAULT_CAFFEINATE_ARGS;
|
|
36
|
+
// 기능 토글이 꺼져 있거나 macOS가 아니면 전부 no-op으로 동작한다.
|
|
37
|
+
const supported = (deps.enabled ?? true) && platform() === "darwin";
|
|
38
|
+
let activeSessions = 0;
|
|
39
|
+
let caffeinate = null;
|
|
40
|
+
let monitorInterval = null;
|
|
41
|
+
const readPowerSource = () => {
|
|
42
|
+
try {
|
|
43
|
+
const output = String(execFileSyncFn(PMSET_PATH, ["-g", "batt"], { encoding: "utf8" }));
|
|
44
|
+
return parsePowerSource(output);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
log.warn("Failed to read power source via pmset", {
|
|
48
|
+
error: error instanceof Error ? error.message : String(error)
|
|
49
|
+
});
|
|
50
|
+
return "UNKNOWN";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const startCaffeinate = () => {
|
|
54
|
+
if (caffeinate) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const child = spawnFn(CAFFEINATE_PATH, caffeinateArgs, { stdio: "ignore" });
|
|
59
|
+
child.on("error", (error) => {
|
|
60
|
+
log.warn("caffeinate process failed", {
|
|
61
|
+
error: error instanceof Error ? error.message : String(error)
|
|
62
|
+
});
|
|
63
|
+
if (caffeinate === child) {
|
|
64
|
+
caffeinate = null;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
child.on("exit", () => {
|
|
68
|
+
if (caffeinate === child) {
|
|
69
|
+
caffeinate = null;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
caffeinate = child;
|
|
73
|
+
log.info("Sleep prevention started", { pid: child.pid ?? null, args: caffeinateArgs });
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
log.warn("Failed to start caffeinate", {
|
|
77
|
+
error: error instanceof Error ? error.message : String(error)
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const stopCaffeinate = (reason) => {
|
|
82
|
+
if (!caffeinate) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const child = caffeinate;
|
|
86
|
+
caffeinate = null;
|
|
87
|
+
try {
|
|
88
|
+
child.kill("SIGTERM");
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// 이미 종료되었거나 종료할 수 없는 경우 무시한다.
|
|
92
|
+
}
|
|
93
|
+
log.info("Sleep prevention stopped", { reason });
|
|
94
|
+
};
|
|
95
|
+
// 의도한 상태(세션 존재 && AC 전원)와 실제 caffeinate 실행 여부를 일치시킨다.
|
|
96
|
+
const reconcile = () => {
|
|
97
|
+
if (!supported) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (activeSessions <= 0) {
|
|
101
|
+
stopCaffeinate("no-active-sessions");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const source = readPowerSource();
|
|
105
|
+
if (source === "AC") {
|
|
106
|
+
startCaffeinate();
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
stopCaffeinate(source === "BATTERY" ? "on-battery" : "power-source-unknown");
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const startMonitor = () => {
|
|
113
|
+
if (monitorInterval) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
monitorInterval = setIntervalFn(() => reconcile(), recheckIntervalMs);
|
|
117
|
+
// 절전 방지 모니터가 데몬 종료를 막지 않도록 unref 처리한다.
|
|
118
|
+
if (typeof monitorInterval.unref === "function") {
|
|
119
|
+
monitorInterval.unref();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const stopMonitor = () => {
|
|
123
|
+
if (!monitorInterval) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
clearIntervalFn(monitorInterval);
|
|
127
|
+
monitorInterval = null;
|
|
128
|
+
};
|
|
129
|
+
const acquire = (label) => {
|
|
130
|
+
if (!supported) {
|
|
131
|
+
return noopRelease;
|
|
132
|
+
}
|
|
133
|
+
activeSessions += 1;
|
|
134
|
+
const source = readPowerSource();
|
|
135
|
+
if (source !== "AC") {
|
|
136
|
+
log.info("Sleep prevention skipped while on battery or unknown power", { source, label: label ?? null });
|
|
137
|
+
}
|
|
138
|
+
reconcile();
|
|
139
|
+
startMonitor();
|
|
140
|
+
let released = false;
|
|
141
|
+
return () => {
|
|
142
|
+
if (released) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
released = true;
|
|
146
|
+
activeSessions = Math.max(0, activeSessions - 1);
|
|
147
|
+
reconcile();
|
|
148
|
+
if (activeSessions === 0) {
|
|
149
|
+
stopMonitor();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
return { acquire };
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=power-save-blocker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-save-blocker.js","sourceRoot":"","sources":["../../src/utils/power-save-blocker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import { createPowerSaveBlocker, parsePowerSource } from "./power-save-blocker.js";
|
|
5
|
+
const AC_OUTPUT = "Now drawing from 'AC Power'\n -InternalBattery-0 (id=123)\t100%; charged; 0:00 remaining present: true";
|
|
6
|
+
const BATTERY_OUTPUT = "Now drawing from 'Battery Power'\n -InternalBattery-0 (id=123)\t80%; discharging; 3:20 remaining present: true";
|
|
7
|
+
const createFakeChild = (pid) => {
|
|
8
|
+
const emitter = new EventEmitter();
|
|
9
|
+
emitter.pid = pid;
|
|
10
|
+
emitter.killed = false;
|
|
11
|
+
emitter.kill = () => {
|
|
12
|
+
emitter.killed = true;
|
|
13
|
+
return true;
|
|
14
|
+
};
|
|
15
|
+
return emitter;
|
|
16
|
+
};
|
|
17
|
+
const silentLogger = {
|
|
18
|
+
info: () => undefined,
|
|
19
|
+
warn: () => undefined
|
|
20
|
+
};
|
|
21
|
+
// setInterval/clearInterval를 주입해 모니터 루프가 실제 타이머를 만들지 않게 한다.
|
|
22
|
+
const noopTimers = {
|
|
23
|
+
setInterval: (() => ({ unref: () => undefined })),
|
|
24
|
+
clearInterval: (() => undefined)
|
|
25
|
+
};
|
|
26
|
+
test("parsePowerSource detects AC, battery, and unknown sources", () => {
|
|
27
|
+
assert.equal(parsePowerSource(AC_OUTPUT), "AC");
|
|
28
|
+
assert.equal(parsePowerSource(BATTERY_OUTPUT), "BATTERY");
|
|
29
|
+
assert.equal(parsePowerSource("garbage output"), "UNKNOWN");
|
|
30
|
+
});
|
|
31
|
+
test("acquire spawns caffeinate on macOS while on AC power", () => {
|
|
32
|
+
const spawned = [];
|
|
33
|
+
const child = createFakeChild(4242);
|
|
34
|
+
const blocker = createPowerSaveBlocker({
|
|
35
|
+
platform: () => "darwin",
|
|
36
|
+
execFileSync: (() => AC_OUTPUT),
|
|
37
|
+
spawn: ((command, args) => {
|
|
38
|
+
spawned.push({ command, args });
|
|
39
|
+
return child;
|
|
40
|
+
}),
|
|
41
|
+
logger: silentLogger,
|
|
42
|
+
...noopTimers
|
|
43
|
+
});
|
|
44
|
+
const release = blocker.acquire("trigger-1");
|
|
45
|
+
assert.equal(spawned.length, 1);
|
|
46
|
+
assert.equal(spawned[0]?.command, "/usr/bin/caffeinate");
|
|
47
|
+
assert.deepEqual(spawned[0]?.args, ["-i", "-m", "-s"]);
|
|
48
|
+
release();
|
|
49
|
+
assert.equal(child.killed, true);
|
|
50
|
+
});
|
|
51
|
+
test("acquire is a no-op while on battery power", () => {
|
|
52
|
+
let spawnCalls = 0;
|
|
53
|
+
const blocker = createPowerSaveBlocker({
|
|
54
|
+
platform: () => "darwin",
|
|
55
|
+
execFileSync: (() => BATTERY_OUTPUT),
|
|
56
|
+
spawn: (() => {
|
|
57
|
+
spawnCalls += 1;
|
|
58
|
+
return createFakeChild(1);
|
|
59
|
+
}),
|
|
60
|
+
logger: silentLogger,
|
|
61
|
+
...noopTimers
|
|
62
|
+
});
|
|
63
|
+
const release = blocker.acquire();
|
|
64
|
+
assert.equal(spawnCalls, 0);
|
|
65
|
+
release();
|
|
66
|
+
});
|
|
67
|
+
test("acquire is a no-op on non-macOS platforms", () => {
|
|
68
|
+
let spawnCalls = 0;
|
|
69
|
+
let pmsetCalls = 0;
|
|
70
|
+
const blocker = createPowerSaveBlocker({
|
|
71
|
+
platform: () => "linux",
|
|
72
|
+
execFileSync: (() => {
|
|
73
|
+
pmsetCalls += 1;
|
|
74
|
+
return AC_OUTPUT;
|
|
75
|
+
}),
|
|
76
|
+
spawn: (() => {
|
|
77
|
+
spawnCalls += 1;
|
|
78
|
+
return createFakeChild(1);
|
|
79
|
+
}),
|
|
80
|
+
logger: silentLogger,
|
|
81
|
+
...noopTimers
|
|
82
|
+
});
|
|
83
|
+
const release = blocker.acquire();
|
|
84
|
+
assert.equal(spawnCalls, 0);
|
|
85
|
+
assert.equal(pmsetCalls, 0);
|
|
86
|
+
release();
|
|
87
|
+
});
|
|
88
|
+
test("acquire is a no-op when the feature is disabled", () => {
|
|
89
|
+
let spawnCalls = 0;
|
|
90
|
+
const blocker = createPowerSaveBlocker({
|
|
91
|
+
platform: () => "darwin",
|
|
92
|
+
enabled: false,
|
|
93
|
+
execFileSync: (() => AC_OUTPUT),
|
|
94
|
+
spawn: (() => {
|
|
95
|
+
spawnCalls += 1;
|
|
96
|
+
return createFakeChild(1);
|
|
97
|
+
}),
|
|
98
|
+
logger: silentLogger,
|
|
99
|
+
...noopTimers
|
|
100
|
+
});
|
|
101
|
+
blocker.acquire()();
|
|
102
|
+
assert.equal(spawnCalls, 0);
|
|
103
|
+
});
|
|
104
|
+
test("release can be called multiple times without killing twice", () => {
|
|
105
|
+
let killCount = 0;
|
|
106
|
+
const child = createFakeChild(7);
|
|
107
|
+
child.kill = () => {
|
|
108
|
+
killCount += 1;
|
|
109
|
+
child.killed = true;
|
|
110
|
+
return true;
|
|
111
|
+
};
|
|
112
|
+
const blocker = createPowerSaveBlocker({
|
|
113
|
+
platform: () => "darwin",
|
|
114
|
+
execFileSync: (() => AC_OUTPUT),
|
|
115
|
+
spawn: (() => child),
|
|
116
|
+
logger: silentLogger,
|
|
117
|
+
...noopTimers
|
|
118
|
+
});
|
|
119
|
+
const release = blocker.acquire();
|
|
120
|
+
release();
|
|
121
|
+
release();
|
|
122
|
+
release();
|
|
123
|
+
assert.equal(killCount, 1);
|
|
124
|
+
});
|
|
125
|
+
test("concurrent sessions keep caffeinate alive until the last release", () => {
|
|
126
|
+
let spawnCalls = 0;
|
|
127
|
+
const child = createFakeChild(9);
|
|
128
|
+
const blocker = createPowerSaveBlocker({
|
|
129
|
+
platform: () => "darwin",
|
|
130
|
+
execFileSync: (() => AC_OUTPUT),
|
|
131
|
+
spawn: (() => {
|
|
132
|
+
spawnCalls += 1;
|
|
133
|
+
return child;
|
|
134
|
+
}),
|
|
135
|
+
logger: silentLogger,
|
|
136
|
+
...noopTimers
|
|
137
|
+
});
|
|
138
|
+
const releaseA = blocker.acquire("a");
|
|
139
|
+
const releaseB = blocker.acquire("b");
|
|
140
|
+
// 두 세션이 동일한 caffeinate 프로세스를 공유한다.
|
|
141
|
+
assert.equal(spawnCalls, 1);
|
|
142
|
+
releaseA();
|
|
143
|
+
assert.equal(child.killed, false);
|
|
144
|
+
releaseB();
|
|
145
|
+
assert.equal(child.killed, true);
|
|
146
|
+
});
|
|
147
|
+
test("monitor releases caffeinate when power switches to battery mid-run", () => {
|
|
148
|
+
let powerOutput = AC_OUTPUT;
|
|
149
|
+
const monitorTicks = [];
|
|
150
|
+
const child = createFakeChild(11);
|
|
151
|
+
const blocker = createPowerSaveBlocker({
|
|
152
|
+
platform: () => "darwin",
|
|
153
|
+
execFileSync: (() => powerOutput),
|
|
154
|
+
spawn: (() => child),
|
|
155
|
+
logger: silentLogger,
|
|
156
|
+
setInterval: ((handler) => {
|
|
157
|
+
monitorTicks.push(handler);
|
|
158
|
+
return { unref: () => undefined };
|
|
159
|
+
}),
|
|
160
|
+
clearInterval: (() => undefined)
|
|
161
|
+
});
|
|
162
|
+
blocker.acquire();
|
|
163
|
+
assert.equal(child.killed, false);
|
|
164
|
+
// 배터리로 전환된 뒤 모니터가 동작하면 caffeinate가 종료되어야 한다.
|
|
165
|
+
powerOutput = BATTERY_OUTPUT;
|
|
166
|
+
assert.equal(monitorTicks.length, 1, "monitor interval should be registered");
|
|
167
|
+
monitorTicks[0]?.();
|
|
168
|
+
assert.equal(child.killed, true);
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=power-save-blocker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-save-blocker.test.js","sourceRoot":"","sources":["../../src/utils/power-save-blocker.test.ts"],"names":[],"mappings":"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"}
|