mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
1bcc4c5e70
* feat(gateway): add cooperative suspension preparation * style: satisfy suspension lint checks * test(gateway): reset work admission between shared suites * fix(gateway): reject upgrades during suspension * fix(gateway): preserve admitted work during suspension * test(gateway): isolate suspension and restart state * fix(gateway): close suspension false-ready gaps * refactor(protocol): slim suspension declaration graph * refactor(plugin-sdk): sever protocol registry edges * fix(gateway): preserve admitted restart follow-ups * fix(gateway): make suspension recovery fail closed * fix(protocol): keep validation formatter re-export only * test(gateway): simplify deferred fixture type * style(gateway): clarify suspension entry name * fix(gateway): retain detached work admission
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import type { EventFrame, ResponseFrame } from "./schema/frames.js";
|
|
export type {
|
|
ConnectParams,
|
|
ErrorShape,
|
|
EventFrame,
|
|
GatewayFrame,
|
|
HelloOk,
|
|
RequestFrame,
|
|
ResponseFrame,
|
|
} from "./schema/frames.js";
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
}
|
|
|
|
function isNonEmptyString(value: unknown): value is string {
|
|
return typeof value === "string" && value.length > 0;
|
|
}
|
|
|
|
function isNonNegativeInteger(value: unknown): value is number {
|
|
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
}
|
|
|
|
function isGatewayErrorShape(value: unknown): boolean {
|
|
if (!isRecord(value)) {
|
|
return false;
|
|
}
|
|
if (!isNonEmptyString(value.code) || !isNonEmptyString(value.message)) {
|
|
return false;
|
|
}
|
|
if (value.retryable !== undefined && typeof value.retryable !== "boolean") {
|
|
return false;
|
|
}
|
|
return value.retryAfterMs === undefined || isNonNegativeInteger(value.retryAfterMs);
|
|
}
|
|
|
|
// These lightweight guards validate dispatch-critical envelope fields without
|
|
// compiling the full schemas or rejecting additive payload fields.
|
|
export function isGatewayEventFrame(value: unknown): value is EventFrame {
|
|
if (!isRecord(value) || value.type !== "event" || !isNonEmptyString(value.event)) {
|
|
return false;
|
|
}
|
|
return value.seq === undefined || isNonNegativeInteger(value.seq);
|
|
}
|
|
|
|
export function isGatewayResponseFrame(value: unknown): value is ResponseFrame {
|
|
if (
|
|
!isRecord(value) ||
|
|
value.type !== "res" ||
|
|
!isNonEmptyString(value.id) ||
|
|
typeof value.ok !== "boolean"
|
|
) {
|
|
return false;
|
|
}
|
|
return value.error === undefined || isGatewayErrorShape(value.error);
|
|
}
|