feat: add Screeps console monitoring with configurable error handling and shard support #84

Merged
Philipp merged 9 commits from feature/console-monitor into main 2026-05-16 19:44:39 +02:00
4 changed files with 66 additions and 2 deletions
Showing only changes of commit b6cef04a9c - Show all commits
+27
View File
@@ -455,4 +455,31 @@ describe("monitorConsole", () => {
);
expect(api.socket.disconnect).toHaveBeenCalledTimes(1);
});
it("exits early if a traceback occurs and onTraceback='fail'", async () => {
// startTick=100, monitor=10 ticks.
// If it didn't exit early, it would call api.time() many times.
const api = buildMockApi({
ticks: [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110],
});
// Fire a traceback event after the first poll
setTimeout(() => {
api._fireConsole({
messages: { log: [], results: [] },
error:
"TypeError: fail-fast test\n at Object.<anonymous> (main:1:1)",
});
}, 100);
const result = await monitorConsole(api, {
...BASE_OPTS,
monitor: 10,
onTraceback: "fail",
});
expect(result.sawTraceback).toBe(true);
// We expect it to have called api.time fewer than 10 times (excluding the startTick call)
expect(api.time.mock.calls.length).toBeLessThan(10);
});
});
+1 -1
View File
File diff suppressed because one or more lines are too long
+9 -1
View File
@@ -224,9 +224,10 @@ export async function pollUntilDone(
shard,
intervalMs,
onProgress,
shouldStop = () => false,
) {
let elapsed = 0;
while (elapsed < targetTicks) {
while (elapsed < targetTicks && !shouldStop()) {
await sleep(intervalMs);
const { time } = await api.time(shard);
elapsed = time - startTick;
@@ -332,6 +333,13 @@ export async function monitorConsole(api, opts) {
lastProgressTick = elapsed;
}
},
() => {
// Fail-fast logic: stop monitoring if any 'fail' action is triggered
if (opts.onTraceback === "fail" && state.sawTraceback) return true;
if (opts.onErrorLog === "fail" && state.sawErrorLog) return true;
if (opts.onWarningLog === "fail" && state.sawWarningLog) return true;
return false;
},
);
} finally {
// ── Step 5: always disconnect cleanly ────────────────────────────────
+29
View File
@@ -0,0 +1,29 @@
import { glob } from "glob";
import path from "path";
import os from "os";
import fs from "fs";
async function test() {
const tempDir = await fs.promises.mkdtemp(
path.join(os.tmpdir(), "glob-test-"),
);
const file = path.join(tempDir, "test.js");
await fs.promises.writeFile(file, "test");
const pattern = "*.js";
const globPattern = path.join(tempDir, pattern);
console.log("globPattern:", globPattern);
const files = await glob(globPattern);
console.log("found files:", files);
// Fix for windows
const fixedPattern = globPattern.replace(/\\/g, "/");
console.log("fixedPattern:", fixedPattern);
const fixedFiles = await glob(fixedPattern);
console.log("found fixed files:", fixedFiles);
await fs.promises.rm(tempDir, { recursive: true, force: true });
}
test();