diff --git a/extensions/feishu/src/comment-shared.ts b/extensions/feishu/src/comment-shared.ts index 8d63e32b45b..8497e78b634 100644 --- a/extensions/feishu/src/comment-shared.ts +++ b/extensions/feishu/src/comment-shared.ts @@ -1,7 +1,9 @@ import { asOptionalRecord, hasNonEmptyString as sharedHasNonEmptyString, + isRecord as sharedIsRecord, normalizeOptionalString, + readStringValue, } from "openclaw/plugin-sdk/text-runtime"; export function encodeQuery(params: Record): string { @@ -16,15 +18,11 @@ export function encodeQuery(params: Record): string return queryString ? `?${queryString}` : ""; } -export function readString(value: unknown): string | undefined { - return typeof value === "string" ? value : undefined; -} +export const readString = readStringValue; export const normalizeString = normalizeOptionalString; -export function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null; -} +export const isRecord = sharedIsRecord; export const asRecord = asOptionalRecord; diff --git a/packages/plugin-package-contract/src/index.ts b/packages/plugin-package-contract/src/index.ts index bb8e6000ccb..e5506684e78 100644 --- a/packages/plugin-package-contract/src/index.ts +++ b/packages/plugin-package-contract/src/index.ts @@ -1,3 +1,5 @@ +import { isRecord } from "../../../src/utils.js"; + export type JsonObject = Record; export type ExternalPluginCompatibility = { @@ -22,10 +24,6 @@ export const EXTERNAL_CODE_PLUGIN_REQUIRED_FIELD_PATHS = [ "openclaw.build.openclawVersion", ] as const; -function isRecord(value: unknown): value is JsonObject { - return Boolean(value) && typeof value === "object" && !Array.isArray(value); -} - function getTrimmedString(value: unknown): string | undefined { return typeof value === "string" && value.trim() ? value.trim() : undefined; } diff --git a/scripts/label-open-issues.ts b/scripts/label-open-issues.ts index 499ebfa788c..e4f6ea36cd4 100644 --- a/scripts/label-open-issues.ts +++ b/scripts/label-open-issues.ts @@ -2,6 +2,7 @@ import { execFileSync } from "node:child_process"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { homedir } from "node:os"; import { dirname, join } from "node:path"; +import { isRecord } from "../src/utils.js"; function writeStdoutLine(message = ""): void { process.stdout.write(`${message}\n`); @@ -546,10 +547,6 @@ function extractResponseText(payload: OpenAIResponse): string { return chunks.join("\n").trim(); } -function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null; -} - function fallbackCategory(issueText: string): "bug" | "enhancement" { const lower = issueText.toLowerCase(); const bugSignals = [ diff --git a/scripts/lib/bundled-extension-manifest.ts b/scripts/lib/bundled-extension-manifest.ts index d7fca5cbba7..04d6c17513c 100644 --- a/scripts/lib/bundled-extension-manifest.ts +++ b/scripts/lib/bundled-extension-manifest.ts @@ -1,8 +1,5 @@ import { validateMinHostVersion } from "../../src/plugins/min-host-version.ts"; - -function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null; -} +import { isRecord } from "../../src/utils.js"; export type ExtensionPackageJson = { name?: string; diff --git a/scripts/lib/record-shared.mjs b/scripts/lib/record-shared.mjs new file mode 100644 index 00000000000..a7aafcbe132 --- /dev/null +++ b/scripts/lib/record-shared.mjs @@ -0,0 +1,7 @@ +export function isRecord(value) { + return value !== null && typeof value === "object" && !Array.isArray(value); +} + +export function trimString(value) { + return typeof value === "string" ? value.trim() : ""; +} diff --git a/scripts/write-official-channel-catalog.mjs b/scripts/write-official-channel-catalog.mjs index 3020949fe61..aaa64425990 100644 --- a/scripts/write-official-channel-catalog.mjs +++ b/scripts/write-official-channel-catalog.mjs @@ -1,18 +1,11 @@ import fs from "node:fs"; import path from "node:path"; import { pathToFileURL } from "node:url"; +import { isRecord, trimString } from "./lib/record-shared.mjs"; import { writeTextFileIfChanged } from "./runtime-postbuild-shared.mjs"; export const OFFICIAL_CHANNEL_CATALOG_RELATIVE_PATH = "dist/channel-catalog.json"; -function isRecord(value) { - return value !== null && typeof value === "object" && !Array.isArray(value); -} - -function trimString(value) { - return typeof value === "string" ? value.trim() : ""; -} - function toCatalogInstall(value, packageName) { const install = isRecord(value) ? value : {}; const npmSpec = trimString(install.npmSpec) || packageName;