langgraph-api 0.0.28rc1__py3-none-any.whl → 0.0.31__py3-none-any.whl
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.
Potentially problematic release.
This version of langgraph-api might be problematic. Click here for more details.
- langgraph_api/api/__init__.py +2 -0
- langgraph_api/api/assistants.py +2 -1
- langgraph_api/api/runs.py +2 -0
- langgraph_api/auth/custom.py +6 -2
- langgraph_api/auth/middleware.py +5 -0
- langgraph_api/cli.py +2 -36
- langgraph_api/config.py +83 -2
- langgraph_api/js/client.mts +4 -2
- langgraph_api/js/src/parser/parser.mts +5 -0
- langgraph_api/js/src/schema/types.mts +0 -120
- langgraph_api/js/src/schema/types.template.mts +13 -11
- langgraph_api/js/tests/api.test.mts +1 -1
- langgraph_api/lifespan.py +3 -0
- langgraph_api/logging.py +4 -3
- {langgraph_api-0.0.28rc1.dist-info → langgraph_api-0.0.31.dist-info}/METADATA +4 -4
- {langgraph_api-0.0.28rc1.dist-info → langgraph_api-0.0.31.dist-info}/RECORD +21 -21
- langgraph_storage/ops.py +1 -1
- langgraph_storage/store.py +4 -0
- {langgraph_api-0.0.28rc1.dist-info → langgraph_api-0.0.31.dist-info}/LICENSE +0 -0
- {langgraph_api-0.0.28rc1.dist-info → langgraph_api-0.0.31.dist-info}/WHEEL +0 -0
- {langgraph_api-0.0.28rc1.dist-info → langgraph_api-0.0.31.dist-info}/entry_points.txt +0 -0
langgraph_api/api/__init__.py
CHANGED
|
@@ -64,6 +64,8 @@ if HTTP_CONFIG:
|
|
|
64
64
|
protected_routes.extend(threads_routes)
|
|
65
65
|
if not HTTP_CONFIG.get("disable_store"):
|
|
66
66
|
protected_routes.extend(store_routes)
|
|
67
|
+
if not HTTP_CONFIG.get("disable_ui"):
|
|
68
|
+
protected_routes.extend(ui_routes)
|
|
67
69
|
else:
|
|
68
70
|
protected_routes.extend(assistants_routes)
|
|
69
71
|
protected_routes.extend(runs_routes)
|
langgraph_api/api/assistants.py
CHANGED
|
@@ -184,7 +184,8 @@ async def get_assistant_graph(
|
|
|
184
184
|
return ApiResponse(drawable_graph.to_json())
|
|
185
185
|
|
|
186
186
|
try:
|
|
187
|
-
|
|
187
|
+
drawable_graph = await graph.aget_graph(xray=xray)
|
|
188
|
+
return ApiResponse(drawable_graph.to_json())
|
|
188
189
|
except NotImplementedError:
|
|
189
190
|
raise HTTPException(
|
|
190
191
|
422, detail="The graph does not support visualization"
|
langgraph_api/api/runs.py
CHANGED
|
@@ -354,11 +354,13 @@ async def join_run_stream_endpoint(request: ApiRequest):
|
|
|
354
354
|
cancel_on_disconnect = cancel_on_disconnect_str.lower() in {"true", "yes", "1"}
|
|
355
355
|
validate_uuid(thread_id, "Invalid thread ID: must be a UUID")
|
|
356
356
|
validate_uuid(run_id, "Invalid run ID: must be a UUID")
|
|
357
|
+
stream_mode = request.query_params.get("stream_mode") or None
|
|
357
358
|
return EventSourceResponse(
|
|
358
359
|
Runs.Stream.join(
|
|
359
360
|
run_id,
|
|
360
361
|
thread_id=thread_id,
|
|
361
362
|
cancel_on_disconnect=cancel_on_disconnect,
|
|
363
|
+
stream_mode=stream_mode,
|
|
362
364
|
)
|
|
363
365
|
)
|
|
364
366
|
|
langgraph_api/auth/custom.py
CHANGED
|
@@ -18,6 +18,7 @@ from starlette.authentication import (
|
|
|
18
18
|
BaseUser,
|
|
19
19
|
)
|
|
20
20
|
from starlette.concurrency import run_in_threadpool
|
|
21
|
+
from starlette.datastructures import QueryParams
|
|
21
22
|
from starlette.exceptions import HTTPException
|
|
22
23
|
from starlette.requests import HTTPConnection, Request
|
|
23
24
|
from starlette.responses import Response
|
|
@@ -37,7 +38,7 @@ SUPPORTED_PARAMETERS = {
|
|
|
37
38
|
"scopes": list[str],
|
|
38
39
|
"path_params": dict[str, str] | None,
|
|
39
40
|
"query_params": dict[str, str] | None,
|
|
40
|
-
"headers": dict[
|
|
41
|
+
"headers": dict[bytes, bytes] | None,
|
|
41
42
|
"authorization": str | None,
|
|
42
43
|
"scope": dict[str, Any],
|
|
43
44
|
}
|
|
@@ -271,7 +272,7 @@ def _extract_arguments_from_scope(
|
|
|
271
272
|
if "path" in param_names:
|
|
272
273
|
args["path"] = scope["path"]
|
|
273
274
|
if "query_params" in param_names:
|
|
274
|
-
args["query_params"] = scope.get("
|
|
275
|
+
args["query_params"] = QueryParams(scope.get("query_string"))
|
|
275
276
|
if "headers" in param_names:
|
|
276
277
|
args["headers"] = dict(scope.get("headers", {}))
|
|
277
278
|
if "authorization" in param_names:
|
|
@@ -478,6 +479,9 @@ class ProxyUser(BaseUser):
|
|
|
478
479
|
"""Proxy any other attributes to the underlying user object."""
|
|
479
480
|
return getattr(self._user, name)
|
|
480
481
|
|
|
482
|
+
def __str__(self) -> str:
|
|
483
|
+
return f"{self._user}"
|
|
484
|
+
|
|
481
485
|
|
|
482
486
|
class SimpleUser(ProxyUser):
|
|
483
487
|
def __init__(self, username: str):
|
langgraph_api/auth/middleware.py
CHANGED
|
@@ -42,6 +42,11 @@ class ConditionalAuthenticationMiddleware(AuthenticationMiddleware):
|
|
|
42
42
|
await self.app(scope, receive, send)
|
|
43
43
|
return
|
|
44
44
|
|
|
45
|
+
if scope["path"].startswith("/ui") and scope["method"] == "GET":
|
|
46
|
+
# disable auth for UI asset requests
|
|
47
|
+
await self.app(scope, receive, send)
|
|
48
|
+
return
|
|
49
|
+
|
|
45
50
|
return await super().__call__(scope, receive, send)
|
|
46
51
|
|
|
47
52
|
|
langgraph_api/cli.py
CHANGED
|
@@ -10,7 +10,7 @@ from collections.abc import Mapping, Sequence
|
|
|
10
10
|
from typing_extensions import TypedDict
|
|
11
11
|
|
|
12
12
|
if typing.TYPE_CHECKING:
|
|
13
|
-
from langgraph_api.config import HttpConfig
|
|
13
|
+
from langgraph_api.config import HttpConfig, StoreConfig
|
|
14
14
|
|
|
15
15
|
logging.basicConfig(level=logging.INFO)
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
@@ -75,40 +75,6 @@ def patch_environment(**kwargs):
|
|
|
75
75
|
os.environ[key] = value
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
class IndexConfig(TypedDict, total=False):
|
|
79
|
-
"""Configuration for indexing documents for semantic search in the store."""
|
|
80
|
-
|
|
81
|
-
dims: int
|
|
82
|
-
"""Number of dimensions in the embedding vectors.
|
|
83
|
-
|
|
84
|
-
Common embedding models have the following dimensions:
|
|
85
|
-
- OpenAI text-embedding-3-large: 256, 1024, or 3072
|
|
86
|
-
- OpenAI text-embedding-3-small: 512 or 1536
|
|
87
|
-
- OpenAI text-embedding-ada-002: 1536
|
|
88
|
-
- Cohere embed-english-v3.0: 1024
|
|
89
|
-
- Cohere embed-english-light-v3.0: 384
|
|
90
|
-
- Cohere embed-multilingual-v3.0: 1024
|
|
91
|
-
- Cohere embed-multilingual-light-v3.0: 384
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
embed: str
|
|
95
|
-
"""Either a path to an embedding model (./path/to/file.py:embedding_model)
|
|
96
|
-
or a name of an embedding model (openai:text-embedding-3-small)
|
|
97
|
-
|
|
98
|
-
Note: LangChain is required to use the model format specification.
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
fields: list[str] | None
|
|
102
|
-
"""Fields to extract text from for embedding generation.
|
|
103
|
-
|
|
104
|
-
Defaults to the root ["$"], which embeds the json object as a whole.
|
|
105
|
-
"""
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class StoreConfig(TypedDict, total=False):
|
|
109
|
-
index: IndexConfig
|
|
110
|
-
|
|
111
|
-
|
|
112
78
|
class SecurityConfig(TypedDict, total=False):
|
|
113
79
|
securitySchemes: dict
|
|
114
80
|
security: list
|
|
@@ -160,7 +126,7 @@ def run_server(
|
|
|
160
126
|
env: str | pathlib.Path | Mapping[str, str] | None = None,
|
|
161
127
|
reload_includes: Sequence[str] | None = None,
|
|
162
128
|
reload_excludes: Sequence[str] | None = None,
|
|
163
|
-
store: StoreConfig
|
|
129
|
+
store: typing.Optional["StoreConfig"] = None,
|
|
164
130
|
auth: AuthConfig | None = None,
|
|
165
131
|
http: typing.Optional["HttpConfig"] = None,
|
|
166
132
|
**kwargs: typing.Any,
|
langgraph_api/config.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from os import environ, getenv
|
|
2
|
-
from typing import TypedDict
|
|
2
|
+
from typing import Literal, TypedDict
|
|
3
3
|
|
|
4
4
|
import orjson
|
|
5
5
|
from starlette.config import Config, undefined
|
|
@@ -34,6 +34,66 @@ class HttpConfig(TypedDict, total=False):
|
|
|
34
34
|
cors: CorsConfig | None
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
class IndexConfig(TypedDict, total=False):
|
|
38
|
+
"""Configuration for indexing documents for semantic search in the store."""
|
|
39
|
+
|
|
40
|
+
dims: int
|
|
41
|
+
"""Number of dimensions in the embedding vectors.
|
|
42
|
+
|
|
43
|
+
Common embedding models have the following dimensions:
|
|
44
|
+
- OpenAI text-embedding-3-large: 256, 1024, or 3072
|
|
45
|
+
- OpenAI text-embedding-3-small: 512 or 1536
|
|
46
|
+
- OpenAI text-embedding-ada-002: 1536
|
|
47
|
+
- Cohere embed-english-v3.0: 1024
|
|
48
|
+
- Cohere embed-english-light-v3.0: 384
|
|
49
|
+
- Cohere embed-multilingual-v3.0: 1024
|
|
50
|
+
- Cohere embed-multilingual-light-v3.0: 384
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
embed: str
|
|
54
|
+
"""Either a path to an embedding model (./path/to/file.py:embedding_model)
|
|
55
|
+
or a name of an embedding model (openai:text-embedding-3-small)
|
|
56
|
+
|
|
57
|
+
Note: LangChain is required to use the model format specification.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
fields: list[str] | None
|
|
61
|
+
"""Fields to extract text from for embedding generation.
|
|
62
|
+
|
|
63
|
+
Defaults to the root ["$"], which embeds the json object as a whole.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TTLConfig(TypedDict, total=False):
|
|
68
|
+
"""Configuration for TTL (time-to-live) behavior in the store."""
|
|
69
|
+
|
|
70
|
+
refresh_on_read: bool
|
|
71
|
+
"""Default behavior for refreshing TTLs on read operations (GET and SEARCH).
|
|
72
|
+
|
|
73
|
+
If True, TTLs will be refreshed on read operations (get/search) by default.
|
|
74
|
+
This can be overridden per-operation by explicitly setting refresh_ttl.
|
|
75
|
+
Defaults to True if not configured.
|
|
76
|
+
"""
|
|
77
|
+
default_ttl: float | None
|
|
78
|
+
"""Default TTL (time-to-live) in minutes for new items.
|
|
79
|
+
|
|
80
|
+
If provided, new items will expire after this many minutes after their last access.
|
|
81
|
+
The expiration timer refreshes on both read and write operations.
|
|
82
|
+
Defaults to None (no expiration).
|
|
83
|
+
"""
|
|
84
|
+
sweep_interval_minutes: int | None
|
|
85
|
+
"""Interval in minutes between TTL sweep operations.
|
|
86
|
+
|
|
87
|
+
If provided, the store will periodically delete expired items based on TTL.
|
|
88
|
+
Defaults to None (no sweeping).
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class StoreConfig(TypedDict, total=False):
|
|
93
|
+
index: IndexConfig
|
|
94
|
+
ttl: TTLConfig
|
|
95
|
+
|
|
96
|
+
|
|
37
97
|
# env
|
|
38
98
|
|
|
39
99
|
env = Config()
|
|
@@ -55,6 +115,18 @@ STATS_INTERVAL_SECS = env("STATS_INTERVAL_SECS", cast=int, default=60)
|
|
|
55
115
|
DATABASE_URI = env("DATABASE_URI", cast=str, default=getenv("POSTGRES_URI", undefined))
|
|
56
116
|
MIGRATIONS_PATH = env("MIGRATIONS_PATH", cast=str, default="/storage/migrations")
|
|
57
117
|
|
|
118
|
+
|
|
119
|
+
def _get_encryption_key(key_str: str | None):
|
|
120
|
+
if not key_str:
|
|
121
|
+
return None
|
|
122
|
+
key = key_str.encode(encoding="utf-8")
|
|
123
|
+
if len(key) not in (16, 24, 32):
|
|
124
|
+
raise ValueError("LANGGRAPH_AES_KEY must be 16, 24, or 32 bytes long.")
|
|
125
|
+
return key
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
LANGGRAPH_AES_KEY = env("LANGGRAPH_AES_KEY", default=None, cast=_get_encryption_key)
|
|
129
|
+
|
|
58
130
|
# redis
|
|
59
131
|
REDIS_URI = env("REDIS_URI", cast=str)
|
|
60
132
|
REDIS_CLUSTER = env("REDIS_CLUSTER", cast=bool, default=False)
|
|
@@ -69,7 +141,9 @@ See https://developer.chrome.com/blog/private-network-access-update-2024-03
|
|
|
69
141
|
"""
|
|
70
142
|
|
|
71
143
|
HTTP_CONFIG: HttpConfig | None = env("LANGGRAPH_HTTP", cast=_parse_json, default=None)
|
|
72
|
-
STORE_CONFIG:
|
|
144
|
+
STORE_CONFIG: StoreConfig | None = env(
|
|
145
|
+
"LANGGRAPH_STORE", cast=_parse_json, default=None
|
|
146
|
+
)
|
|
73
147
|
CORS_ALLOW_ORIGINS = env("CORS_ALLOW_ORIGINS", cast=CommaSeparatedStrings, default="*")
|
|
74
148
|
if HTTP_CONFIG and HTTP_CONFIG.get("cors"):
|
|
75
149
|
CORS_CONFIG = HTTP_CONFIG["cors"]
|
|
@@ -132,6 +206,13 @@ FF_CRONS_ENABLED = env("FF_CRONS_ENABLED", cast=bool, default=True)
|
|
|
132
206
|
# auth
|
|
133
207
|
|
|
134
208
|
LANGGRAPH_AUTH_TYPE = env("LANGGRAPH_AUTH_TYPE", cast=str, default="noop")
|
|
209
|
+
LANGGRAPH_POSTGRES_EXTENSIONS: Literal["standard", "lite"] = env(
|
|
210
|
+
"LANGGRAPH_POSTGRES_EXTENSIONS", cast=str, default="standard"
|
|
211
|
+
)
|
|
212
|
+
if LANGGRAPH_POSTGRES_EXTENSIONS not in ("standard", "lite"):
|
|
213
|
+
raise ValueError(
|
|
214
|
+
f"Unknown LANGGRAPH_POSTGRES_EXTENSIONS value: {LANGGRAPH_POSTGRES_EXTENSIONS}"
|
|
215
|
+
)
|
|
135
216
|
LANGGRAPH_AUTH = env("LANGGRAPH_AUTH", cast=_parse_json, default=None)
|
|
136
217
|
LANGSMITH_TENANT_ID = env("LANGSMITH_TENANT_ID", cast=str, default=None)
|
|
137
218
|
LANGSMITH_AUTH_VERIFY_TENANT_ID = env(
|
langgraph_api/js/client.mts
CHANGED
|
@@ -493,6 +493,7 @@ const StreamModeSchema = z.union([
|
|
|
493
493
|
z.literal("updates"),
|
|
494
494
|
z.literal("debug"),
|
|
495
495
|
z.literal("values"),
|
|
496
|
+
z.literal("custom"),
|
|
496
497
|
]);
|
|
497
498
|
|
|
498
499
|
const ExtraStreamModeSchema = z.union([
|
|
@@ -529,8 +530,9 @@ async function* streamEventsRequest(
|
|
|
529
530
|
? payload.stream_mode
|
|
530
531
|
: [payload.stream_mode];
|
|
531
532
|
|
|
532
|
-
const graphStreamMode: Set<
|
|
533
|
-
|
|
533
|
+
const graphStreamMode: Set<
|
|
534
|
+
"updates" | "debug" | "values" | "messages" | "custom"
|
|
535
|
+
> = new Set();
|
|
534
536
|
if (payload.stream_mode) {
|
|
535
537
|
for (const mode of userStreamMode) {
|
|
536
538
|
if (mode === "messages") {
|
|
@@ -348,6 +348,11 @@ export class SubgraphExtractor {
|
|
|
348
348
|
|
|
349
349
|
const fsMap = new Map<string, string>();
|
|
350
350
|
const system = vfs.createFSBackedSystem(fsMap, dirname, ts);
|
|
351
|
+
|
|
352
|
+
// TODO: investigate if we should create a PR in @typescript/vfs
|
|
353
|
+
const oldReadFile = system.readFile.bind(system);
|
|
354
|
+
system.readFile = (fileName) => oldReadFile(fileName) ?? "// Non-existent file";
|
|
355
|
+
|
|
351
356
|
const host = vfs.createVirtualCompilerHost(system, compilerOptions, ts);
|
|
352
357
|
|
|
353
358
|
const targetPath =
|
|
@@ -2014,123 +2014,3 @@ export function buildGenerator(
|
|
|
2014
2014
|
settings
|
|
2015
2015
|
);
|
|
2016
2016
|
}
|
|
2017
|
-
|
|
2018
|
-
export async function extractGraphSchema(
|
|
2019
|
-
id: string,
|
|
2020
|
-
userPath: string,
|
|
2021
|
-
exportName: string
|
|
2022
|
-
) {
|
|
2023
|
-
const filePath = path.resolve(process.cwd(), userPath);
|
|
2024
|
-
const parentPath = path.dirname(filePath);
|
|
2025
|
-
|
|
2026
|
-
const typePath = path.resolve(parentPath, `__$0${id}.mts`);
|
|
2027
|
-
const importPath = path.relative(parentPath, filePath);
|
|
2028
|
-
|
|
2029
|
-
try {
|
|
2030
|
-
await fs.writeFile(
|
|
2031
|
-
typePath,
|
|
2032
|
-
dedent`
|
|
2033
|
-
import { ${exportName} as __graph } from "./${importPath}";
|
|
2034
|
-
import type { BaseMessage } from "@langchain/core/messages";
|
|
2035
|
-
import type {
|
|
2036
|
-
StateType,
|
|
2037
|
-
UpdateType,
|
|
2038
|
-
StateDefinition,
|
|
2039
|
-
} from "@langchain/langgraph";
|
|
2040
|
-
|
|
2041
|
-
type Wrap<T> = (a: T) => void;
|
|
2042
|
-
type MatchBaseMessage<T> = T extends BaseMessage ? BaseMessage : never;
|
|
2043
|
-
type MatchBaseMessageArray<T> =
|
|
2044
|
-
T extends Array<infer C>
|
|
2045
|
-
? Wrap<MatchBaseMessage<C>> extends Wrap<BaseMessage>
|
|
2046
|
-
? BaseMessage[]
|
|
2047
|
-
: never
|
|
2048
|
-
: never;
|
|
2049
|
-
|
|
2050
|
-
type Defactorify<T> = T extends (...args: any[]) => infer R
|
|
2051
|
-
? Awaited<R>
|
|
2052
|
-
: Awaited<T>;
|
|
2053
|
-
|
|
2054
|
-
type Inspect<T> = T extends unknown
|
|
2055
|
-
? {
|
|
2056
|
-
[K in keyof T]: 0 extends 1 & T[K]
|
|
2057
|
-
? T[K]
|
|
2058
|
-
: Wrap<MatchBaseMessageArray<T[K]>> extends Wrap<BaseMessage[]>
|
|
2059
|
-
? BaseMessage[]
|
|
2060
|
-
: Wrap<MatchBaseMessage<T[K]>> extends Wrap<BaseMessage>
|
|
2061
|
-
? BaseMessage
|
|
2062
|
-
: Inspect<T[K]>;
|
|
2063
|
-
}
|
|
2064
|
-
: never;
|
|
2065
|
-
|
|
2066
|
-
type ReflectCompiled<T> = T extends { RunInput: infer S; RunOutput: infer U }
|
|
2067
|
-
? { state: S; update: U }
|
|
2068
|
-
: never;
|
|
2069
|
-
|
|
2070
|
-
type Reflect<T> =
|
|
2071
|
-
Defactorify<T> extends infer DT
|
|
2072
|
-
? DT extends {
|
|
2073
|
-
compile(...args: any[]): infer Compiled;
|
|
2074
|
-
}
|
|
2075
|
-
? ReflectCompiled<Compiled>
|
|
2076
|
-
: ReflectCompiled<DT>
|
|
2077
|
-
: never;
|
|
2078
|
-
|
|
2079
|
-
type __reflect = Reflect<typeof __graph>;
|
|
2080
|
-
export type __state = Inspect<__reflect["state"]>;
|
|
2081
|
-
export type __update = Inspect<__reflect["update"]>;
|
|
2082
|
-
|
|
2083
|
-
type BuilderReflectCompiled<T> = T extends {
|
|
2084
|
-
builder: {
|
|
2085
|
-
_inputDefinition: infer I extends StateDefinition;
|
|
2086
|
-
_outputDefinition: infer O extends StateDefinition;
|
|
2087
|
-
_configSchema?: infer C extends StateDefinition | undefined;
|
|
2088
|
-
};
|
|
2089
|
-
}
|
|
2090
|
-
? { input: UpdateType<I>; output: StateType<O>; config: UpdateType<C> }
|
|
2091
|
-
: never;
|
|
2092
|
-
|
|
2093
|
-
type BuilderReflect<T> =
|
|
2094
|
-
Defactorify<T> extends infer DT
|
|
2095
|
-
? DT extends {
|
|
2096
|
-
compile(...args: any[]): infer Compiled;
|
|
2097
|
-
}
|
|
2098
|
-
? BuilderReflectCompiled<Compiled>
|
|
2099
|
-
: BuilderReflectCompiled<DT>
|
|
2100
|
-
: never;
|
|
2101
|
-
|
|
2102
|
-
type __builder = BuilderReflect<typeof __graph>;
|
|
2103
|
-
type FilterAny<T> = 0 extends 1 & T ? never : T;
|
|
2104
|
-
export type __input = Inspect<FilterAny<__builder["input"]>>;
|
|
2105
|
-
export type __output = Inspect<FilterAny<__builder["output"]>>;
|
|
2106
|
-
export type __config = Inspect<FilterAny<__builder["config"]>>;
|
|
2107
|
-
`
|
|
2108
|
-
);
|
|
2109
|
-
const program = ts.createProgram([typePath], {
|
|
2110
|
-
noEmit: true,
|
|
2111
|
-
strict: true,
|
|
2112
|
-
allowUnusedLabels: true,
|
|
2113
|
-
});
|
|
2114
|
-
|
|
2115
|
-
const schema = buildGenerator(program);
|
|
2116
|
-
|
|
2117
|
-
const trySymbol = (schema: JsonSchemaGenerator | null, symbol: string) => {
|
|
2118
|
-
try {
|
|
2119
|
-
return schema?.getSchemaForSymbol(symbol) ?? undefined;
|
|
2120
|
-
} catch (e) {
|
|
2121
|
-
console.error(`Failed to obtain symbol "${symbol}":`, e?.message);
|
|
2122
|
-
}
|
|
2123
|
-
return undefined;
|
|
2124
|
-
};
|
|
2125
|
-
|
|
2126
|
-
return {
|
|
2127
|
-
state: trySymbol(schema, "__state"),
|
|
2128
|
-
update: trySymbol(schema, "__update"),
|
|
2129
|
-
input: trySymbol(schema, "__input"),
|
|
2130
|
-
output: trySymbol(schema, "__output"),
|
|
2131
|
-
config: trySymbol(schema, "__config"),
|
|
2132
|
-
};
|
|
2133
|
-
} finally {
|
|
2134
|
-
await fs.unlink(typePath);
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
@@ -23,17 +23,19 @@ type Defactorify<T> = T extends (...args: any[]) => infer R
|
|
|
23
23
|
? Awaited<R>
|
|
24
24
|
: Awaited<T>;
|
|
25
25
|
|
|
26
|
-
type Inspect<T> =
|
|
27
|
-
?
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
?
|
|
32
|
-
: Wrap<
|
|
33
|
-
? BaseMessage
|
|
34
|
-
:
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
type Inspect<T, CNT extends Array<0> = []> = CNT extends [0, 0, 0]
|
|
27
|
+
? any
|
|
28
|
+
: T extends unknown
|
|
29
|
+
? {
|
|
30
|
+
[K in keyof T]: 0 extends 1 & T[K]
|
|
31
|
+
? T[K]
|
|
32
|
+
: Wrap<MatchBaseMessageArray<T[K]>> extends Wrap<BaseMessage[]>
|
|
33
|
+
? BaseMessage[]
|
|
34
|
+
: Wrap<MatchBaseMessage<T[K]>> extends Wrap<BaseMessage>
|
|
35
|
+
? BaseMessage
|
|
36
|
+
: Inspect<T[K], [0, ...CNT]>;
|
|
37
|
+
}
|
|
38
|
+
: never;
|
|
37
39
|
|
|
38
40
|
type ReflectCompiled<T> = T extends { RunInput: infer S; RunOutput: infer U }
|
|
39
41
|
? { state: S; update: U }
|
|
@@ -765,7 +765,7 @@ describe("runs", () => {
|
|
|
765
765
|
|
|
766
766
|
it.concurrent(
|
|
767
767
|
"human in the loop - no modification",
|
|
768
|
-
{ retry:
|
|
768
|
+
{ retry: 3 },
|
|
769
769
|
async () => {
|
|
770
770
|
const assistant = await client.assistants.create({ graphId: "agent" });
|
|
771
771
|
const thread = await client.threads.create();
|
langgraph_api/lifespan.py
CHANGED
|
@@ -12,6 +12,7 @@ from langgraph_api.metadata import metadata_loop
|
|
|
12
12
|
from langgraph_license.validation import get_license_status, plus_features_enabled
|
|
13
13
|
from langgraph_storage.database import start_pool, stop_pool
|
|
14
14
|
from langgraph_storage.queue import queue
|
|
15
|
+
from langgraph_storage.store import Store
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
@asynccontextmanager
|
|
@@ -44,6 +45,8 @@ async def lifespan(
|
|
|
44
45
|
and plus_features_enabled()
|
|
45
46
|
):
|
|
46
47
|
tg.create_task(cron_scheduler())
|
|
48
|
+
if config.STORE_CONFIG and config.STORE_CONFIG.get("ttl"):
|
|
49
|
+
tg.create_task(Store().start_ttl_sweeper())
|
|
47
50
|
yield
|
|
48
51
|
finally:
|
|
49
52
|
await stop_remote_graphs()
|
langgraph_api/logging.py
CHANGED
|
@@ -6,9 +6,6 @@ import structlog
|
|
|
6
6
|
from starlette.config import Config
|
|
7
7
|
from structlog.typing import EventDict
|
|
8
8
|
|
|
9
|
-
from langgraph_api.metadata import append_log
|
|
10
|
-
from langgraph_api.serde import json_dumpb
|
|
11
|
-
|
|
12
9
|
# env
|
|
13
10
|
|
|
14
11
|
log_env = Config()
|
|
@@ -52,6 +49,8 @@ class JSONRenderer:
|
|
|
52
49
|
"""
|
|
53
50
|
The return type of this depends on the return type of self._dumps.
|
|
54
51
|
"""
|
|
52
|
+
from langgraph_api.serde import json_dumpb
|
|
53
|
+
|
|
55
54
|
return json_dumpb(event_dict).decode()
|
|
56
55
|
|
|
57
56
|
|
|
@@ -69,6 +68,8 @@ class TapForMetadata:
|
|
|
69
68
|
event_dict["logger"].startswith("langgraph")
|
|
70
69
|
and LEVELS[event_dict["level"].upper()] > LEVELS["INFO"]
|
|
71
70
|
):
|
|
71
|
+
from langgraph_api.metadata import append_log
|
|
72
|
+
|
|
72
73
|
append_log(event_dict.copy())
|
|
73
74
|
return event_dict
|
|
74
75
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.31
|
|
4
4
|
Summary:
|
|
5
5
|
License: Elastic-2.0
|
|
6
6
|
Author: Nuno Campos
|
|
@@ -12,11 +12,11 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Requires-Dist: cryptography (>=43.0.3,<44.0.0)
|
|
14
14
|
Requires-Dist: httpx (>=0.25.0)
|
|
15
|
-
Requires-Dist: jsonschema-rs (>=0.20.0,<0.
|
|
15
|
+
Requires-Dist: jsonschema-rs (>=0.20.0,<0.30)
|
|
16
16
|
Requires-Dist: langchain-core (>=0.2.38,<0.4.0)
|
|
17
17
|
Requires-Dist: langgraph (>=0.2.56,<0.4.0)
|
|
18
|
-
Requires-Dist: langgraph-checkpoint (>=2.0.
|
|
19
|
-
Requires-Dist: langgraph-sdk (>=0.1.
|
|
18
|
+
Requires-Dist: langgraph-checkpoint (>=2.0.21,<3.0)
|
|
19
|
+
Requires-Dist: langgraph-sdk (>=0.1.57,<0.2.0)
|
|
20
20
|
Requires-Dist: langsmith (>=0.1.63,<0.4.0)
|
|
21
21
|
Requires-Dist: orjson (>=3.9.7)
|
|
22
22
|
Requires-Dist: pyjwt (>=2.9.0,<3.0.0)
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
2
2
|
langgraph_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
langgraph_api/api/__init__.py,sha256=
|
|
4
|
-
langgraph_api/api/assistants.py,sha256=
|
|
3
|
+
langgraph_api/api/__init__.py,sha256=B2kHOBhKjBRdNiWPljYuJFxP__wYPCvgtgTaWYKZGTQ,5129
|
|
4
|
+
langgraph_api/api/assistants.py,sha256=2HEIcxaOJJ4_JQ00TKT1ehx7DMbYCGpvhShK0ZiWsSE,14043
|
|
5
5
|
langgraph_api/api/meta.py,sha256=ifJ_Ki0Qf2DYbmY6OKlqKhLGxbt55gm0lEqH1A0cJbw,2790
|
|
6
6
|
langgraph_api/api/openapi.py,sha256=f9gfmWN2AMKNUpLCpSgZuw_aeOF9jCXPdOtFT5PaTWM,10960
|
|
7
|
-
langgraph_api/api/runs.py,sha256=
|
|
7
|
+
langgraph_api/api/runs.py,sha256=_RWKtmjD89ALnTk56dwo2rJwEi2oghk2Tqp0l1aCcZg,16677
|
|
8
8
|
langgraph_api/api/store.py,sha256=VzAJVOwO0IxosBB7km5TTf2rhlWGyPkVz_LpvbxetVY,5437
|
|
9
9
|
langgraph_api/api/threads.py,sha256=taU61XPcCEhBPCYPZcMDsgVDwwWUWJs8p-PrXFXWY48,8661
|
|
10
10
|
langgraph_api/api/ui.py,sha256=LiOZVewKOPbKEykCm30hCEaOA7vuS_Ti5hB32EEy4vw,2082
|
|
11
11
|
langgraph_api/asyncio.py,sha256=ipxOGL0CuKZeHw8895ojtfoBU2fj0iJOp48uhiLAmss,7786
|
|
12
12
|
langgraph_api/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
langgraph_api/auth/custom.py,sha256=
|
|
13
|
+
langgraph_api/auth/custom.py,sha256=z69UvpG7wPSXtRmp_UFmA8fY7HeQD4AEIWu3qlpJOBc,21210
|
|
14
14
|
langgraph_api/auth/langsmith/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
langgraph_api/auth/langsmith/backend.py,sha256=InScaL-HYCnxYEauhxU198gRZV9pJn9SzzBoR9Edn7g,2654
|
|
16
16
|
langgraph_api/auth/langsmith/client.py,sha256=eKchvAom7hdkUXauD8vHNceBDDUijrFgdTV8bKd7x4Q,3998
|
|
17
|
-
langgraph_api/auth/middleware.py,sha256=
|
|
17
|
+
langgraph_api/auth/middleware.py,sha256=jU8aDSIZHdzCGdifejRF7ndHkSjBtqIHcBwFIuUdHEA,1875
|
|
18
18
|
langgraph_api/auth/noop.py,sha256=Bk6Nf3p8D_iMVy_OyfPlyiJp_aEwzL-sHrbxoXpCbac,586
|
|
19
19
|
langgraph_api/auth/studio_user.py,sha256=FzFQRROKDlA9JjtBuwyZvk6Mbwno5M9RVYjDO6FU3F8,186
|
|
20
|
-
langgraph_api/cli.py,sha256=
|
|
21
|
-
langgraph_api/config.py,sha256=
|
|
20
|
+
langgraph_api/cli.py,sha256=3SAwPv8EDKqJx52oD3CB3h0vN7m-LI3lT0RmYFMfkNM,11671
|
|
21
|
+
langgraph_api/config.py,sha256=XMJEVfPe1LrmVKGM5sisQs1eZOUDyU3JwscwJOm0q_k,8572
|
|
22
22
|
langgraph_api/cron_scheduler.py,sha256=9yzbbGxzNgJdIg4ZT7yu2oTwT_wRuPxD1c2sbbd52xs,2630
|
|
23
23
|
langgraph_api/errors.py,sha256=Bu_i5drgNTyJcLiyrwVE_6-XrSU50BHf9TDpttki9wQ,1690
|
|
24
24
|
langgraph_api/graph.py,sha256=viFyQa8-BRRNRZqNNUzLB31cB4IypEMkMucQEJQYLWY,16556
|
|
@@ -26,7 +26,7 @@ langgraph_api/http.py,sha256=gYbxxjY8aLnsXeJymcJ7G7Nj_yToOGpPYQqmZ1_ggfA,5240
|
|
|
26
26
|
langgraph_api/js/.gitignore,sha256=l5yI6G_V6F1600I1IjiUKn87f4uYIrBAYU1MOyBBhg4,59
|
|
27
27
|
langgraph_api/js/base.py,sha256=BpE8-xkUp8HFPRjSKx1tfUQubvoV4jYl6OwZdre3veI,209
|
|
28
28
|
langgraph_api/js/build.mts,sha256=ArAEn74HHY_KXt0JCne76FTyGP34VQCHMe6OfPyxLM8,2915
|
|
29
|
-
langgraph_api/js/client.mts,sha256=
|
|
29
|
+
langgraph_api/js/client.mts,sha256=2dptAX8fMowV9OC4DU4khjpZUgALBLVBTu3jTQbeUJY,24394
|
|
30
30
|
langgraph_api/js/errors.py,sha256=Cm1TKWlUCwZReDC5AQ6SgNIVGD27Qov2xcgHyf8-GXo,361
|
|
31
31
|
langgraph_api/js/global.d.ts,sha256=cLJRZfYVGmgQ6o_xFevVNNTIi918ZUdxVRnpLVSjiAY,133
|
|
32
32
|
langgraph_api/js/package.json,sha256=j6DMoVgwRqWqTwdd7R1f-kvmiTUAbO3HaUhM8K64lbE,1224
|
|
@@ -34,15 +34,15 @@ langgraph_api/js/remote.py,sha256=jUUgdskUbDR_tuhZFrJo4OewbndQ76joczBv-mZHG9k,22
|
|
|
34
34
|
langgraph_api/js/schema.py,sha256=7idnv7URlYUdSNMBXQcw7E4SxaPxCq_Oxwnlml8q5ik,408
|
|
35
35
|
langgraph_api/js/src/graph.mts,sha256=mRyMUp03Fwd5DlmNIFl3RiUCQuJ5XwmFp1AfAeKDfVc,3169
|
|
36
36
|
langgraph_api/js/src/hooks.mjs,sha256=XtktgmIHlls_DsknAuwib-z7TqCm0haRoTXvnkgzMuo,601
|
|
37
|
-
langgraph_api/js/src/parser/parser.mts,sha256=
|
|
37
|
+
langgraph_api/js/src/parser/parser.mts,sha256=c7WLEtMMwtVzir9O8VpJFVHKuLjtI86rde-In2lvaM0,13217
|
|
38
38
|
langgraph_api/js/src/parser/parser.worker.mjs,sha256=2K6D0GlUmkk7LE39I8mryB8VZVE3-N9Cblji-ArPhFo,386
|
|
39
|
-
langgraph_api/js/src/schema/types.mts,sha256=
|
|
40
|
-
langgraph_api/js/src/schema/types.template.mts,sha256=
|
|
39
|
+
langgraph_api/js/src/schema/types.mts,sha256=SRCYZTWjxyc7528DaapR_DCm3G5bfDSh4vf-JsYpk0w,62633
|
|
40
|
+
langgraph_api/js/src/schema/types.template.mts,sha256=Dbjj_8d-OubqH4QY_OaxSu8ocZ4dVjI94oncL20fqtk,2235
|
|
41
41
|
langgraph_api/js/src/utils/importMap.mts,sha256=pX4TGOyUpuuWF82kXcxcv3-8mgusRezOGe6Uklm2O5A,1644
|
|
42
42
|
langgraph_api/js/src/utils/pythonSchemas.mts,sha256=98IW7Z_VP7L_CHNRMb3_MsiV3BgLE2JsWQY_PQcRR3o,685
|
|
43
43
|
langgraph_api/js/src/utils/serde.mts,sha256=OuyyO9btvwWd55rU_H4x91dFEJiaPxL-lL9O6Zgo908,742
|
|
44
44
|
langgraph_api/js/sse.py,sha256=lsfp4nyJyA1COmlKG9e2gJnTttf_HGCB5wyH8OZBER8,4105
|
|
45
|
-
langgraph_api/js/tests/api.test.mts,sha256=
|
|
45
|
+
langgraph_api/js/tests/api.test.mts,sha256=RTJb9ZMX_IhqUPcShK61LZG9v_-xzdIZ0oEmOIjbJ4c,57709
|
|
46
46
|
langgraph_api/js/tests/compose-postgres.yml,sha256=wV1Kws7WwUWVIudPkB--v58MOPL9hOcV0MUK-cvNrpA,1738
|
|
47
47
|
langgraph_api/js/tests/graphs/.gitignore,sha256=26J8MarZNXh7snXD5eTpV3CPFTht5Znv8dtHYCLNfkw,12
|
|
48
48
|
langgraph_api/js/tests/graphs/agent.css,sha256=QgcOC0W7IBsrg4pSqqpull-WTgtULZfx_lF_5ZxLdag,23
|
|
@@ -58,8 +58,8 @@ langgraph_api/js/tests/graphs/yarn.lock,sha256=i2AAIgXA3XBLM8-oU45wgUefCSG-Tne4g
|
|
|
58
58
|
langgraph_api/js/tests/parser.test.mts,sha256=dEC8KTqKygeb1u39ZvpPqCT4HtfPD947nLmITt2buxA,27883
|
|
59
59
|
langgraph_api/js/tests/utils.mts,sha256=2kTybJ3O7Yfe1q3ehDouqV54ibXkNzsPZ_wBZLJvY-4,421
|
|
60
60
|
langgraph_api/js/yarn.lock,sha256=W89dVYZMThcec08lJMcYnvEEnQK7VM5cPglvwpIdRv0,82773
|
|
61
|
-
langgraph_api/lifespan.py,sha256=
|
|
62
|
-
langgraph_api/logging.py,sha256=
|
|
61
|
+
langgraph_api/lifespan.py,sha256=u5Fv9I4JqfLk30p5cNqkcEqeB2vTRMGSM5WlFHlE0mU,2219
|
|
62
|
+
langgraph_api/logging.py,sha256=KB1ciduIWcMFfG0q9c5_SZemGrscht1RZXLZfeJSS00,3619
|
|
63
63
|
langgraph_api/metadata.py,sha256=jPLNIRxHi7taZ0g60UdOEXenkvDwoYdI11tsmHenb28,3443
|
|
64
64
|
langgraph_api/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
65
65
|
langgraph_api/middleware/http_logger.py,sha256=yuFPNFIWwn-4AE1CogBfWlo8KytzywLi_Bd4ccsyVQE,3150
|
|
@@ -86,15 +86,15 @@ langgraph_storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
86
86
|
langgraph_storage/checkpoint.py,sha256=V4t2GwYEJdPCHbhq_4Udhlv0TWKDzlMu_rlNPdTDc50,3589
|
|
87
87
|
langgraph_storage/database.py,sha256=I0AgFeJ-NSTT34vxKxQBUf1z2syFP0S8QpKCqTixrzY,5652
|
|
88
88
|
langgraph_storage/inmem_stream.py,sha256=8bxkILIuFpr7P7RQ37SQAxrpRKvmbHdRB_nbfFiomlk,3263
|
|
89
|
-
langgraph_storage/ops.py,sha256=
|
|
89
|
+
langgraph_storage/ops.py,sha256=6qj3zh3T7KZco_vz9FW1cI82sbrefo6u2BRmrUDXvZI,69529
|
|
90
90
|
langgraph_storage/queue.py,sha256=UDgsUTtUMfBSRDrQ8Onis-FJO4n7KTsX6sdpbY8Hs0A,5055
|
|
91
91
|
langgraph_storage/retry.py,sha256=XmldOP4e_H5s264CagJRVnQMDFcEJR_dldVR1Hm5XvM,763
|
|
92
|
-
langgraph_storage/store.py,sha256=
|
|
92
|
+
langgraph_storage/store.py,sha256=33-J5-Xvobb9ArSa-GezP5KtfXgzWkHUHPyjRYmdw-E,2985
|
|
93
93
|
langgraph_storage/ttl_dict.py,sha256=FlpEY8EANeXWKo_G5nmIotPquABZGyIJyk6HD9u6vqY,1533
|
|
94
94
|
logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
|
|
95
95
|
openapi.json,sha256=8NhoZn3Dse6Ia0i7fXCB46sdGnEg5qAhov_8of-6m0o,125282
|
|
96
|
-
langgraph_api-0.0.
|
|
97
|
-
langgraph_api-0.0.
|
|
98
|
-
langgraph_api-0.0.
|
|
99
|
-
langgraph_api-0.0.
|
|
100
|
-
langgraph_api-0.0.
|
|
96
|
+
langgraph_api-0.0.31.dist-info/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
97
|
+
langgraph_api-0.0.31.dist-info/METADATA,sha256=lSR24lckxz9BgmrjjqG7b04Q22m5m1W49dHtggG6BeY,4027
|
|
98
|
+
langgraph_api-0.0.31.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
99
|
+
langgraph_api-0.0.31.dist-info/entry_points.txt,sha256=3EYLgj89DfzqJHHYGxPH4A_fEtClvlRbWRUHaXO7hj4,77
|
|
100
|
+
langgraph_api-0.0.31.dist-info/RECORD,,
|
langgraph_storage/ops.py
CHANGED
|
@@ -1757,7 +1757,7 @@ class Runs(Authenticated):
|
|
|
1757
1757
|
queue = (
|
|
1758
1758
|
stream_mode
|
|
1759
1759
|
if isinstance(stream_mode, asyncio.Queue)
|
|
1760
|
-
else await Runs.Stream.subscribe(run_id)
|
|
1760
|
+
else await Runs.Stream.subscribe(run_id, stream_mode=stream_mode)
|
|
1761
1761
|
)
|
|
1762
1762
|
|
|
1763
1763
|
try:
|
langgraph_storage/store.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import os
|
|
2
3
|
import threading
|
|
3
4
|
from collections import defaultdict
|
|
@@ -42,6 +43,9 @@ class DiskBackedInMemStore(InMemoryStore):
|
|
|
42
43
|
f"Unexpected error loading store {which} from {container.filename}: {str(e)}"
|
|
43
44
|
) from e
|
|
44
45
|
|
|
46
|
+
async def start_ttl_sweeper(self) -> asyncio.Task[None]:
|
|
47
|
+
return asyncio.create_task(asyncio.sleep(0))
|
|
48
|
+
|
|
45
49
|
def close(self) -> None:
|
|
46
50
|
self._data.close()
|
|
47
51
|
self._vectors.close()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|