feat: pagination and tracing

This commit is contained in:
Arjun Natarajan
2025-06-10 15:35:27 -04:00
parent e8509436cf
commit f26c0ef7b3
4 changed files with 63 additions and 19 deletions
+10 -5
View File
@@ -1,19 +1,19 @@
import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { v4 as uuid } from "uuid";
import { z } from "zod";
import {
getAssistantId,
getGraph,
getCachedStaticGraphSchema,
getGraph,
} from "../graph/load.mjs";
import { getRuntimeGraphSchema } from "../graph/parser/index.mjs";
import { Assistants } from "../storage/ops.mjs";
import * as schemas from "../schemas.mjs";
import { HTTPException } from "hono/http-exception";
import * as schemas from "../schemas.mjs";
import { Assistants } from "../storage/ops.mjs";
const api = new Hono();
const RunnableConfigSchema = z.object({
@@ -71,6 +71,7 @@ api.post(
const payload = c.req.valid("json");
const result: unknown[] = [];
let total = 0;
for await (const item of Assistants.search(
{
graph_id: payload.graph_id,
@@ -80,9 +81,13 @@ api.post(
},
c.var.auth,
)) {
result.push(item);
result.push(item.assistant);
if (total === 0) {
total = item.total;
}
}
c.res.headers.set("X-Pagination-Total", total.toString());
return c.json(result);
},
);
+26 -1
View File
@@ -2,7 +2,32 @@ import { Hono } from "hono";
const api = new Hono();
api.get("/info", (c) => c.json({ flags: { assistants: true, crons: false } }));
// read env variable
const env = process.env;
api.get("/info", (c) => {
const langsmithApiKey = env["LANGSMITH_API_KEY"] || env["LANGCHAIN_API_KEY"];
const langsmithTracing = (() => {
if (langsmithApiKey) {
// Check if any tracing variable is explicitly set to "false"
const tracingVars = [
env["LANGCHAIN_TRACING_V2"],
env["LANGCHAIN_TRACING"],
env["LANGSMITH_TRACING_V2"],
env["LANGSMITH_TRACING"],
];
// Return true unless explicitly disabled
return !tracingVars.some((val) => val === "false" || val === "False");
}
return undefined;
})();
return c.json({
flags: { assistants: true, crons: false, langsmith: langsmithTracing },
env,
});
});
api.get("/ok", (c) => c.json({ ok: true }));
+16 -11
View File
@@ -17,7 +17,7 @@ export const cors = (
if (cors == null) {
return honoCors({
origin: "*",
exposeHeaders: ["content-location"],
exposeHeaders: ["content-location", "x-pagination-total"],
});
}
@@ -33,16 +33,21 @@ export const cors = (
}
: (cors.allow_origins ?? []);
if (
!!cors.expose_headers?.length &&
cors.expose_headers.some(
(i) => i.toLocaleLowerCase() === "content-location",
)
) {
console.warn(
"Adding missing `Content-Location` header in `cors.expose_headers`.",
);
cors.expose_headers.push("content-location");
if (cors.expose_headers?.length) {
const headersSet = new Set(cors.expose_headers.map((h) => h.toLowerCase()));
if (!headersSet.has("content-location")) {
console.warn(
"Adding missing `Content-Location` header in `cors.expose_headers`.",
);
cors.expose_headers.push("content-location");
}
if (!headersSet.has("x-pagination-total")) {
console.warn(
"Adding missing `X-Pagination-Total` header in `cors.expose_headers`.",
);
cors.expose_headers.push("x-pagination-total");
}
}
// TODO: handle `cors.allow_credentials`
+11 -2
View File
@@ -323,7 +323,7 @@ export class Assistants {
offset: number;
},
auth: AuthContext | undefined,
) {
): AsyncGenerator<{ assistant: Assistant; total: number }> {
const [filters] = await handleAuthEvent(auth, "assistants:search", {
graph_id: options.graph_id,
metadata: options.metadata,
@@ -360,11 +360,20 @@ export class Assistants {
return bCreatedAt - aCreatedAt;
});
// Calculate total count before pagination
const total = filtered.length;
for (const assistant of filtered.slice(
options.offset,
options.offset + options.limit,
)) {
yield { ...assistant, name: assistant.name ?? assistant.graph_id };
yield {
assistant: {
...assistant,
name: assistant.name ?? assistant.graph_id,
},
total,
};
}
});
}