1faba62f9b
Memind CI / Test, build, and release guards (push) Failing after 6s
Production WeChat delivery strips localPath from artifacts, so share-preview auto-repair never wrote back to HTML. Resolve paths via publishDir + relativePath, repair at materialize and delivery prep, and pass h5Root from Portal so page.generate can patch missing meta before sending links. Co-authored-by: Cursor <cursoragent@cursor.com>
126 lines
4.0 KiB
JavaScript
126 lines
4.0 KiB
JavaScript
import { buildPagePublishFailureText } from '../prompts/page-generate.mjs';
|
|
import { selectSendableHtmlArtifacts, verifyPageArtifactContent } from '../verify/page-artifact.mjs';
|
|
import { repairArtifactSharePreview } from '../verify/share-preview-repair.mjs';
|
|
import { filterSharePreviewReadyArtifacts, verifyArtifactSharePreview } from '../verify/share-preview.mjs';
|
|
|
|
export function evaluatePageGenerateSendableArtifacts({
|
|
verifiedArtifacts = [],
|
|
confirmedArtifacts = [],
|
|
repairContext = {},
|
|
} = {}) {
|
|
const publishDir = String(repairContext.publishDir ?? '').trim();
|
|
const previewOptions = { publishDir };
|
|
const sendable = selectSendableHtmlArtifacts({
|
|
verifiedArtifacts,
|
|
confirmedArtifacts,
|
|
publishDir,
|
|
});
|
|
const verified = sendable.filter((artifact) =>
|
|
verifyPageArtifactContent(artifact, previewOptions).ok,
|
|
);
|
|
const candidates = verified.length > 0 ? verified : sendable;
|
|
const ready = filterSharePreviewReadyArtifacts(candidates, previewOptions);
|
|
if (ready.length > 0) return ready;
|
|
|
|
const repaired = [];
|
|
for (const artifact of candidates) {
|
|
if (!verifyPageArtifactContent(artifact, previewOptions).ok) continue;
|
|
const result = repairArtifactSharePreview(artifact, repairContext);
|
|
if (result.ok && verifyArtifactSharePreview(artifact, previewOptions).ok) {
|
|
repaired.push(artifact);
|
|
}
|
|
}
|
|
return repaired;
|
|
}
|
|
|
|
/**
|
|
* Decide whether a page.generate reply may be delivered to the user.
|
|
* Returns { action: 'send'|'fail'|'session_retry', failureText?, reason? }
|
|
*/
|
|
export function resolvePageGenerateOutcome({
|
|
reply,
|
|
confirmedArtifacts = [],
|
|
verifiedArtifacts = [],
|
|
suspiciousPublishClaim = false,
|
|
bareCompletionReply = false,
|
|
htmlGenerationNeedsRetry = false,
|
|
replyHasPublicLinks = false,
|
|
topic = '',
|
|
repairContext = {},
|
|
}) {
|
|
const context = {
|
|
topic: String(topic || repairContext.topic || '').trim(),
|
|
publishDir: String(repairContext.publishDir ?? '').trim(),
|
|
...repairContext,
|
|
};
|
|
const previewOptions = { publishDir: context.publishDir };
|
|
const sendable = evaluatePageGenerateSendableArtifacts({
|
|
verifiedArtifacts,
|
|
confirmedArtifacts,
|
|
repairContext: context,
|
|
});
|
|
|
|
if (sendable.length > 0) {
|
|
return { action: 'send', artifacts: sendable };
|
|
}
|
|
|
|
if (
|
|
suspiciousPublishClaim ||
|
|
bareCompletionReply ||
|
|
(htmlGenerationNeedsRetry && replyHasPublicLinks && confirmedArtifacts.length === 0)
|
|
) {
|
|
return { action: 'session_retry', reason: 'poisoned_or_fake_claim' };
|
|
}
|
|
|
|
if (htmlGenerationNeedsRetry || suspiciousPublishClaim) {
|
|
return {
|
|
action: 'fail',
|
|
failureText: buildPagePublishFailureText(),
|
|
reason: 'skill_or_stub',
|
|
};
|
|
}
|
|
|
|
const previewCandidates = filterSharePreviewReadyArtifacts(
|
|
selectSendableHtmlArtifacts({
|
|
verifiedArtifacts,
|
|
confirmedArtifacts,
|
|
publishDir: context.publishDir,
|
|
}),
|
|
previewOptions,
|
|
);
|
|
if (previewCandidates.length === 0 && confirmedArtifacts.length > 0) {
|
|
const previewIssue = verifyArtifactSharePreview(
|
|
selectSendableHtmlArtifacts({
|
|
verifiedArtifacts,
|
|
confirmedArtifacts,
|
|
publishDir: context.publishDir,
|
|
})[0] ?? confirmedArtifacts[0],
|
|
previewOptions,
|
|
);
|
|
return {
|
|
action: 'fail',
|
|
failureText: buildPagePublishFailureText({
|
|
missingPlatformBrand: previewIssue.reason === 'missing_platform_brand',
|
|
missingSharePreview: previewIssue.reason !== 'missing_platform_brand',
|
|
}),
|
|
reason: previewIssue.reason ?? 'missing_share_preview',
|
|
};
|
|
}
|
|
|
|
if (!String(reply?.text ?? '').trim() && sendable.length === 0) {
|
|
return {
|
|
action: 'fail',
|
|
failureText: buildPagePublishFailureText(),
|
|
reason: 'empty_reply',
|
|
};
|
|
}
|
|
|
|
// Fail closed: page.generate must deliver a verified public HTML artifact.
|
|
// Text-only planning replies ("我先搜索…") must not mark WeChat delivery done.
|
|
return {
|
|
action: 'fail',
|
|
failureText: buildPagePublishFailureText(),
|
|
reason: 'missing_page_artifact',
|
|
};
|
|
}
|