- 删除已弃用的 compositor_client.go - 删除激光合成微服务代码 - 添加 gateway 合成控制器和测试文件 - 添加 Dify prompt 补丁脚本 Co-Authored-By: Claude <noreply@anthropic.com>
118 lines
4.0 KiB
JavaScript
118 lines
4.0 KiB
JavaScript
#!/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)
|
||
})
|