diff --git a/wechat-mp.mjs b/wechat-mp.mjs index 5ba17d0..a872798 100644 --- a/wechat-mp.mjs +++ b/wechat-mp.mjs @@ -310,7 +310,13 @@ function extractHtmlWriteTargets(messages = []) { const args = toolCall?.arguments ?? {}; const action = String(args.action ?? '').toLowerCase(); const writeLikeDeveloper = name === 'developer' && action === 'write'; - const writeLikeSandbox = (name === 'write_file' || name === 'edit_file') && typeof args.path === 'string'; + const normalizedName = String(name ?? '').trim(); + const writeLikeSandbox = + (normalizedName === 'write_file' || + normalizedName === 'edit_file' || + normalizedName.endsWith('__write_file') || + normalizedName.endsWith('__edit_file')) && + typeof args.path === 'string'; if (!writeLikeDeveloper && !writeLikeSandbox) continue; const candidate = String(args.path ?? '').trim(); if (candidate.toLowerCase().endsWith('.html')) targets.add(candidate); @@ -377,7 +383,9 @@ function buildPublicHtmlUrl(workingDir, relativePath, publicBaseUrl) { function ensurePublicHtmlArtifact(htmlPath, workingDir) { const workspaceRoot = path.resolve(workingDir); - const source = path.resolve(htmlPath); + const source = path.isAbsolute(String(htmlPath ?? '')) + ? path.resolve(String(htmlPath)) + : path.resolve(workspaceRoot, String(htmlPath ?? '')); if (source !== workspaceRoot && !source.startsWith(`${workspaceRoot}${path.sep}`)) return null; if (!fs.existsSync(source) || !fs.statSync(source).isFile()) return null; diff --git a/wechat-mp.test.mjs b/wechat-mp.test.mjs index 3646877..2602800 100644 --- a/wechat-mp.test.mjs +++ b/wechat-mp.test.mjs @@ -253,6 +253,47 @@ test('maybeAttachPublishedHtmlLink copies generated root html into public and re ); }); +test('maybeAttachPublishedHtmlLink recognizes sandbox-fs write_file html outputs', async () => { + const workspaceRoot = fs.mkdtempSync('/tmp/wechat-mp-sandbox-fs-'); + const htmlPath = `${workspaceRoot}/public/codex-verify.html`; + fs.mkdirSync(`${workspaceRoot}/public`, { recursive: true }); + fs.writeFileSync(htmlPath, 'Codex Verify'); + + const text = await maybeAttachPublishedHtmlLink( + { + text: '页面已生成 ✅', + messages: [ + { + role: 'assistant', + content: [ + { + type: 'toolRequest', + toolCall: { + value: { + name: 'sandbox-fs__write_file', + arguments: { + path: 'public/codex-verify.html', + content: 'Codex Verify', + }, + }, + }, + }, + ], + }, + ], + }, + { + workingDir: workspaceRoot, + publicBaseUrl: 'https://m.tkmind.cn', + }, + ); + + assert.match( + text, + /https:\/\/m\.tkmind\.cn\/MindSpace\/.+\/public\/codex-verify\.html/, + ); +}); + test('wechat mp service splits long agent replies into multiple customer messages', async () => { const token = 'token'; const timestamp = '1710000000';