diff --git a/extensions/browser/src/record-shared.ts b/extensions/browser/src/record-shared.ts index 52eb5813b91..8f4a0b98703 100644 --- a/extensions/browser/src/record-shared.ts +++ b/extensions/browser/src/record-shared.ts @@ -1,10 +1,12 @@ -import { asNullableRecord, isRecord } from "openclaw/plugin-sdk/text-runtime"; +import { + asNullableRecord, + hasNonEmptyString as sharedHasNonEmptyString, + isRecord, +} from "openclaw/plugin-sdk/text-runtime"; export { asNullableRecord as asRecord, isRecord }; -export function hasNonEmptyString(value: unknown): value is string { - return typeof value === "string" && value.trim().length > 0; -} +export const hasNonEmptyString = sharedHasNonEmptyString; export function normalizeString(value: unknown): string | undefined { if (typeof value === "string") { diff --git a/extensions/feishu/src/comment-shared.ts b/extensions/feishu/src/comment-shared.ts index a626cb2fa6e..8d63e32b45b 100644 --- a/extensions/feishu/src/comment-shared.ts +++ b/extensions/feishu/src/comment-shared.ts @@ -1,4 +1,8 @@ -import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; +import { + asOptionalRecord, + hasNonEmptyString as sharedHasNonEmptyString, + normalizeOptionalString, +} from "openclaw/plugin-sdk/text-runtime"; export function encodeQuery(params: Record): string { const query = new URLSearchParams(); @@ -24,9 +28,7 @@ export function isRecord(value: unknown): value is Record { export const asRecord = asOptionalRecord; -export function hasNonEmptyString(value: unknown): value is string { - return typeof value === "string" && value.trim().length > 0; -} +export const hasNonEmptyString = sharedHasNonEmptyString; export function extractCommentElementText(element: unknown): string | undefined { if (!isRecord(element)) { diff --git a/extensions/memory-core/src/dreaming-shared.ts b/extensions/memory-core/src/dreaming-shared.ts index 8ae0c9e3292..fa574306a77 100644 --- a/extensions/memory-core/src/dreaming-shared.ts +++ b/extensions/memory-core/src/dreaming-shared.ts @@ -1,4 +1,5 @@ export { asNullableRecord as asRecord } from "openclaw/plugin-sdk/text-runtime"; +export { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; export function normalizeTrimmedString(value: unknown): string | undefined { if (typeof value !== "string") { @@ -7,7 +8,3 @@ export function normalizeTrimmedString(value: unknown): string | undefined { const trimmed = value.trim(); return trimmed.length > 0 ? trimmed : undefined; } - -export function formatErrorMessage(err: unknown): string { - return err instanceof Error ? err.message : String(err); -} diff --git a/extensions/tlon/src/monitor/utils.ts b/extensions/tlon/src/monitor/utils.ts index d54903092b8..7868f728456 100644 --- a/extensions/tlon/src/monitor/utils.ts +++ b/extensions/tlon/src/monitor/utils.ts @@ -1,3 +1,4 @@ +import { formatErrorMessage as sharedFormatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { asNullableObjectRecord } from "openclaw/plugin-sdk/text-runtime"; import { normalizeShip } from "../targets.js"; @@ -183,10 +184,7 @@ export async function resolveAuthorizedMessageText(params: { } export const asRecord = asNullableObjectRecord; - -export function formatErrorMessage(error: unknown): string { - return error instanceof Error ? error.message : String(error); -} +export const formatErrorMessage = sharedFormatErrorMessage; export function readString( record: Record | null, diff --git a/src/infra/outbound/channel-target.ts b/src/infra/outbound/channel-target.ts index 3df81fd8776..f87f2b8f1b0 100644 --- a/src/infra/outbound/channel-target.ts +++ b/src/infra/outbound/channel-target.ts @@ -1,15 +1,14 @@ +import { hasNonEmptyString as sharedHasNonEmptyString } from "../../shared/string-coerce.js"; import { MESSAGE_ACTION_TARGET_MODE } from "./message-action-spec.js"; +export const hasNonEmptyString = sharedHasNonEmptyString; + export const CHANNEL_TARGET_DESCRIPTION = "Recipient/channel: E.164 for WhatsApp/Signal, Telegram chat id/@username, Discord/Slack channel/user, or iMessage handle/chat_id"; export const CHANNEL_TARGETS_DESCRIPTION = "Recipient/channel targets (same format as --target); accepts ids or names when the directory is available."; -export function hasNonEmptyString(value: unknown): value is string { - return typeof value === "string" && value.trim().length > 0; -} - export function applyTargetToParams(params: { action: string; args: Record; diff --git a/src/shared/string-coerce.ts b/src/shared/string-coerce.ts index e8f17905ac7..a07ba3b0c4f 100644 --- a/src/shared/string-coerce.ts +++ b/src/shared/string-coerce.ts @@ -9,3 +9,7 @@ export function normalizeNullableString(value: unknown): string | null { export function normalizeOptionalString(value: unknown): string | undefined { return normalizeNullableString(value) ?? undefined; } + +export function hasNonEmptyString(value: unknown): value is string { + return typeof value === "string" && value.trim().length > 0; +}