mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 05:43:14 +00:00
init commit
This commit is contained in:
commit
e2415aee3f
23 changed files with 6359 additions and 0 deletions
0
.codespellignore
Normal file
0
.codespellignore
Normal file
4
.dockerignore
Normal file
4
.dockerignore
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
.next
|
||||
.git
|
||||
.env
|
||||
14
.env.example
Normal file
14
.env.example
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Required
|
||||
OPENAI_API_KEY=""
|
||||
# GOOGLE_API_KEY=""
|
||||
# ANTHROPIC_API_KEY=""
|
||||
|
||||
MCP_URL=""
|
||||
|
||||
# Optional, but recommended for best in class tracing and observability.
|
||||
# LANGSMITH_PROJECT="default"
|
||||
# LANGSMITH_API_KEY=""
|
||||
# LANGSMITH_TRACING_V2=true
|
||||
|
||||
# Optional
|
||||
# FINANCIAL_DATASETS_API_KEY=""
|
||||
68
.github/workflows/ci.yml
vendored
Normal file
68
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# Run formatting on all PRs
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
workflow_dispatch: # Allows triggering the workflow manually in GitHub UI
|
||||
|
||||
# If another push to the same PR or branch happens while this workflow is still running,
|
||||
# cancel the earlier run in favor of the next run.
|
||||
#
|
||||
# There's no point in testing an outdated version of the code. GitHub only allows
|
||||
# a limited number of job runners to be active at the same time, so it's better to cancel
|
||||
# pointless jobs early so that more useful jobs can run sooner.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
format:
|
||||
name: Check formatting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "18.x"
|
||||
cache: "yarn"
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
- name: Check formatting
|
||||
run: yarn format:check
|
||||
|
||||
lint:
|
||||
name: Check linting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "18.x"
|
||||
cache: "yarn"
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
- name: Check linting
|
||||
run: yarn lint
|
||||
|
||||
readme-spelling:
|
||||
name: Check README spelling
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: codespell-project/actions-codespell@v2
|
||||
with:
|
||||
ignore_words_file: .codespellignore
|
||||
path: README.md
|
||||
|
||||
check-spelling:
|
||||
name: Check code spelling
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: codespell-project/actions-codespell@v2
|
||||
with:
|
||||
ignore_words_file: .codespellignore
|
||||
path: src
|
||||
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# LangGraph API
|
||||
.langgraph_api
|
||||
.env
|
||||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Brace Sproul
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1
README.md
Normal file
1
README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# OpenCodex
|
||||
77
eslint.config.js
Normal file
77
eslint.config.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
import eslintImport from "eslint-plugin-import";
|
||||
import eslintNoInstanceof from "eslint-plugin-no-instanceof";
|
||||
|
||||
export default tseslint.config(
|
||||
tseslint.configs.recommendedTypeChecked,
|
||||
js.configs.recommended,
|
||||
{ ignores: ["dist", "eslint.config.js"] },
|
||||
{
|
||||
files: ["**/*.ts"],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.browser,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
import: eslintImport,
|
||||
"no-instanceof": eslintNoInstanceof,
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
||||
"@typescript-eslint/no-empty-function": 0,
|
||||
"@typescript-eslint/no-shadow": 0,
|
||||
"@typescript-eslint/no-unsafe-assignment": 0,
|
||||
"@typescript-eslint/no-unsafe-member-access": 0,
|
||||
"@typescript-eslint/no-unsafe-return": 0,
|
||||
"@typescript-eslint/no-unsafe-argument": 0,
|
||||
"@typescript-eslint/no-empty-interface": 0,
|
||||
"@typescript-eslint/no-use-before-define": ["error", "nofunc"],
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_|^UNUSED_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
destructuredArrayIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
"@typescript-eslint/no-misused-promises": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
camelcase: 0,
|
||||
"class-methods-use-this": 0,
|
||||
"import/extensions": [2, "ignorePackages"],
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{ devDependencies: ["**/*.test.ts"] },
|
||||
],
|
||||
"import/no-unresolved": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"keyword-spacing": "error",
|
||||
"max-classes-per-file": 0,
|
||||
"max-len": 0,
|
||||
"no-await-in-loop": 0,
|
||||
"no-bitwise": 0,
|
||||
"no-console": 0,
|
||||
"no-restricted-syntax": 0,
|
||||
"no-shadow": 0,
|
||||
"no-continue": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-use-before-define": 0,
|
||||
"no-useless-constructor": 0,
|
||||
"no-return-await": 0,
|
||||
"consistent-return": 0,
|
||||
"no-else-return": 0,
|
||||
"new-cap": ["error", { properties: false, capIsNew: false }],
|
||||
},
|
||||
},
|
||||
);
|
||||
18
jest.config.js
Normal file
18
jest.config.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
export default {
|
||||
preset: "ts-jest/presets/default-esm",
|
||||
moduleNameMapper: {
|
||||
"^(\\.{1,2}/.*)\\.js$": "$1",
|
||||
},
|
||||
transform: {
|
||||
"^.+\\.tsx?$": [
|
||||
"ts-jest",
|
||||
{
|
||||
useESM: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
extensionsToTreatAsEsm: [".ts"],
|
||||
setupFiles: ["dotenv/config"],
|
||||
passWithNoTests: true,
|
||||
testTimeout: 20_000,
|
||||
};
|
||||
8
langgraph.json
Normal file
8
langgraph.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"node_version": "20",
|
||||
"graphs": {
|
||||
"agent": "./src/index.ts:graph"
|
||||
},
|
||||
"env": ".env",
|
||||
"dependencies": ["."]
|
||||
}
|
||||
53
package.json
Normal file
53
package.json
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"name": "open-codex",
|
||||
"homepage": "https://github.com/langchain-ai/open-codex/blob/main/README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/langchain-ai/open-codex.git"
|
||||
},
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "langgraphjs dev --no-browser",
|
||||
"build": "tsc",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --testPathPattern=\\.test\\.ts$ --testPathIgnorePatterns=\\.int\\.test\\.ts$",
|
||||
"test:int": "node --experimental-vm-modules node_modules/jest/bin/jest.js --testPathPattern=\\.int\\.test\\.ts$",
|
||||
"test:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.js --testTimeout 100000"
|
||||
},
|
||||
"dependencies": {
|
||||
"@langchain/anthropic": "^0.3.20",
|
||||
"@langchain/core": "^0.3.56",
|
||||
"@langchain/google-genai": "^0.2.9",
|
||||
"@langchain/langgraph": "^0.2.73",
|
||||
"@langchain/openai": "^0.5.10",
|
||||
"langchain": "^0.3.26",
|
||||
"uuid": "^11.0.5",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@langchain/langgraph-cli": "latest",
|
||||
"@tsconfig/recommended": "^1.0.8",
|
||||
"@types/node": "^22.13.5",
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint": "^9.19.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"@types/jest": "^29.5.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"jest": "^29.7.0",
|
||||
"eslint-plugin-no-instanceof": "^1.0.1",
|
||||
"@jest/globals": "^29.7.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"prettier": "^3.5.2",
|
||||
"typescript": "~5.7.2",
|
||||
"typescript-eslint": "^8.22.0"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22"
|
||||
}
|
||||
92
src/index.ts
Normal file
92
src/index.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import { END, START, StateGraph } from "@langchain/langgraph";
|
||||
import { GraphAnnotation, GraphConfiguration, GraphState } from "./types.js";
|
||||
import {
|
||||
generatePlan,
|
||||
initialize,
|
||||
generateAction,
|
||||
takeAction,
|
||||
rewritePlan,
|
||||
summarizeSession,
|
||||
} from "./nodes/index.js";
|
||||
import { isAIMessage, isToolMessage } from "@langchain/core/messages";
|
||||
|
||||
/**
|
||||
* After generating a plan, ensure there is an approved tool message.
|
||||
* If there is, route to the generate-action node. Otherwise, route to the rewrite-plan node.
|
||||
*/
|
||||
function routeAfterPlan(state: GraphState): "generate-action" | "rewrite-plan" {
|
||||
const { messages } = state;
|
||||
// Search for a tool message responding to the "session_plan" tool call where the content is "approved"
|
||||
const planApprovedMessage = messages.find(
|
||||
(m) =>
|
||||
isToolMessage(m) && m.name === "session_plan" && m.content === "approved",
|
||||
);
|
||||
if (planApprovedMessage) {
|
||||
return "generate-action";
|
||||
}
|
||||
// If this does not exist, we should rewrite the plan.
|
||||
return "rewrite-plan";
|
||||
}
|
||||
|
||||
/**
|
||||
* After taking action, ensure there is an AI message with tool calls.
|
||||
* If there is, route to the take-action node. Otherwise, end the graph.
|
||||
* We do not want to route to the summarize session node here, as the generation
|
||||
* likely means the LLM is asking a question, or failed to generate an action.
|
||||
*/
|
||||
function takeActionOrEnd(state: GraphState): typeof END | "take-action" {
|
||||
const { messages } = state;
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
// If the message is an AI message, and it has tool calls, we should take action.
|
||||
if (isAIMessage(lastMessage) && lastMessage.tool_calls?.length) {
|
||||
return "take-action";
|
||||
}
|
||||
return END;
|
||||
}
|
||||
|
||||
/**
|
||||
* After taking action, check if there are any uncompleted plan items.
|
||||
* If there are, route to the generate-action node. Otherwise, route to the summarize-session node.
|
||||
* The summarize session node is the final node, and will end the graph.
|
||||
*/
|
||||
function generateActionOrSummarize(
|
||||
state: GraphState,
|
||||
): "generate-action" | "summarize-session" {
|
||||
const { plan } = state;
|
||||
|
||||
const hasUncompletedPlanItems = !!plan.filter((item) => !item.completed)
|
||||
.length;
|
||||
if (hasUncompletedPlanItems) {
|
||||
return "generate-action";
|
||||
}
|
||||
return "summarize-session";
|
||||
}
|
||||
|
||||
const workflow = new StateGraph(GraphAnnotation, GraphConfiguration)
|
||||
.addNode("initialize", initialize)
|
||||
.addNode("generate-plan", generatePlan)
|
||||
.addNode("rewrite-plan", rewritePlan)
|
||||
.addNode("generate-action", generateAction)
|
||||
.addNode("take-action", takeAction)
|
||||
.addNode("summarize-session", summarizeSession)
|
||||
.addEdge(START, "initialize")
|
||||
.addEdge("initialize", "generate-plan")
|
||||
.addConditionalEdges("generate-plan", routeAfterPlan, [
|
||||
"generate-action",
|
||||
"rewrite-plan",
|
||||
])
|
||||
.addConditionalEdges("rewrite-plan", routeAfterPlan, [
|
||||
"generate-action",
|
||||
"rewrite-plan",
|
||||
])
|
||||
.addEdge("generate-plan", "generate-action")
|
||||
.addConditionalEdges("generate-action", takeActionOrEnd, ["take-action", END])
|
||||
.addConditionalEdges("take-action", generateActionOrSummarize, [
|
||||
"generate-action",
|
||||
"summarize-session",
|
||||
])
|
||||
.addEdge("summarize-session", END);
|
||||
|
||||
export const graph = workflow.compile();
|
||||
graph.name = "LangGraph ReAct MCP";
|
||||
12
src/nodes/generate-action.ts
Normal file
12
src/nodes/generate-action.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { GraphState, GraphConfig, GraphUpdate } from "../types.js";
|
||||
|
||||
/**
|
||||
* Initializes the session. This ensures there's an active VM session, and that
|
||||
* the proper credentials are provided for taking actions on GitHub.
|
||||
*/
|
||||
export function generateAction(
|
||||
state: GraphState,
|
||||
config: GraphConfig,
|
||||
): Promise<GraphUpdate> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
8
src/nodes/generate-plan.ts
Normal file
8
src/nodes/generate-plan.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { GraphState, GraphConfig, GraphUpdate } from "../types.js";
|
||||
|
||||
export function generatePlan(
|
||||
state: GraphState,
|
||||
config: GraphConfig,
|
||||
): Promise<GraphUpdate> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
6
src/nodes/index.ts
Normal file
6
src/nodes/index.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export * from "./generate-plan.js";
|
||||
export * from "./initialize.js";
|
||||
export * from "./generate-action.js";
|
||||
export * from "./take-action.js";
|
||||
export * from "./rewrite-plan.js";
|
||||
export * from "./summarize-session.js";
|
||||
12
src/nodes/initialize.ts
Normal file
12
src/nodes/initialize.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { GraphState, GraphConfig, GraphUpdate } from "../types.js";
|
||||
|
||||
/**
|
||||
* Initializes the session. This ensures there's an active VM session, and that
|
||||
* the proper credentials are provided for taking actions on GitHub.
|
||||
*/
|
||||
export function initialize(
|
||||
state: GraphState,
|
||||
config: GraphConfig,
|
||||
): Promise<GraphUpdate> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
12
src/nodes/rewrite-plan.ts
Normal file
12
src/nodes/rewrite-plan.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { GraphState, GraphConfig, GraphUpdate } from "../types.js";
|
||||
|
||||
/**
|
||||
* Initializes the session. This ensures there's an active VM session, and that
|
||||
* the proper credentials are provided for taking actions on GitHub.
|
||||
*/
|
||||
export function rewritePlan(
|
||||
state: GraphState,
|
||||
config: GraphConfig,
|
||||
): Promise<GraphUpdate> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
12
src/nodes/summarize-session.ts
Normal file
12
src/nodes/summarize-session.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { GraphState, GraphConfig, GraphUpdate } from "../types.js";
|
||||
|
||||
/**
|
||||
* Initializes the session. This ensures there's an active VM session, and that
|
||||
* the proper credentials are provided for taking actions on GitHub.
|
||||
*/
|
||||
export function summarizeSession(
|
||||
state: GraphState,
|
||||
config: GraphConfig,
|
||||
): Promise<GraphUpdate> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
12
src/nodes/take-action.ts
Normal file
12
src/nodes/take-action.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { GraphState, GraphConfig, GraphUpdate } from "../types.js";
|
||||
|
||||
/**
|
||||
* Initializes the session. This ensures there's an active VM session, and that
|
||||
* the proper credentials are provided for taking actions on GitHub.
|
||||
*/
|
||||
export function takeAction(
|
||||
state: GraphState,
|
||||
config: GraphConfig,
|
||||
): Promise<GraphUpdate> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
147
src/types.ts
Normal file
147
src/types.ts
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
import "@langchain/langgraph/zod";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Annotation,
|
||||
LangGraphRunnableConfig,
|
||||
MessagesAnnotation,
|
||||
} from "@langchain/langgraph";
|
||||
|
||||
type PlanItem = {
|
||||
id: string;
|
||||
plan: string;
|
||||
completed: boolean;
|
||||
};
|
||||
|
||||
export const GraphAnnotation = Annotation.Root({
|
||||
messages: MessagesAnnotation.spec.messages,
|
||||
plan: Annotation<PlanItem[]>({
|
||||
reducer: (_state, update) => update,
|
||||
default: () => [],
|
||||
}),
|
||||
});
|
||||
|
||||
export type GraphState = typeof GraphAnnotation.State;
|
||||
export type GraphUpdate = typeof GraphAnnotation.Update;
|
||||
|
||||
export const MCPConfig = z.object({
|
||||
/**
|
||||
* The MCP server URL.
|
||||
*/
|
||||
url: z.string(),
|
||||
/**
|
||||
* The list of tools to provide to the LLM.
|
||||
*/
|
||||
tools: z.array(z.string()),
|
||||
});
|
||||
|
||||
export const GraphConfiguration = z.object({
|
||||
/**
|
||||
* The model ID to use for the reflection generation.
|
||||
* Should be in the format `provider/model_name`.
|
||||
* Defaults to `anthropic/claude-3-7-sonnet-latest`.
|
||||
*/
|
||||
modelName: z
|
||||
.string()
|
||||
.optional()
|
||||
.langgraph.metadata({
|
||||
x_lg_ui_config: {
|
||||
type: "select",
|
||||
default: "anthropic/claude-3-7-sonnet-latest",
|
||||
description: "The model to use in all generations",
|
||||
options: [
|
||||
{
|
||||
label: "Claude 3.7 Sonnet",
|
||||
value: "anthropic/claude-3-7-sonnet-latest",
|
||||
},
|
||||
{
|
||||
label: "Claude 3.5 Sonnet",
|
||||
value: "anthropic/claude-3-5-sonnet-latest",
|
||||
},
|
||||
{
|
||||
label: "GPT 4o",
|
||||
value: "openai/gpt-4o",
|
||||
},
|
||||
{
|
||||
label: "GPT 4.1",
|
||||
value: "openai/gpt-4.1",
|
||||
},
|
||||
{
|
||||
label: "o3",
|
||||
value: "openai/o3",
|
||||
},
|
||||
{
|
||||
label: "o3 mini",
|
||||
value: "openai/o3-mini",
|
||||
},
|
||||
{
|
||||
label: "o4",
|
||||
value: "openai/o4",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
/**
|
||||
* The temperature to use for the reflection generation.
|
||||
* Defaults to `0.7`.
|
||||
*/
|
||||
temperature: z
|
||||
.number()
|
||||
.optional()
|
||||
.langgraph.metadata({
|
||||
x_lg_ui_config: {
|
||||
type: "slider",
|
||||
default: 0.7,
|
||||
min: 0,
|
||||
max: 2,
|
||||
step: 0.1,
|
||||
description: "Controls randomness (0 = deterministic, 2 = creative)",
|
||||
},
|
||||
}),
|
||||
/**
|
||||
* The maximum number of tokens to generate.
|
||||
* Defaults to `1000`.
|
||||
*/
|
||||
maxTokens: z
|
||||
.number()
|
||||
.optional()
|
||||
.langgraph.metadata({
|
||||
x_lg_ui_config: {
|
||||
type: "number",
|
||||
default: 4000,
|
||||
min: 1,
|
||||
description: "The maximum number of tokens to generate",
|
||||
},
|
||||
}),
|
||||
systemPrompt: z
|
||||
.string()
|
||||
.optional()
|
||||
.langgraph.metadata({
|
||||
x_lg_ui_config: {
|
||||
type: "textarea",
|
||||
placeholder: "Enter a system prompt...",
|
||||
description: "The system prompt to use in all generations",
|
||||
},
|
||||
}),
|
||||
/**
|
||||
* MCP configuration for tool selection
|
||||
*/
|
||||
mcpConfig: z
|
||||
.lazy(() => MCPConfig)
|
||||
.optional()
|
||||
.langgraph.metadata({
|
||||
x_lg_ui_config: {
|
||||
type: "mcp",
|
||||
// Add custom tools here.
|
||||
// default: {
|
||||
// tools: ["Math_Divide", "Math_Mod"]
|
||||
// }
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export type GraphConfig = LangGraphRunnableConfig<
|
||||
z.infer<typeof GraphConfiguration> & {
|
||||
thread_id: string;
|
||||
assistant_id: string;
|
||||
}
|
||||
>;
|
||||
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"extends": "@tsconfig/recommended",
|
||||
"compilerOptions": {
|
||||
"target": "ES2021",
|
||||
"lib": ["ES2021", "ES2022.Object", "DOM"],
|
||||
"module": "NodeNext",
|
||||
"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": ["jest", "node"],
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.js", "jest.setup.cjs"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue