r028: recover stuck tool call slots
This commit is contained in:
1 parent
5d2550668a
commit
1c41175a86
11 files changed
+266
-48
No files matched your search
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
|
||||
import { parseConfig, SAFE_DEFAULT_TOOLS } from "./auth";
|
||||
import { installCommunityApp, runReadOnlyCommand, sanitizeLogOutput } from "./helpers";
|
||||
import { getToolRisk, toolByName } from "./tools";
|
||||
import { ToolCallGate, withHardTimeout } from "./concurrency";
|
||||
|
||||
describe("secure tool configuration", () => {
|
||||
test("new and incomplete configs use the read-only baseline", () => {
|
||||
@@ -117,6 +118,37 @@ describe("direct Unraid terminal", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("tool-call concurrency recovery", () => {
|
||||
test("stale leases heal without corrupting newer leases", () => {
|
||||
const gate = new ToolCallGate(1);
|
||||
const first = gate.acquire("first", 10, 100);
|
||||
expect(first).not.toBeNull();
|
||||
expect(gate.acquire("blocked", 10, 105)).toBeNull();
|
||||
|
||||
const second = gate.acquire("second", 100, 111);
|
||||
expect(second).not.toBeNull();
|
||||
gate.release(first!.id); // late release must not affect the newer lease
|
||||
expect(gate.snapshot(112).active).toBe(1);
|
||||
gate.release(second!.id);
|
||||
expect(gate.snapshot(113).active).toBe(0);
|
||||
});
|
||||
|
||||
test("hard timeout rejects work that never settles", async () => {
|
||||
const never = new Promise<string>(() => {});
|
||||
await expect(withHardTimeout(never, 20, "stuck test")).rejects.toThrow(
|
||||
"exceeded hard timeout",
|
||||
);
|
||||
});
|
||||
|
||||
test("shell timeout rejects even when a descendant keeps pipes open", async () => {
|
||||
const tool = toolByName("unraid_system_shell");
|
||||
expect(tool).toBeDefined();
|
||||
await expect(
|
||||
tool!.handler({ command: "sleep 2 &", timeout_seconds: 1 }),
|
||||
).rejects.toThrow("timed out after 1 seconds");
|
||||
});
|
||||
});
|
||||
|
||||
describe("read-only shell", () => {
|
||||
test("executes an allowlisted program without a shell", async () => {
|
||||
const result = JSON.parse(await runReadOnlyCommand("ls", ["-ld", "/"], 5));
|
||||
|
||||
Reference in new issue
Block a user