mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-03 12:43:30 +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