refactor: consolidate coercion contracts (#122458)

* refactor: consolidate coercion contracts

Centralize exact string, record, numeric, date, Boolean, argument, and structured-error coercions while preserving call-site semantics.

Migrate canonical-name collisions and deprecated internal SDK bypasses, deleting 55 net production/tooling lines. Expand declaration ownership enforcement to 101 allowed helpers and add a narrow export-completeness audit.

* fix: preserve standalone script coercions

Keep copied Control UI tooling self-contained and retain the trusted release harness module-relative source seam when the harness runs against an old target cwd.
This commit is contained in:
Peter Steinberger
2026-08-11 23:26:37 -07:00
committed by GitHub
parent 66fe424590
commit b080dd1e76
276 changed files with 1685 additions and 1663 deletions
+4 -9
View File
@@ -11,19 +11,14 @@ vi.mock("openclaw/plugin-sdk/text-utility-runtime", () => ({
fetchWithTimeout: fetchWithTimeoutMock,
}));
vi.mock("openclaw/plugin-sdk/string-coerce-runtime", () => {
vi.mock("openclaw/plugin-sdk/string-coerce-runtime", async (importOriginal) => {
const { normalizeOptionalString } =
await importOriginal<typeof import("openclaw/plugin-sdk/string-coerce-runtime")>();
const isMockRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null;
const normalizeMockOptionalString = (value: unknown) => {
if (typeof value !== "string") {
return undefined;
}
const trimmed = value.trim();
return trimmed ? trimmed : undefined;
};
return {
isRecord: isMockRecord,
normalizeOptionalString: normalizeMockOptionalString,
normalizeOptionalString,
};
});
@@ -12,6 +12,7 @@ import {
} from "openclaw/plugin-sdk/conversation-runtime";
import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
import { logVerbose, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
import type { TelegramApprovalCallback } from "./approval-callback-data.js";
import {
buildTelegramCanonicalApprovalTerminalText,
@@ -420,11 +421,7 @@ const updateMultiSelectKeyboard = (
);
const resolvePluginCallbackSubmitText = (submitText: unknown): string | undefined => {
if (typeof submitText !== "string") {
return undefined;
}
const trimmed = submitText.trim();
return trimmed ? trimmed : undefined;
return normalizeOptionalString(submitText);
};
const isReplySessionInitConflictError = (err: unknown): boolean =>
@@ -10,6 +10,7 @@ import {
resolveAmbientTranscriptWatermarkKey,
type SessionEntry,
} from "openclaw/plugin-sdk/session-store-runtime";
import { asFiniteNumber } from "openclaw/plugin-sdk/string-coerce-runtime";
import { stripInlineDirectiveTagsForDelivery } from "openclaw/plugin-sdk/text-chunking";
import { resolveDefaultModelForAgent } from "./bot-handlers.agent.runtime.js";
import type { RegisterTelegramHandlerParams } from "./bot-handlers.types.js";
@@ -98,7 +99,7 @@ export type ResolvePromptContextAmbientWatermarkParams = {
};
export const normalizePromptContextMinTimestampMs = (timestampMs?: number) =>
typeof timestampMs === "number" && Number.isFinite(timestampMs) ? timestampMs : undefined;
asFiniteNumber(timestampMs);
export function promptContextBoundaryOptions(
timestampMs?: number,
@@ -1,5 +1,6 @@
// Telegram tests cover bot.create telegram bot.media group skip warning plugin behavior.
import { setTimeout as delay } from "node:timers/promises";
import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { telegramBotInfoForTest } from "./bot.create-telegram-bot.test-support.js";
@@ -21,7 +22,7 @@ vi.mock("./bot/delivery.resolve-media.runtime.js", async () => {
);
return {
readRemoteMediaBuffer: (...args: unknown[]) => readRemoteMediaBuffer(...args),
formatErrorMessage: (err: unknown) => (err instanceof Error ? err.message : String(err)),
formatErrorMessage: coerceErrorMessage,
logVerbose: () => {},
MediaFetchError: actual.MediaFetchError,
resolveTelegramApiBase: (apiRoot?: string) =>
@@ -1,5 +1,6 @@
import { GrammyError } from "grammy";
import type { Message } from "grammy/types";
import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
// Telegram tests cover delivery.resolve media retry plugin behavior.
import { createRequireRecord } from "openclaw/plugin-sdk/test-fixtures";
@@ -56,7 +57,7 @@ vi.mock("./delivery.resolve-media.runtime.js", () => {
}
return {
readRemoteMediaBuffer: (...args: unknown[]) => readRemoteMediaBuffer(...args),
formatErrorMessage: (err: unknown) => (err instanceof Error ? err.message : String(err)),
formatErrorMessage: coerceErrorMessage,
logVerbose: () => {},
MediaFetchError,
resolveTelegramApiBase: (apiRoot?: string) =>
@@ -1,4 +1,5 @@
import type { Message } from "grammy/types";
import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
// Telegram tests cover delivery.resolve media retry plugin behavior.
import { createRequireRecord } from "openclaw/plugin-sdk/test-fixtures";
@@ -55,7 +56,7 @@ vi.mock("./delivery.resolve-media.runtime.js", () => {
}
return {
readRemoteMediaBuffer: (...args: unknown[]) => readRemoteMediaBuffer(...args),
formatErrorMessage: (err: unknown) => (err instanceof Error ? err.message : String(err)),
formatErrorMessage: coerceErrorMessage,
logVerbose: () => {},
MediaFetchError,
resolveTelegramApiBase: (apiRoot?: string) =>
@@ -2,9 +2,8 @@
import type { TelegramNetworkConfig } from "openclaw/plugin-sdk/config-contracts";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("openclaw/plugin-sdk/runtime-env", () => ({
isTruthyEnvValue: (value: string | undefined) =>
typeof value === "string" && /^(1|true|yes|on)$/i.test(value.trim()),
vi.mock("openclaw/plugin-sdk/runtime-env", async (importOriginal) => ({
...(await importOriginal<typeof import("openclaw/plugin-sdk/runtime-env")>()),
isWSL2Sync: vi.fn(() => false),
}));
+2 -1
View File
@@ -2,6 +2,7 @@
import { GrammyError } from "grammy";
import type { MessageEntity } from "grammy/types";
import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
import { asFiniteNumber } from "openclaw/plugin-sdk/string-coerce-runtime";
import { buildTelegramThreadParams, type TelegramThreadSpec } from "./bot/helpers.js";
import { normalizeTelegramReplyToMessageId } from "./outbound-params.js";
@@ -118,7 +119,7 @@ export function getTelegramNativeQuoteReplyMessageId(
return undefined;
}
const messageId = (replyParameters as { message_id?: unknown }).message_id;
return typeof messageId === "number" && Number.isFinite(messageId) ? messageId : undefined;
return asFiniteNumber(messageId);
}
export function isTelegramQuoteParamError(err: unknown): boolean {
+4 -8
View File
@@ -11,7 +11,7 @@ import {
resolveEnabledConfiguredAccountId,
type AccountStatusSnapshot,
} from "openclaw/plugin-sdk/status-helpers";
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
import { asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
const TELEGRAM_POLLING_CONNECT_GRACE_MS = 120_000;
const TELEGRAM_POLLING_STALE_TRANSPORT_MS = 30 * 60_000;
@@ -41,10 +41,6 @@ type TelegramGroupMembershipAuditSummary = {
}>;
};
function asFiniteNumberOrNull(value: unknown): number | null {
return typeof value === "number" && Number.isFinite(value) ? value : null;
}
function appendTelegramRuntimeError(message: string, lastError: unknown): string {
const error = normalizeOptionalString(lastError);
return error ? `${message}: ${error}` : message;
@@ -69,8 +65,8 @@ function collectTelegramPollingRuntimeIssues(params: {
return;
}
const lastStartAt = asFiniteNumberOrNull(account.lastStartAt);
const lastTransportActivityAt = asFiniteNumberOrNull(account.lastTransportActivityAt);
const lastStartAt = asFiniteNumber(account.lastStartAt) ?? null;
const lastTransportActivityAt = asFiniteNumber(account.lastTransportActivityAt) ?? null;
const fix = `Run: ${formatCliCommand("openclaw channels status --probe")} (or restart the gateway). Check the bot token, proxy/network settings, and logs if it persists.`;
if (account.connected === false) {
@@ -129,7 +125,7 @@ function collectTelegramWebhookRuntimeIssues(params: {
return;
}
const lastStartAt = asFiniteNumberOrNull(account.lastStartAt);
const lastStartAt = asFiniteNumber(account.lastStartAt) ?? null;
const withinStartupGrace =
lastStartAt != null && now - lastStartAt < TELEGRAM_WEBHOOK_CONNECT_GRACE_MS;
if (withinStartupGrace) {
@@ -4,6 +4,7 @@ import {
sleepWithAbort,
type BackoffPolicy,
} from "openclaw/plugin-sdk/runtime-env";
import { asSafeIntegerInRange } from "openclaw/plugin-sdk/string-coerce-runtime";
const OFFSET_PERSIST_RETRY_POLICY: BackoffPolicy = {
initialMs: 250,
@@ -21,10 +22,7 @@ type TelegramUpdateOffsetPersistenceOptions = {
};
export function normalizeTelegramUpdateId(value: number | null): number | null {
if (value === null || !Number.isSafeInteger(value) || value < 0) {
return null;
}
return value;
return asSafeIntegerInRange(value, { min: 0 }) ?? null;
}
export function createTelegramUpdateOffsetPersistence(