feat(workshop): AI创作弹窗v4-上传需求附件(doc/docx/txt/pdf)→AI打磨携带+创作上下文
* attachment-parser.js 零依赖(node:zlib)txt/docx/pdf纯文本提取;.doc明确400报错
* server.js 新增 POST /api/req/parse-attachment(20MB/30MB/3万字符限);
/api/ai/clarify 入参增 attach 拼【附件素材】段(2万字符)
* data-pages.js confirmAiScript:req-input-box内左侧回形针(新ICON_PATHS paperclip)
+ 隐藏 file input + attach chip 行(paperclip+文件名+字数+×);
空输入但有附件自动发引导语;sendTurn 携带 attach;
buildCreatePrompt 增第5参 attachText→【附件素材】段并入创作 prompt
* style.css:req-attach-row/req-chip/chip-x/req-paper 系列样式;req-input-box padding-left 调
* 端到端 4 路径 API 验证 OK;CDP 9224 冒烟(纯Runtime+DataTransfer 注入 + 持久WS)全绿;
真实 Dify 一轮打磨确认附件诉求已吸收进需求清单
* 测试样例 tmp/attach-tests/{req.txt,req.docx,old.doc}.b64(make_samples.py)
9-02 16:31 已改中立内容,避免冒烟带真实账号名
This commit is contained in:
1 parent
e0dec07721
commit
50bbed30f7
5 files changed
+294
-13
No files matched your search
@@ -10,6 +10,7 @@ const os = require('os');
|
||||
const { execFileSync } = require('child_process');
|
||||
const { URL } = require('url');
|
||||
const dsh = require('./dsh-data');
|
||||
const { parseAttachment } = require('./scripts/attachment-parser');
|
||||
|
||||
// 09-01 默认端口由 8899 改为 8900:本机 8899 被小米 PC 管家 MiPCAudio.exe 系统服务占用(0.0.0.0 监听且自动复活),
|
||||
// 此时 127.0.0.1:8899 绑定不生效 → 默认直接起在 8900;仍可 `node server.js <端口>` 显式换端口
|
||||
@@ -657,7 +658,7 @@ const server = http.createServer((req, res) => {
|
||||
req.on('data', (c) => { body += c; if (body.length > 1e6) req.destroy(); });
|
||||
req.on('end', async () => {
|
||||
try {
|
||||
const { accountName, turn, reqMd, history } = JSON.parse(body || '{}');
|
||||
const { accountName, turn, reqMd, history, attach } = JSON.parse(body || '{}');
|
||||
if (!accountName || typeof accountName !== 'string') return sendErr(400, '缺少账号名');
|
||||
if (!turn || typeof turn !== 'string' || !turn.trim()) return sendErr(400, '缺少用户输入');
|
||||
// 1) 账号设定摘要(工作台库,与选题接口同源)
|
||||
@@ -688,10 +689,12 @@ const server = http.createServer((req, res) => {
|
||||
const his = Array.isArray(history) ? history.filter((h) => h && h.u).slice(-2) : [];
|
||||
const histText = his.map((h) => '你:' + String(h.a || '') + '\n达人:' + String(h.u || '')).join('\n');
|
||||
const reqMdText = String(reqMd || '').trim();
|
||||
const attachText = String(attach || '').trim().slice(0, 20000);
|
||||
const query = '你是资深短视频编导,正在创作前通过多轮对话,帮达人「' + accountName + '」把创作需求打磨清楚。'
|
||||
+ '你的职责只限需求澄清、整理与追问;严禁生成脚本正文、台词、分镜或完整故事。\n\n'
|
||||
+ '【账号设定摘要】\n' + (personaText || '(暂无可用账号设定,按通用编导经验澄清)') + '\n'
|
||||
+ (contentText ? '【账号定位】\n' + contentText + '\n' : '')
|
||||
+ (attachText ? '【附件素材】(达人上传的需求文档/资料,打磨与最终创作都须充分参考;把其中的关键诉求/约束吸收进需求清单)\n' + attachText + '\n' : '')
|
||||
+ '【当前需求清单】\n' + (reqMdText || '(空:等待用户先给出初步想法)') + '\n'
|
||||
+ (histText ? '【对话历史】\n' + histText + '\n' : '')
|
||||
+ '【达人本轮输入】\n' + turn.trim() + '\n\n'
|
||||
@@ -727,6 +730,27 @@ const server = http.createServer((req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 需求附件解析(09-02 新增):txt/docx/pdf → 纯文本(供 AI 打磨与创作上下文)
|
||||
if (p === '/api/req/parse-attachment' && req.method === 'POST') {
|
||||
let body = '';
|
||||
req.on('data', (c) => { body += c; if (body.length > 30e6) req.destroy(); }); // 附件 base64 上限约 22MB 原文件
|
||||
req.on('end', async () => {
|
||||
try {
|
||||
const { name, data } = JSON.parse(body || '{}');
|
||||
if (!name || typeof name !== 'string' || !data || typeof data !== 'string') return sendErr(400, '缺少文件参数');
|
||||
const buf = Buffer.from(data, 'base64');
|
||||
if (buf.length > 20e6) return sendErr(413, '文件过大(上限 20MB)');
|
||||
const r = parseAttachment(name, buf);
|
||||
if (r.error) return sendErr(400, r.error);
|
||||
const text = String(r.text || '').slice(0, 30000); // 打磨上下文上限 3 万字符
|
||||
return dshOk(200, { text, chars: text.length, warn: r.warn || '', sourceChars: r.chars });
|
||||
} catch (e) {
|
||||
return sendErr(500, '附件解析失败: ' + e.message);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 分析产物同步入库(09-01 新增):扫描账号产出目录 → 写工作台库 mcn-plugin.db
|
||||
if (p === '/api/import/account' && req.method === 'POST') {
|
||||
let body = '';
|
||||
|
||||
Reference in new issue
Block a user