topfans/backend/scripts/patch_dify_overlay_prompt.mjs
Lenticular Studio Agent 67cf3d4177 chore: 清理 laserCompositor 微服务残留
- 删除已弃用的 compositor_client.go
- 删除激光合成微服务代码
- 添加 gateway 合成控制器和测试文件
- 添加 Dify prompt 补丁脚本

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-23 22:44:03 +08:00

118 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* 一键更新 Dify workflow 的装饰层 prompt
*
* 用法:
* 1) 在 Dify 控制台 → Settings → Account → 生成 Personal Access Token(管理员权限)
* 2) 运行: DIFY_BASE_URL=https://api.dify.ai/v1 DIFY_ADMIN_TOKEN=pat-xxx node patch_dify_overlay_prompt.mjs <app_id>
*
* app_id 在 URL 里: https://your-dify/app/<APP_ID>/workflow
*
* 说明:
* - 脚本会:
* 1) GET /apps/{app_id}/export → 下载当前 DSL
* 2) 在 workflow.graph.nodes 中找到 title === "MiniMax 批量装饰图" 的节点
* 3) 把 body.data.prompt 改成新模板
* 4) POST /apps/import → 创建新 App(避免直接覆盖线上)
* 5) 输出新 App 的 ID,您可选择:
* a) 直接把新 App 当作 laser_card_variants_v2 部署
* b) 或者导出 DSL 后手工在控制台替换原 App
*/
import fs from 'node:fs/promises'
import path from 'node:path'
const DIFY_BASE_URL = process.env.DIFY_BASE_URL || 'http://localhost/v1'
const DIFY_ADMIN_TOKEN = process.env.DIFY_ADMIN_TOKEN
const NEW_OVERLAY_PROMPT =
'镭射卡装饰叠加层透明背景软光晕与微光粒子飘散光影流动效果营造氛围而非遮挡主体。生成5种不同风格的装饰变体: {{#code-param.overlay_prompts_all#}}'
if (!DIFY_ADMIN_TOKEN) {
console.error('❌ Missing DIFY_ADMIN_TOKEN env var (PAT with admin scope)')
process.exit(1)
}
const appId = process.argv[2]
if (!appId) {
console.error('❌ Usage: node patch_dify_overlay_prompt.mjs <app_id>')
process.exit(1)
}
const headers = {
Authorization: `Bearer ${DIFY_ADMIN_TOKEN}`,
'Content-Type': 'application/json',
}
async function api(method, urlPath, body) {
const url = `${DIFY_BASE_URL.replace(/\/$/, '')}${urlPath}`
const init = { method, headers }
if (body) init.body = JSON.stringify(body)
const res = await fetch(url, init)
const text = await res.text()
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${method} ${urlPath}\n${text.slice(0, 500)}`)
}
return text ? JSON.parse(text) : null
}
async function main() {
console.log(`▶ Exporting app ${appId}...`)
const dsl = await api('GET', `/apps/${appId}/export`)
const nodes = dsl?.workflow?.graph?.nodes || []
const overlayNode = nodes.find((n) => n?.data?.title === 'MiniMax 批量装饰图')
if (!overlayNode) {
console.error('❌ 未找到 "MiniMax 批量装饰图" 节点,请检查 app_id 或确认 workflow 未被改名')
process.exit(2)
}
console.log(`▶ 找到节点 ${overlayNode.id},更新 prompt...`)
const oldData = overlayNode.data
let oldPrompt = ''
try {
const parsed = JSON.parse(oldData.body?.data || '{}')
oldPrompt = parsed.prompt || ''
} catch {
console.warn('⚠️ 现有 body.data 不是合法 JSON,跳过 oldPrompt 对比')
}
console.log(` 旧 prompt: ${oldPrompt.slice(0, 80)}...`)
console.log(` 新 prompt: ${NEW_OVERLAY_PROMPT.slice(0, 80)}...`)
// 构造新 body.data(必须保持 JSON 字符串格式,这是 Dify 节点存储方式)
const newBodyData = JSON.stringify({
model: 'image-01',
prompt: NEW_OVERLAY_PROMPT,
aspect_ratio: '3:4',
n: 5,
prompt_optimizer: true,
response_format: 'url',
})
oldData.body = { ...(oldData.body || {}), data: newBodyData }
console.log(`▶ Importing as new app...`)
const imported = await api('POST', '/apps/import', {
data: dsl,
import_mode: 'yaml-content',
})
const newAppId = imported?.app_id || imported?.id
console.log('')
console.log('✅ 完成!')
console.log(` 新 App ID: ${newAppId}`)
console.log(` 新 App 名称: ${imported?.name}`)
console.log('')
console.log('下一步:')
console.log(' 1) 进 Dify 控制台打开新 App,确认装饰层 prompt 已更新')
console.log(' 2) 发布新 App,获取新 API Key')
console.log(' 3) 替换 backend/.env 中的 DIFY_API_KEY')
console.log(' 4) 重启 Gateway')
console.log('')
console.log('或者:把当前 App 在控制台手工改一个节点的 prompt 也可以,见 docs/laser-card-style-pool.md 方案 A')
}
main().catch((err) => {
console.error('❌ 失败:', err.message)
process.exit(99)
})