mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 08:03:15 +00:00
feat: Tsconfig tool and typescript template (#660)
* feat: Tsconfig tool and typescript template * cr
This commit is contained in:
parent
700bbf20f5
commit
71e6094421
7 changed files with 180 additions and 14 deletions
|
|
@ -19,6 +19,7 @@ import {
|
|||
createUpdatePlanToolFields,
|
||||
createGetURLContentTool,
|
||||
createSearchDocumentForTool,
|
||||
createWriteDefaultTsConfigTool,
|
||||
} from "../../../../tools/index.js";
|
||||
import { formatPlanPrompt } from "../../../../utils/plan-prompt.js";
|
||||
import { stopSandbox } from "../../../../utils/sandbox.js";
|
||||
|
|
@ -181,6 +182,7 @@ async function createToolsAndPrompt(
|
|||
createInstallDependenciesTool(state, config),
|
||||
createMarkTaskCompletedToolFields(),
|
||||
createSearchDocumentForTool(state, config),
|
||||
createWriteDefaultTsConfigTool(state, config),
|
||||
...mcpTools,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
createTextEditorTool,
|
||||
createShellTool,
|
||||
createSearchDocumentForTool,
|
||||
createWriteDefaultTsConfigTool,
|
||||
} from "../../../tools/index.js";
|
||||
import {
|
||||
GraphState,
|
||||
|
|
@ -59,11 +60,16 @@ export async function takeAction(
|
|||
const getURLContentTool = createGetURLContentTool(state);
|
||||
const searchDocumentForTool = createSearchDocumentForTool(state, config);
|
||||
const mcpTools = await getMcpTools(config);
|
||||
const writeDefaultTsConfigTool = createWriteDefaultTsConfigTool(
|
||||
state,
|
||||
config,
|
||||
);
|
||||
|
||||
const higherContextLimitToolNames = [
|
||||
...mcpTools.map((t) => t.name),
|
||||
getURLContentTool.name,
|
||||
searchDocumentForTool.name,
|
||||
writeDefaultTsConfigTool.name,
|
||||
];
|
||||
|
||||
const allTools = [
|
||||
|
|
@ -74,6 +80,7 @@ export async function takeAction(
|
|||
applyPatchTool,
|
||||
getURLContentTool,
|
||||
searchDocumentForTool,
|
||||
writeDefaultTsConfigTool,
|
||||
...mcpTools,
|
||||
];
|
||||
const toolsMap = Object.fromEntries(
|
||||
|
|
|
|||
83
apps/open-swe/src/tools/default-tsconfig.ts
Normal file
83
apps/open-swe/src/tools/default-tsconfig.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import path from "path";
|
||||
import { tool } from "@langchain/core/tools";
|
||||
import { createWriteDefaultTsConfigToolFields } from "@open-swe/shared/open-swe/tools";
|
||||
import { GraphConfig, GraphState } from "@open-swe/shared/open-swe/types";
|
||||
import { createShellExecutor } from "../utils/shell-executor/index.js";
|
||||
import { TIMEOUT_SEC } from "@open-swe/shared/constants";
|
||||
import { getSandboxErrorFields } from "../utils/sandbox-error-fields.js";
|
||||
|
||||
const DEFAULT_TS_CONFIG = {
|
||||
extends: "@tsconfig/recommended",
|
||||
compilerOptions: {
|
||||
target: "ES2021",
|
||||
module: "NodeNext",
|
||||
lib: ["ES2023"],
|
||||
moduleResolution: "nodenext",
|
||||
esModuleInterop: true,
|
||||
noImplicitReturns: true,
|
||||
declaration: true,
|
||||
noFallthroughCasesInSwitch: true,
|
||||
noUnusedLocals: true,
|
||||
noUnusedParameters: true,
|
||||
useDefineForClassFields: true,
|
||||
strictPropertyInitialization: false,
|
||||
allowJs: true,
|
||||
strict: true,
|
||||
strictFunctionTypes: false,
|
||||
outDir: "dist",
|
||||
types: ["node"],
|
||||
resolveJsonModule: true,
|
||||
},
|
||||
include: ["**/*.ts"],
|
||||
exclude: ["node_modules", "dist"],
|
||||
};
|
||||
|
||||
export function createWriteDefaultTsConfigTool(
|
||||
state: Pick<GraphState, "sandboxSessionId" | "targetRepository">,
|
||||
config: GraphConfig,
|
||||
) {
|
||||
const writeDefaultTsConfigTool = tool(
|
||||
async (input): Promise<{ result: string; status: "success" | "error" }> => {
|
||||
const { workdir } = input;
|
||||
const executor = createShellExecutor(config);
|
||||
const tsConfigFileName = "tsconfig.json";
|
||||
|
||||
try {
|
||||
const response = await executor.executeCommand({
|
||||
command: `echo '${JSON.stringify(DEFAULT_TS_CONFIG)}' > ${tsConfigFileName}`,
|
||||
workdir,
|
||||
timeout: TIMEOUT_SEC,
|
||||
});
|
||||
if (response.exitCode !== 0) {
|
||||
throw new Error(
|
||||
`Failed to write default tsconfig.json. Exit code: ${response.exitCode}\nError: ${response.result}`,
|
||||
);
|
||||
}
|
||||
|
||||
const destinationPath = path.join(workdir, tsConfigFileName);
|
||||
return {
|
||||
result: `Successfully wrote to tsconfig.json to ${destinationPath}`,
|
||||
status: "success",
|
||||
};
|
||||
} catch (error) {
|
||||
const errorFields = getSandboxErrorFields(error);
|
||||
if (errorFields) {
|
||||
return {
|
||||
result: `Error: ${errorFields.result ?? errorFields.artifacts?.stdout}`,
|
||||
status: "error",
|
||||
};
|
||||
}
|
||||
|
||||
const errorString =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
result: `Error: ${errorString}`,
|
||||
status: "error",
|
||||
};
|
||||
}
|
||||
},
|
||||
createWriteDefaultTsConfigToolFields(state.targetRepository),
|
||||
);
|
||||
|
||||
return writeDefaultTsConfigTool;
|
||||
}
|
||||
|
|
@ -10,4 +10,4 @@ export {
|
|||
} from "@open-swe/shared/open-swe/tools";
|
||||
export * from "./grep.js";
|
||||
export * from "./install-dependencies.js";
|
||||
export * from "./planner-notes.js";
|
||||
export * from "./default-tsconfig.js";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Dispatch, SetStateAction } from "react";
|
||||
import { Card, CardDescription, CardHeader, CardTitle } from "../ui/card";
|
||||
import { GitHubSVG } from "../icons/github";
|
||||
|
||||
const GENERATE_RULES_PROMPT = `You're given a task to write a collection of rules, context and guidelines on the repository you're provided. Please gather context on the following categories, then write an \`AGENTS.md\` file in the root of the repository.
|
||||
|
||||
|
|
@ -55,6 +56,61 @@ function DevReadmePromptQuickAction({
|
|||
);
|
||||
}
|
||||
|
||||
function AgentsMarkdownQuickAction({
|
||||
setQuickActionPrompt,
|
||||
}: QuickActionsProps) {
|
||||
return (
|
||||
<Card
|
||||
onClick={() => setQuickActionPrompt(GENERATE_RULES_PROMPT)}
|
||||
className="border-border bg-card hover:bg-muted/30 dark:hover:bg-muted/20 hover:shadow-primary/2 cursor-pointer py-3 transition-all duration-200 hover:shadow-sm"
|
||||
>
|
||||
<CardHeader className="px-3">
|
||||
<CardTitle className="text-foreground text-sm">
|
||||
Generate Agent Rules
|
||||
</CardTitle>
|
||||
<CardDescription className="text-muted-foreground text-xs">
|
||||
Generate an AGENTS.md file for the repository.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function RepositoryTemplateQuickAction(props: {
|
||||
owner: string;
|
||||
repo: string;
|
||||
title: string;
|
||||
description: string;
|
||||
}) {
|
||||
const repoUrl = `https://github.com/${props.owner}/${props.repo}`;
|
||||
return (
|
||||
<a
|
||||
href={repoUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Card className="border-border bg-card hover:bg-muted/30 dark:hover:bg-muted/20 hover:shadow-primary/2 cursor-pointer py-3 transition-all duration-200 hover:shadow-sm">
|
||||
<CardHeader className="px-3">
|
||||
<CardTitle className="text-foreground text-sm">
|
||||
{props.title}
|
||||
<p className="text-foreground/80 mt-1 flex items-center gap-1 font-mono text-xs">
|
||||
<GitHubSVG
|
||||
width="12"
|
||||
height="12"
|
||||
className="flex-shrink-0"
|
||||
/>
|
||||
{props.owner}/{props.repo}
|
||||
</p>
|
||||
</CardTitle>
|
||||
<CardDescription className="text-muted-foreground text-xs">
|
||||
{props.description}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
interface QuickActionsProps {
|
||||
setQuickActionPrompt: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
|
@ -69,19 +125,15 @@ export function QuickActions({ setQuickActionPrompt }: QuickActionsProps) {
|
|||
<DevReadmePromptQuickAction
|
||||
setQuickActionPrompt={setQuickActionPrompt}
|
||||
/>
|
||||
<Card
|
||||
onClick={() => setQuickActionPrompt(GENERATE_RULES_PROMPT)}
|
||||
className="border-border bg-card hover:bg-muted/30 dark:hover:bg-muted/20 hover:shadow-primary/2 cursor-pointer py-3 transition-all duration-200 hover:shadow-sm"
|
||||
>
|
||||
<CardHeader className="px-3">
|
||||
<CardTitle className="text-foreground text-sm">
|
||||
Generate Agent Rules
|
||||
</CardTitle>
|
||||
<CardDescription className="text-muted-foreground text-xs">
|
||||
Generate an AGENTS.md file for the repository.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<AgentsMarkdownQuickAction
|
||||
setQuickActionPrompt={setQuickActionPrompt}
|
||||
/>
|
||||
<RepositoryTemplateQuickAction
|
||||
owner="bracesproul"
|
||||
repo="typescript-template"
|
||||
title="Clone a TypeScript Template"
|
||||
description="Bootstrap a new TypeScript project with pre-configured build tools, linting, testing setup, etc."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -579,3 +579,25 @@ export function createViewToolFields(
|
|||
schema: viewSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function createWriteDefaultTsConfigToolFields(
|
||||
targetRepository: TargetRepository,
|
||||
) {
|
||||
const repoRoot = getRepoAbsolutePath(targetRepository);
|
||||
|
||||
const writeDefaultTsConfigToolSchema = z.object({
|
||||
workdir: z
|
||||
.string()
|
||||
.default(repoRoot)
|
||||
.describe(
|
||||
`The directory which the tsconfig.json file will be written to. The default value is the root of the repository: \`${repoRoot}\`.`,
|
||||
),
|
||||
});
|
||||
|
||||
return {
|
||||
name: "write_default_tsconfig",
|
||||
description:
|
||||
"Writes a default tsconfig.json file to the specified directory. This should ONLY be called when creating a new TypeScript project.",
|
||||
schema: writeDefaultTsConfigToolSchema,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue