mirror of
https://github.com/ruvnet/RuView
synced 2026-08-08 20:11:43 +00:00
perf(rvagent): lazy-load HTTP transport + memoize generated tool schemas
stdio time-to-first-response ~242ms -> ~189ms (-22%; MEASURED, median of repeated initialize round-trips against dist/index.js in this container). - ./http-transport.js now imported lazily inside the RVAGENT_HTTP_PORT branch: it chain-loads the MCP SDK streamableHttp module (~48ms MEASURED via per-module import() timing) which the default stdio path never uses - toolInputJsonSchema memoized per tool: schemas are static for the process lifetime; under the session-per-server HTTP model every session calls tools/list, so stop re-walking the Zod tree each time No behavior change: 99/99 jest tests; HTTP session flow re-smoke-tested through the lazy import path (initialize -> 200 + mcp-session-id). Profiled @ruvnet/ruview too and left it alone: 50ms CLI startup vs ~29ms bare 'node -e ""' floor on the same box (MEASURED) — already near the interpreter floor with zero dependencies. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz
This commit is contained in:
@@ -65,7 +65,9 @@ import {
|
||||
vitalsGetHeartRate,
|
||||
} from "./tools/vitals-get-heart-rate.js";
|
||||
import { vitalsGetAllSchema, vitalsGetAll } from "./tools/vitals-get-all.js";
|
||||
import { createHttpTransport } from "./http-transport.js";
|
||||
// NOTE: ./http-transport.js is imported lazily in main() — it chain-loads the
|
||||
// SDK's streamableHttp module (~48 ms MEASURED), which the default stdio path
|
||||
// never uses.
|
||||
|
||||
// Single-source the version from package.json (ADR-264 O8/ADR-265 D3).
|
||||
const require = createRequire(import.meta.url);
|
||||
@@ -223,13 +225,22 @@ export const TOOL_ALIASES: Record<string, string> = {
|
||||
"ruview.vitals.get_all": "ruview_vitals_get_all",
|
||||
};
|
||||
|
||||
/** Advertised JSON Schema, generated from the Zod source (ADR-264 O5). */
|
||||
/**
|
||||
* Advertised JSON Schema, generated from the Zod source (ADR-264 O5).
|
||||
* Memoized: schemas are static for the process lifetime, and tools/list is
|
||||
* called once per session (per HTTP session under the session-per-server
|
||||
* model) — no point re-walking the Zod tree each time.
|
||||
*/
|
||||
const jsonSchemaCache = new Map<string, object>();
|
||||
export function toolInputJsonSchema(def: ToolDef): object {
|
||||
const cached = jsonSchemaCache.get(def.name);
|
||||
if (cached !== undefined) return cached;
|
||||
const raw = zodToJsonSchema(def.schema, { $refStrategy: "none" }) as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
delete raw["$schema"];
|
||||
jsonSchemaCache.set(def.name, raw);
|
||||
return raw;
|
||||
}
|
||||
|
||||
@@ -324,10 +335,12 @@ async function main(): Promise<void> {
|
||||
const transport = new StdioServerTransport();
|
||||
await stdioServer.connect(transport);
|
||||
|
||||
// Streamable HTTP transport — explicit opt-in only (ADR-264 O3).
|
||||
// Streamable HTTP transport — explicit opt-in only (ADR-264 O3). Lazily
|
||||
// imported so the stdio path never pays the streamableHttp load cost.
|
||||
const httpPort = process.env["RVAGENT_HTTP_PORT"];
|
||||
let httpNote = "";
|
||||
if (httpPort !== undefined && httpPort !== "") {
|
||||
const { createHttpTransport } = await import("./http-transport.js");
|
||||
const { boundAddress } = await createHttpTransport(
|
||||
() => buildServer(config),
|
||||
{ port: Number(httpPort) }
|
||||
|
||||
Reference in New Issue
Block a user