fix(gateway): defer chat startup helpers

This commit is contained in:
Vincent Koc
2026-04-26 23:14:56 -07:00
parent 1dac448ff0
commit ab237fe7b0
4 changed files with 16 additions and 13 deletions

View File

@@ -40,6 +40,7 @@ Docs: https://docs.openclaw.ai
- Gateway/startup: split lightweight HTTP auth helpers away from model-override helpers so Gateway bind no longer imports model catalog selection while wiring base HTTP routes. Thanks @vincentkoc.
- Gateway/startup: lazy-load plugin HTTP route dispatch when active plugin routes exist so no-plugin Gateway boot skips plugin route runtime scope setup. Thanks @vincentkoc.
- Gateway/startup: move chat run/subscriber registries onto a lightweight state module and defer chat/session event projection until the first event so Gateway boot skips session IO imports. Thanks @vincentkoc.
- Gateway/startup: keep node session runtime on a lightweight JSON parser instead of importing gateway method validation helpers during boot. Thanks @vincentkoc.
- CLI/Gateway: use a parse-only config snapshot for plain `gateway status` reads and reuse same-path service config context so status no longer spends tens of seconds in full config validation before printing. Thanks @vincentkoc.
- Lobster/Gateway: memoize repeated Ajv schema compilation before loading the embedded Lobster runtime so scheduled workflows and `llm.invoke` loops stop growing gateway heap on content-identical schemas. Fixes #71148. Thanks @cmi525, @vsolaz, and @vincentkoc.
- Codex harness: normalize cached input tokens before session/context accounting so prompt cache reads are not double-counted in `/status`, `session_status`, or persisted `sessionEntry.totalTokens`. Fixes #69298. Thanks @richardmqq.

View File

@@ -0,0 +1,13 @@
import { normalizeOptionalString } from "../shared/string-coerce.js";
export function safeParseJson(value: string | null | undefined): unknown {
const trimmed = normalizeOptionalString(value);
if (!trimmed) {
return undefined;
}
try {
return JSON.parse(trimmed) as unknown;
} catch {
return { payloadJSON: value };
}
}

View File

@@ -1,6 +1,7 @@
import type { ErrorObject } from "ajv";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import { ErrorCodes, errorShape, formatValidationErrors } from "../protocol/index.js";
export { safeParseJson } from "../server-json.js";
import { formatForLog } from "../ws-log.js";
import type { RespondFn } from "./types.js";
@@ -38,18 +39,6 @@ export function uniqueSortedStrings(values: unknown[]) {
.toSorted();
}
export function safeParseJson(value: string | null | undefined): unknown {
const trimmed = normalizeOptionalString(value);
if (!trimmed) {
return undefined;
}
try {
return JSON.parse(trimmed) as unknown;
} catch {
return { payloadJSON: value };
}
}
export function respondUnavailableOnNodeInvokeError<T extends { ok: boolean; error?: unknown }>(
respond: RespondFn,
res: T,

View File

@@ -3,7 +3,7 @@ import {
createSessionEventSubscriberRegistry,
createSessionMessageSubscriberRegistry,
} from "./server-chat-state.js";
import { safeParseJson } from "./server-methods/nodes.helpers.js";
import { safeParseJson } from "./server-json.js";
import { hasConnectedMobileNode } from "./server-mobile-nodes.js";
import { createNodeSubscriptionManager } from "./server-node-subscriptions.js";