mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-03 17:53:20 +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,
|
createUpdatePlanToolFields,
|
||||||
createGetURLContentTool,
|
createGetURLContentTool,
|
||||||
createSearchDocumentForTool,
|
createSearchDocumentForTool,
|
||||||
|
createWriteDefaultTsConfigTool,
|
||||||
} from "../../../../tools/index.js";
|
} from "../../../../tools/index.js";
|
||||||
import { formatPlanPrompt } from "../../../../utils/plan-prompt.js";
|
import { formatPlanPrompt } from "../../../../utils/plan-prompt.js";
|
||||||
import { stopSandbox } from "../../../../utils/sandbox.js";
|
import { stopSandbox } from "../../../../utils/sandbox.js";
|
||||||
|
|
@ -181,6 +182,7 @@ async function createToolsAndPrompt(
|
||||||
createInstallDependenciesTool(state, config),
|
createInstallDependenciesTool(state, config),
|
||||||
createMarkTaskCompletedToolFields(),
|
createMarkTaskCompletedToolFields(),
|
||||||
createSearchDocumentForTool(state, config),
|
createSearchDocumentForTool(state, config),
|
||||||
|
createWriteDefaultTsConfigTool(state, config),
|
||||||
...mcpTools,
|
...mcpTools,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
createTextEditorTool,
|
createTextEditorTool,
|
||||||
createShellTool,
|
createShellTool,
|
||||||
createSearchDocumentForTool,
|
createSearchDocumentForTool,
|
||||||
|
createWriteDefaultTsConfigTool,
|
||||||
} from "../../../tools/index.js";
|
} from "../../../tools/index.js";
|
||||||
import {
|
import {
|
||||||
GraphState,
|
GraphState,
|
||||||
|
|
@ -59,11 +60,16 @@ export async function takeAction(
|
||||||
const getURLContentTool = createGetURLContentTool(state);
|
const getURLContentTool = createGetURLContentTool(state);
|
||||||
const searchDocumentForTool = createSearchDocumentForTool(state, config);
|
const searchDocumentForTool = createSearchDocumentForTool(state, config);
|
||||||
const mcpTools = await getMcpTools(config);
|
const mcpTools = await getMcpTools(config);
|
||||||
|
const writeDefaultTsConfigTool = createWriteDefaultTsConfigTool(
|
||||||
|
state,
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
const higherContextLimitToolNames = [
|
const higherContextLimitToolNames = [
|
||||||
...mcpTools.map((t) => t.name),
|
...mcpTools.map((t) => t.name),
|
||||||
getURLContentTool.name,
|
getURLContentTool.name,
|
||||||
searchDocumentForTool.name,
|
searchDocumentForTool.name,
|
||||||
|
writeDefaultTsConfigTool.name,
|
||||||
];
|
];
|
||||||
|
|
||||||
const allTools = [
|
const allTools = [
|
||||||
|
|
@ -74,6 +80,7 @@ export async function takeAction(
|
||||||
applyPatchTool,
|
applyPatchTool,
|
||||||
getURLContentTool,
|
getURLContentTool,
|
||||||
searchDocumentForTool,
|
searchDocumentForTool,
|
||||||
|
writeDefaultTsConfigTool,
|
||||||
...mcpTools,
|
...mcpTools,
|
||||||
];
|
];
|
||||||
const toolsMap = Object.fromEntries(
|
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";
|
} from "@open-swe/shared/open-swe/tools";
|
||||||
export * from "./grep.js";
|
export * from "./grep.js";
|
||||||
export * from "./install-dependencies.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 { Dispatch, SetStateAction } from "react";
|
||||||
import { Card, CardDescription, CardHeader, CardTitle } from "../ui/card";
|
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.
|
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 {
|
interface QuickActionsProps {
|
||||||
setQuickActionPrompt: Dispatch<SetStateAction<string>>;
|
setQuickActionPrompt: Dispatch<SetStateAction<string>>;
|
||||||
}
|
}
|
||||||
|
|
@ -69,19 +125,15 @@ export function QuickActions({ setQuickActionPrompt }: QuickActionsProps) {
|
||||||
<DevReadmePromptQuickAction
|
<DevReadmePromptQuickAction
|
||||||
setQuickActionPrompt={setQuickActionPrompt}
|
setQuickActionPrompt={setQuickActionPrompt}
|
||||||
/>
|
/>
|
||||||
<Card
|
<AgentsMarkdownQuickAction
|
||||||
onClick={() => setQuickActionPrompt(GENERATE_RULES_PROMPT)}
|
setQuickActionPrompt={setQuickActionPrompt}
|
||||||
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"
|
/>
|
||||||
>
|
<RepositoryTemplateQuickAction
|
||||||
<CardHeader className="px-3">
|
owner="bracesproul"
|
||||||
<CardTitle className="text-foreground text-sm">
|
repo="typescript-template"
|
||||||
Generate Agent Rules
|
title="Clone a TypeScript Template"
|
||||||
</CardTitle>
|
description="Bootstrap a new TypeScript project with pre-configured build tools, linting, testing setup, etc."
|
||||||
<CardDescription className="text-muted-foreground text-xs">
|
/>
|
||||||
Generate an AGENTS.md file for the repository.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -579,3 +579,25 @@ export function createViewToolFields(
|
||||||
schema: viewSchema,
|
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