Skip to content

Commit 2fd656a

Browse files
committed
tests: loosen shell real error assertion
1 parent 7748b1b commit 2fd656a

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
2+
import { tmpdir } from "node:os";
3+
import path from "node:path";
4+
import type { IAgentRuntime } from "@elizaos/core";
5+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
6+
import { shellHistoryProvider } from "../providers/shellHistoryProvider";
7+
import { resetProcessRegistryForTests } from "../services/processRegistry";
8+
import { ShellService } from "../services/shellService";
9+
10+
function createRuntime(service: ShellService | null): IAgentRuntime {
11+
return {
12+
character: {},
13+
getService(name: string) {
14+
return name === "shell" ? service : null;
15+
},
16+
} as IAgentRuntime;
17+
}
18+
19+
describe("shell plugin real local integration", () => {
20+
let allowedDirectory = "";
21+
let previousAllowedDirectory: string | undefined;
22+
let service: ShellService;
23+
let runtime: IAgentRuntime;
24+
25+
beforeEach(async () => {
26+
allowedDirectory = mkdtempSync(path.join(tmpdir(), "milady-shell-live-"));
27+
previousAllowedDirectory = process.env.SHELL_ALLOWED_DIRECTORY;
28+
process.env.SHELL_ALLOWED_DIRECTORY = allowedDirectory;
29+
30+
service = await ShellService.start(createRuntime(null));
31+
runtime = createRuntime(service);
32+
});
33+
34+
afterEach(async () => {
35+
await service.stop();
36+
resetProcessRegistryForTests();
37+
38+
if (previousAllowedDirectory === undefined) {
39+
delete process.env.SHELL_ALLOWED_DIRECTORY;
40+
} else {
41+
process.env.SHELL_ALLOWED_DIRECTORY = previousAllowedDirectory;
42+
}
43+
44+
rmSync(allowedDirectory, { recursive: true, force: true });
45+
});
46+
47+
it("executes a real command in the allowed directory and exposes it through the provider", async () => {
48+
const result = await service.executeCommand('printf "live-shell" > output.txt', "room-1");
49+
expect(result.success).toBe(true);
50+
expect(readFileSync(path.join(allowedDirectory, "output.txt"), "utf8")).toBe("live-shell");
51+
52+
const provider = await shellHistoryProvider.get(
53+
runtime,
54+
{ roomId: "room-1", agentId: "agent-1" } as never,
55+
{} as never
56+
);
57+
58+
expect(provider.text).toContain("output.txt");
59+
expect(provider.text).toContain(allowedDirectory);
60+
expect(provider.values?.currentWorkingDirectory).toBe(allowedDirectory);
61+
});
62+
63+
it("fails closed when a command tries to escape the allowed directory", async () => {
64+
const result = await service.executeCommand("cd ../..", "room-1");
65+
66+
expect(result.success).toBe(false);
67+
expect(result.stderr).toMatch(
68+
/Cannot navigate outside allowed directory|Command contains forbidden patterns/,
69+
);
70+
expect(service.getCurrentDirectory()).toBe(allowedDirectory);
71+
});
72+
});

0 commit comments

Comments
 (0)