@langchain/langgraph-api 1.1.1 → 1.1.8

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.
Files changed (100) hide show
  1. package/package.json +10 -9
  2. package/CHANGELOG.md +0 -290
  3. package/dist/api/assistants.d.mts +0 -3
  4. package/dist/api/assistants.mjs +0 -193
  5. package/dist/api/meta.d.mts +0 -3
  6. package/dist/api/meta.mjs +0 -65
  7. package/dist/api/runs.d.mts +0 -3
  8. package/dist/api/runs.mjs +0 -324
  9. package/dist/api/store.d.mts +0 -3
  10. package/dist/api/store.mjs +0 -111
  11. package/dist/api/threads.d.mts +0 -3
  12. package/dist/api/threads.mjs +0 -143
  13. package/dist/auth/custom.d.mts +0 -9
  14. package/dist/auth/custom.mjs +0 -32
  15. package/dist/auth/index.d.mts +0 -43
  16. package/dist/auth/index.mjs +0 -163
  17. package/dist/cli/entrypoint.d.mts +0 -1
  18. package/dist/cli/entrypoint.mjs +0 -41
  19. package/dist/cli/spawn.d.mts +0 -42
  20. package/dist/cli/spawn.mjs +0 -47
  21. package/dist/cli/utils/ipc/client.d.mts +0 -5
  22. package/dist/cli/utils/ipc/client.mjs +0 -47
  23. package/dist/cli/utils/ipc/utils/get-pipe-path.d.mts +0 -1
  24. package/dist/cli/utils/ipc/utils/get-pipe-path.mjs +0 -29
  25. package/dist/cli/utils/ipc/utils/temporary-directory.d.mts +0 -5
  26. package/dist/cli/utils/ipc/utils/temporary-directory.mjs +0 -40
  27. package/dist/command.d.mts +0 -11
  28. package/dist/command.mjs +0 -15
  29. package/dist/experimental/embed.d.mts +0 -42
  30. package/dist/experimental/embed.mjs +0 -299
  31. package/dist/graph/api.d.mts +0 -1
  32. package/dist/graph/api.mjs +0 -2
  33. package/dist/graph/load.d.mts +0 -19
  34. package/dist/graph/load.hooks.d.mts +0 -2
  35. package/dist/graph/load.hooks.mjs +0 -52
  36. package/dist/graph/load.mjs +0 -96
  37. package/dist/graph/load.utils.d.mts +0 -22
  38. package/dist/graph/load.utils.mjs +0 -49
  39. package/dist/graph/parser/index.d.mts +0 -23
  40. package/dist/graph/parser/index.mjs +0 -58
  41. package/dist/graph/parser/parser.d.mts +0 -77
  42. package/dist/graph/parser/parser.mjs +0 -429
  43. package/dist/graph/parser/parser.worker.d.mts +0 -1
  44. package/dist/graph/parser/parser.worker.mjs +0 -7
  45. package/dist/graph/parser/schema/types.d.mts +0 -154
  46. package/dist/graph/parser/schema/types.mjs +0 -1496
  47. package/dist/graph/parser/schema/types.template.d.mts +0 -1
  48. package/dist/graph/parser/schema/types.template.mts +0 -92
  49. package/dist/http/custom.d.mts +0 -6
  50. package/dist/http/custom.mjs +0 -10
  51. package/dist/http/middleware.d.mts +0 -11
  52. package/dist/http/middleware.mjs +0 -57
  53. package/dist/logging.d.mts +0 -10
  54. package/dist/logging.mjs +0 -115
  55. package/dist/loopback.d.mts +0 -4
  56. package/dist/loopback.mjs +0 -10
  57. package/dist/preload.d.mts +0 -1
  58. package/dist/preload.mjs +0 -29
  59. package/dist/queue.d.mts +0 -2
  60. package/dist/queue.mjs +0 -119
  61. package/dist/schemas.d.mts +0 -1552
  62. package/dist/schemas.mjs +0 -492
  63. package/dist/semver/index.d.mts +0 -15
  64. package/dist/semver/index.mjs +0 -46
  65. package/dist/server.d.mts +0 -175
  66. package/dist/server.mjs +0 -181
  67. package/dist/state.d.mts +0 -3
  68. package/dist/state.mjs +0 -30
  69. package/dist/storage/checkpoint.d.mts +0 -19
  70. package/dist/storage/checkpoint.mjs +0 -127
  71. package/dist/storage/context.d.mts +0 -3
  72. package/dist/storage/context.mjs +0 -11
  73. package/dist/storage/importMap.d.mts +0 -55
  74. package/dist/storage/importMap.mjs +0 -55
  75. package/dist/storage/ops.d.mts +0 -169
  76. package/dist/storage/ops.mjs +0 -1262
  77. package/dist/storage/persist.d.mts +0 -18
  78. package/dist/storage/persist.mjs +0 -81
  79. package/dist/storage/store.d.mts +0 -17
  80. package/dist/storage/store.mjs +0 -41
  81. package/dist/storage/types.d.mts +0 -301
  82. package/dist/storage/types.mjs +0 -1
  83. package/dist/stream.d.mts +0 -43
  84. package/dist/stream.mjs +0 -235
  85. package/dist/ui/load.d.mts +0 -8
  86. package/dist/ui/load.mjs +0 -53
  87. package/dist/utils/abort.d.mts +0 -1
  88. package/dist/utils/abort.mjs +0 -8
  89. package/dist/utils/hono.d.mts +0 -5
  90. package/dist/utils/hono.mjs +0 -24
  91. package/dist/utils/importMap.d.mts +0 -55
  92. package/dist/utils/importMap.mjs +0 -55
  93. package/dist/utils/runnableConfig.d.mts +0 -3
  94. package/dist/utils/runnableConfig.mjs +0 -45
  95. package/dist/utils/serde.d.mts +0 -5
  96. package/dist/utils/serde.mjs +0 -20
  97. package/dist/vitest.config.d.ts +0 -2
  98. package/dist/vitest.config.js +0 -12
  99. package/dist/webhook.d.mts +0 -11
  100. package/dist/webhook.mjs +0 -30
package/dist/api/runs.mjs DELETED
@@ -1,324 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { Hono } from "hono";
3
- import { HTTPException } from "hono/http-exception";
4
- import { streamSSE } from "hono/streaming";
5
- import { v4 as uuid4 } from "uuid";
6
- import { z } from "zod/v3";
7
- import { getAssistantId } from "../graph/load.mjs";
8
- import { logError, logger } from "../logging.mjs";
9
- import * as schemas from "../schemas.mjs";
10
- import { runs, threads } from "../storage/context.mjs";
11
- import { getDisconnectAbortSignal, jsonExtra, waitKeepAlive, } from "../utils/hono.mjs";
12
- import { serialiseAsDict } from "../utils/serde.mjs";
13
- const api = new Hono();
14
- const createValidRun = async (threadId, payload, kwargs) => {
15
- const { assistant_id: assistantId, ...run } = payload;
16
- const { auth, headers } = kwargs ?? {};
17
- const runId = uuid4();
18
- const streamMode = Array.isArray(payload.stream_mode)
19
- ? payload.stream_mode
20
- : payload.stream_mode != null
21
- ? [payload.stream_mode]
22
- : [];
23
- if (streamMode.length === 0)
24
- streamMode.push("values");
25
- const multitaskStrategy = payload.multitask_strategy ?? "reject";
26
- const preventInsertInInflight = multitaskStrategy === "reject";
27
- const config = { ...run.config };
28
- if (run.checkpoint_id) {
29
- config.configurable ??= {};
30
- config.configurable.checkpoint_id = run.checkpoint_id;
31
- }
32
- if (run.checkpoint) {
33
- config.configurable ??= {};
34
- Object.assign(config.configurable, run.checkpoint);
35
- }
36
- if (run.langsmith_tracer) {
37
- config.configurable ??= {};
38
- Object.assign(config.configurable, {
39
- langsmith_project: run.langsmith_tracer.project_name,
40
- langsmith_example_id: run.langsmith_tracer.example_id,
41
- });
42
- }
43
- if (headers) {
44
- for (const [rawKey, value] of headers.entries()) {
45
- const key = rawKey.toLowerCase();
46
- if (key.startsWith("x-")) {
47
- if (["x-api-key", "x-tenant-id", "x-service-key"].includes(key)) {
48
- continue;
49
- }
50
- config.configurable ??= {};
51
- config.configurable[key] = value;
52
- }
53
- else if (key === "user-agent") {
54
- config.configurable ??= {};
55
- config.configurable[key] = value;
56
- }
57
- }
58
- }
59
- let userId;
60
- if (auth) {
61
- userId = auth.user.identity ?? auth.user.id;
62
- config.configurable ??= {};
63
- config.configurable["langgraph_auth_user"] = auth.user;
64
- config.configurable["langgraph_auth_user_id"] = userId;
65
- config.configurable["langgraph_auth_permissions"] = auth.scopes;
66
- }
67
- let feedbackKeys = run.feedback_keys != null
68
- ? Array.isArray(run.feedback_keys)
69
- ? run.feedback_keys
70
- : [run.feedback_keys]
71
- : undefined;
72
- if (!feedbackKeys?.length)
73
- feedbackKeys = undefined;
74
- const [first, ...inflight] = await runs().put(runId, getAssistantId(assistantId), {
75
- input: run.input,
76
- command: run.command,
77
- config,
78
- context: run.context,
79
- stream_mode: streamMode,
80
- interrupt_before: run.interrupt_before,
81
- interrupt_after: run.interrupt_after,
82
- webhook: run.webhook,
83
- feedback_keys: feedbackKeys,
84
- temporary: threadId == null && (run.on_completion ?? "delete") === "delete",
85
- subgraphs: run.stream_subgraphs ?? false,
86
- resumable: run.stream_resumable ?? false,
87
- }, {
88
- threadId,
89
- userId,
90
- metadata: run.metadata,
91
- status: "pending",
92
- multitaskStrategy,
93
- preventInsertInInflight,
94
- afterSeconds: payload.after_seconds,
95
- ifNotExists: payload.if_not_exists,
96
- }, auth);
97
- if (first?.run_id === runId) {
98
- logger.info("Created run", { run_id: runId, thread_id: threadId });
99
- if ((multitaskStrategy === "interrupt" || multitaskStrategy === "rollback") &&
100
- inflight.length > 0) {
101
- try {
102
- await runs().cancel(threadId, inflight.map((run) => run.run_id), { action: multitaskStrategy }, auth);
103
- }
104
- catch (error) {
105
- logger.warn("Failed to cancel inflight runs, might be already cancelled", {
106
- error,
107
- run_ids: inflight.map((run) => run.run_id),
108
- thread_id: threadId,
109
- });
110
- }
111
- }
112
- return first;
113
- }
114
- else if (multitaskStrategy === "reject") {
115
- throw new HTTPException(422, {
116
- message: "Thread is already running a task. Wait for it to finish or choose a different multitask strategy.",
117
- });
118
- }
119
- throw new HTTPException(500, {
120
- message: "Unreachable state when creating run",
121
- });
122
- };
123
- api.post("/runs/crons", zValidator("json", schemas.CronCreate), async () => {
124
- // Create Thread Cron
125
- throw new HTTPException(500, { message: "Not implemented" });
126
- });
127
- api.post("/runs/crons/search", zValidator("json", schemas.CronSearch), async () => {
128
- // Search Crons
129
- throw new HTTPException(500, { message: "Not implemented" });
130
- });
131
- api.delete("/runs/crons/:cron_id", zValidator("param", z.object({ cron_id: z.string().uuid() })), async () => {
132
- // Delete Cron
133
- throw new HTTPException(500, { message: "Not implemented" });
134
- });
135
- api.post("/threads/:thread_id/runs/crons", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.CronCreate), async () => {
136
- // Create Thread Cron
137
- throw new HTTPException(500, { message: "Not implemented" });
138
- });
139
- api.post("/runs/stream", zValidator("json", schemas.RunCreate), async (c) => {
140
- // Stream Stateless Run
141
- const payload = c.req.valid("json");
142
- const run = await createValidRun(undefined, payload, {
143
- auth: c.var.auth,
144
- headers: c.req.raw.headers,
145
- });
146
- c.header("Content-Location", `/runs/${run.run_id}`);
147
- return streamSSE(c, async (stream) => {
148
- const cancelOnDisconnect = payload.on_disconnect === "cancel"
149
- ? getDisconnectAbortSignal(c, stream)
150
- : undefined;
151
- try {
152
- for await (const { event, data } of runs().stream.join(run.run_id, undefined, {
153
- cancelOnDisconnect,
154
- lastEventId: run.kwargs.resumable ? "-1" : undefined,
155
- ignore404: true,
156
- }, c.var.auth)) {
157
- await stream.writeSSE({ data: serialiseAsDict(data), event });
158
- }
159
- }
160
- catch (error) {
161
- logError(error, { prefix: "Error streaming run" });
162
- }
163
- });
164
- });
165
- // TODO: port to Python API
166
- api.get("/runs/:run_id/stream", zValidator("param", z.object({ run_id: z.string().uuid() })), zValidator("query", z.object({ cancel_on_disconnect: schemas.coercedBoolean.optional() })), async (c) => {
167
- const { run_id } = c.req.valid("param");
168
- const query = c.req.valid("query");
169
- const lastEventId = c.req.header("Last-Event-ID") || undefined;
170
- c.header("Content-Location", `/runs/${run_id}`);
171
- return streamSSE(c, async (stream) => {
172
- const cancelOnDisconnect = query.cancel_on_disconnect
173
- ? getDisconnectAbortSignal(c, stream)
174
- : undefined;
175
- try {
176
- for await (const { id, event, data } of runs().stream.join(run_id, undefined, { cancelOnDisconnect, lastEventId, ignore404: true }, c.var.auth)) {
177
- await stream.writeSSE({ id, data: serialiseAsDict(data), event });
178
- }
179
- }
180
- catch (error) {
181
- logError(error, { prefix: "Error streaming run" });
182
- }
183
- });
184
- });
185
- api.post("/runs/wait", zValidator("json", schemas.RunCreate), async (c) => {
186
- // Wait Stateless Run
187
- const payload = c.req.valid("json");
188
- const run = await createValidRun(undefined, payload, {
189
- auth: c.var.auth,
190
- headers: c.req.raw.headers,
191
- });
192
- c.header("Content-Location", `/runs/${run.run_id}`);
193
- return waitKeepAlive(c, runs().wait(run.run_id, undefined, c.var.auth));
194
- });
195
- api.post("/runs", zValidator("json", schemas.RunCreate), async (c) => {
196
- // Create Stateless Run
197
- const payload = c.req.valid("json");
198
- const run = await createValidRun(undefined, payload, {
199
- auth: c.var.auth,
200
- headers: c.req.raw.headers,
201
- });
202
- c.header("Content-Location", `/runs/${run.run_id}`);
203
- return jsonExtra(c, run);
204
- });
205
- api.post("/runs/batch", zValidator("json", schemas.RunBatchCreate), async (c) => {
206
- // Batch Runs
207
- const payload = c.req.valid("json");
208
- const runs = await Promise.all(payload.map((run) => createValidRun(undefined, run, {
209
- auth: c.var.auth,
210
- headers: c.req.raw.headers,
211
- })));
212
- return jsonExtra(c, runs);
213
- });
214
- api.get("/threads/:thread_id/runs", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("query", z.object({
215
- limit: z.coerce.number().nullish(),
216
- offset: z.coerce.number().nullish(),
217
- status: z.string().nullish(),
218
- metadata: z.record(z.string(), z.unknown()).nullish(),
219
- })), async (c) => {
220
- // List runs
221
- const { thread_id } = c.req.valid("param");
222
- const { limit, offset, status, metadata } = c.req.valid("query");
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
- ]);
227
- return jsonExtra(c, runsResponse);
228
- });
229
- api.post("/threads/:thread_id/runs", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.RunCreate), async (c) => {
230
- // Create Run
231
- const { thread_id } = c.req.valid("param");
232
- const payload = c.req.valid("json");
233
- const run = await createValidRun(thread_id, payload, {
234
- auth: c.var.auth,
235
- headers: c.req.raw.headers,
236
- });
237
- c.header("Content-Location", `/threads/${thread_id}/runs/${run.run_id}`);
238
- return jsonExtra(c, run);
239
- });
240
- api.post("/threads/:thread_id/runs/stream", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.RunCreate), async (c) => {
241
- // Stream Run
242
- const { thread_id } = c.req.valid("param");
243
- const payload = c.req.valid("json");
244
- const run = await createValidRun(thread_id, payload, {
245
- auth: c.var.auth,
246
- headers: c.req.raw.headers,
247
- });
248
- c.header("Content-Location", `/threads/${thread_id}/runs/${run.run_id}`);
249
- return streamSSE(c, async (stream) => {
250
- const cancelOnDisconnect = payload.on_disconnect === "cancel"
251
- ? getDisconnectAbortSignal(c, stream)
252
- : undefined;
253
- try {
254
- for await (const { id, event, data } of runs().stream.join(run.run_id, thread_id, {
255
- cancelOnDisconnect,
256
- lastEventId: run.kwargs.resumable ? "-1" : undefined,
257
- }, c.var.auth)) {
258
- await stream.writeSSE({ id, data: serialiseAsDict(data), event });
259
- }
260
- }
261
- catch (error) {
262
- logError(error, { prefix: "Error streaming run" });
263
- }
264
- });
265
- });
266
- api.post("/threads/:thread_id/runs/wait", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.RunCreate), async (c) => {
267
- // Wait Run
268
- const { thread_id } = c.req.valid("param");
269
- const payload = c.req.valid("json");
270
- const run = await createValidRun(thread_id, payload, {
271
- auth: c.var.auth,
272
- headers: c.req.raw.headers,
273
- });
274
- c.header("Content-Location", `/threads/${thread_id}/runs/${run.run_id}`);
275
- return waitKeepAlive(c, runs().join(run.run_id, thread_id, c.var.auth));
276
- });
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
- const { thread_id, run_id } = c.req.valid("param");
279
- const [run] = await Promise.all([
280
- runs().get(run_id, thread_id, c.var.auth),
281
- threads().get(thread_id, c.var.auth),
282
- ]);
283
- if (run == null)
284
- throw new HTTPException(404, { message: "Run not found" });
285
- return jsonExtra(c, run);
286
- });
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
- // Delete Run
289
- const { thread_id, run_id } = c.req.valid("param");
290
- await runs().delete(run_id, thread_id, c.var.auth);
291
- return c.body(null, 204);
292
- });
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
- // Join Run Http
295
- const { thread_id, run_id } = c.req.valid("param");
296
- return jsonExtra(c, await runs().join(run_id, thread_id, c.var.auth));
297
- });
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
- // Stream Run Http
300
- const { thread_id, run_id } = c.req.valid("param");
301
- const { cancel_on_disconnect } = c.req.valid("query");
302
- const lastEventId = c.req.header("Last-Event-ID") || undefined;
303
- return streamSSE(c, async (stream) => {
304
- const signal = cancel_on_disconnect
305
- ? getDisconnectAbortSignal(c, stream)
306
- : undefined;
307
- for await (const { id, event, data } of runs().stream.join(run_id, thread_id, { cancelOnDisconnect: signal, lastEventId }, c.var.auth)) {
308
- await stream.writeSSE({ id, data: serialiseAsDict(data), event });
309
- }
310
- });
311
- });
312
- api.post("/threads/:thread_id/runs/:run_id/cancel", zValidator("param", z.object({ thread_id: z.string().uuid(), run_id: z.string().uuid() })), zValidator("query", z.object({
313
- wait: z.coerce.boolean().optional().default(false),
314
- action: z.enum(["interrupt", "rollback"]).optional().default("interrupt"),
315
- })), async (c) => {
316
- // Cancel Run Http
317
- const { thread_id, run_id } = c.req.valid("param");
318
- const { wait, action } = c.req.valid("query");
319
- await runs().cancel(thread_id, [run_id], { action }, c.var.auth);
320
- if (wait)
321
- await runs().join(run_id, thread_id, c.var.auth);
322
- return c.body(null, wait ? 204 : 202);
323
- });
324
- export default api;
@@ -1,3 +0,0 @@
1
- import { Hono } from "hono";
2
- declare const api: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
- export default api;
@@ -1,111 +0,0 @@
1
- import { Hono } from "hono";
2
- import { zValidator } from "@hono/zod-validator";
3
- import * as schemas from "../schemas.mjs";
4
- import { HTTPException } from "hono/http-exception";
5
- import { store as storageStore } from "../storage/store.mjs";
6
- import { handleAuthEvent } from "../auth/index.mjs";
7
- const api = new Hono();
8
- const validateNamespace = (namespace) => {
9
- if (!namespace || namespace.length === 0) {
10
- throw new HTTPException(400, { message: "Namespace is required" });
11
- }
12
- for (const label of namespace) {
13
- if (!label || label.includes(".")) {
14
- throw new HTTPException(422, {
15
- message: "Namespace labels cannot be empty or contain periods. Received: " +
16
- namespace.join("."),
17
- });
18
- }
19
- }
20
- };
21
- const mapItemsToApi = (item) => {
22
- if (item == null)
23
- return null;
24
- const clonedItem = { ...item };
25
- delete clonedItem.createdAt;
26
- delete clonedItem.updatedAt;
27
- clonedItem.created_at = item.createdAt;
28
- clonedItem.updated_at = item.updatedAt;
29
- return clonedItem;
30
- };
31
- api.post("/store/namespaces", zValidator("json", schemas.StoreListNamespaces), async (c) => {
32
- // List Namespaces
33
- const payload = c.req.valid("json");
34
- if (payload.prefix)
35
- validateNamespace(payload.prefix);
36
- if (payload.suffix)
37
- validateNamespace(payload.suffix);
38
- await handleAuthEvent(c.var.auth, "store:list_namespaces", {
39
- namespace: payload.prefix,
40
- suffix: payload.suffix,
41
- max_depth: payload.max_depth,
42
- limit: payload.limit,
43
- offset: payload.offset,
44
- });
45
- return c.json({
46
- namespaces: await storageStore.listNamespaces({
47
- limit: payload.limit ?? 100,
48
- offset: payload.offset ?? 0,
49
- prefix: payload.prefix,
50
- suffix: payload.suffix,
51
- maxDepth: payload.max_depth,
52
- }),
53
- });
54
- });
55
- api.post("/store/items/search", zValidator("json", schemas.StoreSearchItems), async (c) => {
56
- // Search Items
57
- const payload = c.req.valid("json");
58
- if (payload.namespace_prefix)
59
- validateNamespace(payload.namespace_prefix);
60
- await handleAuthEvent(c.var.auth, "store:search", {
61
- namespace: payload.namespace_prefix,
62
- filter: payload.filter,
63
- limit: payload.limit,
64
- offset: payload.offset,
65
- query: payload.query,
66
- });
67
- const items = await storageStore.search(payload.namespace_prefix, {
68
- filter: payload.filter,
69
- limit: payload.limit ?? 10,
70
- offset: payload.offset ?? 0,
71
- query: payload.query,
72
- });
73
- return c.json({ items: items.map(mapItemsToApi) });
74
- });
75
- api.put("/store/items", zValidator("json", schemas.StorePutItem), async (c) => {
76
- // Put Item
77
- const payload = c.req.valid("json");
78
- if (payload.namespace)
79
- validateNamespace(payload.namespace);
80
- await handleAuthEvent(c.var.auth, "store:put", {
81
- namespace: payload.namespace,
82
- key: payload.key,
83
- value: payload.value,
84
- });
85
- await storageStore.put(payload.namespace, payload.key, payload.value);
86
- return c.body(null, 204);
87
- });
88
- api.delete("/store/items", zValidator("json", schemas.StoreDeleteItem), async (c) => {
89
- // Delete Item
90
- const payload = c.req.valid("json");
91
- if (payload.namespace)
92
- validateNamespace(payload.namespace);
93
- await handleAuthEvent(c.var.auth, "store:delete", {
94
- namespace: payload.namespace,
95
- key: payload.key,
96
- });
97
- await storageStore.delete(payload.namespace ?? [], payload.key);
98
- return c.body(null, 204);
99
- });
100
- api.get("/store/items", zValidator("query", schemas.StoreGetItem), async (c) => {
101
- // Get Item
102
- const payload = c.req.valid("query");
103
- await handleAuthEvent(c.var.auth, "store:get", {
104
- namespace: payload.namespace,
105
- key: payload.key,
106
- });
107
- const key = payload.key;
108
- const namespace = payload.namespace;
109
- return c.json(mapItemsToApi(await storageStore.get(namespace, key)));
110
- });
111
- export default api;
@@ -1,3 +0,0 @@
1
- import { Hono } from "hono";
2
- declare const api: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
- export default api;
@@ -1,143 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { Hono } from "hono";
3
- import { v4 as uuid4 } from "uuid";
4
- import { z } from "zod/v3";
5
- import * as schemas from "../schemas.mjs";
6
- import { stateSnapshotToThreadState } from "../state.mjs";
7
- import { threads } from "../storage/context.mjs";
8
- import { jsonExtra } from "../utils/hono.mjs";
9
- const api = new Hono();
10
- // Threads Routes
11
- api.post("/threads", zValidator("json", schemas.ThreadCreate), async (c) => {
12
- // Create Thread
13
- const payload = c.req.valid("json");
14
- const thread = await threads().put(payload.thread_id || uuid4(), { metadata: payload.metadata, if_exists: payload.if_exists ?? "raise" }, c.var.auth);
15
- if (payload.supersteps?.length) {
16
- await threads().state.bulk({ configurable: { thread_id: thread.thread_id } }, payload.supersteps, c.var.auth);
17
- }
18
- return jsonExtra(c, thread);
19
- });
20
- api.post("/threads/search", zValidator("json", schemas.ThreadSearchRequest), async (c) => {
21
- // Search Threads
22
- const payload = c.req.valid("json");
23
- const result = [];
24
- let total = 0;
25
- for await (const item of threads().search({
26
- status: payload.status,
27
- values: payload.values,
28
- metadata: payload.metadata,
29
- ids: payload.ids,
30
- limit: payload.limit ?? 10,
31
- offset: payload.offset ?? 0,
32
- sort_by: payload.sort_by ?? "created_at",
33
- sort_order: payload.sort_order ?? "desc",
34
- select: payload.select,
35
- }, c.var.auth)) {
36
- result.push(Object.fromEntries(Object.entries(item.thread).filter(([k]) => !payload.select || payload.select.includes(k))));
37
- // Only set total if it's the first item
38
- if (total === 0) {
39
- total = item.total;
40
- }
41
- }
42
- const nextOffset = (payload.offset ?? 0) + total;
43
- if (total === payload.limit) {
44
- c.res.headers.set("X-Pagination-Next", nextOffset.toString());
45
- c.res.headers.set("X-Pagination-Total", (nextOffset + 1).toString());
46
- }
47
- else {
48
- c.res.headers.set("X-Pagination-Total", nextOffset.toString());
49
- }
50
- return jsonExtra(c, result);
51
- });
52
- api.post("/threads/count", zValidator("json", schemas.ThreadCountRequest), async (c) => {
53
- const payload = c.req.valid("json");
54
- const total = await threads().count(payload, c.var.auth);
55
- return c.json(total);
56
- });
57
- 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) => {
58
- // Get Latest Thread State
59
- const { thread_id } = c.req.valid("param");
60
- const { subgraphs } = c.req.valid("query");
61
- const state = stateSnapshotToThreadState(await threads().state.get({ configurable: { thread_id } }, { subgraphs }, c.var.auth));
62
- return jsonExtra(c, state);
63
- });
64
- api.post("/threads/:thread_id/state", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.ThreadStateUpdate), async (c) => {
65
- // Update Thread State
66
- const { thread_id } = c.req.valid("param");
67
- const payload = c.req.valid("json");
68
- const config = { configurable: { thread_id } };
69
- if (payload.checkpoint_id) {
70
- config.configurable ??= {};
71
- config.configurable.checkpoint_id = payload.checkpoint_id;
72
- }
73
- if (payload.checkpoint) {
74
- config.configurable ??= {};
75
- Object.assign(config.configurable, payload.checkpoint);
76
- }
77
- const inserted = await threads().state.post(config, payload.values, payload.as_node, c.var.auth);
78
- return jsonExtra(c, inserted);
79
- });
80
- api.get("/threads/:thread_id/state/:checkpoint_id", zValidator("param", z.object({
81
- thread_id: z.string().uuid(),
82
- checkpoint_id: z.string().uuid(),
83
- })), zValidator("query", z.object({ subgraphs: schemas.coercedBoolean.optional() })), async (c) => {
84
- // Get Thread State At Checkpoint
85
- const { thread_id, checkpoint_id } = c.req.valid("param");
86
- const { subgraphs } = c.req.valid("query");
87
- const state = stateSnapshotToThreadState(await threads().state.get({ configurable: { thread_id, checkpoint_id } }, { subgraphs }, c.var.auth));
88
- return jsonExtra(c, state);
89
- });
90
- api.post("/threads/:thread_id/state/checkpoint", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", z.object({
91
- subgraphs: schemas.coercedBoolean.optional(),
92
- checkpoint: schemas.CheckpointSchema.nullish(),
93
- })), async (c) => {
94
- // Get Thread State At Checkpoint Post
95
- const { thread_id } = c.req.valid("param");
96
- const { checkpoint, subgraphs } = c.req.valid("json");
97
- const state = stateSnapshotToThreadState(await threads().state.get({ configurable: { thread_id, ...checkpoint } }, { subgraphs }, c.var.auth));
98
- return jsonExtra(c, state);
99
- });
100
- api.get("/threads/:thread_id/history", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("query", z.object({
101
- limit: z
102
- .string()
103
- .optional()
104
- .default("10")
105
- .transform((value) => parseInt(value, 10)),
106
- before: z.string().optional(),
107
- })), async (c) => {
108
- // Get Thread History
109
- const { thread_id } = c.req.valid("param");
110
- const { limit, before } = c.req.valid("query");
111
- const states = await threads().state.list({ configurable: { thread_id, checkpoint_ns: "" } }, { limit, before }, c.var.auth);
112
- return jsonExtra(c, states.map(stateSnapshotToThreadState));
113
- });
114
- api.post("/threads/:thread_id/history", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.ThreadHistoryRequest), async (c) => {
115
- // Get Thread History Post
116
- const { thread_id } = c.req.valid("param");
117
- const { limit, before, metadata, checkpoint } = c.req.valid("json");
118
- const states = await threads().state.list({ configurable: { thread_id, checkpoint_ns: "", ...checkpoint } }, { limit, before, metadata }, c.var.auth);
119
- return jsonExtra(c, states.map(stateSnapshotToThreadState));
120
- });
121
- api.get("/threads/:thread_id", zValidator("param", z.object({ thread_id: z.string().uuid() })), async (c) => {
122
- // Get Thread
123
- const { thread_id } = c.req.valid("param");
124
- return jsonExtra(c, await threads().get(thread_id, c.var.auth));
125
- });
126
- api.delete("/threads/:thread_id", zValidator("param", z.object({ thread_id: z.string().uuid() })), async (c) => {
127
- // Delete Thread
128
- const { thread_id } = c.req.valid("param");
129
- await threads().delete(thread_id, c.var.auth);
130
- return new Response(null, { status: 204 });
131
- });
132
- api.patch("/threads/:thread_id", zValidator("param", z.object({ thread_id: z.string().uuid() })), zValidator("json", schemas.ThreadPatchRequest), async (c) => {
133
- // Patch Thread
134
- const { thread_id } = c.req.valid("param");
135
- const { metadata } = c.req.valid("json");
136
- return jsonExtra(c, await threads().patch(thread_id, { metadata }, c.var.auth));
137
- });
138
- api.post("/threads/:thread_id/copy", zValidator("param", z.object({ thread_id: z.string().uuid() })), async (c) => {
139
- // Copy Thread
140
- const { thread_id } = c.req.valid("param");
141
- return jsonExtra(c, await threads().copy(thread_id, c.var.auth));
142
- });
143
- export default api;
@@ -1,9 +0,0 @@
1
- import type { MiddlewareHandler } from "hono";
2
- import { type AuthContext } from "./index.mjs";
3
- declare module "hono" {
4
- interface ContextVariableMap {
5
- auth?: AuthContext | undefined;
6
- }
7
- }
8
- export declare const auth: () => MiddlewareHandler;
9
- export { registerAuth } from "./index.mjs";
@@ -1,32 +0,0 @@
1
- import { authenticate, isAuthRegistered, isStudioAuthDisabled, } from "./index.mjs";
2
- const STUDIO_USER = {
3
- kind: "StudioUser",
4
- display_name: "langgraph-studio-user",
5
- identity: "langgraph-studio-user",
6
- permissions: [],
7
- is_authenticated: true,
8
- };
9
- export const auth = () => {
10
- return async (c, next) => {
11
- if (!isAuthRegistered())
12
- return next();
13
- // skip for /info
14
- if (c.req.path === "/info")
15
- return next();
16
- // skip for UI asset requests
17
- if (c.req.path.startsWith("/ui") && c.req.method === "GET")
18
- return next();
19
- if (!isStudioAuthDisabled() &&
20
- c.req.header("x-auth-scheme") === "langsmith") {
21
- c.set("auth", {
22
- user: STUDIO_USER,
23
- scopes: STUDIO_USER.permissions.slice(),
24
- });
25
- return next();
26
- }
27
- const auth = await authenticate(c.req.raw);
28
- c.set("auth", auth);
29
- return next();
30
- };
31
- };
32
- export { registerAuth } from "./index.mjs";
@@ -1,43 +0,0 @@
1
- import type { AuthEventValueMap } from "@langchain/langgraph-sdk/auth";
2
- export declare const isAuthRegistered: () => boolean;
3
- export declare const isStudioAuthDisabled: () => boolean;
4
- export type AuthFilters = Record<string, string | {
5
- $eq?: string;
6
- $contains?: string | string[];
7
- }> | undefined;
8
- export interface AuthContext {
9
- user: {
10
- identity: string;
11
- permissions: string[];
12
- display_name: string;
13
- is_authenticated: boolean;
14
- [key: string]: unknown;
15
- };
16
- scopes: string[];
17
- }
18
- export declare function authorize(payload: {
19
- resource: string;
20
- action: string;
21
- value: unknown;
22
- context: AuthContext | undefined | null;
23
- }): Promise<{
24
- filters: AuthFilters;
25
- value: unknown;
26
- }>;
27
- export declare function authenticate(request: Request): Promise<{
28
- scopes: string[];
29
- user: {
30
- permissions: string[];
31
- is_authenticated: boolean;
32
- display_name: string;
33
- identity: string;
34
- };
35
- } | undefined>;
36
- export declare function registerAuth(auth: {
37
- path?: string;
38
- disable_studio_auth?: boolean;
39
- }, options: {
40
- cwd: string;
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;