mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 01:31:08 +00:00
refactor: dedupe extension trimmed readers
This commit is contained in:
@@ -314,7 +314,7 @@ async function uploadInputImage(params: {
|
||||
form.set(
|
||||
"image",
|
||||
new Blob([toBlobBytes(params.image.buffer)], { type: params.image.mimeType }),
|
||||
params.image.fileName?.trim() ||
|
||||
normalizeOptionalString(params.image.fileName) ||
|
||||
`input.${inferFileExtension({ mimeType: params.image.mimeType })}`,
|
||||
);
|
||||
form.set("type", "input");
|
||||
@@ -337,7 +337,8 @@ async function uploadInputImage(params: {
|
||||
errorPrefix: "Comfy image upload failed",
|
||||
});
|
||||
|
||||
const uploadedName = payload.filename?.trim() || payload.name?.trim();
|
||||
const uploadedName =
|
||||
normalizeOptionalString(payload.filename) || normalizeOptionalString(payload.name);
|
||||
if (!uploadedName) {
|
||||
throw new Error("Comfy image upload response missing filename");
|
||||
}
|
||||
@@ -473,15 +474,16 @@ async function downloadOutputFile(params: {
|
||||
mode: ComfyMode;
|
||||
capability: ComfyCapability;
|
||||
}): Promise<{ buffer: Buffer; mimeType: string }> {
|
||||
const fileName = params.file.filename?.trim() || params.file.name?.trim();
|
||||
const fileName =
|
||||
normalizeOptionalString(params.file.filename) || normalizeOptionalString(params.file.name);
|
||||
if (!fileName) {
|
||||
throw new Error("Comfy output entry missing filename");
|
||||
}
|
||||
|
||||
const query = new URLSearchParams({
|
||||
filename: fileName,
|
||||
subfolder: params.file.subfolder?.trim() ?? "",
|
||||
type: params.file.type?.trim() ?? "output",
|
||||
subfolder: normalizeOptionalString(params.file.subfolder) ?? "",
|
||||
type: normalizeOptionalString(params.file.type) ?? "output",
|
||||
});
|
||||
const viewPath = params.mode === "cloud" ? "/api/view" : "/view";
|
||||
const auditContext = `comfy-${params.capability}-download`;
|
||||
@@ -504,7 +506,7 @@ async function downloadOutputFile(params: {
|
||||
params.mode === "cloud" &&
|
||||
[301, 302, 303, 307, 308].includes(firstResponse.response.status)
|
||||
) {
|
||||
const redirectUrl = firstResponse.response.headers.get("location")?.trim();
|
||||
const redirectUrl = normalizeOptionalString(firstResponse.response.headers.get("location"));
|
||||
if (!redirectUrl) {
|
||||
throw new Error("Comfy cloud output redirect missing location header");
|
||||
}
|
||||
@@ -520,7 +522,8 @@ async function downloadOutputFile(params: {
|
||||
try {
|
||||
await assertOkOrThrowHttpError(redirected.response, "Comfy output download failed");
|
||||
const mimeType =
|
||||
redirected.response.headers.get("content-type")?.trim() || "application/octet-stream";
|
||||
normalizeOptionalString(redirected.response.headers.get("content-type")) ||
|
||||
"application/octet-stream";
|
||||
return {
|
||||
buffer: Buffer.from(await redirected.response.arrayBuffer()),
|
||||
mimeType,
|
||||
@@ -532,7 +535,8 @@ async function downloadOutputFile(params: {
|
||||
|
||||
await assertOkOrThrowHttpError(firstResponse.response, "Comfy output download failed");
|
||||
const mimeType =
|
||||
firstResponse.response.headers.get("content-type")?.trim() || "application/octet-stream";
|
||||
normalizeOptionalString(firstResponse.response.headers.get("content-type")) ||
|
||||
"application/octet-stream";
|
||||
return {
|
||||
buffer: Buffer.from(await firstResponse.response.arrayBuffer()),
|
||||
mimeType,
|
||||
@@ -592,7 +596,7 @@ export async function runComfyWorkflow(params: {
|
||||
readConfigInteger(capabilityConfig, "pollIntervalMs") ?? DEFAULT_POLL_INTERVAL_MS;
|
||||
const timeoutMs =
|
||||
readConfigInteger(capabilityConfig, "timeoutMs") ?? params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
||||
const providerModel = params.model?.trim() || DEFAULT_COMFY_MODEL;
|
||||
const providerModel = normalizeOptionalString(params.model) || DEFAULT_COMFY_MODEL;
|
||||
|
||||
setWorkflowInput({
|
||||
workflow,
|
||||
@@ -687,7 +691,7 @@ export async function runComfyWorkflow(params: {
|
||||
errorPrefix: "Comfy workflow submit failed",
|
||||
});
|
||||
|
||||
const promptId = promptResponse.prompt_id?.trim();
|
||||
const promptId = normalizeOptionalString(promptResponse.prompt_id);
|
||||
if (!promptId) {
|
||||
throw new Error("Comfy workflow submit response missing prompt_id");
|
||||
}
|
||||
@@ -755,7 +759,8 @@ export async function runComfyWorkflow(params: {
|
||||
capability: params.capability,
|
||||
});
|
||||
assetIndex += 1;
|
||||
const originalName = output.file.filename?.trim() || output.file.name?.trim();
|
||||
const originalName =
|
||||
normalizeOptionalString(output.file.filename) || normalizeOptionalString(output.file.name);
|
||||
assets.push({
|
||||
buffer: downloaded.buffer,
|
||||
mimeType: downloaded.mimeType,
|
||||
|
||||
@@ -32,36 +32,32 @@ export function extractCommentElementText(element: unknown): string | undefined
|
||||
if (!isRecord(element)) {
|
||||
return undefined;
|
||||
}
|
||||
const type = readString(element.type)?.trim();
|
||||
const type = normalizeString(element.type);
|
||||
if (type === "text_run" && isRecord(element.text_run)) {
|
||||
return (
|
||||
readString(element.text_run.content)?.trim() ||
|
||||
readString(element.text_run.text)?.trim() ||
|
||||
undefined
|
||||
);
|
||||
return normalizeString(element.text_run.content) || normalizeString(element.text_run.text);
|
||||
}
|
||||
if (type === "mention") {
|
||||
const mention = isRecord(element.mention) ? element.mention : undefined;
|
||||
const mentionName =
|
||||
readString(mention?.name)?.trim() ||
|
||||
readString(mention?.display_name)?.trim() ||
|
||||
readString(element.name)?.trim();
|
||||
normalizeString(mention?.name) ||
|
||||
normalizeString(mention?.display_name) ||
|
||||
normalizeString(element.name);
|
||||
return mentionName ? `@${mentionName}` : "@mention";
|
||||
}
|
||||
if (type === "docs_link") {
|
||||
const docsLink = isRecord(element.docs_link) ? element.docs_link : undefined;
|
||||
return (
|
||||
readString(docsLink?.text)?.trim() ||
|
||||
readString(docsLink?.url)?.trim() ||
|
||||
readString(element.text)?.trim() ||
|
||||
readString(element.url)?.trim() ||
|
||||
normalizeString(docsLink?.text) ||
|
||||
normalizeString(docsLink?.url) ||
|
||||
normalizeString(element.text) ||
|
||||
normalizeString(element.url) ||
|
||||
undefined
|
||||
);
|
||||
}
|
||||
return (
|
||||
readString(element.text)?.trim() ||
|
||||
readString(element.content)?.trim() ||
|
||||
readString(element.name)?.trim() ||
|
||||
normalizeString(element.text) ||
|
||||
normalizeString(element.content) ||
|
||||
normalizeString(element.name) ||
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ import {
|
||||
formatDocsLink,
|
||||
setSetupChannelEnabled,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
normalizeOptionalString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveDefaultIrcAccountId, resolveIrcAccount } from "./accounts.js";
|
||||
import {
|
||||
isChannelTarget,
|
||||
@@ -96,7 +100,7 @@ async function promptIrcNickServConfig(params: {
|
||||
await params.prompter.text({
|
||||
message: "NickServ service nick",
|
||||
initialValue: existing?.service || "NickServ",
|
||||
validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
validate: (value) => (normalizeStringifiedOptionalString(value) ? undefined : "Required"),
|
||||
}),
|
||||
).trim();
|
||||
|
||||
@@ -139,7 +143,7 @@ async function promptIrcNickServConfig(params: {
|
||||
(params.accountId === DEFAULT_ACCOUNT_ID
|
||||
? process.env.IRC_NICKSERV_REGISTER_EMAIL
|
||||
: undefined),
|
||||
validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
validate: (value) => (normalizeStringifiedOptionalString(value) ? undefined : "Required"),
|
||||
}),
|
||||
).trim()
|
||||
: undefined;
|
||||
@@ -199,8 +203,8 @@ export const ircSetupWizard: ChannelSetupWizard = {
|
||||
prepare: async ({ cfg, accountId, credentialValues, prompter }) => {
|
||||
const resolved = resolveIrcAccount({ cfg: cfg as CoreConfig, accountId });
|
||||
const isDefaultAccount = accountId === DEFAULT_ACCOUNT_ID;
|
||||
const envHost = isDefaultAccount ? process.env.IRC_HOST?.trim() : "";
|
||||
const envNick = isDefaultAccount ? process.env.IRC_NICK?.trim() : "";
|
||||
const envHost = isDefaultAccount ? (normalizeOptionalString(process.env.IRC_HOST) ?? "") : "";
|
||||
const envNick = isDefaultAccount ? (normalizeOptionalString(process.env.IRC_NICK) ?? "") : "";
|
||||
const envReady = Boolean(envHost && envNick && !resolved.config.host && !resolved.config.nick);
|
||||
|
||||
if (envReady) {
|
||||
@@ -243,8 +247,8 @@ export const ircSetupWizard: ChannelSetupWizard = {
|
||||
currentValue: ({ cfg, accountId }) =>
|
||||
resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }).config.host || undefined,
|
||||
shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1",
|
||||
validate: ({ value }) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => String(value).trim(),
|
||||
validate: ({ value }) => (normalizeStringifiedOptionalString(value) ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
updateIrcAccountConfig(cfg as CoreConfig, accountId, {
|
||||
enabled: true,
|
||||
@@ -264,7 +268,7 @@ export const ircSetupWizard: ChannelSetupWizard = {
|
||||
return String(defaultPort);
|
||||
},
|
||||
validate: ({ value }) => {
|
||||
const parsed = Number.parseInt(String(value ?? "").trim(), 10);
|
||||
const parsed = Number.parseInt(normalizeStringifiedOptionalString(value) ?? "", 10);
|
||||
return Number.isFinite(parsed) && parsed >= 1 && parsed <= 65535
|
||||
? undefined
|
||||
: "Use a port between 1 and 65535";
|
||||
@@ -282,8 +286,8 @@ export const ircSetupWizard: ChannelSetupWizard = {
|
||||
currentValue: ({ cfg, accountId }) =>
|
||||
resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }).config.nick || undefined,
|
||||
shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1",
|
||||
validate: ({ value }) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => String(value).trim(),
|
||||
validate: ({ value }) => (normalizeStringifiedOptionalString(value) ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
updateIrcAccountConfig(cfg as CoreConfig, accountId, {
|
||||
enabled: true,
|
||||
@@ -300,8 +304,8 @@ export const ircSetupWizard: ChannelSetupWizard = {
|
||||
resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }).config.username ||
|
||||
credentialValues.token ||
|
||||
"openclaw",
|
||||
validate: ({ value }) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => String(value).trim(),
|
||||
validate: ({ value }) => (normalizeStringifiedOptionalString(value) ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
updateIrcAccountConfig(cfg as CoreConfig, accountId, {
|
||||
enabled: true,
|
||||
@@ -316,8 +320,8 @@ export const ircSetupWizard: ChannelSetupWizard = {
|
||||
shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1",
|
||||
initialValue: ({ cfg, accountId }) =>
|
||||
resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }).config.realname || "OpenClaw",
|
||||
validate: ({ value }) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => String(value).trim(),
|
||||
validate: ({ value }) => (normalizeStringifiedOptionalString(value) ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
updateIrcAccountConfig(cfg as CoreConfig, accountId, {
|
||||
enabled: true,
|
||||
|
||||
@@ -10,6 +10,10 @@ import {
|
||||
type ChannelSetupWizard,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
normalizeOptionalString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import { buildTlonAccountFields } from "./account-fields.js";
|
||||
import { normalizeShip } from "./targets.js";
|
||||
import { listTlonAccountIds, resolveTlonAccount, type TlonResolvedAccount } from "./types.js";
|
||||
@@ -78,8 +82,10 @@ export function createTlonSetupWizardBase(params: TlonSetupWizardBaseParams): Ch
|
||||
message: "Ship name",
|
||||
placeholder: "~sampel-palnet",
|
||||
currentValue: ({ cfg, accountId }) => resolveTlonAccount(cfg, accountId).ship ?? undefined,
|
||||
validate: ({ value }) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => normalizeShip(String(value).trim()),
|
||||
validate: ({ value }) =>
|
||||
normalizeStringifiedOptionalString(value) ? undefined : "Required",
|
||||
normalizeValue: ({ value }) =>
|
||||
normalizeShip(normalizeStringifiedOptionalString(value) ?? ""),
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
applyTlonSetupConfig({
|
||||
cfg,
|
||||
@@ -99,7 +105,7 @@ export function createTlonSetupWizardBase(params: TlonSetupWizardBaseParams): Ch
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
normalizeValue: ({ value }) => String(value).trim(),
|
||||
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
applyTlonSetupConfig({
|
||||
cfg,
|
||||
@@ -112,8 +118,9 @@ export function createTlonSetupWizardBase(params: TlonSetupWizardBaseParams): Ch
|
||||
message: "Login code",
|
||||
placeholder: "lidlut-tabwed-pillex-ridrup",
|
||||
currentValue: ({ cfg, accountId }) => resolveTlonAccount(cfg, accountId).code ?? undefined,
|
||||
validate: ({ value }) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
normalizeValue: ({ value }) => String(value).trim(),
|
||||
validate: ({ value }) =>
|
||||
normalizeStringifiedOptionalString(value) ? undefined : "Required",
|
||||
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
||||
applySet: async ({ cfg, accountId, value }) =>
|
||||
applyTlonSetupConfig({
|
||||
cfg,
|
||||
@@ -206,9 +213,9 @@ export const tlonSetupAdapter: ChannelSetupAdapter = {
|
||||
validateInput: createSetupInputPresenceValidator({
|
||||
validate: ({ cfg, accountId, input }) => {
|
||||
const resolved = resolveTlonAccount(cfg, accountId ?? undefined);
|
||||
const ship = input.ship?.trim() || resolved.ship;
|
||||
const url = input.url?.trim() || resolved.url;
|
||||
const code = input.code?.trim() || resolved.code;
|
||||
const ship = normalizeOptionalString(input.ship) || resolved.ship;
|
||||
const url = normalizeOptionalString(input.url) || resolved.url;
|
||||
const code = normalizeOptionalString(input.code) || resolved.code;
|
||||
if (!ship) {
|
||||
return "Tlon requires --ship.";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user