mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-08 18:57:52 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8086a20865 | ||
|
|
fcfb9dd3a7 |
@@ -87,18 +87,3 @@ jobs:
|
|||||||
working-directory: libs/cli/js-examples
|
working-directory: libs/cli/js-examples
|
||||||
run: |
|
run: |
|
||||||
langgraph build -t langgraph-test-e
|
langgraph build -t langgraph-test-e
|
||||||
|
|
||||||
- name: Build JS monorepo service
|
|
||||||
if: steps.changed-files.outputs.all
|
|
||||||
working-directory: libs/cli/js-monorepo-example
|
|
||||||
run: |
|
|
||||||
langgraph build -t langgraph-test-f -c apps/agent/langgraph.json --build-command "yarn run turbo build" --install-command "yarn install"
|
|
||||||
|
|
||||||
- name: Build Python monorepo service
|
|
||||||
if: steps.changed-files.outputs.all
|
|
||||||
working-directory: libs/cli/python-monorepo-example
|
|
||||||
run: |
|
|
||||||
langgraph build -t langgraph-test-g -c apps/agent/langgraph.json
|
|
||||||
cp apps/agent/.env.example apps/agent/.env
|
|
||||||
if [ -n "${{ secrets.LANGSMITH_API_KEY }}" ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> apps/agent/.env; fi
|
|
||||||
timeout 60 python ../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-g -c apps/agent/langgraph.json
|
|
||||||
|
|||||||
@@ -29,10 +29,6 @@
|
|||||||
"name": "Store",
|
"name": "Store",
|
||||||
"description": "Store is an API for managing persistent key-value store (long-term memory) that is available from any thread."
|
"description": "Store is an API for managing persistent key-value store (long-term memory) that is available from any thread."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "A2A",
|
|
||||||
"description": "Agent-to-Agent Protocol related endpoints for exposing assistants as A2A-compliant agents."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "MCP",
|
"name": "MCP",
|
||||||
"description": "Model Context Protocol related endpoints for exposing an agent as an MCP server."
|
"description": "Model Context Protocol related endpoints for exposing an agent as an MCP server."
|
||||||
@@ -1554,29 +1550,6 @@
|
|||||||
},
|
},
|
||||||
"name": "Last-Event-ID",
|
"name": "Last-Event-ID",
|
||||||
"in": "header"
|
"in": "header"
|
||||||
},
|
|
||||||
{
|
|
||||||
"required": false,
|
|
||||||
"schema": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["lifecycle", "run_modes", "state_update"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["lifecycle", "run_modes", "state_update"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default": ["run_modes"],
|
|
||||||
"title": "Stream Modes",
|
|
||||||
"description": "Stream modes to control which events are returned. 'lifecycle' returns only run start/end events, 'run_modes' returns all run events (default behavior), 'state_update' returns only state update events."
|
|
||||||
},
|
|
||||||
"name": "stream_modes",
|
|
||||||
"in": "query"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -3186,195 +3159,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/a2a/{assistant_id}": {
|
|
||||||
"post": {
|
|
||||||
"operationId": "post_a2a",
|
|
||||||
"summary": "A2A Post",
|
|
||||||
"description": "Communicate with an assistant using the Agent-to-Agent Protocol.\nSends a JSON-RPC 2.0 message to the assistant.\n\n- **Request**: Provide an object with `jsonrpc`, `id`, `method`, and optional `params`.\n- **Response**: Returns a JSON-RPC response with task information or error.\n\n**Supported Methods:**\n- `message/send`: Send a message to the assistant\n- `tasks/get`: Get the status and result of a task\n\n**Notes:**\n- Supports threaded conversations via thread context\n- Messages can contain text and data parts\n- Tasks run asynchronously and return completion status\n",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "assistant_id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uuid"
|
|
||||||
},
|
|
||||||
"description": "The ID of the assistant to communicate with"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Accept",
|
|
||||||
"in": "header",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["application/json"]
|
|
||||||
},
|
|
||||||
"description": "Must be application/json"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"required": true,
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"jsonrpc": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["2.0"],
|
|
||||||
"description": "JSON-RPC version"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Request identifier"
|
|
||||||
},
|
|
||||||
"method": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["message/send", "tasks/get"],
|
|
||||||
"description": "The method to invoke"
|
|
||||||
},
|
|
||||||
"params": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Method parameters",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"title": "Message Send Parameters",
|
|
||||||
"properties": {
|
|
||||||
"message": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"role": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["user", "assistant"],
|
|
||||||
"description": "Message role"
|
|
||||||
},
|
|
||||||
"parts": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"title": "Text Part",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"kind": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["text"]
|
|
||||||
},
|
|
||||||
"text": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["kind", "text"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Data Part",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"kind": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["data"]
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"type": "object"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["kind", "data"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"description": "Message parts"
|
|
||||||
},
|
|
||||||
"messageId": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Unique message identifier"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["role", "parts", "messageId"]
|
|
||||||
},
|
|
||||||
"thread": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"threadId": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Thread identifier for conversation context"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": "Optional thread context"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["message"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Task Get Parameters",
|
|
||||||
"properties": {
|
|
||||||
"taskId": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Task identifier to retrieve"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["taskId"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["jsonrpc", "id", "method"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "JSON-RPC response",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"jsonrpc": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["2.0"]
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Success result containing task information or task details"
|
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"code": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": "Error information if request failed"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["jsonrpc", "id"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad request - invalid JSON-RPC or missing Accept header"
|
|
||||||
},
|
|
||||||
"404": {
|
|
||||||
"description": "Assistant not found"
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal server error"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": [
|
|
||||||
"A2A"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/mcp/": {
|
"/mcp/": {
|
||||||
"post": {
|
"post": {
|
||||||
"operationId": "post_mcp",
|
"operationId": "post_mcp",
|
||||||
@@ -4629,17 +4413,6 @@
|
|||||||
"title": "Checkpoint During",
|
"title": "Checkpoint During",
|
||||||
"description": "Whether to checkpoint during the run.",
|
"description": "Whether to checkpoint during the run.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
|
||||||
"durability": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"sync",
|
|
||||||
"async",
|
|
||||||
"exit"
|
|
||||||
],
|
|
||||||
"title": "Durability",
|
|
||||||
"description": "Durability level for the run. Must be one of 'sync', 'async', or 'exit'.",
|
|
||||||
"default": "async"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -4876,17 +4649,6 @@
|
|||||||
"title": "Checkpoint During",
|
"title": "Checkpoint During",
|
||||||
"description": "Whether to checkpoint during the run.",
|
"description": "Whether to checkpoint during the run.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
|
||||||
"durability": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"sync",
|
|
||||||
"async",
|
|
||||||
"exit"
|
|
||||||
],
|
|
||||||
"title": "Durability",
|
|
||||||
"description": "Durability level for the run. Must be one of 'sync', 'async', or 'exit'.",
|
|
||||||
"default": "async"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -5015,12 +4777,6 @@
|
|||||||
},
|
},
|
||||||
"ThreadSearchRequest": {
|
"ThreadSearchRequest": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"ids": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {"type": "string", "format": "uuid"},
|
|
||||||
"title": "Ids",
|
|
||||||
"description": "List of thread IDs to include. Others are excluded."
|
|
||||||
},
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "Metadata",
|
"title": "Metadata",
|
||||||
@@ -5261,30 +5017,11 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "Metadata",
|
"title": "Metadata",
|
||||||
"description": "Metadata to merge with existing thread metadata."
|
"description": "Metadata to merge with existing thread metadata."
|
||||||
},
|
|
||||||
"ttl": {
|
|
||||||
"type": "object",
|
|
||||||
"title": "TTL",
|
|
||||||
"description": "The time-to-live for the thread.",
|
|
||||||
"properties": {
|
|
||||||
"strategy": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"delete"
|
|
||||||
],
|
|
||||||
"description": "The TTL strategy. 'delete' removes the entire thread.",
|
|
||||||
"default": "delete"
|
|
||||||
},
|
|
||||||
"ttl": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "The time-to-live in minutes from now until thread should be swept."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "ThreadPatch",
|
"title": "ThreadPatch",
|
||||||
"description": "Payload for updating a thread."
|
"description": "Payload for creating a thread."
|
||||||
},
|
},
|
||||||
"ThreadStateCheckpointRequest": {
|
"ThreadStateCheckpointRequest": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -483,19 +483,19 @@ The LangGraph CLI requires a JSON configuration file that follows this [schema](
|
|||||||
|
|
||||||
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir -c /api/constraints.txt langchain_community langchain_anthropic langchain_openai wikipedia scikit-learn
|
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir -c /api/constraints.txt langchain_community langchain_anthropic langchain_openai wikipedia scikit-learn
|
||||||
|
|
||||||
ADD ./graphs /deps/outer-graphs/src
|
ADD ./graphs /deps/__outer_graphs/src
|
||||||
RUN set -ex && \
|
RUN set -ex && \
|
||||||
for line in '[project]' \
|
for line in '[project]' \
|
||||||
'name = "graphs"' \
|
'name = "graphs"' \
|
||||||
'version = "0.1"' \
|
'version = "0.1"' \
|
||||||
'[tool.setuptools.package-data]' \
|
'[tool.setuptools.package-data]' \
|
||||||
'"*" = ["**/*"]'; do \
|
'"*" = ["**/*"]'; do \
|
||||||
echo "$line" >> /deps/outer-graphs/pyproject.toml; \
|
echo "$line" >> /deps/__outer_graphs/pyproject.toml; \
|
||||||
done
|
done
|
||||||
|
|
||||||
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
|
|
||||||
ENV LANGSERVE_GRAPHS='{"agent": "/deps/outer-graphs/src/agent.py:graph", "storm": "/deps/outer-graphs/src/storm.py:graph"}'
|
ENV LANGSERVE_GRAPHS='{"agent": "/deps/__outer_graphs/src/agent.py:graph", "storm": "/deps/__outer_graphs/src/storm.py:graph"}'
|
||||||
```
|
```
|
||||||
|
|
||||||
???+ note "Updating your langgraph.json file"
|
???+ note "Updating your langgraph.json file"
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
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: {
|
|
||||||
"no-process-env": 2,
|
|
||||||
"no-instanceof/no-instanceof": 2,
|
|
||||||
"@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": ["warn", { args: "none" }],
|
|
||||||
"@typescript-eslint/no-floating-promises": "error",
|
|
||||||
"@typescript-eslint/no-misused-promises": "error",
|
|
||||||
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 }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"node_version": "20",
|
|
||||||
"graphs": {
|
|
||||||
"agent": "./src/graph.ts:graph"
|
|
||||||
},
|
|
||||||
"env": "../../.env"
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@js-monorepo-example/agent",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"type": "module",
|
|
||||||
"main": "src/graph.ts",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"clean": "rm -rf dist"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@js-monorepo-example/shared": "*",
|
|
||||||
"@langchain/core": "^0.3.2",
|
|
||||||
"@langchain/langgraph": "^0.2.5"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^5.3.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* Simple LangGraph.js example for monorepo testing
|
|
||||||
*/
|
|
||||||
import { StateGraph } from "@langchain/langgraph";
|
|
||||||
import { RunnableConfig } from "@langchain/core/runnables";
|
|
||||||
import { StateAnnotation } from "./state.js";
|
|
||||||
import { getGreeting } from "@js-monorepo-example/shared";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple node that uses the shared library
|
|
||||||
*/
|
|
||||||
const callModel = async (
|
|
||||||
state: typeof StateAnnotation.State,
|
|
||||||
_config: RunnableConfig,
|
|
||||||
): Promise<typeof StateAnnotation.Update> => {
|
|
||||||
// Use functions from the shared library
|
|
||||||
const greeting = getGreeting();
|
|
||||||
|
|
||||||
return {
|
|
||||||
messages: [
|
|
||||||
{
|
|
||||||
role: "assistant",
|
|
||||||
content: `${greeting}`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple routing function
|
|
||||||
*/
|
|
||||||
export const route = (
|
|
||||||
state: typeof StateAnnotation.State,
|
|
||||||
): "__end__" | "callModel" => {
|
|
||||||
if (state.messages.length > 0) {
|
|
||||||
return "__end__";
|
|
||||||
}
|
|
||||||
return "callModel";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the graph
|
|
||||||
const builder = new StateGraph(StateAnnotation)
|
|
||||||
.addNode("callModel", callModel)
|
|
||||||
.addEdge("__start__", "callModel")
|
|
||||||
.addConditionalEdges("callModel", route);
|
|
||||||
|
|
||||||
export const graph = builder.compile();
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { BaseMessage, BaseMessageLike } from "@langchain/core/messages";
|
|
||||||
import { Annotation, messagesStateReducer } from "@langchain/langgraph";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple state annotation for the agent
|
|
||||||
*/
|
|
||||||
export const StateAnnotation = Annotation.Root({
|
|
||||||
/**
|
|
||||||
* Messages track the primary execution state of the agent.
|
|
||||||
*/
|
|
||||||
messages: Annotation<BaseMessage[], BaseMessageLike[]>({
|
|
||||||
reducer: messagesStateReducer,
|
|
||||||
default: () => [],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./dist",
|
|
||||||
"rootDir": "./src"
|
|
||||||
},
|
|
||||||
"include": ["src/**/*"],
|
|
||||||
"exclude": ["node_modules", "dist"]
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@js-monorepo-example/shared",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"type": "module",
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"types": "dist/index.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"clean": "rm -rf dist"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^5.3.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/**
|
|
||||||
* Simple utility functions for monorepo testing
|
|
||||||
*/
|
|
||||||
export function getGreeting(): string {
|
|
||||||
return "Hello from shared library!";
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./dist",
|
|
||||||
"rootDir": "./src"
|
|
||||||
},
|
|
||||||
"include": ["src/**/*"],
|
|
||||||
"exclude": ["node_modules", "dist"]
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "js-monorepo-example",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"packageManager": "yarn@1.22.22",
|
|
||||||
"description": "A simple monorepo example for LangGraph integration testing.",
|
|
||||||
"private": true,
|
|
||||||
"workspaces": [
|
|
||||||
"libs/*",
|
|
||||||
"apps/*"
|
|
||||||
],
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "turbo build",
|
|
||||||
"clean": "turbo clean",
|
|
||||||
"test": "turbo test",
|
|
||||||
"format": "prettier --write .",
|
|
||||||
"lint": "eslint 'apps/**/*.ts' 'libs/**/*.ts'"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"turbo": "^2.5.0",
|
|
||||||
"typescript": "^5.3.3",
|
|
||||||
"@tsconfig/recommended": "^1.0.7",
|
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
|
||||||
"@eslint/js": "^9.9.1",
|
|
||||||
"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",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
|
||||||
"@typescript-eslint/parser": "^5.59.8",
|
|
||||||
"prettier": "^3.3.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@tsconfig/recommended",
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2022",
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"strict": true,
|
|
||||||
"declaration": true,
|
|
||||||
"outDir": "./dist"
|
|
||||||
},
|
|
||||||
"include": ["apps/**/*", "libs/**/*"],
|
|
||||||
"exclude": ["node_modules", "dist"]
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://turbo.build/schema.json",
|
|
||||||
"tasks": {
|
|
||||||
"build": {
|
|
||||||
"dependsOn": ["^build"],
|
|
||||||
"outputs": ["dist/**"]
|
|
||||||
},
|
|
||||||
"clean": {
|
|
||||||
"dependsOn": ["^clean"]
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"dependsOn": ["^test"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
|||||||
__version__ = "0.4.1"
|
__version__ = "0.4.0"
|
||||||
|
|||||||
@@ -303,8 +303,6 @@ def _build(
|
|||||||
pull: bool,
|
pull: bool,
|
||||||
tag: str,
|
tag: str,
|
||||||
passthrough: Sequence[str] = (),
|
passthrough: Sequence[str] = (),
|
||||||
install_command: Optional[str] = None,
|
|
||||||
build_command: Optional[str] = None,
|
|
||||||
):
|
):
|
||||||
# pull latest images
|
# pull latest images
|
||||||
if pull:
|
if pull:
|
||||||
@@ -324,38 +322,22 @@ def _build(
|
|||||||
"-t",
|
"-t",
|
||||||
tag,
|
tag,
|
||||||
]
|
]
|
||||||
# determine build context: use current directory for JS projects, config parent for Python
|
|
||||||
is_js_project = config_json.get("node_version") and not config_json.get(
|
|
||||||
"python_version"
|
|
||||||
)
|
|
||||||
# build/install commands only apply to JS projects for now
|
|
||||||
# without install/build command, JS projects will follow the old behavior
|
|
||||||
if is_js_project and (build_command or install_command):
|
|
||||||
build_context = str(pathlib.Path.cwd())
|
|
||||||
else:
|
|
||||||
build_context = str(config.parent)
|
|
||||||
|
|
||||||
# apply config
|
# apply config
|
||||||
stdin, additional_contexts = langgraph_cli.config.config_to_docker(
|
stdin, additional_contexts = langgraph_cli.config.config_to_docker(
|
||||||
config,
|
config, config_json, base_image, api_version
|
||||||
config_json,
|
|
||||||
base_image,
|
|
||||||
api_version,
|
|
||||||
install_command,
|
|
||||||
build_command,
|
|
||||||
build_context,
|
|
||||||
)
|
)
|
||||||
# add additional_contexts
|
# add additional_contexts
|
||||||
if additional_contexts:
|
if additional_contexts:
|
||||||
for k, v in additional_contexts.items():
|
for k, v in additional_contexts.items():
|
||||||
args.extend(["--build-context", f"{k}={v}"])
|
args.extend(["--build-context", f"{k}={v}"])
|
||||||
|
# run docker build
|
||||||
runner.run(
|
runner.run(
|
||||||
subp_exec(
|
subp_exec(
|
||||||
"docker",
|
"docker",
|
||||||
"build",
|
"build",
|
||||||
*args,
|
*args,
|
||||||
*passthrough,
|
*passthrough,
|
||||||
build_context,
|
str(config.parent),
|
||||||
input=stdin,
|
input=stdin,
|
||||||
verbose=True,
|
verbose=True,
|
||||||
)
|
)
|
||||||
@@ -384,14 +366,6 @@ def _build(
|
|||||||
"\n --base-image langchain/langgraph-server:0.2 # Pin to a minor version (Python)",
|
"\n --base-image langchain/langgraph-server:0.2 # Pin to a minor version (Python)",
|
||||||
)
|
)
|
||||||
@OPT_API_VERSION
|
@OPT_API_VERSION
|
||||||
@click.option(
|
|
||||||
"--install-command",
|
|
||||||
help="Custom install command to run from the build context root. If not provided, auto-detects based on package manager files.",
|
|
||||||
)
|
|
||||||
@click.option(
|
|
||||||
"--build-command",
|
|
||||||
help="Custom build command to run from the langgraph.json directory. If not provided, uses default build process.",
|
|
||||||
)
|
|
||||||
@click.argument("docker_build_args", nargs=-1, type=click.UNPROCESSED)
|
@click.argument("docker_build_args", nargs=-1, type=click.UNPROCESSED)
|
||||||
@cli.command(
|
@cli.command(
|
||||||
help="📦 Build LangGraph API server Docker image.",
|
help="📦 Build LangGraph API server Docker image.",
|
||||||
@@ -407,8 +381,6 @@ def build(
|
|||||||
api_version: Optional[str],
|
api_version: Optional[str],
|
||||||
pull: bool,
|
pull: bool,
|
||||||
tag: str,
|
tag: str,
|
||||||
install_command: Optional[str],
|
|
||||||
build_command: Optional[str],
|
|
||||||
):
|
):
|
||||||
with Runner() as runner, Progress(message="Pulling...") as set:
|
with Runner() as runner, Progress(message="Pulling...") as set:
|
||||||
if shutil.which("docker") is None:
|
if shutil.which("docker") is None:
|
||||||
@@ -425,8 +397,6 @@ def build(
|
|||||||
pull,
|
pull,
|
||||||
tag,
|
tag,
|
||||||
docker_build_args,
|
docker_build_args,
|
||||||
install_command,
|
|
||||||
build_command,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -913,10 +913,10 @@ def _assemble_local_deps(config_path: pathlib.Path, config: Config) -> LocalDeps
|
|||||||
"Rename the directory to use it as flat-layout package."
|
"Rename the directory to use it as flat-layout package."
|
||||||
)
|
)
|
||||||
check_reserved(resolved.name, local_dep)
|
check_reserved(resolved.name, local_dep)
|
||||||
container_path = f"/deps/outer-{resolved.name}/{resolved.name}"
|
container_path = f"/deps/__outer_{resolved.name}/{resolved.name}"
|
||||||
else:
|
else:
|
||||||
# src layout
|
# src layout
|
||||||
container_path = f"/deps/outer-{resolved.name}/src"
|
container_path = f"/deps/__outer_{resolved.name}/src"
|
||||||
for file in files:
|
for file in files:
|
||||||
rfile = resolved / file
|
rfile = resolved / file
|
||||||
if (
|
if (
|
||||||
@@ -1286,7 +1286,7 @@ def python_config_to_docker(
|
|||||||
if local_deps.pip_reqs:
|
if local_deps.pip_reqs:
|
||||||
pip_reqs_str = os.linesep.join(
|
pip_reqs_str = os.linesep.join(
|
||||||
(
|
(
|
||||||
f"COPY --from=outer-{reqpath.name} requirements.txt {destpath}"
|
f"COPY --from=__outer_{reqpath.name} requirements.txt {destpath}"
|
||||||
if reqpath.parent in local_deps.additional_contexts
|
if reqpath.parent in local_deps.additional_contexts
|
||||||
else f"ADD {reqpath.relative_to(config_path.parent)} {destpath}"
|
else f"ADD {reqpath.relative_to(config_path.parent)} {destpath}"
|
||||||
)
|
)
|
||||||
@@ -1305,7 +1305,7 @@ def python_config_to_docker(
|
|||||||
faux_pkgs_str = f"{os.linesep}{os.linesep}".join(
|
faux_pkgs_str = f"{os.linesep}{os.linesep}".join(
|
||||||
(
|
(
|
||||||
f"""# -- Adding non-package dependency {fullpath.name} --
|
f"""# -- Adding non-package dependency {fullpath.name} --
|
||||||
COPY --from=outer-{fullpath.name} . {destpath}"""
|
COPY --from=__outer_{fullpath.name} . {destpath}"""
|
||||||
if fullpath in local_deps.additional_contexts
|
if fullpath in local_deps.additional_contexts
|
||||||
else f"""# -- Adding non-package dependency {fullpath.name} --
|
else f"""# -- Adding non-package dependency {fullpath.name} --
|
||||||
ADD {relpath} {destpath}"""
|
ADD {relpath} {destpath}"""
|
||||||
@@ -1320,7 +1320,7 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-{fullpath.name}/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_{fullpath.name}/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency {fullpath.name} --"""
|
# -- End of non-package dependency {fullpath.name} --"""
|
||||||
for fullpath, (relpath, destpath) in local_deps.faux_pkgs.items()
|
for fullpath, (relpath, destpath) in local_deps.faux_pkgs.items()
|
||||||
@@ -1423,7 +1423,7 @@ ADD {relpath} /deps/{name}
|
|||||||
if p in local_deps.real_pkgs:
|
if p in local_deps.real_pkgs:
|
||||||
name = local_deps.real_pkgs[p][1]
|
name = local_deps.real_pkgs[p][1]
|
||||||
elif p in local_deps.faux_pkgs:
|
elif p in local_deps.faux_pkgs:
|
||||||
name = f"outer-{p.name}"
|
name = f"__outer_{p.name}"
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"Unknown additional context: {p}")
|
raise RuntimeError(f"Unknown additional context: {p}")
|
||||||
additional_contexts[name] = str(p)
|
additional_contexts[name] = str(p)
|
||||||
@@ -1436,28 +1436,9 @@ def node_config_to_docker(
|
|||||||
config: Config,
|
config: Config,
|
||||||
base_image: str,
|
base_image: str,
|
||||||
api_version: Optional[str] = None,
|
api_version: Optional[str] = None,
|
||||||
install_command: Optional[str] = None,
|
|
||||||
build_command: Optional[str] = None,
|
|
||||||
build_context: Optional[str] = None,
|
|
||||||
) -> tuple[str, dict[str, str]]:
|
) -> tuple[str, dict[str, str]]:
|
||||||
# Calculate paths for monorepo support
|
|
||||||
if build_context:
|
|
||||||
relative_workdir = _calculate_relative_workdir(config_path, build_context)
|
|
||||||
container_name = pathlib.Path(build_context).name
|
|
||||||
if relative_workdir:
|
|
||||||
faux_path = f"/deps/{container_name}/{relative_workdir}"
|
|
||||||
else:
|
|
||||||
faux_path = f"/deps/{container_name}"
|
|
||||||
else:
|
|
||||||
# Backward compatibility: use the original behavior
|
|
||||||
faux_path = f"/deps/{config_path.parent.name}"
|
faux_path = f"/deps/{config_path.parent.name}"
|
||||||
|
|
||||||
# Use custom install command or auto-detect
|
|
||||||
if install_command:
|
|
||||||
install_cmd = install_command
|
|
||||||
else:
|
|
||||||
install_cmd = _get_node_pm_install_cmd(config_path, config)
|
install_cmd = _get_node_pm_install_cmd(config_path, config)
|
||||||
|
|
||||||
image_str = docker_tag(config, base_image, api_version)
|
image_str = docker_tag(config, base_image, api_version)
|
||||||
|
|
||||||
env_vars: list[str] = []
|
env_vars: list[str] = []
|
||||||
@@ -1484,35 +1465,20 @@ def node_config_to_docker(
|
|||||||
|
|
||||||
env_vars.append(f"ENV LANGSERVE_GRAPHS='{json.dumps(config['graphs'])}'")
|
env_vars.append(f"ENV LANGSERVE_GRAPHS='{json.dumps(config['graphs'])}'")
|
||||||
|
|
||||||
# For monorepo support, we need to handle install and build commands differently
|
|
||||||
if build_context:
|
|
||||||
# Monorepo case: install from root, build from config directory
|
|
||||||
container_root = f"/deps/{pathlib.Path(build_context).name}"
|
|
||||||
install_step = f"RUN cd {container_root} && {install_cmd}"
|
|
||||||
|
|
||||||
if build_command:
|
|
||||||
build_step = f"RUN cd {faux_path} && {build_command}"
|
|
||||||
else:
|
|
||||||
build_step = 'RUN (test ! -f /api/langgraph_api/js/build.mts && echo "Prebuild script not found, skipping") || tsx /api/langgraph_api/js/build.mts'
|
|
||||||
else:
|
|
||||||
# Original behavior: everything happens in the same directory
|
|
||||||
install_step = f"RUN cd {faux_path} && {install_cmd}"
|
|
||||||
build_step = 'RUN (test ! -f /api/langgraph_api/js/build.mts && echo "Prebuild script not found, skipping") || tsx /api/langgraph_api/js/build.mts'
|
|
||||||
|
|
||||||
docker_file_contents = [
|
docker_file_contents = [
|
||||||
f"FROM {image_str}",
|
f"FROM {image_str}",
|
||||||
"",
|
"",
|
||||||
os.linesep.join(config["dockerfile_lines"]),
|
os.linesep.join(config["dockerfile_lines"]),
|
||||||
"",
|
"",
|
||||||
f"ADD . {faux_path if not build_context else container_root}",
|
f"ADD . {faux_path}",
|
||||||
"",
|
"",
|
||||||
install_step,
|
f"RUN cd {faux_path} && {install_cmd}",
|
||||||
"",
|
"",
|
||||||
os.linesep.join(env_vars),
|
os.linesep.join(env_vars),
|
||||||
"",
|
"",
|
||||||
f"WORKDIR {faux_path}",
|
f"WORKDIR {faux_path}",
|
||||||
"",
|
"",
|
||||||
build_step,
|
'RUN (test ! -f /api/langgraph_api/js/build.mts && echo "Prebuild script not found, skipping") || tsx /api/langgraph_api/js/build.mts',
|
||||||
]
|
]
|
||||||
|
|
||||||
return os.linesep.join(docker_file_contents), {}
|
return os.linesep.join(docker_file_contents), {}
|
||||||
@@ -1560,42 +1526,16 @@ def docker_tag(
|
|||||||
return f"{base_image}:{full_tag}"
|
return f"{base_image}:{full_tag}"
|
||||||
|
|
||||||
|
|
||||||
def _calculate_relative_workdir(config_path: pathlib.Path, build_context: str) -> str:
|
|
||||||
"""Calculate the relative path from build context to langgraph.json directory."""
|
|
||||||
config_dir = config_path.parent.resolve()
|
|
||||||
build_context_path = pathlib.Path(build_context).resolve()
|
|
||||||
|
|
||||||
try:
|
|
||||||
relative_path = config_dir.relative_to(build_context_path)
|
|
||||||
return str(relative_path) if str(relative_path) != "." else ""
|
|
||||||
except ValueError as _:
|
|
||||||
raise ValueError(
|
|
||||||
f"Configuration file {config_path} is not under the build context {build_context}. "
|
|
||||||
f"Please run the command from a directory that contains your langgraph.json file, "
|
|
||||||
) from None
|
|
||||||
|
|
||||||
|
|
||||||
def config_to_docker(
|
def config_to_docker(
|
||||||
config_path: pathlib.Path,
|
config_path: pathlib.Path,
|
||||||
config: Config,
|
config: Config,
|
||||||
base_image: Optional[str] = None,
|
base_image: Optional[str] = None,
|
||||||
api_version: Optional[str] = None,
|
api_version: Optional[str] = None,
|
||||||
install_command: Optional[str] = None,
|
|
||||||
build_command: Optional[str] = None,
|
|
||||||
build_context: Optional[str] = None,
|
|
||||||
) -> tuple[str, dict[str, str]]:
|
) -> tuple[str, dict[str, str]]:
|
||||||
base_image = base_image or default_base_image(config)
|
base_image = base_image or default_base_image(config)
|
||||||
|
|
||||||
if config.get("node_version") and not config.get("python_version"):
|
if config.get("node_version") and not config.get("python_version"):
|
||||||
return node_config_to_docker(
|
return node_config_to_docker(config_path, config, base_image, api_version)
|
||||||
config_path,
|
|
||||||
config,
|
|
||||||
base_image,
|
|
||||||
api_version,
|
|
||||||
install_command,
|
|
||||||
build_command,
|
|
||||||
build_context,
|
|
||||||
)
|
|
||||||
|
|
||||||
return python_config_to_docker(config_path, config, base_image, api_version)
|
return python_config_to_docker(config_path, config, base_image, api_version)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": [".", "../../libs/shared", "../../libs/common"],
|
|
||||||
"graphs": {
|
|
||||||
"agent": "./src/agent/graph.py:graph"
|
|
||||||
},
|
|
||||||
"env": ".env"
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[project]
|
|
||||||
name = "agent"
|
|
||||||
version = "0.0.1"
|
|
||||||
description = "Agent for the Python monorepo"
|
|
||||||
authors = [
|
|
||||||
{ name = "Developer", email = "dev@example.com" },
|
|
||||||
]
|
|
||||||
license = { text = "MIT" }
|
|
||||||
requires-python = ">=3.11,<4.0"
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools>=73.0.0", "wheel"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
|
|
||||||
[tool.setuptools]
|
|
||||||
packages = ["agent"]
|
|
||||||
|
|
||||||
[tool.setuptools.package-dir]
|
|
||||||
"agent" = "src/agent"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
"""Agent package."""
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
"""Simple LangGraph agent for monorepo testing."""
|
|
||||||
|
|
||||||
from common import get_common_prefix
|
|
||||||
from langchain_core.messages import AIMessage
|
|
||||||
from langgraph.graph import END, START, StateGraph
|
|
||||||
from shared import get_dummy_message
|
|
||||||
|
|
||||||
from agent.state import State
|
|
||||||
|
|
||||||
|
|
||||||
def call_model(state: State) -> dict:
|
|
||||||
"""Simple node that uses the shared libraries."""
|
|
||||||
# Use functions from both shared packages
|
|
||||||
dummy_message = get_dummy_message()
|
|
||||||
prefix = get_common_prefix()
|
|
||||||
|
|
||||||
message = AIMessage(content=f"{prefix} Agent says: {dummy_message}")
|
|
||||||
|
|
||||||
return {"messages": [message]}
|
|
||||||
|
|
||||||
|
|
||||||
def should_continue(state: State):
|
|
||||||
"""Conditional edge - end after first message."""
|
|
||||||
messages = state["messages"]
|
|
||||||
if len(messages) > 0:
|
|
||||||
return END
|
|
||||||
return "call_model"
|
|
||||||
|
|
||||||
|
|
||||||
# Build the graph
|
|
||||||
workflow = StateGraph(State)
|
|
||||||
|
|
||||||
# Add the node
|
|
||||||
workflow.add_node("call_model", call_model)
|
|
||||||
|
|
||||||
# Add edges
|
|
||||||
workflow.add_edge(START, "call_model")
|
|
||||||
workflow.add_conditional_edges("call_model", should_continue)
|
|
||||||
|
|
||||||
graph = workflow.compile()
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
"""State definition for the agent."""
|
|
||||||
|
|
||||||
from collections.abc import Sequence
|
|
||||||
from typing import Annotated, TypedDict
|
|
||||||
|
|
||||||
from langchain_core.messages import BaseMessage
|
|
||||||
from langgraph.graph.message import add_messages
|
|
||||||
|
|
||||||
|
|
||||||
class State(TypedDict):
|
|
||||||
"""The state of the agent."""
|
|
||||||
|
|
||||||
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
"""Common helper functions package."""
|
|
||||||
|
|
||||||
from .helpers import get_common_prefix
|
|
||||||
|
|
||||||
__all__ = ["get_common_prefix"]
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
"""Common helper functions."""
|
|
||||||
|
|
||||||
|
|
||||||
def get_common_prefix() -> str:
|
|
||||||
"""Get a common prefix for messages."""
|
|
||||||
return "[COMMON]"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
[project]
|
|
||||||
name = "shared"
|
|
||||||
version = "0.0.1"
|
|
||||||
description = "Shared utilities for the Python monorepo"
|
|
||||||
authors = [
|
|
||||||
{ name = "Developer", email = "dev@example.com" },
|
|
||||||
]
|
|
||||||
license = { text = "MIT" }
|
|
||||||
requires-python = ">=3.11,<4.0"
|
|
||||||
dependencies = []
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools>=73.0.0", "wheel"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
|
|
||||||
[tool.setuptools]
|
|
||||||
packages = ["shared"]
|
|
||||||
|
|
||||||
[tool.setuptools.package-dir]
|
|
||||||
"shared" = "src/shared"
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
"""Shared utilities package."""
|
|
||||||
|
|
||||||
from .utils import get_dummy_message
|
|
||||||
|
|
||||||
__all__ = ["get_dummy_message"]
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
"""Shared utility functions."""
|
|
||||||
|
|
||||||
|
|
||||||
def get_dummy_message() -> str:
|
|
||||||
"""Get a dummy message for testing."""
|
|
||||||
return "Hello from shared library!"
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
[project]
|
|
||||||
name = "python-monorepo-example"
|
|
||||||
version = "0.0.1"
|
|
||||||
description = "A Python monorepo example with LangGraph agents and shared packages"
|
|
||||||
authors = [
|
|
||||||
{ name = "Developer", email = "dev@example.com" },
|
|
||||||
]
|
|
||||||
license = { text = "MIT" }
|
|
||||||
requires-python = ">=3.11,<4.0"
|
|
||||||
dependencies = [
|
|
||||||
"langgraph>=0.6.0,<0.7.0",
|
|
||||||
"langchain-core>=0.2.14",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.uv.workspace]
|
|
||||||
members = ["apps/*", "libs/shared"]
|
|
||||||
|
|
||||||
[tool.uv.sources]
|
|
||||||
shared = { workspace = true }
|
|
||||||
|
|
||||||
[project.optional-dependencies]
|
|
||||||
dev = ["mypy>=1.11.1", "ruff>=0.6.1"]
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools>=73.0.0", "wheel"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
|
|
||||||
[tool.ruff]
|
|
||||||
lint.select = [
|
|
||||||
"E", # pycodestyle
|
|
||||||
"F", # pyflakes
|
|
||||||
"I", # isort
|
|
||||||
"D", # pydocstyle
|
|
||||||
"UP",
|
|
||||||
]
|
|
||||||
lint.ignore = [
|
|
||||||
"D100", # Missing docstring in public module
|
|
||||||
"D101", # Missing docstring in public class
|
|
||||||
"D102", # Missing docstring in public method
|
|
||||||
"D103", # Missing docstring in public function
|
|
||||||
"D104", # Missing docstring in public package
|
|
||||||
"D105", # Missing docstring in magic method
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.ruff.lint.pydocstyle]
|
|
||||||
convention = "google"
|
|
||||||
@@ -570,7 +570,7 @@ def test_build_generate_proper_build_context():
|
|||||||
catch_exceptions=True,
|
catch_exceptions=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
build_context_pattern = re.compile(r"--build-context\s+([\w-]+)=([^\s]+)")
|
build_context_pattern = re.compile(r"--build-context\s+(\w+)=([^\s]+)")
|
||||||
|
|
||||||
build_contexts = re.findall(build_context_pattern, result.output)
|
build_contexts = re.findall(build_context_pattern, result.output)
|
||||||
assert len(build_contexts) == 2, (
|
assert len(build_contexts) == 2, (
|
||||||
|
|||||||
@@ -421,14 +421,14 @@ def test_config_to_docker_simple():
|
|||||||
expected_docker_stdin = f"""\
|
expected_docker_stdin = f"""\
|
||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
# -- Installing local requirements --
|
# -- Installing local requirements --
|
||||||
COPY --from=outer-requirements.txt requirements.txt /deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt
|
COPY --from=__outer_requirements.txt requirements.txt /deps/__outer_graphs_reqs_a/graphs_reqs_a/requirements.txt
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r /deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r /deps/__outer_graphs_reqs_a/graphs_reqs_a/requirements.txt
|
||||||
# -- End of local requirements install --
|
# -- End of local requirements install --
|
||||||
# -- Adding local package ../../examples --
|
# -- Adding local package ../../examples --
|
||||||
COPY --from=examples . /deps/examples
|
COPY --from=examples . /deps/examples
|
||||||
# -- End of local package ../../examples --
|
# -- End of local package ../../examples --
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -438,11 +438,11 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Adding non-package dependency graphs_reqs_a --
|
# -- Adding non-package dependency graphs_reqs_a --
|
||||||
COPY --from=outer-graphs_reqs_a . /deps/outer-graphs_reqs_a/graphs_reqs_a
|
COPY --from=__outer_graphs_reqs_a . /deps/__outer_graphs_reqs_a/graphs_reqs_a
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "graphs_reqs_a"' \\
|
'name = "graphs_reqs_a"' \\
|
||||||
@@ -452,21 +452,21 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-graphs_reqs_a/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_graphs_reqs_a/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency graphs_reqs_a --
|
# -- End of non-package dependency graphs_reqs_a --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGGRAPH_HTTP='{{"app": "/deps/examples/my_app.py:app"}}'
|
ENV LANGGRAPH_HTTP='{{"app": "/deps/examples/my_app.py:app"}}'
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
{FORMATTED_CLEANUP_LINES}
|
{FORMATTED_CLEANUP_LINES}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests\
|
WORKDIR /deps/__outer_unit_tests/unit_tests\
|
||||||
"""
|
"""
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
|
|
||||||
assert additional_contexts == {
|
assert additional_contexts == {
|
||||||
"outer-graphs_reqs_a": str(
|
"__outer_graphs_reqs_a": str(
|
||||||
(pathlib.Path(__file__).parent / "../../examples/graphs_reqs_a").resolve()
|
(pathlib.Path(__file__).parent / "../../examples/graphs_reqs_a").resolve()
|
||||||
),
|
),
|
||||||
"examples": str((pathlib.Path(__file__).parent / "../../examples").resolve()),
|
"examples": str((pathlib.Path(__file__).parent / "../../examples").resolve()),
|
||||||
@@ -484,7 +484,7 @@ def test_config_to_docker_outside_path():
|
|||||||
"""\
|
"""\
|
||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -494,11 +494,11 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Adding non-package dependency tests --
|
# -- Adding non-package dependency tests --
|
||||||
COPY --from=outer-tests . /deps/outer-tests/tests
|
COPY --from=__outer_tests . /deps/__outer_tests/tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "tests"' \\
|
'name = "tests"' \\
|
||||||
@@ -508,22 +508,22 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency tests --
|
# -- End of non-package dependency tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}'
|
ENV LANGSERVE_GRAPHS='{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}'
|
||||||
"""
|
"""
|
||||||
+ FORMATTED_CLEANUP_LINES
|
+ FORMATTED_CLEANUP_LINES
|
||||||
+ """
|
+ """
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests\
|
WORKDIR /deps/__outer_unit_tests/unit_tests\
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
assert additional_contexts == {
|
assert additional_contexts == {
|
||||||
"outer-tests": str(pathlib.Path(__file__).parent.parent.absolute()),
|
"__outer_tests": str(pathlib.Path(__file__).parent.parent.absolute()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ def test_config_to_docker_pipconfig():
|
|||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
ADD pipconfig.txt /pipconfig.txt
|
ADD pipconfig.txt /pipconfig.txt
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -555,17 +555,17 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}'
|
ENV LANGSERVE_GRAPHS='{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}'
|
||||||
"""
|
"""
|
||||||
+ FORMATTED_CLEANUP_LINES
|
+ FORMATTED_CLEANUP_LINES
|
||||||
+ """
|
+ """
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests\
|
WORKDIR /deps/__outer_unit_tests/unit_tests\
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
@@ -607,7 +607,7 @@ def test_config_to_docker_local_deps():
|
|||||||
expected_docker_stdin = f"""\
|
expected_docker_stdin = f"""\
|
||||||
FROM langchain/langgraph-api-custom:3.11
|
FROM langchain/langgraph-api-custom:3.11
|
||||||
# -- Adding non-package dependency graphs --
|
# -- Adding non-package dependency graphs --
|
||||||
ADD ./graphs /deps/outer-graphs/src
|
ADD ./graphs /deps/__outer_graphs/src
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "graphs"' \\
|
'name = "graphs"' \\
|
||||||
@@ -617,13 +617,13 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-graphs/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_graphs/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency graphs --
|
# -- End of non-package dependency graphs --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-graphs/src/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_graphs/src/agent.py:graph"}}'
|
||||||
{FORMATTED_CLEANUP_LINES}\
|
{FORMATTED_CLEANUP_LINES}\
|
||||||
"""
|
"""
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
@@ -691,7 +691,7 @@ ARG foo
|
|||||||
ADD pipconfig.txt /pipconfig.txt
|
ADD pipconfig.txt /pipconfig.txt
|
||||||
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt langchain langchain_openai
|
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt langchain langchain_openai
|
||||||
# -- Adding non-package dependency graphs --
|
# -- Adding non-package dependency graphs --
|
||||||
ADD ./graphs/ /deps/outer-graphs/src
|
ADD ./graphs/ /deps/__outer_graphs/src
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "graphs"' \\
|
'name = "graphs"' \\
|
||||||
@@ -701,13 +701,13 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-graphs/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_graphs/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency graphs --
|
# -- End of non-package dependency graphs --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PIP_CONFIG_FILE=/pipconfig.txt PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-graphs/src/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_graphs/src/agent.py:graph"}}'
|
||||||
{FORMATTED_CLEANUP_LINES}"""
|
{FORMATTED_CLEANUP_LINES}"""
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
assert additional_contexts == {}
|
assert additional_contexts == {}
|
||||||
@@ -797,7 +797,7 @@ def test_config_to_docker_gen_ui_python():
|
|||||||
expected_docker_stdin = f"""FROM langchain/langgraph-api:3.11
|
expected_docker_stdin = f"""FROM langchain/langgraph-api:3.11
|
||||||
RUN /storage/install-node.sh
|
RUN /storage/install-node.sh
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -807,7 +807,7 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
@@ -815,13 +815,13 @@ RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/con
|
|||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGGRAPH_UI='{{"agent": "./graphs/agent.ui.jsx"}}'
|
ENV LANGGRAPH_UI='{{"agent": "./graphs/agent.ui.jsx"}}'
|
||||||
ENV LANGGRAPH_UI_CONFIG='{{"shared": ["nuqs"]}}'
|
ENV LANGGRAPH_UI_CONFIG='{{"shared": ["nuqs"]}}'
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
# -- Installing JS dependencies --
|
# -- Installing JS dependencies --
|
||||||
ENV NODE_VERSION=20
|
ENV NODE_VERSION=20
|
||||||
RUN cd /deps/outer-unit_tests/unit_tests && npm i && tsx /api/langgraph_api/js/build.mts
|
RUN cd /deps/__outer_unit_tests/unit_tests && npm i && tsx /api/langgraph_api/js/build.mts
|
||||||
# -- End of JS dependencies install --
|
# -- End of JS dependencies install --
|
||||||
{FORMATTED_CLEANUP_LINES}
|
{FORMATTED_CLEANUP_LINES}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests"""
|
WORKDIR /deps/__outer_unit_tests/unit_tests"""
|
||||||
|
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
assert additional_contexts == {}
|
assert additional_contexts == {}
|
||||||
@@ -843,7 +843,7 @@ def test_config_to_docker_multiplatform():
|
|||||||
expected_docker_stdin = f"""FROM langchain/langgraph-api:3.11
|
expected_docker_stdin = f"""FROM langchain/langgraph-api:3.11
|
||||||
RUN /storage/install-node.sh
|
RUN /storage/install-node.sh
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -853,19 +853,19 @@ RUN set -ex && \\
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"python": "/deps/outer-unit_tests/unit_tests/multiplatform/python.py:graph", "js": "/deps/outer-unit_tests/unit_tests/multiplatform/js.mts:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"python": "/deps/__outer_unit_tests/unit_tests/multiplatform/python.py:graph", "js": "/deps/__outer_unit_tests/unit_tests/multiplatform/js.mts:graph"}}'
|
||||||
# -- Installing JS dependencies --
|
# -- Installing JS dependencies --
|
||||||
ENV NODE_VERSION=22
|
ENV NODE_VERSION=22
|
||||||
RUN cd /deps/outer-unit_tests/unit_tests && npm i && tsx /api/langgraph_api/js/build.mts
|
RUN cd /deps/__outer_unit_tests/unit_tests && npm i && tsx /api/langgraph_api/js/build.mts
|
||||||
# -- End of JS dependencies install --
|
# -- End of JS dependencies install --
|
||||||
{FORMATTED_CLEANUP_LINES}
|
{FORMATTED_CLEANUP_LINES}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests"""
|
WORKDIR /deps/__outer_unit_tests/unit_tests"""
|
||||||
|
|
||||||
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
assert clean_empty_lines(actual_docker_stdin) == expected_docker_stdin
|
||||||
assert additional_contexts == {}
|
assert additional_contexts == {}
|
||||||
@@ -984,7 +984,7 @@ def test_config_to_compose_simple_config():
|
|||||||
dockerfile_inline: |
|
dockerfile_inline: |
|
||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -994,15 +994,15 @@ def test_config_to_compose_simple_config():
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests
|
WORKDIR /deps/__outer_unit_tests/unit_tests
|
||||||
"""
|
"""
|
||||||
actual_compose_stdin = config_to_compose(
|
actual_compose_stdin = config_to_compose(
|
||||||
PATH_TO_CONFIG,
|
PATH_TO_CONFIG,
|
||||||
@@ -1025,7 +1025,7 @@ def test_config_to_compose_env_vars():
|
|||||||
dockerfile_inline: |
|
dockerfile_inline: |
|
||||||
FROM langchain/langgraph-api-custom:3.11
|
FROM langchain/langgraph-api-custom:3.11
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -1035,15 +1035,15 @@ def test_config_to_compose_env_vars():
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests
|
WORKDIR /deps/__outer_unit_tests/unit_tests
|
||||||
"""
|
"""
|
||||||
openai_api_key = "key"
|
openai_api_key = "key"
|
||||||
actual_compose_stdin = config_to_compose(
|
actual_compose_stdin = config_to_compose(
|
||||||
@@ -1070,7 +1070,7 @@ def test_config_to_compose_env_file():
|
|||||||
dockerfile_inline: |
|
dockerfile_inline: |
|
||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -1080,15 +1080,15 @@ def test_config_to_compose_env_file():
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests
|
WORKDIR /deps/__outer_unit_tests/unit_tests
|
||||||
"""
|
"""
|
||||||
actual_compose_stdin = config_to_compose(
|
actual_compose_stdin = config_to_compose(
|
||||||
PATH_TO_CONFIG,
|
PATH_TO_CONFIG,
|
||||||
@@ -1108,7 +1108,7 @@ def test_config_to_compose_watch():
|
|||||||
dockerfile_inline: |
|
dockerfile_inline: |
|
||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -1118,15 +1118,15 @@ def test_config_to_compose_watch():
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests
|
WORKDIR /deps/__outer_unit_tests/unit_tests
|
||||||
|
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
@@ -1155,7 +1155,7 @@ def test_config_to_compose_end_to_end():
|
|||||||
dockerfile_inline: |
|
dockerfile_inline: |
|
||||||
FROM langchain/langgraph-api:3.11
|
FROM langchain/langgraph-api:3.11
|
||||||
# -- Adding non-package dependency unit_tests --
|
# -- Adding non-package dependency unit_tests --
|
||||||
ADD . /deps/outer-unit_tests/unit_tests
|
ADD . /deps/__outer_unit_tests/unit_tests
|
||||||
RUN set -ex && \\
|
RUN set -ex && \\
|
||||||
for line in '[project]' \\
|
for line in '[project]' \\
|
||||||
'name = "unit_tests"' \\
|
'name = "unit_tests"' \\
|
||||||
@@ -1165,15 +1165,15 @@ def test_config_to_compose_end_to_end():
|
|||||||
'[build-system]' \\
|
'[build-system]' \\
|
||||||
'requires = ["setuptools>=61"]' \\
|
'requires = ["setuptools>=61"]' \\
|
||||||
'build-backend = "setuptools.build_meta"'; do \\
|
'build-backend = "setuptools.build_meta"'; do \\
|
||||||
echo "$line" >> /deps/outer-unit_tests/pyproject.toml; \\
|
echo "$line" >> /deps/__outer_unit_tests/pyproject.toml; \\
|
||||||
done
|
done
|
||||||
# -- End of non-package dependency unit_tests --
|
# -- End of non-package dependency unit_tests --
|
||||||
# -- Installing all local dependencies --
|
# -- Installing all local dependencies --
|
||||||
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/*
|
||||||
# -- End of local dependencies install --
|
# -- End of local dependencies install --
|
||||||
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-unit_tests/unit_tests/agent.py:graph"}}'
|
ENV LANGSERVE_GRAPHS='{{"agent": "/deps/__outer_unit_tests/unit_tests/agent.py:graph"}}'
|
||||||
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|
||||||
WORKDIR /deps/outer-unit_tests/unit_tests
|
WORKDIR /deps/__outer_unit_tests/unit_tests
|
||||||
|
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
"Bash(python:*)",
|
"Bash(python:*)",
|
||||||
"Bash(grep:*)",
|
"Bash(grep:*)",
|
||||||
"Bash(sed:*)",
|
"Bash(sed:*)",
|
||||||
"Bash(awk:*)",
|
"Bash(awk:*)"
|
||||||
"Bash(uv run mypy:*)",
|
|
||||||
"Bash(uv run:*)"
|
|
||||||
],
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -443,7 +443,12 @@ class ToolNode(RunnableCallable):
|
|||||||
return invalid_tool_message
|
return invalid_tool_message
|
||||||
try:
|
try:
|
||||||
call_args = {**call, **{"type": "tool_call"}}
|
call_args = {**call, **{"type": "tool_call"}}
|
||||||
response = self.tools_by_name[call["name"]].invoke(call_args, config)
|
tool = self.tools_by_name[call["name"]]
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = tool.invoke(call_args, config)
|
||||||
|
except NotImplementedError:
|
||||||
|
response = asyncio.run(tool.ainvoke(call_args, config))
|
||||||
|
|
||||||
# GraphInterrupt is a special exception that will always be raised.
|
# GraphInterrupt is a special exception that will always be raised.
|
||||||
# It can be triggered in the following scenarios,
|
# It can be triggered in the following scenarios,
|
||||||
|
|||||||
@@ -1156,3 +1156,36 @@ async def test_tool_node_command_remove_all_messages():
|
|||||||
command = result[0]
|
command = result[0]
|
||||||
assert isinstance(command, Command)
|
assert isinstance(command, Command)
|
||||||
assert command.update == {"messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES)]}
|
assert command.update == {"messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES)]}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_tool_called_syncly() -> None:
|
||||||
|
"""Confirm that async tools can be called synchronously."""
|
||||||
|
|
||||||
|
@dec_tool
|
||||||
|
async def async_tool():
|
||||||
|
"""An async tool."""
|
||||||
|
return "async tool"
|
||||||
|
|
||||||
|
tool_node = ToolNode([async_tool])
|
||||||
|
result = tool_node.invoke(
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
AIMessage(
|
||||||
|
content="",
|
||||||
|
tool_calls=[
|
||||||
|
{
|
||||||
|
"name": "async_tool",
|
||||||
|
"args": {},
|
||||||
|
"id": "1",
|
||||||
|
"type": "tool_call",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert result == {
|
||||||
|
"messages": [
|
||||||
|
ToolMessage(content="async tool", name="async_tool", tool_call_id="1")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from langgraph_sdk.auth import Auth
|
from langgraph_sdk.auth import Auth
|
||||||
from langgraph_sdk.client import get_client, get_sync_client
|
from langgraph_sdk.client import get_client, get_sync_client
|
||||||
|
|
||||||
__version__ = "0.2.6"
|
__version__ = "0.2.4"
|
||||||
|
|
||||||
__all__ = ["Auth", "get_client", "get_sync_client"]
|
__all__ = ["Auth", "get_client", "get_sync_client"]
|
||||||
|
|||||||
@@ -400,20 +400,6 @@ class AuthContext(BaseAuthContext):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ThreadTTL(typing.TypedDict, total=False):
|
|
||||||
"""Time-to-live configuration for a thread.
|
|
||||||
|
|
||||||
Matches the OpenAPI schema where TTL is represented as an object with
|
|
||||||
an optional strategy and a time value in minutes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
strategy: typing.Literal["delete"]
|
|
||||||
"""TTL strategy. Currently only 'delete' is supported."""
|
|
||||||
|
|
||||||
ttl: int
|
|
||||||
"""Time-to-live in minutes from now until the thread should be swept."""
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadsCreate(typing.TypedDict, total=False):
|
class ThreadsCreate(typing.TypedDict, total=False):
|
||||||
"""Parameters for creating a new thread.
|
"""Parameters for creating a new thread.
|
||||||
|
|
||||||
@@ -436,9 +422,6 @@ class ThreadsCreate(typing.TypedDict, total=False):
|
|||||||
if_exists: OnConflictBehavior
|
if_exists: OnConflictBehavior
|
||||||
"""Behavior when a thread with the same ID already exists."""
|
"""Behavior when a thread with the same ID already exists."""
|
||||||
|
|
||||||
ttl: ThreadTTL
|
|
||||||
"""Optional TTL configuration for the thread."""
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadsRead(typing.TypedDict, total=False):
|
class ThreadsRead(typing.TypedDict, total=False):
|
||||||
"""Parameters for reading thread state or run information.
|
"""Parameters for reading thread state or run information.
|
||||||
@@ -506,9 +489,6 @@ class ThreadsSearch(typing.TypedDict, total=False):
|
|||||||
offset: int
|
offset: int
|
||||||
"""Offset for pagination."""
|
"""Offset for pagination."""
|
||||||
|
|
||||||
ids: Sequence[UUID] | None
|
|
||||||
"""typing.Optional list of thread IDs to filter by."""
|
|
||||||
|
|
||||||
thread_id: UUID | None
|
thread_id: UUID | None
|
||||||
"""typing.Optional thread ID to filter by."""
|
"""typing.Optional thread ID to filter by."""
|
||||||
|
|
||||||
|
|||||||
@@ -1179,7 +1179,6 @@ class ThreadsClient:
|
|||||||
if_exists: OnConflictBehavior | None = None,
|
if_exists: OnConflictBehavior | None = None,
|
||||||
supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]] | None = None,
|
supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]] | None = None,
|
||||||
graph_id: str | None = None,
|
graph_id: str | None = None,
|
||||||
ttl: int | Mapping[str, Any] | None = None,
|
|
||||||
headers: Mapping[str, str] | None = None,
|
headers: Mapping[str, str] | None = None,
|
||||||
params: QueryParamTypes | None = None,
|
params: QueryParamTypes | None = None,
|
||||||
) -> Thread:
|
) -> Thread:
|
||||||
@@ -1194,9 +1193,6 @@ class ThreadsClient:
|
|||||||
supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates.
|
supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates.
|
||||||
Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments.
|
Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments.
|
||||||
graph_id: Optional graph ID to associate with the thread.
|
graph_id: Optional graph ID to associate with the thread.
|
||||||
ttl: Optional time-to-live in minutes for the thread. You can pass an
|
|
||||||
integer (minutes) or a mapping with keys `ttl` and optional
|
|
||||||
`strategy` (defaults to "delete").
|
|
||||||
headers: Optional custom headers to include with the request.
|
headers: Optional custom headers to include with the request.
|
||||||
params: Optional query parameters to include with the request.
|
params: Optional query parameters to include with the request.
|
||||||
|
|
||||||
@@ -1238,11 +1234,6 @@ class ThreadsClient:
|
|||||||
}
|
}
|
||||||
for s in supersteps
|
for s in supersteps
|
||||||
]
|
]
|
||||||
if ttl is not None:
|
|
||||||
if isinstance(ttl, (int, float)):
|
|
||||||
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
|
|
||||||
else:
|
|
||||||
payload["ttl"] = ttl
|
|
||||||
|
|
||||||
return await self.http.post(
|
return await self.http.post(
|
||||||
"/threads", json=payload, headers=headers, params=params
|
"/threads", json=payload, headers=headers, params=params
|
||||||
@@ -1253,7 +1244,6 @@ class ThreadsClient:
|
|||||||
thread_id: str,
|
thread_id: str,
|
||||||
*,
|
*,
|
||||||
metadata: Mapping[str, Any],
|
metadata: Mapping[str, Any],
|
||||||
ttl: int | Mapping[str, Any] | None = None,
|
|
||||||
headers: Mapping[str, str] | None = None,
|
headers: Mapping[str, str] | None = None,
|
||||||
params: QueryParamTypes | None = None,
|
params: QueryParamTypes | None = None,
|
||||||
) -> Thread:
|
) -> Thread:
|
||||||
@@ -1262,9 +1252,6 @@ class ThreadsClient:
|
|||||||
Args:
|
Args:
|
||||||
thread_id: ID of thread to update.
|
thread_id: ID of thread to update.
|
||||||
metadata: Metadata to merge with existing thread metadata.
|
metadata: Metadata to merge with existing thread metadata.
|
||||||
ttl: Optional time-to-live in minutes for the thread. You can pass an
|
|
||||||
integer (minutes) or a mapping with keys `ttl` and optional
|
|
||||||
`strategy` (defaults to "delete").
|
|
||||||
headers: Optional custom headers to include with the request.
|
headers: Optional custom headers to include with the request.
|
||||||
params: Optional query parameters to include with the request.
|
params: Optional query parameters to include with the request.
|
||||||
|
|
||||||
@@ -1278,19 +1265,12 @@ class ThreadsClient:
|
|||||||
thread = await client.threads.update(
|
thread = await client.threads.update(
|
||||||
thread_id="my-thread-id",
|
thread_id="my-thread-id",
|
||||||
metadata={"number":1},
|
metadata={"number":1},
|
||||||
ttl=43_200,
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
""" # noqa: E501
|
""" # noqa: E501
|
||||||
payload: dict[str, Any] = {"metadata": metadata}
|
|
||||||
if ttl is not None:
|
|
||||||
if isinstance(ttl, (int, float)):
|
|
||||||
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
|
|
||||||
else:
|
|
||||||
payload["ttl"] = ttl
|
|
||||||
return await self.http.patch(
|
return await self.http.patch(
|
||||||
f"/threads/{thread_id}",
|
f"/threads/{thread_id}",
|
||||||
json=payload,
|
json={"metadata": metadata},
|
||||||
headers=headers,
|
headers=headers,
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
@@ -1329,7 +1309,6 @@ class ThreadsClient:
|
|||||||
*,
|
*,
|
||||||
metadata: Json = None,
|
metadata: Json = None,
|
||||||
values: Json = None,
|
values: Json = None,
|
||||||
ids: Sequence[str] | None = None,
|
|
||||||
status: ThreadStatus | None = None,
|
status: ThreadStatus | None = None,
|
||||||
limit: int = 10,
|
limit: int = 10,
|
||||||
offset: int = 0,
|
offset: int = 0,
|
||||||
@@ -1344,7 +1323,6 @@ class ThreadsClient:
|
|||||||
Args:
|
Args:
|
||||||
metadata: Thread metadata to filter on.
|
metadata: Thread metadata to filter on.
|
||||||
values: State values to filter on.
|
values: State values to filter on.
|
||||||
ids: List of thread IDs to filter by.
|
|
||||||
status: Thread status to filter on.
|
status: Thread status to filter on.
|
||||||
Must be one of 'idle', 'busy', 'interrupted' or 'error'.
|
Must be one of 'idle', 'busy', 'interrupted' or 'error'.
|
||||||
limit: Limit on number of threads to return.
|
limit: Limit on number of threads to return.
|
||||||
@@ -1378,8 +1356,6 @@ class ThreadsClient:
|
|||||||
payload["metadata"] = metadata
|
payload["metadata"] = metadata
|
||||||
if values:
|
if values:
|
||||||
payload["values"] = values
|
payload["values"] = values
|
||||||
if ids:
|
|
||||||
payload["ids"] = ids
|
|
||||||
if status:
|
if status:
|
||||||
payload["status"] = status
|
payload["status"] = status
|
||||||
if sort_by:
|
if sort_by:
|
||||||
@@ -4352,7 +4328,6 @@ class SyncThreadsClient:
|
|||||||
if_exists: OnConflictBehavior | None = None,
|
if_exists: OnConflictBehavior | None = None,
|
||||||
supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]] | None = None,
|
supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]] | None = None,
|
||||||
graph_id: str | None = None,
|
graph_id: str | None = None,
|
||||||
ttl: int | Mapping[str, Any] | None = None,
|
|
||||||
headers: Mapping[str, str] | None = None,
|
headers: Mapping[str, str] | None = None,
|
||||||
params: QueryParamTypes | None = None,
|
params: QueryParamTypes | None = None,
|
||||||
) -> Thread:
|
) -> Thread:
|
||||||
@@ -4367,9 +4342,6 @@ class SyncThreadsClient:
|
|||||||
supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates.
|
supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates.
|
||||||
Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments.
|
Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments.
|
||||||
graph_id: Optional graph ID to associate with the thread.
|
graph_id: Optional graph ID to associate with the thread.
|
||||||
ttl: Optional time-to-live in minutes for the thread. You can pass an
|
|
||||||
integer (minutes) or a mapping with keys `ttl` and optional
|
|
||||||
`strategy` (defaults to "delete").
|
|
||||||
headers: Optional custom headers to include with the request.
|
headers: Optional custom headers to include with the request.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -4411,11 +4383,6 @@ class SyncThreadsClient:
|
|||||||
}
|
}
|
||||||
for s in supersteps
|
for s in supersteps
|
||||||
]
|
]
|
||||||
if ttl is not None:
|
|
||||||
if isinstance(ttl, (int, float)):
|
|
||||||
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
|
|
||||||
else:
|
|
||||||
payload["ttl"] = ttl
|
|
||||||
|
|
||||||
return self.http.post("/threads", json=payload, headers=headers, params=params)
|
return self.http.post("/threads", json=payload, headers=headers, params=params)
|
||||||
|
|
||||||
@@ -4424,7 +4391,6 @@ class SyncThreadsClient:
|
|||||||
thread_id: str,
|
thread_id: str,
|
||||||
*,
|
*,
|
||||||
metadata: Mapping[str, Any],
|
metadata: Mapping[str, Any],
|
||||||
ttl: int | Mapping[str, Any] | None = None,
|
|
||||||
headers: Mapping[str, str] | None = None,
|
headers: Mapping[str, str] | None = None,
|
||||||
params: QueryParamTypes | None = None,
|
params: QueryParamTypes | None = None,
|
||||||
) -> Thread:
|
) -> Thread:
|
||||||
@@ -4433,11 +4399,7 @@ class SyncThreadsClient:
|
|||||||
Args:
|
Args:
|
||||||
thread_id: ID of thread to update.
|
thread_id: ID of thread to update.
|
||||||
metadata: Metadata to merge with existing thread metadata.
|
metadata: Metadata to merge with existing thread metadata.
|
||||||
ttl: Optional time-to-live in minutes for the thread. You can pass an
|
|
||||||
integer (minutes) or a mapping with keys `ttl` and optional
|
|
||||||
`strategy` (defaults to "delete").
|
|
||||||
headers: Optional custom headers to include with the request.
|
headers: Optional custom headers to include with the request.
|
||||||
params: Optional query parameters to include with the request.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Thread: The created thread.
|
Thread: The created thread.
|
||||||
@@ -4449,19 +4411,12 @@ class SyncThreadsClient:
|
|||||||
thread = client.threads.update(
|
thread = client.threads.update(
|
||||||
thread_id="my-thread-id",
|
thread_id="my-thread-id",
|
||||||
metadata={"number":1},
|
metadata={"number":1},
|
||||||
ttl=43_200,
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
""" # noqa: E501
|
""" # noqa: E501
|
||||||
payload: dict[str, Any] = {"metadata": metadata}
|
|
||||||
if ttl is not None:
|
|
||||||
if isinstance(ttl, (int, float)):
|
|
||||||
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
|
|
||||||
else:
|
|
||||||
payload["ttl"] = ttl
|
|
||||||
return self.http.patch(
|
return self.http.patch(
|
||||||
f"/threads/{thread_id}",
|
f"/threads/{thread_id}",
|
||||||
json=payload,
|
json={"metadata": metadata},
|
||||||
headers=headers,
|
headers=headers,
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
@@ -4499,7 +4454,6 @@ class SyncThreadsClient:
|
|||||||
*,
|
*,
|
||||||
metadata: Json = None,
|
metadata: Json = None,
|
||||||
values: Json = None,
|
values: Json = None,
|
||||||
ids: Sequence[str] | None = None,
|
|
||||||
status: ThreadStatus | None = None,
|
status: ThreadStatus | None = None,
|
||||||
limit: int = 10,
|
limit: int = 10,
|
||||||
offset: int = 0,
|
offset: int = 0,
|
||||||
@@ -4514,7 +4468,6 @@ class SyncThreadsClient:
|
|||||||
Args:
|
Args:
|
||||||
metadata: Thread metadata to filter on.
|
metadata: Thread metadata to filter on.
|
||||||
values: State values to filter on.
|
values: State values to filter on.
|
||||||
ids: List of thread IDs to filter by.
|
|
||||||
status: Thread status to filter on.
|
status: Thread status to filter on.
|
||||||
Must be one of 'idle', 'busy', 'interrupted' or 'error'.
|
Must be one of 'idle', 'busy', 'interrupted' or 'error'.
|
||||||
limit: Limit on number of threads to return.
|
limit: Limit on number of threads to return.
|
||||||
@@ -4544,8 +4497,6 @@ class SyncThreadsClient:
|
|||||||
payload["metadata"] = metadata
|
payload["metadata"] = metadata
|
||||||
if values:
|
if values:
|
||||||
payload["values"] = values
|
payload["values"] = values
|
||||||
if ids:
|
|
||||||
payload["ids"] = ids
|
|
||||||
if status:
|
if status:
|
||||||
payload["status"] = status
|
payload["status"] = status
|
||||||
if sort_by:
|
if sort_by:
|
||||||
|
|||||||
Reference in New Issue
Block a user