fix(api): send Content-Location header for stateless runs (#1512)

This commit is contained in:
David Duong
2025-08-08 17:21:54 +02:00
committed by GitHub
parent c9c809280d
commit f65f619cae
3 changed files with 31 additions and 2 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@langchain/langgraph-api": patch
---
fix(api): send Content-Location header for stateless runs
+4 -1
View File
@@ -205,6 +205,7 @@ api.post("/runs/stream", zValidator("json", schemas.RunCreate), async (c) => {
headers: c.req.raw.headers,
});
c.header("Content-Location", `/runs/${run.run_id}`);
return streamSSE(c, async (stream) => {
const cancelOnDisconnect =
payload.on_disconnect === "cancel"
@@ -243,7 +244,7 @@ api.get(
const query = c.req.valid("query");
const lastEventId = c.req.header("Last-Event-ID") || undefined;
c.header("Content-Location", `/runs/${run_id}`);
return streamSSE(c, async (stream) => {
const cancelOnDisconnect = query.cancel_on_disconnect
? getDisconnectAbortSignal(c, stream)
@@ -272,6 +273,7 @@ api.post("/runs/wait", zValidator("json", schemas.RunCreate), async (c) => {
auth: c.var.auth,
headers: c.req.raw.headers,
});
c.header("Content-Location", `/runs/${run.run_id}`);
return waitKeepAlive(c, Runs.wait(run.run_id, undefined, c.var.auth));
});
@@ -282,6 +284,7 @@ api.post("/runs", zValidator("json", schemas.RunCreate), async (c) => {
auth: c.var.auth,
headers: c.req.raw.headers,
});
c.header("Content-Location", `/runs/${run.run_id}`);
return jsonExtra(c, run);
});
+22 -1
View File
@@ -9,7 +9,15 @@ import {
} from "@langchain/langgraph-sdk";
import { RemoteGraph } from "@langchain/langgraph/remote";
import postgres from "postgres";
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
import {
afterAll,
beforeAll,
beforeEach,
describe,
expect,
it,
vi,
} from "vitest";
import { findLast, gatherIterator, truncate } from "./utils.mjs";
import { type ChildProcess, spawn } from "node:child_process";
import { randomUUID } from "node:crypto";
@@ -2812,12 +2820,17 @@ describe("runtime API", () => {
});
const thread = await client.threads.create();
const onRunCreated = vi.fn();
expect(
await client.runs.wait(thread.thread_id, assistant.assistant_id, {
input: { messages: [{ role: "human", content: "input" }] },
context: { model: "openai" },
onRunCreated,
})
).toEqual({ model: "openai" });
expect(onRunCreated).toHaveBeenCalledTimes(1);
});
it("schema", async () => {
@@ -2851,11 +2864,14 @@ describe("runtime API", () => {
context: { model: "anthropic" },
});
const onRunCreated = vi.fn();
expect(
await client.runs.wait(null, assistant.assistant_id, {
input: { messages: [{ role: "human", content: "input" }] },
onRunCreated,
})
).toEqual({ model: "anthropic" });
expect(onRunCreated).toHaveBeenCalledTimes(1);
// patch to say openai
await client.assistants.update(assistant.assistant_id, {
@@ -2865,15 +2881,20 @@ describe("runtime API", () => {
expect(
await client.runs.wait(null, assistant.assistant_id, {
input: { messages: [{ role: "human", content: "input" }] },
onRunCreated,
})
).toEqual({ model: "openai" });
expect(onRunCreated).toHaveBeenCalledTimes(2);
});
it("default from env", async () => {
const onRunCreated = vi.fn();
expect(
await client.runs.wait(null, "simple_runtime", {
input: { messages: [{ role: "human", content: "input" }] },
onRunCreated,
})
).toEqual({ model: "unknown" });
expect(onRunCreated).toHaveBeenCalledTimes(1);
});
});