@langchain/langgraph-api 0.0.59 → 0.0.61
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.
- package/CHANGELOG.md +16 -0
- package/dist/api/assistants.mjs +16 -11
- package/dist/api/meta.mjs +24 -17
- package/dist/api/runs.mjs +19 -19
- package/dist/api/store.mjs +1 -1
- package/dist/api/threads.mjs +19 -14
- package/dist/auth/custom.d.mts +1 -4
- package/dist/auth/custom.mjs +1 -34
- package/dist/auth/index.d.mts +3 -0
- package/dist/auth/index.mjs +33 -0
- package/dist/experimental/embed.d.mts +1 -1
- package/dist/graph/api.d.mts +1 -0
- package/dist/graph/api.mjs +2 -0
- package/dist/graph/load.d.mts +3 -1
- package/dist/graph/load.mjs +9 -5
- package/dist/http/middleware.mjs +14 -10
- package/dist/loopback.d.mts +2 -1
- package/dist/queue.d.mts +2 -1
- package/dist/queue.mjs +10 -11
- package/dist/schemas.d.mts +141 -118
- package/dist/schemas.mjs +25 -0
- package/dist/server.d.mts +16 -13
- package/dist/server.mjs +27 -8
- package/dist/state.d.mts +1 -1
- package/dist/storage/context.d.mts +3 -0
- package/dist/storage/context.mjs +11 -0
- package/dist/storage/ops.d.mts +62 -202
- package/dist/storage/ops.mjs +187 -94
- package/dist/storage/types.d.mts +288 -0
- package/dist/storage/types.mjs +1 -0
- package/dist/stream.d.mts +1 -1
- package/dist/stream.mjs +12 -0
- package/dist/utils/runnableConfig.d.mts +1 -1
- package/dist/webhook.d.mts +1 -1
- package/package.json +16 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @langchain/langgraph-api
|
|
2
2
|
|
|
3
|
+
## 0.0.61
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a334897: feat(api): add /count endpoints for threads and assistants
|
|
8
|
+
- 9357bb7: chore(api): abstract internal operations away from createServer
|
|
9
|
+
- 9f13d74: fix(api): prevent overriding default CORS config when applying a single override
|
|
10
|
+
- @langchain/langgraph-ui@0.0.61
|
|
11
|
+
|
|
12
|
+
## 0.0.60
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 9c57526: fix(api): serialization of "checkpoints" and "tasks" stream modes
|
|
17
|
+
- @langchain/langgraph-ui@0.0.60
|
|
18
|
+
|
|
3
19
|
## 0.0.59
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/api/assistants.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { getAssistantId, getCachedStaticGraphSchema, getGraph, } from "../graph/
|
|
|
6
6
|
import { getRuntimeGraphSchema } from "../graph/parser/index.mjs";
|
|
7
7
|
import { HTTPException } from "hono/http-exception";
|
|
8
8
|
import * as schemas from "../schemas.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { assistants } from "../storage/context.mjs";
|
|
10
10
|
const api = new Hono();
|
|
11
11
|
const RunnableConfigSchema = z.object({
|
|
12
12
|
tags: z.array(z.string()).optional(),
|
|
@@ -33,7 +33,7 @@ const getRunnableConfig = (userConfig) => {
|
|
|
33
33
|
api.post("/assistants", zValidator("json", schemas.AssistantCreate), async (c) => {
|
|
34
34
|
// Create Assistant
|
|
35
35
|
const payload = c.req.valid("json");
|
|
36
|
-
const assistant = await
|
|
36
|
+
const assistant = await assistants().put(payload.assistant_id ?? uuid(), {
|
|
37
37
|
config: payload.config ?? {},
|
|
38
38
|
context: payload.context ?? {},
|
|
39
39
|
graph_id: payload.graph_id,
|
|
@@ -48,7 +48,7 @@ api.post("/assistants/search", zValidator("json", schemas.AssistantSearchRequest
|
|
|
48
48
|
const payload = c.req.valid("json");
|
|
49
49
|
const result = [];
|
|
50
50
|
let total = 0;
|
|
51
|
-
for await (const item of
|
|
51
|
+
for await (const item of assistants().search({
|
|
52
52
|
graph_id: payload.graph_id,
|
|
53
53
|
metadata: payload.metadata,
|
|
54
54
|
limit: payload.limit ?? 10,
|
|
@@ -62,26 +62,31 @@ api.post("/assistants/search", zValidator("json", schemas.AssistantSearchRequest
|
|
|
62
62
|
c.res.headers.set("X-Pagination-Total", total.toString());
|
|
63
63
|
return c.json(result);
|
|
64
64
|
});
|
|
65
|
+
api.post("/assistants/count", zValidator("json", schemas.AssistantCountRequest), async (c) => {
|
|
66
|
+
const payload = c.req.valid("json");
|
|
67
|
+
const total = await assistants().count(payload, c.var.auth);
|
|
68
|
+
return c.json(total);
|
|
69
|
+
});
|
|
65
70
|
api.get("/assistants/:assistant_id", async (c) => {
|
|
66
71
|
// Get Assistant
|
|
67
72
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
68
|
-
return c.json(await
|
|
73
|
+
return c.json(await assistants().get(assistantId, c.var.auth));
|
|
69
74
|
});
|
|
70
75
|
api.delete("/assistants/:assistant_id", async (c) => {
|
|
71
76
|
// Delete Assistant
|
|
72
77
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
73
|
-
return c.json(await
|
|
78
|
+
return c.json(await assistants().delete(assistantId, c.var.auth));
|
|
74
79
|
});
|
|
75
80
|
api.patch("/assistants/:assistant_id", zValidator("json", schemas.AssistantPatch), async (c) => {
|
|
76
81
|
// Patch Assistant
|
|
77
82
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
78
83
|
const payload = c.req.valid("json");
|
|
79
|
-
return c.json(await
|
|
84
|
+
return c.json(await assistants().patch(assistantId, payload, c.var.auth));
|
|
80
85
|
});
|
|
81
86
|
api.get("/assistants/:assistant_id/graph", zValidator("query", z.object({ xray: schemas.coercedBoolean.optional() })), async (c) => {
|
|
82
87
|
// Get Assistant Graph
|
|
83
88
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
84
|
-
const assistant = await
|
|
89
|
+
const assistant = await assistants().get(assistantId, c.var.auth);
|
|
85
90
|
const { xray } = c.req.valid("query");
|
|
86
91
|
const config = getRunnableConfig(assistant.config);
|
|
87
92
|
const graph = await getGraph(assistant.graph_id, config);
|
|
@@ -95,7 +100,7 @@ api.get("/assistants/:assistant_id/schemas", zValidator("json", z.object({ confi
|
|
|
95
100
|
// Get Assistant Schemas
|
|
96
101
|
const json = c.req.valid("json");
|
|
97
102
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
98
|
-
const assistant = await
|
|
103
|
+
const assistant = await assistants().get(assistantId, c.var.auth);
|
|
99
104
|
const config = getRunnableConfig(json.config);
|
|
100
105
|
const graph = await getGraph(assistant.graph_id, config);
|
|
101
106
|
const schema = await (async () => {
|
|
@@ -124,7 +129,7 @@ api.get("/assistants/:assistant_id/subgraphs/:namespace?", zValidator("param", z
|
|
|
124
129
|
const { assistant_id, namespace } = c.req.valid("param");
|
|
125
130
|
const { recurse } = c.req.valid("query");
|
|
126
131
|
const assistantId = getAssistantId(assistant_id);
|
|
127
|
-
const assistant = await
|
|
132
|
+
const assistant = await assistants().get(assistantId, c.var.auth);
|
|
128
133
|
const config = getRunnableConfig(assistant.config);
|
|
129
134
|
const graph = await getGraph(assistant.graph_id, config);
|
|
130
135
|
const result = [];
|
|
@@ -156,7 +161,7 @@ api.post("/assistants/:assistant_id/latest", zValidator("json", schemas.Assistan
|
|
|
156
161
|
// Set Latest Assistant Version
|
|
157
162
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
158
163
|
const { version } = c.req.valid("json");
|
|
159
|
-
return c.json(await
|
|
164
|
+
return c.json(await assistants().setLatest(assistantId, version, c.var.auth));
|
|
160
165
|
});
|
|
161
166
|
api.post("/assistants/:assistant_id/versions", zValidator("json", z.object({
|
|
162
167
|
limit: z.number().min(1).max(1000).optional().default(10),
|
|
@@ -166,7 +171,7 @@ api.post("/assistants/:assistant_id/versions", zValidator("json", z.object({
|
|
|
166
171
|
// Get Assistant Versions
|
|
167
172
|
const assistantId = getAssistantId(c.req.param("assistant_id"));
|
|
168
173
|
const { limit, offset, metadata } = c.req.valid("json");
|
|
169
|
-
const versions = await
|
|
174
|
+
const versions = await assistants().getVersions(assistantId, { limit, offset, metadata }, c.var.auth);
|
|
170
175
|
if (!versions?.length) {
|
|
171
176
|
throw new HTTPException(404, {
|
|
172
177
|
message: `Assistant "${assistantId}" not found.`,
|
package/dist/api/meta.mjs
CHANGED
|
@@ -7,26 +7,33 @@ const api = new Hono();
|
|
|
7
7
|
const packageJsonPath = path.resolve(url.fileURLToPath(import.meta.url), "../../../package.json");
|
|
8
8
|
let version;
|
|
9
9
|
let langgraph_js_version;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
console.warn("Could not determine version of langgraph-api");
|
|
16
|
-
}
|
|
17
|
-
// Get the installed version of @langchain/langgraph
|
|
18
|
-
try {
|
|
19
|
-
const langgraphPkg = await import("@langchain/langgraph/package.json");
|
|
20
|
-
if (langgraphPkg?.default?.version) {
|
|
21
|
-
langgraph_js_version = langgraphPkg.default.version;
|
|
10
|
+
let versionInfoLoaded = false;
|
|
11
|
+
const loadVersionInfo = async () => {
|
|
12
|
+
try {
|
|
13
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
|
|
14
|
+
version = packageJson.version;
|
|
22
15
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
catch {
|
|
17
|
+
console.warn("Could not determine version of langgraph-api");
|
|
18
|
+
}
|
|
19
|
+
// Get the installed version of @langchain/langgraph
|
|
20
|
+
try {
|
|
21
|
+
const langgraphPkg = await import("@langchain/langgraph/package.json");
|
|
22
|
+
if (langgraphPkg?.default?.version) {
|
|
23
|
+
langgraph_js_version = langgraphPkg.default.version;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
console.warn("Could not determine version of @langchain/langgraph");
|
|
28
|
+
}
|
|
29
|
+
};
|
|
27
30
|
// read env variable
|
|
28
31
|
const env = process.env;
|
|
29
|
-
api.get("/info", (c) => {
|
|
32
|
+
api.get("/info", async (c) => {
|
|
33
|
+
if (!versionInfoLoaded) {
|
|
34
|
+
await loadVersionInfo();
|
|
35
|
+
versionInfoLoaded = true;
|
|
36
|
+
}
|
|
30
37
|
const langsmithApiKey = env["LANGSMITH_API_KEY"] || env["LANGCHAIN_API_KEY"];
|
|
31
38
|
const langsmithTracing = (() => {
|
|
32
39
|
if (langsmithApiKey) {
|
package/dist/api/runs.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { z } from "zod";
|
|
|
7
7
|
import { getAssistantId } from "../graph/load.mjs";
|
|
8
8
|
import { logError, logger } from "../logging.mjs";
|
|
9
9
|
import * as schemas from "../schemas.mjs";
|
|
10
|
-
import {
|
|
10
|
+
import { runs, threads } from "../storage/context.mjs";
|
|
11
11
|
import { getDisconnectAbortSignal, jsonExtra, waitKeepAlive, } from "../utils/hono.mjs";
|
|
12
12
|
import { serialiseAsDict } from "../utils/serde.mjs";
|
|
13
13
|
const api = new Hono();
|
|
@@ -71,7 +71,7 @@ const createValidRun = async (threadId, payload, kwargs) => {
|
|
|
71
71
|
: undefined;
|
|
72
72
|
if (!feedbackKeys?.length)
|
|
73
73
|
feedbackKeys = undefined;
|
|
74
|
-
const [first, ...inflight] = await
|
|
74
|
+
const [first, ...inflight] = await runs().put(runId, getAssistantId(assistantId), {
|
|
75
75
|
input: run.input,
|
|
76
76
|
command: run.command,
|
|
77
77
|
config,
|
|
@@ -99,7 +99,7 @@ const createValidRun = async (threadId, payload, kwargs) => {
|
|
|
99
99
|
if ((multitaskStrategy === "interrupt" || multitaskStrategy === "rollback") &&
|
|
100
100
|
inflight.length > 0) {
|
|
101
101
|
try {
|
|
102
|
-
await
|
|
102
|
+
await runs().cancel(threadId, inflight.map((run) => run.run_id), { action: multitaskStrategy }, auth);
|
|
103
103
|
}
|
|
104
104
|
catch (error) {
|
|
105
105
|
logger.warn("Failed to cancel inflight runs, might be already cancelled", {
|
|
@@ -149,7 +149,7 @@ api.post("/runs/stream", zValidator("json", schemas.RunCreate), async (c) => {
|
|
|
149
149
|
? getDisconnectAbortSignal(c, stream)
|
|
150
150
|
: undefined;
|
|
151
151
|
try {
|
|
152
|
-
for await (const { event, data } of
|
|
152
|
+
for await (const { event, data } of runs().stream.join(run.run_id, undefined, {
|
|
153
153
|
cancelOnDisconnect,
|
|
154
154
|
lastEventId: run.kwargs.resumable ? "-1" : undefined,
|
|
155
155
|
ignore404: true,
|
|
@@ -173,7 +173,7 @@ api.get("/runs/:run_id/stream", zValidator("param", z.object({ run_id: z.string(
|
|
|
173
173
|
? getDisconnectAbortSignal(c, stream)
|
|
174
174
|
: undefined;
|
|
175
175
|
try {
|
|
176
|
-
for await (const { id, event, data } of
|
|
176
|
+
for await (const { id, event, data } of runs().stream.join(run_id, undefined, { cancelOnDisconnect, lastEventId, ignore404: true }, c.var.auth)) {
|
|
177
177
|
await stream.writeSSE({ id, data: serialiseAsDict(data), event });
|
|
178
178
|
}
|
|
179
179
|
}
|
|
@@ -190,7 +190,7 @@ api.post("/runs/wait", zValidator("json", schemas.RunCreate), async (c) => {
|
|
|
190
190
|
headers: c.req.raw.headers,
|
|
191
191
|
});
|
|
192
192
|
c.header("Content-Location", `/runs/${run.run_id}`);
|
|
193
|
-
return waitKeepAlive(c,
|
|
193
|
+
return waitKeepAlive(c, runs().wait(run.run_id, undefined, c.var.auth));
|
|
194
194
|
});
|
|
195
195
|
api.post("/runs", zValidator("json", schemas.RunCreate), async (c) => {
|
|
196
196
|
// Create Stateless Run
|
|
@@ -220,11 +220,11 @@ api.get("/threads/:thread_id/runs", zValidator("param", z.object({ thread_id: z.
|
|
|
220
220
|
// List runs
|
|
221
221
|
const { thread_id } = c.req.valid("param");
|
|
222
222
|
const { limit, offset, status, metadata } = c.req.valid("query");
|
|
223
|
-
const [
|
|
224
|
-
|
|
225
|
-
|
|
223
|
+
const [runsResponse] = await Promise.all([
|
|
224
|
+
runs().search(thread_id, { limit, offset, status, metadata }, c.var.auth),
|
|
225
|
+
threads().get(thread_id, c.var.auth),
|
|
226
226
|
]);
|
|
227
|
-
return jsonExtra(c,
|
|
227
|
+
return jsonExtra(c, runsResponse);
|
|
228
228
|
});
|
|
229
229
|
api.post("/threads/:thread_id/runs", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.RunCreate), async (c) => {
|
|
230
230
|
// Create Run
|
|
@@ -251,7 +251,7 @@ api.post("/threads/:thread_id/runs/stream", zValidator("param", z.object({ threa
|
|
|
251
251
|
? getDisconnectAbortSignal(c, stream)
|
|
252
252
|
: undefined;
|
|
253
253
|
try {
|
|
254
|
-
for await (const { id, event, data } of
|
|
254
|
+
for await (const { id, event, data } of runs().stream.join(run.run_id, thread_id, {
|
|
255
255
|
cancelOnDisconnect,
|
|
256
256
|
lastEventId: run.kwargs.resumable ? "-1" : undefined,
|
|
257
257
|
}, c.var.auth)) {
|
|
@@ -272,13 +272,13 @@ api.post("/threads/:thread_id/runs/wait", zValidator("param", z.object({ thread_
|
|
|
272
272
|
headers: c.req.raw.headers,
|
|
273
273
|
});
|
|
274
274
|
c.header("Content-Location", `/threads/${thread_id}/runs/${run.run_id}`);
|
|
275
|
-
return waitKeepAlive(c,
|
|
275
|
+
return waitKeepAlive(c, runs().join(run.run_id, thread_id, c.var.auth));
|
|
276
276
|
});
|
|
277
277
|
api.get("/threads/:thread_id/runs/:run_id", zValidator("param", z.object({ thread_id: z.string().uuid(), run_id: z.string().uuid() })), async (c) => {
|
|
278
278
|
const { thread_id, run_id } = c.req.valid("param");
|
|
279
279
|
const [run] = await Promise.all([
|
|
280
|
-
|
|
281
|
-
|
|
280
|
+
runs().get(run_id, thread_id, c.var.auth),
|
|
281
|
+
threads().get(thread_id, c.var.auth),
|
|
282
282
|
]);
|
|
283
283
|
if (run == null)
|
|
284
284
|
throw new HTTPException(404, { message: "Run not found" });
|
|
@@ -287,13 +287,13 @@ api.get("/threads/:thread_id/runs/:run_id", zValidator("param", z.object({ threa
|
|
|
287
287
|
api.delete("/threads/:thread_id/runs/:run_id", zValidator("param", z.object({ thread_id: z.string().uuid(), run_id: z.string().uuid() })), async (c) => {
|
|
288
288
|
// Delete Run
|
|
289
289
|
const { thread_id, run_id } = c.req.valid("param");
|
|
290
|
-
await
|
|
290
|
+
await runs().delete(run_id, thread_id, c.var.auth);
|
|
291
291
|
return c.body(null, 204);
|
|
292
292
|
});
|
|
293
293
|
api.get("/threads/:thread_id/runs/:run_id/join", zValidator("param", z.object({ thread_id: z.string().uuid(), run_id: z.string().uuid() })), async (c) => {
|
|
294
294
|
// Join Run Http
|
|
295
295
|
const { thread_id, run_id } = c.req.valid("param");
|
|
296
|
-
return jsonExtra(c, await
|
|
296
|
+
return jsonExtra(c, await runs().join(run_id, thread_id, c.var.auth));
|
|
297
297
|
});
|
|
298
298
|
api.get("/threads/:thread_id/runs/:run_id/stream", zValidator("param", z.object({ thread_id: z.string().uuid(), run_id: z.string().uuid() })), zValidator("query", z.object({ cancel_on_disconnect: schemas.coercedBoolean.optional() })), async (c) => {
|
|
299
299
|
// Stream Run Http
|
|
@@ -304,7 +304,7 @@ api.get("/threads/:thread_id/runs/:run_id/stream", zValidator("param", z.object(
|
|
|
304
304
|
const signal = cancel_on_disconnect
|
|
305
305
|
? getDisconnectAbortSignal(c, stream)
|
|
306
306
|
: undefined;
|
|
307
|
-
for await (const { id, event, data } of
|
|
307
|
+
for await (const { id, event, data } of runs().stream.join(run_id, thread_id, { cancelOnDisconnect: signal, lastEventId }, c.var.auth)) {
|
|
308
308
|
await stream.writeSSE({ id, data: serialiseAsDict(data), event });
|
|
309
309
|
}
|
|
310
310
|
});
|
|
@@ -316,9 +316,9 @@ api.post("/threads/:thread_id/runs/:run_id/cancel", zValidator("param", z.object
|
|
|
316
316
|
// Cancel Run Http
|
|
317
317
|
const { thread_id, run_id } = c.req.valid("param");
|
|
318
318
|
const { wait, action } = c.req.valid("query");
|
|
319
|
-
await
|
|
319
|
+
await runs().cancel(thread_id, [run_id], { action }, c.var.auth);
|
|
320
320
|
if (wait)
|
|
321
|
-
await
|
|
321
|
+
await runs().join(run_id, thread_id, c.var.auth);
|
|
322
322
|
return c.body(null, wait ? 204 : 202);
|
|
323
323
|
});
|
|
324
324
|
export default api;
|
package/dist/api/store.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { zValidator } from "@hono/zod-validator";
|
|
|
3
3
|
import * as schemas from "../schemas.mjs";
|
|
4
4
|
import { HTTPException } from "hono/http-exception";
|
|
5
5
|
import { store as storageStore } from "../storage/store.mjs";
|
|
6
|
-
import { handleAuthEvent } from "../auth/
|
|
6
|
+
import { handleAuthEvent } from "../auth/index.mjs";
|
|
7
7
|
const api = new Hono();
|
|
8
8
|
const validateNamespace = (namespace) => {
|
|
9
9
|
if (!namespace || namespace.length === 0) {
|
package/dist/api/threads.mjs
CHANGED
|
@@ -4,16 +4,16 @@ import { v4 as uuid4 } from "uuid";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import * as schemas from "../schemas.mjs";
|
|
6
6
|
import { stateSnapshotToThreadState } from "../state.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { threads } from "../storage/context.mjs";
|
|
8
8
|
import { jsonExtra } from "../utils/hono.mjs";
|
|
9
9
|
const api = new Hono();
|
|
10
10
|
// Threads Routes
|
|
11
11
|
api.post("/threads", zValidator("json", schemas.ThreadCreate), async (c) => {
|
|
12
12
|
// Create Thread
|
|
13
13
|
const payload = c.req.valid("json");
|
|
14
|
-
const thread = await
|
|
14
|
+
const thread = await threads().put(payload.thread_id || uuid4(), { metadata: payload.metadata, if_exists: payload.if_exists ?? "raise" }, c.var.auth);
|
|
15
15
|
if (payload.supersteps?.length) {
|
|
16
|
-
await
|
|
16
|
+
await threads().state.bulk({ configurable: { thread_id: thread.thread_id } }, payload.supersteps, c.var.auth);
|
|
17
17
|
}
|
|
18
18
|
return jsonExtra(c, thread);
|
|
19
19
|
});
|
|
@@ -22,7 +22,7 @@ api.post("/threads/search", zValidator("json", schemas.ThreadSearchRequest), asy
|
|
|
22
22
|
const payload = c.req.valid("json");
|
|
23
23
|
const result = [];
|
|
24
24
|
let total = 0;
|
|
25
|
-
for await (const item of
|
|
25
|
+
for await (const item of threads().search({
|
|
26
26
|
status: payload.status,
|
|
27
27
|
values: payload.values,
|
|
28
28
|
metadata: payload.metadata,
|
|
@@ -44,11 +44,16 @@ api.post("/threads/search", zValidator("json", schemas.ThreadSearchRequest), asy
|
|
|
44
44
|
c.res.headers.set("X-Pagination-Total", total.toString());
|
|
45
45
|
return jsonExtra(c, result);
|
|
46
46
|
});
|
|
47
|
+
api.post("/threads/count", zValidator("json", schemas.ThreadCountRequest), async (c) => {
|
|
48
|
+
const payload = c.req.valid("json");
|
|
49
|
+
const total = await threads().count(payload, c.var.auth);
|
|
50
|
+
return c.json(total);
|
|
51
|
+
});
|
|
47
52
|
api.get("/threads/:thread_id/state", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("query", z.object({ subgraphs: schemas.coercedBoolean.optional() })), async (c) => {
|
|
48
53
|
// Get Latest Thread State
|
|
49
54
|
const { thread_id } = c.req.valid("param");
|
|
50
55
|
const { subgraphs } = c.req.valid("query");
|
|
51
|
-
const state = stateSnapshotToThreadState(await
|
|
56
|
+
const state = stateSnapshotToThreadState(await threads().state.get({ configurable: { thread_id } }, { subgraphs }, c.var.auth));
|
|
52
57
|
return jsonExtra(c, state);
|
|
53
58
|
});
|
|
54
59
|
api.post("/threads/:thread_id/state", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.ThreadStateUpdate), async (c) => {
|
|
@@ -64,7 +69,7 @@ api.post("/threads/:thread_id/state", zValidator("param", z.object({ thread_id:
|
|
|
64
69
|
config.configurable ??= {};
|
|
65
70
|
Object.assign(config.configurable, payload.checkpoint);
|
|
66
71
|
}
|
|
67
|
-
const inserted = await
|
|
72
|
+
const inserted = await threads().state.post(config, payload.values, payload.as_node, c.var.auth);
|
|
68
73
|
return jsonExtra(c, inserted);
|
|
69
74
|
});
|
|
70
75
|
api.get("/threads/:thread_id/state/:checkpoint_id", zValidator("param", z.object({
|
|
@@ -74,7 +79,7 @@ api.get("/threads/:thread_id/state/:checkpoint_id", zValidator("param", z.object
|
|
|
74
79
|
// Get Thread State At Checkpoint
|
|
75
80
|
const { thread_id, checkpoint_id } = c.req.valid("param");
|
|
76
81
|
const { subgraphs } = c.req.valid("query");
|
|
77
|
-
const state = stateSnapshotToThreadState(await
|
|
82
|
+
const state = stateSnapshotToThreadState(await threads().state.get({ configurable: { thread_id, checkpoint_id } }, { subgraphs }, c.var.auth));
|
|
78
83
|
return jsonExtra(c, state);
|
|
79
84
|
});
|
|
80
85
|
api.post("/threads/:thread_id/state/checkpoint", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", z.object({
|
|
@@ -84,7 +89,7 @@ api.post("/threads/:thread_id/state/checkpoint", zValidator("param", z.object({
|
|
|
84
89
|
// Get Thread State At Checkpoint Post
|
|
85
90
|
const { thread_id } = c.req.valid("param");
|
|
86
91
|
const { checkpoint, subgraphs } = c.req.valid("json");
|
|
87
|
-
const state = stateSnapshotToThreadState(await
|
|
92
|
+
const state = stateSnapshotToThreadState(await threads().state.get({ configurable: { thread_id, ...checkpoint } }, { subgraphs }, c.var.auth));
|
|
88
93
|
return jsonExtra(c, state);
|
|
89
94
|
});
|
|
90
95
|
api.get("/threads/:thread_id/history", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("query", z.object({
|
|
@@ -98,36 +103,36 @@ api.get("/threads/:thread_id/history", zValidator("param", z.object({ thread_id:
|
|
|
98
103
|
// Get Thread History
|
|
99
104
|
const { thread_id } = c.req.valid("param");
|
|
100
105
|
const { limit, before } = c.req.valid("query");
|
|
101
|
-
const states = await
|
|
106
|
+
const states = await threads().state.list({ configurable: { thread_id, checkpoint_ns: "" } }, { limit, before }, c.var.auth);
|
|
102
107
|
return jsonExtra(c, states.map(stateSnapshotToThreadState));
|
|
103
108
|
});
|
|
104
109
|
api.post("/threads/:thread_id/history", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.ThreadHistoryRequest), async (c) => {
|
|
105
110
|
// Get Thread History Post
|
|
106
111
|
const { thread_id } = c.req.valid("param");
|
|
107
112
|
const { limit, before, metadata, checkpoint } = c.req.valid("json");
|
|
108
|
-
const states = await
|
|
113
|
+
const states = await threads().state.list({ configurable: { thread_id, checkpoint_ns: "", ...checkpoint } }, { limit, before, metadata }, c.var.auth);
|
|
109
114
|
return jsonExtra(c, states.map(stateSnapshotToThreadState));
|
|
110
115
|
});
|
|
111
116
|
api.get("/threads/:thread_id", zValidator("param", z.object({ thread_id: z.string().uuid() })), async (c) => {
|
|
112
117
|
// Get Thread
|
|
113
118
|
const { thread_id } = c.req.valid("param");
|
|
114
|
-
return jsonExtra(c, await
|
|
119
|
+
return jsonExtra(c, await threads().get(thread_id, c.var.auth));
|
|
115
120
|
});
|
|
116
121
|
api.delete("/threads/:thread_id", zValidator("param", z.object({ thread_id: z.string().uuid() })), async (c) => {
|
|
117
122
|
// Delete Thread
|
|
118
123
|
const { thread_id } = c.req.valid("param");
|
|
119
|
-
await
|
|
124
|
+
await threads().delete(thread_id, c.var.auth);
|
|
120
125
|
return new Response(null, { status: 204 });
|
|
121
126
|
});
|
|
122
127
|
api.patch("/threads/:thread_id", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.ThreadPatchRequest), async (c) => {
|
|
123
128
|
// Patch Thread
|
|
124
129
|
const { thread_id } = c.req.valid("param");
|
|
125
130
|
const { metadata } = c.req.valid("json");
|
|
126
|
-
return jsonExtra(c, await
|
|
131
|
+
return jsonExtra(c, await threads().patch(thread_id, { metadata }, c.var.auth));
|
|
127
132
|
});
|
|
128
133
|
api.post("/threads/:thread_id/copy", zValidator("param", z.object({ thread_id: z.string().uuid() })), async (c) => {
|
|
129
134
|
// Copy Thread
|
|
130
135
|
const { thread_id } = c.req.valid("param");
|
|
131
|
-
return jsonExtra(c, await
|
|
136
|
+
return jsonExtra(c, await threads().copy(thread_id, c.var.auth));
|
|
132
137
|
});
|
|
133
138
|
export default api;
|
package/dist/auth/custom.d.mts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import type { AuthEventValueMap } from "@langchain/langgraph-sdk/auth";
|
|
2
1
|
import type { MiddlewareHandler } from "hono";
|
|
3
|
-
import { type AuthContext
|
|
2
|
+
import { type AuthContext } from "./index.mjs";
|
|
4
3
|
declare module "hono" {
|
|
5
4
|
interface ContextVariableMap {
|
|
6
5
|
auth?: AuthContext | undefined;
|
|
7
6
|
}
|
|
8
7
|
}
|
|
9
|
-
export declare function isAuthMatching(metadata: Record<string, unknown> | undefined, filters: AuthFilters): boolean;
|
|
10
|
-
export declare const handleAuthEvent: <T extends keyof AuthEventValueMap>(context: AuthContext | undefined, event: T, value: AuthEventValueMap[T]) => Promise<[AuthFilters | undefined, value: AuthEventValueMap[T]]>;
|
|
11
8
|
export declare const auth: () => MiddlewareHandler;
|
|
12
9
|
export { registerAuth } from "./index.mjs";
|
package/dist/auth/custom.mjs
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export function isAuthMatching(metadata, filters) {
|
|
3
|
-
if (filters == null)
|
|
4
|
-
return true;
|
|
5
|
-
for (const [key, value] of Object.entries(filters)) {
|
|
6
|
-
if (typeof value === "object" && value != null) {
|
|
7
|
-
if (value.$eq) {
|
|
8
|
-
if (metadata?.[key] !== value.$eq)
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
else if (value.$contains) {
|
|
12
|
-
if (!Array.isArray(metadata?.[key]) ||
|
|
13
|
-
!metadata?.[key].includes(value.$contains)) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
if (metadata?.[key] !== value)
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
export const handleAuthEvent = async (context, event, value) => {
|
|
26
|
-
const [resource, action] = event.split(":");
|
|
27
|
-
const result = await authorize({
|
|
28
|
-
resource,
|
|
29
|
-
action,
|
|
30
|
-
context,
|
|
31
|
-
value,
|
|
32
|
-
});
|
|
33
|
-
return [result.filters, result.value];
|
|
34
|
-
};
|
|
1
|
+
import { authenticate, isAuthRegistered, isStudioAuthDisabled, } from "./index.mjs";
|
|
35
2
|
const STUDIO_USER = {
|
|
36
3
|
kind: "StudioUser",
|
|
37
4
|
display_name: "langgraph-studio-user",
|
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AuthEventValueMap } from "@langchain/langgraph-sdk/auth";
|
|
1
2
|
export declare const isAuthRegistered: () => boolean;
|
|
2
3
|
export declare const isStudioAuthDisabled: () => boolean;
|
|
3
4
|
export type AuthFilters = Record<string, string | {
|
|
@@ -38,3 +39,5 @@ export declare function registerAuth(auth: {
|
|
|
38
39
|
}, options: {
|
|
39
40
|
cwd: string;
|
|
40
41
|
}): Promise<void>;
|
|
42
|
+
export declare const handleAuthEvent: <T extends keyof AuthEventValueMap>(context: AuthContext | undefined, event: T, value: AuthEventValueMap[T]) => Promise<[AuthFilters | undefined, value: AuthEventValueMap[T]]>;
|
|
43
|
+
export declare function isAuthMatching(metadata: Record<string, unknown> | undefined, filters: AuthFilters): boolean;
|
package/dist/auth/index.mjs
CHANGED
|
@@ -118,3 +118,36 @@ export async function registerAuth(auth, options) {
|
|
|
118
118
|
CUSTOM_AUTH = module;
|
|
119
119
|
DISABLE_STUDIO_AUTH = auth.disable_studio_auth ?? false;
|
|
120
120
|
}
|
|
121
|
+
export const handleAuthEvent = async (context, event, value) => {
|
|
122
|
+
const [resource, action] = event.split(":");
|
|
123
|
+
const result = await authorize({
|
|
124
|
+
resource,
|
|
125
|
+
action,
|
|
126
|
+
context,
|
|
127
|
+
value,
|
|
128
|
+
});
|
|
129
|
+
return [result.filters, result.value];
|
|
130
|
+
};
|
|
131
|
+
export function isAuthMatching(metadata, filters) {
|
|
132
|
+
if (filters == null)
|
|
133
|
+
return true;
|
|
134
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
135
|
+
if (typeof value === "object" && value != null) {
|
|
136
|
+
if (value.$eq) {
|
|
137
|
+
if (metadata?.[key] !== value.$eq)
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
else if (value.$contains) {
|
|
141
|
+
if (!Array.isArray(metadata?.[key]) ||
|
|
142
|
+
!metadata?.[key].includes(value.$contains)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
if (metadata?.[key] !== value)
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseCheckpointSaver, BaseStore, Pregel } from "@langchain/langgraph";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
|
-
import type { Metadata } from "../storage/
|
|
3
|
+
import type { Metadata } from "../storage/types.mjs";
|
|
4
4
|
type AnyPregel = Pregel<any, any, any, any, any>;
|
|
5
5
|
interface Thread {
|
|
6
6
|
thread_id: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getGraph, assertGraphExists } from "./load.mjs";
|
package/dist/graph/load.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssistantsRepo } from "../storage/types.mjs";
|
|
1
2
|
import type { BaseCheckpointSaver, BaseStore, CompiledGraph, LangGraphRunnableConfig } from "@langchain/langgraph";
|
|
2
3
|
import { type CompiledGraphFactory } from "./load.utils.mjs";
|
|
3
4
|
import type { GraphSchema, GraphSpec } from "./parser/index.mjs";
|
|
@@ -6,11 +7,12 @@ export declare const GRAPH_SPEC: Record<string, GraphSpec>;
|
|
|
6
7
|
export declare const GRAPH_SCHEMA: Record<string, Record<string, GraphSchema>>;
|
|
7
8
|
export declare const NAMESPACE_GRAPH: Uint8Array<ArrayBufferLike>;
|
|
8
9
|
export declare const getAssistantId: (graphId: string) => string;
|
|
9
|
-
export declare function registerFromEnv(specs: Record<string, string>, options: {
|
|
10
|
+
export declare function registerFromEnv(assistants: AssistantsRepo, specs: Record<string, string>, options: {
|
|
10
11
|
cwd: string;
|
|
11
12
|
}): Promise<(CompiledGraph<string, any, any, Record<string, any>, any, any, unknown> | CompiledGraphFactory<string>)[]>;
|
|
12
13
|
export declare function getGraph(graphId: string, config: LangGraphRunnableConfig | undefined, options?: {
|
|
13
14
|
checkpointer?: BaseCheckpointSaver | null;
|
|
14
15
|
store?: BaseStore;
|
|
15
16
|
}): Promise<CompiledGraph<string, any, any, Record<string, any>, any, any, unknown>>;
|
|
17
|
+
export declare function assertGraphExists(graphId: string): void;
|
|
16
18
|
export declare function getCachedStaticGraphSchema(graphId: string): Promise<Record<string, GraphSchema>>;
|
package/dist/graph/load.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import * as uuid from "uuid";
|
|
3
|
-
import { Assistants } from "../storage/ops.mjs";
|
|
4
3
|
import { HTTPException } from "hono/http-exception";
|
|
5
4
|
import { resolveGraph } from "./load.utils.mjs";
|
|
6
5
|
import { getStaticGraphSchema } from "./parser/index.mjs";
|
|
@@ -17,7 +16,7 @@ export const getAssistantId = (graphId) => {
|
|
|
17
16
|
return uuid.v5(graphId, NAMESPACE_GRAPH);
|
|
18
17
|
return graphId;
|
|
19
18
|
};
|
|
20
|
-
export async function registerFromEnv(specs, options) {
|
|
19
|
+
export async function registerFromEnv(assistants, specs, options) {
|
|
21
20
|
const envConfig = process.env.LANGGRAPH_CONFIG
|
|
22
21
|
? ConfigSchema.parse(JSON.parse(process.env.LANGGRAPH_CONFIG))
|
|
23
22
|
: undefined;
|
|
@@ -32,7 +31,7 @@ export async function registerFromEnv(specs, options) {
|
|
|
32
31
|
// registering the graph runtime
|
|
33
32
|
GRAPHS[graphId] = resolved;
|
|
34
33
|
GRAPH_SPEC[graphId] = spec;
|
|
35
|
-
await
|
|
34
|
+
await assistants.put(uuid.v5(graphId, NAMESPACE_GRAPH), {
|
|
36
35
|
graph_id: graphId,
|
|
37
36
|
metadata: { created_by: "system" },
|
|
38
37
|
config,
|
|
@@ -44,8 +43,7 @@ export async function registerFromEnv(specs, options) {
|
|
|
44
43
|
}));
|
|
45
44
|
}
|
|
46
45
|
export async function getGraph(graphId, config, options) {
|
|
47
|
-
|
|
48
|
-
throw new HTTPException(404, { message: `Graph "${graphId}" not found` });
|
|
46
|
+
assertGraphExists(graphId);
|
|
49
47
|
const compiled = typeof GRAPHS[graphId] === "function"
|
|
50
48
|
? await GRAPHS[graphId](config ?? { configurable: {} })
|
|
51
49
|
: GRAPHS[graphId];
|
|
@@ -58,6 +56,12 @@ export async function getGraph(graphId, config, options) {
|
|
|
58
56
|
compiled.store = options?.store ?? store;
|
|
59
57
|
return compiled;
|
|
60
58
|
}
|
|
59
|
+
export function assertGraphExists(graphId) {
|
|
60
|
+
if (!GRAPHS[graphId])
|
|
61
|
+
throw new HTTPException(404, {
|
|
62
|
+
message: `Graph "${graphId}" not found`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
61
65
|
export async function getCachedStaticGraphSchema(graphId) {
|
|
62
66
|
if (!GRAPH_SPEC[graphId])
|
|
63
67
|
throw new HTTPException(404, {
|