feat: 新增高铁游与车宿徒步游技能及相关基础设施
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
/* ============================================================
|
||||
* debug_rail_replay_wuyuan.js —— 用真实失败案例回放,验证修复有效
|
||||
*
|
||||
* 背景:2026-09-30 生成「婺源」时返回 payload_invalid,唯一 error 是
|
||||
* 「第一天缺「夜逛」环节(night_stroll)」——但 AI 其实排了 19:00 的夜逛。
|
||||
* 根因是校验器写死了 day.label 含「第一天」,而 AI 标的是「周六/周日」。
|
||||
*
|
||||
* 本脚本把那次失败响应的 payload 原样取出来,走一遍「修复 → 校验」,
|
||||
* 用来证明修复后不再误报(同时也顺带检查其余 warning 是否已消除)。
|
||||
*
|
||||
* 用法:
|
||||
* node dev_test_scripts/debug/debug_rail_replay_wuyuan.js 只回放校验,不写任何文件
|
||||
* node dev_test_scripts/debug/debug_rail_replay_wuyuan.js --save 额外把这份结果写回
|
||||
* 技能私有 data/last_result.json,
|
||||
* 这样用户可在页面上点「载入最近一次生成」
|
||||
* 直接看到并导出这份婺源行程(不必重烧 token)
|
||||
*
|
||||
* 为什么需要 --save:服务端只在「校验 0 errors」时才落盘,那次因误判被丢弃,
|
||||
* 用户 4 分钟的生成白费了。这个开关是给「已经拿到完整 payload、只想补落盘」的补救场景用的。
|
||||
* ============================================================ */
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
const SRC = path.join(
|
||||
os.homedir(), 'AppData', 'Roaming', 'Trae CN', 'User', 'workspaceStorage',
|
||||
'540d38674b58f7802a478abf6956abc7', 'long-text', '6ab1e0ff40ac82e5fecf1de9',
|
||||
'munlta58-u92r', '当前状态__失败__....txt'
|
||||
)
|
||||
|
||||
const SKILL = path.join(process.cwd(), 'src', 'server', 'thought_lab', 'labs', 'travel_citytour', 'skills', 'sh_2d_rail_hike')
|
||||
const skillIndex = require(path.join(SKILL, 'index.js'))
|
||||
const { validatePayload } = require(path.join(SKILL, 'validate.js'))
|
||||
const { repairPayload } = require(path.join(SKILL, 'repair.js'))
|
||||
|
||||
if (!fs.existsSync(SRC)) {
|
||||
console.log('找不到失败响应文件(可能已被清理):' + SRC)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const raw = fs.readFileSync(SRC, 'utf-8')
|
||||
|
||||
// 响应体从「返回结果」后的第一个 '{' 开始,到「错误信息」之前结束
|
||||
const startMark = raw.indexOf('返回结果')
|
||||
const start = raw.indexOf('{', startMark)
|
||||
const endMark = raw.indexOf('错误信息', start)
|
||||
const text = raw.slice(start, endMark > 0 ? endMark : undefined).trim()
|
||||
|
||||
let envelope = null
|
||||
try {
|
||||
envelope = JSON.parse(text)
|
||||
} catch (e) {
|
||||
// 兜底:按大括号配平截取
|
||||
let depth = 0, endIdx = -1
|
||||
for (let i = start; i < raw.length; i++) {
|
||||
if (raw[i] === '{') depth++
|
||||
else if (raw[i] === '}') { depth--; if (depth === 0) { endIdx = i; break } }
|
||||
}
|
||||
envelope = JSON.parse(raw.slice(start, endIdx + 1))
|
||||
}
|
||||
|
||||
const payload = envelope.payload
|
||||
const bundle = skillIndex.loadBundle()
|
||||
|
||||
console.log('===== 婺源失败案例回放 =====')
|
||||
console.log('原文 error:' + JSON.stringify(envelope.check && envelope.check.errors))
|
||||
console.log('day.label 实际写法:' + ((payload.timeline && payload.timeline.days) || []).map((d) => JSON.stringify(d.label)).join(' / '))
|
||||
console.log('AI 是否排了夜逛行:' + ((payload.timeline && payload.timeline.days) || [])
|
||||
.reduce((a, d) => a.concat(d.rows || []), [])
|
||||
.some((r) => r.anchor_id === 'night_stroll'))
|
||||
console.log('')
|
||||
|
||||
const repaired = repairPayload(JSON.parse(JSON.stringify(payload)), bundle)
|
||||
const chk = validatePayload(repaired.payload, bundle)
|
||||
|
||||
console.log('— 修复说明 —')
|
||||
repaired.fixes.forEach((f) => console.log(' · ' + f))
|
||||
console.log('')
|
||||
console.log('— 修复后校验结果 —')
|
||||
console.log('errors : ' + chk.errors.length + (chk.errors.length ? '\n ✗ ' + chk.errors.join('\n ✗ ') : ''))
|
||||
console.log('warnings: ' + chk.warnings.length + (chk.warnings.length ? '\n ! ' + chk.warnings.join('\n ! ') : ''))
|
||||
console.log('')
|
||||
console.log(chk.errors.length === 0
|
||||
? '✓ 回放通过:这份真实失败的 payload 修复后 0 errors,不再被误判'
|
||||
: '✗ 仍有 error,需继续排查')
|
||||
|
||||
// --save:把修复后的结果补落盘,供页面「载入最近一次生成」使用
|
||||
if (process.argv.indexOf('--save') >= 0) {
|
||||
if (chk.errors.length) {
|
||||
console.log('\n⚠ 仍有 error,拒绝落盘(避免把不合格结果写进 last_result)')
|
||||
process.exit(1)
|
||||
}
|
||||
const outEnvelope = {
|
||||
ok: true,
|
||||
payload: repaired.payload,
|
||||
report_spec: bundle.report_spec || {},
|
||||
destination_override: null,
|
||||
check: chk,
|
||||
meta: Object.assign({}, envelope.meta, {
|
||||
repairs: repaired.fixes,
|
||||
recovered_from: 'payload_invalid 误判(校验器已修复)'
|
||||
})
|
||||
}
|
||||
const dataDir = path.join(SKILL, 'data')
|
||||
fs.mkdirSync(dataDir, { recursive: true })
|
||||
const out = path.join(dataDir, 'last_result.json')
|
||||
fs.writeFileSync(out, JSON.stringify(outEnvelope), 'utf-8')
|
||||
console.log('\n✓ 已补落盘:' + out)
|
||||
console.log(' 下一步:打开本技能页面 → 点「载入最近一次生成」即可查看/导出这份婺源行程')
|
||||
}
|
||||
|
||||
process.exit(chk.errors.length === 0 ? 0 : 1)
|
||||
Reference in New Issue
Block a user