open-swe/apps/open-swe/src/tools/shell.ts
Brace Sproul 2b1f301848
fix: Better filtering of invalid messages (#417)
* fix: Better filtering of invalid messages

* cr

* cr
2025-07-15 16:14:33 -07:00

57 lines
1.8 KiB
TypeScript

import { tool } from "@langchain/core/tools";
import { GraphState } from "@open-swe/shared/open-swe/types";
import { getSandboxErrorFields } from "../utils/sandbox-error-fields.js";
import { TIMEOUT_SEC } from "@open-swe/shared/constants";
import { createShellToolFields } from "@open-swe/shared/open-swe/tools";
import { getSandboxSessionOrThrow } from "./utils/get-sandbox-id.js";
const DEFAULT_ENV = {
// Prevents corepack from showing a y/n download prompt which causes the command to hang
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
};
export function createShellTool(
state: Pick<GraphState, "sandboxSessionId" | "targetRepository">,
) {
const shellTool = tool(
async (input): Promise<{ result: string; status: "success" | "error" }> => {
try {
const sandbox = await getSandboxSessionOrThrow(input);
const { command, workdir, timeout } = input;
const response = await sandbox.process.executeCommand(
command.join(" "),
workdir,
DEFAULT_ENV,
timeout ?? TIMEOUT_SEC,
);
if (response.exitCode !== 0) {
const errorResult = response.result ?? response.artifacts?.stdout;
throw new Error(
`Command failed. Exit code: ${response.exitCode}\nResult: ${errorResult}`,
);
}
return {
result: response.result ?? `exit code: ${response.exitCode}`,
status: "success",
};
} catch (e) {
const errorFields = getSandboxErrorFields(e);
if (errorFields) {
const errorResult =
errorFields.result ?? errorFields.artifacts?.stdout;
throw new Error(
`Command failed. Exit code: ${errorFields.exitCode}\nError: ${errorResult}`,
);
}
throw e;
}
},
createShellToolFields(state.targetRepository),
);
return shellTool;
}