feat: Initial commit

This commit is contained in:
bracesproul
2025-04-10 15:53:31 -07:00
commit 463d43fc0e
25 changed files with 6962 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
IST
afterAll
+2
View File
@@ -0,0 +1,2 @@
node_modules
dist
+10
View File
@@ -0,0 +1,10 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
[*.{js,json,yml}]
charset = utf-8
indent_style = space
indent_size = 2
+70
View File
@@ -0,0 +1,70 @@
module.exports = {
extends: [
"eslint:recommended",
"prettier",
"plugin:@typescript-eslint/recommended",
],
parserOptions: {
ecmaVersion: 12,
parser: "@typescript-eslint/parser",
project: "./tsconfig.json",
sourceType: "module",
},
plugins: ["import", "@typescript-eslint", "no-instanceof"],
ignorePatterns: [
".eslintrc.cjs",
"scripts",
"src/utils/lodash/*",
"node_modules",
"dist",
"dist-cjs",
"*.js",
"*.cjs",
"*.d.ts",
],
rules: {
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-shadow": 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 }],
},
};
+70
View File
@@ -0,0 +1,70 @@
# 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
- name: Use Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 18.x
cache: "yarn"
- name: Install dependencies
run: yarn install --immutable --mode=skip-build
- name: Check formatting
run: yarn format:check
lint:
name: Check linting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 18.x
cache: "yarn"
- name: Install dependencies
run: yarn install --immutable --mode=skip-build
- name: Check linting
run: yarn run lint:all
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
+35
View File
@@ -0,0 +1,35 @@
index.cjs
index.js
index.d.ts
node_modules
dist
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
yarn-error.log
.turbo
**/.turbo
**/.eslintcache
.env
.env.*
!.env.*.example
.ipynb_checkpoints
# Screenshots taken during tests
src/tests/data/screenshots/
src/agents/verify-reddit-post/nodes/tests/data/
src/agents/verify-reddit-post/nodes/tests/data/openai_o1_vs_recent_leetcode_questions.json
src/agents/curate-data/nodes/tweets/tests/data/*
src/clients/reddit/.secrets/
# LangGraph API
.langgraph_api
__pycache__/
.mypy_cache/
.ruff_cache/
+15
View File
@@ -0,0 +1,15 @@
{
"cSpell.words": [
"agentinbox",
"checkpointer",
"LANGSMITH",
"llmanager",
"Luma",
"Repurposer",
"reranked",
"subreddits",
"Supabase",
"Userless"
],
"python.languageServer": "None"
}
+1
View File
@@ -0,0 +1 @@
nodeLinker: node-modules
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 LangChain
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
View File
@@ -0,0 +1 @@
# LLManager
+18
View 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: ["./jest.setup.cjs"],
passWithNoTests: true,
testTimeout: 20_000,
};
+10
View File
@@ -0,0 +1,10 @@
const dotenv = require("dotenv");
// Check for TEST_ENV environment variable to determine which .env file to load
// Default to regular .env if not specified
const envFile =
process.env.TEST_ENV === "production" ? ".env.production" : ".env";
// Load the appropriate .env file
dotenv.config({ path: envFile });
+8
View File
@@ -0,0 +1,8 @@
{
"node_version": "20",
"graphs": {
"agent": "./src/llmanager/index.ts:graph"
},
"env": ".env",
"dependencies": ["."]
}
+53
View File
@@ -0,0 +1,53 @@
{
"name": "llmanager",
"version": "0.0.0",
"description": "Use an LLM as a manager for approval processes.",
"packageManager": "yarn@3.8.7",
"main": "src/llmanager/index.ts",
"author": "Your Name",
"license": "MIT",
"private": true,
"type": "module",
"scripts": {
"dev": "npx @langchain/langgraph-cli@latest dev --port 2024 --no-browser",
"build": "tsc",
"clean": "rm -rf dist",
"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",
"format": "prettier --write .",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"format:check": "prettier --check ."
},
"dependencies": {
"@langchain/anthropic": "^0.3.17",
"@langchain/core": "^0.3.44",
"@langchain/langgraph": "^0.2.63",
"@langchain/langgraph-sdk": "0.0.66",
"@langchain/openai": "^0.5.5",
"dotenv": "^16.4.7",
"uuid": "^11.0.4",
"zod": "^3.23.8"
},
"devDependencies": {
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.9.1",
"@jest/globals": "^29.7.0",
"@tsconfig/recommended": "^1.0.7",
"@types/jest": "^29.5.0",
"@types/node": "^22.10.6",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-no-instanceof": "^1.0.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.7.0",
"prettier": "^3.3.3",
"ts-jest": "^29.1.0",
"tsx": "^4.19.2",
"typescript": "^5.3.3"
}
}
+24
View File
@@ -0,0 +1,24 @@
import { START, StateGraph } from "@langchain/langgraph";
import { AgentZodState } from "./types.js";
import { buildPrompt } from "./nodes/build-prompt.js";
import { initialReasoning } from "./nodes/initial-reasoning.js";
import { finalGeneration } from "./nodes/final-generation.js";
import { humanNode } from "./nodes/human-node.js";
import { graph as reflectionGraph } from "../reflection/index.js";
const workflow = new StateGraph(AgentZodState)
.addNode("build_prompt", buildPrompt)
.addNode("initial_reasoning", initialReasoning)
.addNode("final_generation", finalGeneration)
.addNode("human_node", humanNode)
.addNode("reflection", reflectionGraph)
.addEdge(START, "build_prompt")
.addEdge("build_prompt", "initial_reasoning")
.addEdge("initial_reasoning", "final_generation")
.addEdge("final_generation", "human_node")
.addEdge("human_node", "reflection")
.addEdge("reflection", "build_prompt");
// TODO: Remove as any once type error fixed
export const graph = workflow.compile() as any;
graph.name = "LLManager Graph";
+5
View File
@@ -0,0 +1,5 @@
import { AgentState, AgentUpdate } from "../types.js";
export async function buildPrompt(state: AgentState): Promise<AgentUpdate> {
throw new Error("Not implemented" + state);
}
+5
View File
@@ -0,0 +1,5 @@
import { AgentState, AgentUpdate } from "../types.js";
export async function finalGeneration(state: AgentState): Promise<AgentUpdate> {
throw new Error("Not implemented" + state);
}
+5
View File
@@ -0,0 +1,5 @@
import { AgentState, AgentUpdate } from "../types.js";
export async function humanNode(state: AgentState): Promise<AgentUpdate> {
throw new Error("Not implemented" + state);
}
+5
View File
@@ -0,0 +1,5 @@
import { AgentState, AgentUpdate } from "../types.js";
export async function initialReasoning(state: AgentState): Promise<AgentUpdate> {
throw new Error("Not implemented" + state);
}
+36
View File
@@ -0,0 +1,36 @@
import { BaseMessage } from "@langchain/core/messages";
import { addMessages } from "@langchain/langgraph";
import "@langchain/langgraph/zod";
import { z } from "zod";
export const AgentZodState = z.object({
/**
* The list of messages, containing the original input message
* from the user.
*/
messages: z
.custom<BaseMessage[]>()
.langgraph.reducer(
(a, b) => addMessages(a, b),
z.custom<BaseMessage | BaseMessage[]>()
),
/**
* The few shot examples to be used in the prompt.
* An array of few shots, with each item containing the example.
*/
fewShots: z.array(z.string()).default(() => []),
/**
* The reasoning generated based on the system prompt, few shots, and input messages.
*/
reasoning: z.string().default(() => ""),
/**
* The final answer, and explanation.
*/
answer: z.object({
answer: z.string(),
explanation: z.string()
}).default(() => ({ answer: "", explanation: "" }))
});
export type AgentState = z.infer<typeof AgentZodState>;
export type AgentUpdate = Partial<AgentState>;
+11
View File
@@ -0,0 +1,11 @@
import { START, StateGraph } from "@langchain/langgraph";
import { ReflectionZodState } from "./types.js";
import { reflect } from "./nodes/reflect.js";
const workflow = new StateGraph(ReflectionZodState)
.addNode("reflect", reflect)
.addEdge(START, "reflect")
// TODO: Remove as any once type error fixed
export const graph = workflow.compile() as any;
graph.name = "Reflection Graph";
+5
View File
@@ -0,0 +1,5 @@
import { ReflectionState, ReflectionUpdate } from "../types.js";
export async function reflect(state: ReflectionState): Promise<ReflectionUpdate> {
throw new Error("Not implemented" + state);
}
+31
View File
@@ -0,0 +1,31 @@
import { BaseMessage } from "@langchain/core/messages";
import { addMessages } from "@langchain/langgraph";
import "@langchain/langgraph/zod";
import { z } from "zod";
export const ReflectionZodState = z.object({
/**
* The list of messages, containing the original input message
* from the user.
*/
messages: z
.custom<BaseMessage[]>()
.langgraph.reducer(
(a, b) => addMessages(a, b),
z.custom<BaseMessage | BaseMessage[]>()
),
/**
* The reasoning generated based on the system prompt, few shots, and input messages.
*/
reasoning: z.string().default(() => ""),
/**
* The final answer, and explanation.
*/
answer: z.object({
answer: z.string(),
explanation: z.string()
}).default(() => ({ answer: "", explanation: "" }))
});
export type ReflectionState = z.infer<typeof ReflectionZodState>;
export type ReflectionUpdate = Partial<ReflectionState>;
+25
View 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"]
}
+6494
View File
File diff suppressed because it is too large Load Diff