import fs from "node:fs"; import path from "node:path"; import { createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result"; import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; import { resolveFeishuAccount } from "./accounts.js"; import { createFeishuClient } from "./client.js"; import { cleanupAmbientCommentTypingReaction } from "./comment-reaction.js"; import { parseFeishuCommentTarget } from "./comment-target.js"; import { deliverCommentThreadText } from "./drive.js"; import { sendMediaFeishu } from "./media.js"; import { chunkTextForOutbound, type ChannelOutboundAdapter } from "./outbound-runtime-api.js"; import { sendMarkdownCardFeishu, sendMessageFeishu, sendStructuredCardFeishu } from "./send.js";
function normalizePossibleLocalImagePath(text: string | undefined): string | null { const raw = text?.trim(); if (!raw) { returnnull;
}
// Only auto-convert when the message is a pure path-like payload. // Avoid converting regular sentences that merely contain a path. const hasWhitespace = /\s/.test(raw); if (hasWhitespace) { returnnull;
}
// Ignore links/data URLs; those should stay in normal mediaUrl/text paths. if (/^(https?:\/\/|data:|file:\/\/)/i.test(raw)) { returnnull;
}
if (!path.isAbsolute(raw)) { returnnull;
} if (!fs.existsSync(raw)) { returnnull;
}
// Fix race condition: wrap statSync in try-catch to handle file deletion // between existsSync and statSync try { if (!fs.statSync(raw).isFile()) { returnnull;
}
} catch { // File may have been deleted or became inaccessible between checks returnnull;
}
// Send text first if provided if (text?.trim()) {
await sendOutboundText({
cfg,
to,
text,
accountId: accountId ?? undefined,
replyToMessageId,
});
}
// Upload and send media if URL or local path provided if (mediaUrl) { try { return await sendMediaFeishu({
cfg,
to,
mediaUrl,
accountId: accountId ?? undefined,
mediaLocalRoots,
replyToMessageId,
});
} catch (err) { // Log the error for debugging
console.error(`[feishu] sendMediaFeishu failed:`, err); // Fallback to URL link if upload fails return await sendOutboundText({
cfg,
to,
text: ` ${mediaUrl}`,
accountId: accountId ?? undefined,
replyToMessageId,
});
}
}
// No media URL, just return text result return await sendOutboundText({
cfg,
to,
text: text ?? "",
accountId: accountId ?? undefined,
replyToMessageId,
});
},
}),
};
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.