@@ -5,7 +5,8 @@ import { registerOAuthProvider } from "@earendil-works/pi-ai/oauth";
|
||||
import lockfile from "proper-lockfile";
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { AuthStorage } from "../src/core/auth-storage.ts";
|
||||
import { clearConfigValueCache } from "../src/core/resolve-config-value.ts";
|
||||
import { clearConfigValueCache, resolveConfigValueUncached } from "../src/core/resolve-config-value.ts";
|
||||
import * as shellModule from "../src/utils/shell.ts";
|
||||
|
||||
describe("AuthStorage", () => {
|
||||
let tempDir: string;
|
||||
@@ -321,6 +322,30 @@ describe("AuthStorage", () => {
|
||||
expect(apiKey).toBe("hello-world");
|
||||
});
|
||||
|
||||
test("command config uses stdin when configured shell requires it", () => {
|
||||
if (process.platform === "win32") return;
|
||||
const platformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
|
||||
vi.spyOn(shellModule, "getShellConfig").mockReturnValue({
|
||||
shell: "/bin/bash",
|
||||
args: ["-s"],
|
||||
commandTransport: "stdin",
|
||||
});
|
||||
|
||||
try {
|
||||
Object.defineProperty(process, "platform", {
|
||||
configurable: true,
|
||||
value: "win32",
|
||||
});
|
||||
const nameExpansion = "$" + "{name}";
|
||||
|
||||
expect(resolveConfigValueUncached(`!name='World'; echo "Hello, ${nameExpansion}!"`)).toBe("Hello, World!");
|
||||
} finally {
|
||||
if (platformDescriptor) {
|
||||
Object.defineProperty(process, "platform", platformDescriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe("caching", () => {
|
||||
test("command is only executed once per process", async () => {
|
||||
// Use a command that writes to a file to count invocations
|
||||
|
||||
@@ -536,6 +536,56 @@ describe("Coding Agent Tools", () => {
|
||||
expect(getShellConfigSpy).toHaveBeenCalledWith("/custom/bash");
|
||||
});
|
||||
|
||||
it("should send commands over stdin when shell resolution requires it", async () => {
|
||||
vi.spyOn(shellModule, "getShellConfig").mockReturnValue({
|
||||
shell: process.execPath,
|
||||
args: [
|
||||
"-e",
|
||||
'let input = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", (chunk) => { input += chunk; }); process.stdin.on("end", () => { process.stdout.write(input); });',
|
||||
],
|
||||
commandTransport: "stdin",
|
||||
});
|
||||
const chunks: Buffer[] = [];
|
||||
const ops = createLocalBashOperations({ shellPath: "C:\\Windows\\System32\\bash.exe" });
|
||||
const nameExpansion = "$" + "{name}";
|
||||
const countExpansion = "$" + "{count}";
|
||||
const iExpansion = "$" + "{i}";
|
||||
const command = `name='World'; echo "Hello, ${nameExpansion}!"; count=3; for i in $(seq 1 ${countExpansion}); do echo "Iteration ${iExpansion} of ${countExpansion}"; done`;
|
||||
|
||||
const result = await ops.exec(command, testDir, {
|
||||
onData: (data) => chunks.push(data),
|
||||
});
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(Buffer.concat(chunks).toString("utf-8")).toBe(command);
|
||||
});
|
||||
|
||||
it("should resolve legacy WSL bash.exe to stdin command transport", () => {
|
||||
if (process.platform === "win32") return;
|
||||
const originalCwd = process.cwd();
|
||||
const platformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
|
||||
const shellPath = "C:\\Windows\\System32\\bash.exe";
|
||||
writeFileSync(join(testDir, shellPath), "");
|
||||
try {
|
||||
process.chdir(testDir);
|
||||
Object.defineProperty(process, "platform", {
|
||||
configurable: true,
|
||||
value: "win32",
|
||||
});
|
||||
|
||||
expect(shellModule.getShellConfig(shellPath)).toEqual({
|
||||
shell: shellPath,
|
||||
args: ["-s"],
|
||||
commandTransport: "stdin",
|
||||
});
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
if (platformDescriptor) {
|
||||
Object.defineProperty(process, "platform", platformDescriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("should prepend command prefix when configured", async () => {
|
||||
const bashWithPrefix = createBashTool(testDir, {
|
||||
commandPrefix: "export TEST_VAR=hello",
|
||||
|
||||
Reference in New Issue
Block a user