langgraph-cli 0.4.2__tar.gz → 0.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/PKG-INFO +1 -1
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graph_prerelease_reqs/agent.py +1 -7
- langgraph_cli-0.4.3/examples/graph_prerelease_reqs/deps/additional_deps/pyproject.toml +9 -0
- langgraph_cli-0.4.3/examples/graph_prerelease_reqs/deps/zuper_deps/pyproject.toml +9 -0
- langgraph_cli-0.4.3/examples/graph_prerelease_reqs/langgraph.json +13 -0
- langgraph_cli-0.4.3/examples/graph_prerelease_reqs/pyproject.toml +14 -0
- langgraph_cli-0.4.3/examples/graph_prerelease_reqs_fail/agent.py +89 -0
- langgraph_cli-0.4.3/examples/graph_prerelease_reqs_fail/pyproject.toml +11 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs/agent.py +8 -7
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs/langgraph.json +1 -0
- {langgraph_cli-0.4.2/examples/graphs_reqs_b → langgraph_cli-0.4.3/examples/graphs_reqs_a}/graphs_submod/agent.py +9 -5
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/langgraph.json +1 -0
- {langgraph_cli-0.4.2/examples/graphs_reqs_a → langgraph_cli-0.4.3/examples/graphs_reqs_b}/graphs_submod/agent.py +9 -4
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/langgraph.json +1 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/langgraph.json +1 -0
- langgraph_cli-0.4.3/langgraph_cli/__init__.py +1 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/config.py +40 -6
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/docker.py +3 -1
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/apps/agent/langgraph.json +1 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/schemas/schema.json +18 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/schemas/schema.v0.json +18 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/cli/test_cli.py +2 -2
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/test_config.py +21 -21
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/test_docker.py +22 -0
- langgraph_cli-0.4.3/tests/unit_tests/test_util.py +188 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/uv.lock +628 -411
- langgraph_cli-0.4.2/examples/graph_prerelease_reqs/requirements.txt +0 -6
- langgraph_cli-0.4.2/langgraph_cli/__init__.py +0 -1
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/.gitignore +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/LICENSE +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/Makefile +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/README.md +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/.env.example +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/.gitignore +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/Makefile +0 -0
- {langgraph_cli-0.4.2/examples/graph_prerelease_reqs → langgraph_cli-0.4.3/examples/graph_prerelease_reqs_fail}/langgraph.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs/storm.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/graphs_submod/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/graphs_submod/subprompt.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/hello.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/prompt.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_a/requirements.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/graphs_submod/subprompt.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/hello.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/prompt.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/requirements.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/utils/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/graphs_reqs_b/utils/greeter.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/langgraph.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/my_app.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/pipconf.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/poetry.lock +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/examples/pyproject.toml +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/generate_schema.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/.dockerignore +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/.env.example +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/.eslintrc.cjs +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/.gitignore +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/LICENSE +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/README.md +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/jest.config.js +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/package.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/src/agent/graph.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/src/agent/state.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/static/studio.png +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/tests/agent.test.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/tests/graph.int.test.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/tsconfig.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-examples/yarn.lock +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/.eslintrc.cjs +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/apps/agent/langgraph.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/apps/agent/package.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/apps/agent/src/graph.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/apps/agent/src/state.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/apps/agent/tsconfig.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/libs/shared/package.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/libs/shared/src/index.ts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/libs/shared/tsconfig.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/package.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/tsconfig.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/turbo.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/js-monorepo-example/yarn.lock +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/__main__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/analytics.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/cli.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/constants.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/exec.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/progress.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/py.typed +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/templates.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/util.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/langgraph_cli/version.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/pyproject.toml +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/apps/agent/.env.example +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/apps/agent/pyproject.toml +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/apps/agent/src/agent/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/apps/agent/src/agent/graph.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/apps/agent/src/agent/state.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/libs/common/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/libs/common/helpers.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/libs/shared/pyproject.toml +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/libs/shared/src/shared/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/libs/shared/src/shared/utils.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/python-monorepo-example/pyproject.toml +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/schemas/version.schema.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/integration_tests/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/integration_tests/test_cli.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/agent.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/cli/__init__.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/cli/langgraph.json +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/cli/pyproject.toml +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/cli/test_templates.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/conftest.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/graphs/agent.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/helpers.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/multiplatform/js.mts +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/multiplatform/python.py +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/pipconfig.txt +0 -0
- {langgraph_cli-0.4.2 → langgraph_cli-0.4.3}/tests/unit_tests/test_config.json +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from collections.abc import Sequence
|
|
2
2
|
from typing import Annotated, Literal, TypedDict
|
|
3
3
|
|
|
4
|
-
from langchain.chat_models import init_chat_model
|
|
5
4
|
from langchain_community.tools.tavily_search import TavilySearchResults
|
|
6
5
|
from langchain_core.messages import BaseMessage
|
|
7
6
|
from langchain_openai import ChatOpenAI
|
|
@@ -10,10 +9,8 @@ from langgraph.prebuilt import ToolNode
|
|
|
10
9
|
|
|
11
10
|
tools = [TavilySearchResults(max_results=1)]
|
|
12
11
|
|
|
13
|
-
model_anth = init_chat_model("claude-3-7-sonnet-20250219", model_provider="anthropic")
|
|
14
12
|
model_oai = ChatOpenAI(temperature=0)
|
|
15
13
|
|
|
16
|
-
model_anth = model_anth.bind_tools(tools)
|
|
17
14
|
model_oai = model_oai.bind_tools(tools)
|
|
18
15
|
|
|
19
16
|
|
|
@@ -35,10 +32,7 @@ def should_continue(state):
|
|
|
35
32
|
|
|
36
33
|
# Define the function that calls the model
|
|
37
34
|
def call_model(state, config):
|
|
38
|
-
|
|
39
|
-
model = model_anth
|
|
40
|
-
else:
|
|
41
|
-
model = model_oai
|
|
35
|
+
model = model_oai
|
|
42
36
|
messages = state["messages"]
|
|
43
37
|
response = model.invoke(messages)
|
|
44
38
|
# We return a list, because this will get added to the existing list
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "graph-prerelease-reqs"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Test for prerelease stuff"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"langchain-openai==1.0.0a2",
|
|
9
|
+
"langgraph==1.0.0a2",
|
|
10
|
+
"langchain_community>=0.3.0",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[tool.uv]
|
|
14
|
+
prerelease = "allow"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Annotated, Literal, TypedDict
|
|
3
|
+
|
|
4
|
+
from langchain_community.tools.tavily_search import TavilySearchResults
|
|
5
|
+
from langchain_core.messages import BaseMessage
|
|
6
|
+
from langchain_openai import ChatOpenAI
|
|
7
|
+
from langgraph.graph import END, StateGraph, add_messages
|
|
8
|
+
from langgraph.prebuilt import ToolNode
|
|
9
|
+
|
|
10
|
+
tools = [TavilySearchResults(max_results=1)]
|
|
11
|
+
|
|
12
|
+
model_oai = ChatOpenAI(temperature=0)
|
|
13
|
+
|
|
14
|
+
model_oai = model_oai.bind_tools(tools)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AgentState(TypedDict):
|
|
18
|
+
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Define the function that determines whether to continue or not
|
|
22
|
+
def should_continue(state):
|
|
23
|
+
messages = state["messages"]
|
|
24
|
+
last_message = messages[-1]
|
|
25
|
+
# If there are no tool calls, then we finish
|
|
26
|
+
if not last_message.tool_calls:
|
|
27
|
+
return "end"
|
|
28
|
+
# Otherwise if there is, we continue
|
|
29
|
+
else:
|
|
30
|
+
return "continue"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Define the function that calls the model
|
|
34
|
+
def call_model(state, config):
|
|
35
|
+
model = model_oai
|
|
36
|
+
messages = state["messages"]
|
|
37
|
+
response = model.invoke(messages)
|
|
38
|
+
# We return a list, because this will get added to the existing list
|
|
39
|
+
return {"messages": [response]}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Define the function to execute tools
|
|
43
|
+
tool_node = ToolNode(tools)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ContextSchema(TypedDict):
|
|
47
|
+
model: Literal["anthropic", "openai"]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Define a new graph
|
|
51
|
+
workflow = StateGraph(AgentState, context_schema=ContextSchema)
|
|
52
|
+
|
|
53
|
+
# Define the two nodes we will cycle between
|
|
54
|
+
workflow.add_node("agent", call_model)
|
|
55
|
+
workflow.add_node("action", tool_node)
|
|
56
|
+
|
|
57
|
+
# Set the entrypoint as `agent`
|
|
58
|
+
# This means that this node is the first one called
|
|
59
|
+
workflow.set_entry_point("agent")
|
|
60
|
+
|
|
61
|
+
# We now add a conditional edge
|
|
62
|
+
workflow.add_conditional_edges(
|
|
63
|
+
# First, we define the start node. We use `agent`.
|
|
64
|
+
# This means these are the edges taken after the `agent` node is called.
|
|
65
|
+
"agent",
|
|
66
|
+
# Next, we pass in the function that will determine which node is called next.
|
|
67
|
+
should_continue,
|
|
68
|
+
# Finally we pass in a mapping.
|
|
69
|
+
# The keys are strings, and the values are other nodes.
|
|
70
|
+
# END is a special node marking that the graph should finish.
|
|
71
|
+
# What will happen is we will call `should_continue`, and then the output of that
|
|
72
|
+
# will be matched against the keys in this mapping.
|
|
73
|
+
# Based on which one it matches, that node will then be called.
|
|
74
|
+
{
|
|
75
|
+
# If `tools`, then we call the tool node.
|
|
76
|
+
"continue": "action",
|
|
77
|
+
# Otherwise we finish.
|
|
78
|
+
"end": END,
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# We now add a normal edge from `tools` to `agent`.
|
|
83
|
+
# This means that after `tools` is called, `agent` node is called next.
|
|
84
|
+
workflow.add_edge("action", "agent")
|
|
85
|
+
|
|
86
|
+
# Finally, we compile it!
|
|
87
|
+
# This compiles it into a LangChain Runnable,
|
|
88
|
+
# meaning you can use it as you would any other runnable
|
|
89
|
+
graph = workflow.compile()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "graph-prerelease-reqs"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Test for prerelease stuff"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"langchain-openai==1.0.0a2",
|
|
9
|
+
"langgraph==1.0.0a2",
|
|
10
|
+
"langchain_community>=0.3.0",
|
|
11
|
+
]
|
|
@@ -7,6 +7,7 @@ from langchain_core.messages import BaseMessage
|
|
|
7
7
|
from langchain_openai import ChatOpenAI
|
|
8
8
|
from langgraph.graph import END, StateGraph, add_messages
|
|
9
9
|
from langgraph.prebuilt import ToolNode
|
|
10
|
+
from langgraph.runtime import Runtime
|
|
10
11
|
|
|
11
12
|
tools = [TavilySearchResults(max_results=1)]
|
|
12
13
|
|
|
@@ -17,6 +18,10 @@ model_anth = model_anth.bind_tools(tools)
|
|
|
17
18
|
model_oai = model_oai.bind_tools(tools)
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
class AgentContext(TypedDict):
|
|
22
|
+
model: Literal["anthropic", "openai"]
|
|
23
|
+
|
|
24
|
+
|
|
20
25
|
class AgentState(TypedDict):
|
|
21
26
|
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
22
27
|
|
|
@@ -34,8 +39,8 @@ def should_continue(state):
|
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
# Define the function that calls the model
|
|
37
|
-
def call_model(state,
|
|
38
|
-
if
|
|
42
|
+
def call_model(state, runtime: Runtime[AgentContext]):
|
|
43
|
+
if runtime.context.get("model", "anthropic") == "anthropic":
|
|
39
44
|
model = model_anth
|
|
40
45
|
else:
|
|
41
46
|
model = model_oai
|
|
@@ -49,12 +54,8 @@ def call_model(state, config):
|
|
|
49
54
|
tool_node = ToolNode(tools)
|
|
50
55
|
|
|
51
56
|
|
|
52
|
-
class ContextSchema(TypedDict):
|
|
53
|
-
model: Literal["anthropic", "openai"]
|
|
54
|
-
|
|
55
|
-
|
|
56
57
|
# Define a new graph
|
|
57
|
-
workflow = StateGraph(AgentState, context_schema=
|
|
58
|
+
workflow = StateGraph(AgentState, context_schema=AgentContext)
|
|
58
59
|
|
|
59
60
|
# Define the two nodes we will cycle between
|
|
60
61
|
workflow.add_node("agent", call_model)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Sequence
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Annotated, TypedDict
|
|
3
|
+
from typing import Annotated, Literal, TypedDict
|
|
4
4
|
|
|
5
5
|
from langchain_anthropic import ChatAnthropic
|
|
6
6
|
from langchain_community.tools.tavily_search import TavilySearchResults
|
|
@@ -8,6 +8,7 @@ from langchain_core.messages import BaseMessage
|
|
|
8
8
|
from langchain_openai import ChatOpenAI
|
|
9
9
|
from langgraph.graph import END, StateGraph, add_messages
|
|
10
10
|
from langgraph.prebuilt import ToolNode
|
|
11
|
+
from langgraph.runtime import Runtime
|
|
11
12
|
|
|
12
13
|
tools = [TavilySearchResults(max_results=1)]
|
|
13
14
|
|
|
@@ -21,6 +22,10 @@ prompt = open(Path(__file__).parent.parent / "prompt.txt").read()
|
|
|
21
22
|
subprompt = open(Path(__file__).parent / "subprompt.txt").read()
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
class AgentContext(TypedDict):
|
|
26
|
+
model: Literal["anthropic", "openai"]
|
|
27
|
+
|
|
28
|
+
|
|
24
29
|
class AgentState(TypedDict):
|
|
25
30
|
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
26
31
|
|
|
@@ -38,8 +43,8 @@ def should_continue(state):
|
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
# Define the function that calls the model
|
|
41
|
-
def call_model(state,
|
|
42
|
-
if
|
|
46
|
+
def call_model(state, runtime: Runtime[AgentContext]):
|
|
47
|
+
if runtime.context.get("model", "anthropic") == "anthropic":
|
|
43
48
|
model = model_anth
|
|
44
49
|
else:
|
|
45
50
|
model = model_oai
|
|
@@ -52,9 +57,8 @@ def call_model(state, config):
|
|
|
52
57
|
# Define the function to execute tools
|
|
53
58
|
tool_node = ToolNode(tools)
|
|
54
59
|
|
|
55
|
-
|
|
56
60
|
# Define a new graph
|
|
57
|
-
workflow = StateGraph(AgentState)
|
|
61
|
+
workflow = StateGraph(AgentState, context_schema=AgentContext)
|
|
58
62
|
|
|
59
63
|
# Define the two nodes we will cycle between
|
|
60
64
|
workflow.add_node("agent", call_model)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Sequence
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Annotated, TypedDict
|
|
3
|
+
from typing import Annotated, Literal, TypedDict
|
|
4
4
|
|
|
5
5
|
from langchain_anthropic import ChatAnthropic
|
|
6
6
|
from langchain_community.tools.tavily_search import TavilySearchResults
|
|
@@ -8,6 +8,7 @@ from langchain_core.messages import BaseMessage
|
|
|
8
8
|
from langchain_openai import ChatOpenAI
|
|
9
9
|
from langgraph.graph import END, StateGraph, add_messages
|
|
10
10
|
from langgraph.prebuilt import ToolNode
|
|
11
|
+
from langgraph.runtime import Runtime
|
|
11
12
|
|
|
12
13
|
tools = [TavilySearchResults(max_results=1)]
|
|
13
14
|
|
|
@@ -21,6 +22,10 @@ prompt = open(Path(__file__).parent.parent / "prompt.txt").read()
|
|
|
21
22
|
subprompt = open(Path(__file__).parent / "subprompt.txt").read()
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
class AgentContext(TypedDict):
|
|
26
|
+
model: Literal["anthropic", "openai"]
|
|
27
|
+
|
|
28
|
+
|
|
24
29
|
class AgentState(TypedDict):
|
|
25
30
|
messages: Annotated[Sequence[BaseMessage], add_messages]
|
|
26
31
|
|
|
@@ -38,8 +43,8 @@ def should_continue(state):
|
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
# Define the function that calls the model
|
|
41
|
-
def call_model(state,
|
|
42
|
-
if
|
|
46
|
+
def call_model(state, runtime: Runtime[AgentContext]):
|
|
47
|
+
if runtime.context.get("model", "anthropic") == "anthropic":
|
|
43
48
|
model = model_anth
|
|
44
49
|
else:
|
|
45
50
|
model = model_oai
|
|
@@ -54,7 +59,7 @@ tool_node = ToolNode(tools)
|
|
|
54
59
|
|
|
55
60
|
|
|
56
61
|
# Define a new graph
|
|
57
|
-
workflow = StateGraph(AgentState)
|
|
62
|
+
workflow = StateGraph(AgentState, context_schema=AgentContext)
|
|
58
63
|
|
|
59
64
|
# Define the two nodes we will cycle between
|
|
60
65
|
workflow.add_node("agent", call_model)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.3"
|
|
@@ -18,6 +18,7 @@ DEFAULT_IMAGE_DISTRO = "debian"
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
Distros = Literal["debian", "wolfi", "bullseye", "bookworm"]
|
|
21
|
+
MiddlewareOrders = Literal["auth_first", "middleware_first"]
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class TTLConfig(TypedDict, total=False):
|
|
@@ -359,6 +360,25 @@ class HttpConfig(TypedDict, total=False):
|
|
|
359
360
|
agent's behavior or permissions on a request's headers."""
|
|
360
361
|
logging_headers: Optional[ConfigurableHeaderConfig]
|
|
361
362
|
"""Optional. Defines which headers are excluded from logging."""
|
|
363
|
+
middleware_order: Optional[MiddlewareOrders]
|
|
364
|
+
"""Optional. Defines the order in which to apply server customizations.
|
|
365
|
+
|
|
366
|
+
Choices:
|
|
367
|
+
- "auth_first": Authentication hooks (custom or default) are evaluated
|
|
368
|
+
before custom middleware.
|
|
369
|
+
- "middleware_first": Custom middleware is evaluated
|
|
370
|
+
before authentication hooks (custom or default).
|
|
371
|
+
|
|
372
|
+
Default is `middleware_first`.
|
|
373
|
+
"""
|
|
374
|
+
enable_custom_route_auth: bool
|
|
375
|
+
"""Optional. If True, authentication is enabled for custom routes,
|
|
376
|
+
not just the routes that are protected by default.
|
|
377
|
+
(Routes protected by default include /assistants, /threads, and /runs).
|
|
378
|
+
|
|
379
|
+
Default is False. This flag only affects authentication behavior
|
|
380
|
+
if `app` is provided and contains custom routes.
|
|
381
|
+
"""
|
|
362
382
|
|
|
363
383
|
|
|
364
384
|
class Config(TypedDict, total=False):
|
|
@@ -1256,16 +1276,22 @@ def python_config_to_docker(
|
|
|
1256
1276
|
else:
|
|
1257
1277
|
pip_installer = "pip"
|
|
1258
1278
|
if pip_installer == "uv":
|
|
1259
|
-
install_cmd = "uv pip install --system
|
|
1279
|
+
install_cmd = "uv pip install --system"
|
|
1260
1280
|
elif pip_installer == "pip":
|
|
1261
1281
|
install_cmd = "pip install"
|
|
1262
1282
|
else:
|
|
1263
1283
|
raise ValueError(f"Invalid pip_installer: {pip_installer}")
|
|
1264
1284
|
|
|
1265
1285
|
# configure pip
|
|
1266
|
-
|
|
1286
|
+
local_reqs_pip_install = f"PYTHONDONTWRITEBYTECODE=1 {install_cmd} --no-cache-dir -c /api/constraints.txt"
|
|
1287
|
+
global_reqs_pip_install = f"PYTHONDONTWRITEBYTECODE=1 {install_cmd} --no-cache-dir -c /api/constraints.txt"
|
|
1267
1288
|
if config.get("pip_config_file"):
|
|
1268
|
-
|
|
1289
|
+
local_reqs_pip_install = (
|
|
1290
|
+
f"PIP_CONFIG_FILE=/pipconfig.txt {local_reqs_pip_install}"
|
|
1291
|
+
)
|
|
1292
|
+
global_reqs_pip_install = (
|
|
1293
|
+
f"PIP_CONFIG_FILE=/pipconfig.txt {global_reqs_pip_install}"
|
|
1294
|
+
)
|
|
1269
1295
|
pip_config_file_str = (
|
|
1270
1296
|
f"ADD {config['pip_config_file']} /pipconfig.txt"
|
|
1271
1297
|
if config.get("pip_config_file")
|
|
@@ -1282,7 +1308,9 @@ def python_config_to_docker(
|
|
|
1282
1308
|
# Rewrite HTTP app path, so it points to the correct location in the Docker container
|
|
1283
1309
|
_update_http_app_path(config_path, config, local_deps)
|
|
1284
1310
|
|
|
1285
|
-
pip_pkgs_str =
|
|
1311
|
+
pip_pkgs_str = (
|
|
1312
|
+
f"RUN {local_reqs_pip_install} {' '.join(pypi_deps)}" if pypi_deps else ""
|
|
1313
|
+
)
|
|
1286
1314
|
if local_deps.pip_reqs:
|
|
1287
1315
|
pip_reqs_str = os.linesep.join(
|
|
1288
1316
|
(
|
|
@@ -1292,7 +1320,7 @@ def python_config_to_docker(
|
|
|
1292
1320
|
)
|
|
1293
1321
|
for reqpath, destpath in local_deps.pip_reqs
|
|
1294
1322
|
)
|
|
1295
|
-
pip_reqs_str += f"{os.linesep}RUN {
|
|
1323
|
+
pip_reqs_str += f"{os.linesep}RUN {local_reqs_pip_install} {' '.join('-r ' + r for _, r in local_deps.pip_reqs)}"
|
|
1296
1324
|
pip_reqs_str = f"""# -- Installing local requirements --
|
|
1297
1325
|
{pip_reqs_str}
|
|
1298
1326
|
# -- End of local requirements install --"""
|
|
@@ -1402,7 +1430,13 @@ ADD {relpath} /deps/{name}
|
|
|
1402
1430
|
installs,
|
|
1403
1431
|
"",
|
|
1404
1432
|
"# -- Installing all local dependencies --",
|
|
1405
|
-
f"RUN
|
|
1433
|
+
f"""RUN for dep in /deps/*; do \
|
|
1434
|
+
echo "Installing $dep"; \
|
|
1435
|
+
if [ -d "$dep" ]; then \
|
|
1436
|
+
echo "Installing $dep"; \
|
|
1437
|
+
(cd "$dep" && {global_reqs_pip_install} .); \
|
|
1438
|
+
fi; \
|
|
1439
|
+
done""",
|
|
1406
1440
|
"# -- End of local dependencies install --",
|
|
1407
1441
|
os.linesep.join(env_vars),
|
|
1408
1442
|
"",
|
|
@@ -40,7 +40,9 @@ def _parse_version(version: str) -> Version:
|
|
|
40
40
|
patch = "0"
|
|
41
41
|
else:
|
|
42
42
|
major, minor, patch = parts
|
|
43
|
-
return Version(
|
|
43
|
+
return Version(
|
|
44
|
+
int(major.lstrip("v")), int(minor), int(patch.split("-")[0].split("+")[0])
|
|
45
|
+
)
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
def check_capabilities(runner) -> DockerCapabilities:
|
|
@@ -577,6 +577,10 @@
|
|
|
577
577
|
"type": "boolean",
|
|
578
578
|
"description": "Optional. If True, /threads routes are removed.\n\nDefault is False.\n"
|
|
579
579
|
},
|
|
580
|
+
"enable_custom_route_auth": {
|
|
581
|
+
"type": "boolean",
|
|
582
|
+
"description": "Optional. If True, authentication is enabled for custom routes,\nnot just the routes that are protected by default.\n(Routes protected by default include /assistants, /threads, and /runs).\n\nDefault is False. This flag only affects authentication behavior\nif `app` is provided and contains custom routes.\n"
|
|
583
|
+
},
|
|
580
584
|
"logging_headers": {
|
|
581
585
|
"anyOf": [
|
|
582
586
|
{
|
|
@@ -587,6 +591,20 @@
|
|
|
587
591
|
}
|
|
588
592
|
],
|
|
589
593
|
"description": "Optional. Defines which headers are excluded from logging."
|
|
594
|
+
},
|
|
595
|
+
"middleware_order": {
|
|
596
|
+
"anyOf": [
|
|
597
|
+
{
|
|
598
|
+
"enum": [
|
|
599
|
+
"auth_first",
|
|
600
|
+
"middleware_first"
|
|
601
|
+
]
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"type": "null"
|
|
605
|
+
}
|
|
606
|
+
],
|
|
607
|
+
"description": "Optional. Defines the order in which to apply server customizations.\n"
|
|
590
608
|
}
|
|
591
609
|
},
|
|
592
610
|
"required": []
|
|
@@ -577,6 +577,10 @@
|
|
|
577
577
|
"type": "boolean",
|
|
578
578
|
"description": "Optional. If True, /threads routes are removed.\n\nDefault is False.\n"
|
|
579
579
|
},
|
|
580
|
+
"enable_custom_route_auth": {
|
|
581
|
+
"type": "boolean",
|
|
582
|
+
"description": "Optional. If True, authentication is enabled for custom routes,\nnot just the routes that are protected by default.\n(Routes protected by default include /assistants, /threads, and /runs).\n\nDefault is False. This flag only affects authentication behavior\nif `app` is provided and contains custom routes.\n"
|
|
583
|
+
},
|
|
580
584
|
"logging_headers": {
|
|
581
585
|
"anyOf": [
|
|
582
586
|
{
|
|
@@ -587,6 +591,20 @@
|
|
|
587
591
|
}
|
|
588
592
|
],
|
|
589
593
|
"description": "Optional. Defines which headers are excluded from logging."
|
|
594
|
+
},
|
|
595
|
+
"middleware_order": {
|
|
596
|
+
"anyOf": [
|
|
597
|
+
{
|
|
598
|
+
"enum": [
|
|
599
|
+
"auth_first",
|
|
600
|
+
"middleware_first"
|
|
601
|
+
]
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"type": "null"
|
|
605
|
+
}
|
|
606
|
+
],
|
|
607
|
+
"description": "Optional. Defines the order in which to apply server customizations.\n"
|
|
590
608
|
}
|
|
591
609
|
},
|
|
592
610
|
"required": []
|
|
@@ -15,7 +15,7 @@ from langgraph_cli.docker import DEFAULT_POSTGRES_URI, DockerCapabilities, Versi
|
|
|
15
15
|
from langgraph_cli.util import clean_empty_lines
|
|
16
16
|
|
|
17
17
|
FORMATTED_CLEANUP_LINES = _get_pip_cleanup_lines(
|
|
18
|
-
install_cmd="uv pip install --system
|
|
18
|
+
install_cmd="uv pip install --system",
|
|
19
19
|
to_uninstall=("pip", "setuptools", "wheel"),
|
|
20
20
|
pip_installer="uv",
|
|
21
21
|
)
|
|
@@ -149,7 +149,7 @@ services:
|
|
|
149
149
|
COPY --from=cli_1 . /deps/cli_1
|
|
150
150
|
# -- End of local package ../../.. --
|
|
151
151
|
# -- Installing all local dependencies --
|
|
152
|
-
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --
|
|
152
|
+
RUN for dep in /deps/*; do echo "Installing $dep"; if [ -d "$dep" ]; then echo "Installing $dep"; (cd "$dep" && PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt .); fi; done
|
|
153
153
|
# -- End of local dependencies install --
|
|
154
154
|
ENV LANGSERVE_GRAPHS='{{"agent": "agent.py:graph"}}'
|
|
155
155
|
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
|