mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
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:
committed by
GitHub
parent
66fe424590
commit
b080dd1e76
@@ -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,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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user