import { readFileSync, writeFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; const scriptDir = dirname(fileURLToPath(import.meta.url)); const root = join(scriptDir, '../..'); const svc = join(root, 'fs-service/src/main/java/com/fs/company/service/workflow'); const srcDir = join(scriptDir, 'lobster_utf8_sources'); function writeUtf8(path, content) { writeFileSync(path, content.replace(/\r\n/g, '\n'), 'utf8'); } function copySource(name, subdir) { const rel = subdir ? `${subdir}/${name}` : name; writeUtf8(join(svc, rel), readFileSync(join(srcDir, name), 'utf8')); } for (const name of [ 'LobsterOutboundQualityGate.java', 'ProductKnowledgeBoundaryPolicy.java', 'TenantProductClaimSemanticAnalyzer.java', 'LobsterProactiveGreetingService.java', 'LobsterMessageTemplateRenderer.java', 'GeneralKnowledgeDialoguePolicy.java', 'CustomerFacingMessageSplitter.java', ]) { copySource(name, name.startsWith('General') || name.startsWith('Customer') ? 'deepdialogue' : 'execution'); console.log('fixed', name); } const sqlPatches = [ { path: join(root, 'fs-agent/src/main/resources/db/migration/tenant/V20260724_07__lobster_udd_industry_corpus.sql'), pairs: [ ['-- ?????????? DDL + ?????UDD ??????????', '-- \u884c\u4e1a\u8bed\u6599\u77e9\u9635 DDL + \u7ba1\u7406\u7aef UDD \u8c03\u8bd5\u83dc\u5355\u521d\u59cb\u5316'], ['-- corpus_kind / industry_type ???????????? vs ???????', '-- corpus_kind / industry_type \u533a\u5206\u9500\u51a0\u8bed\u6599 vs \u884c\u4e1a\u77e9\u9635'], ["COMMENT ''???????'' AFTER corpus_kind", "COMMENT ''\u884c\u4e1a\u5206\u7c7b'' AFTER corpus_kind"], ['-- 29965 ??????????', '-- 29965 \u884c\u4e1a\u8bed\u6599\u77e9\u9635\u83dc\u5355'], ["VALUES (29965, '??????????',", "VALUES (29965, '\u884c\u4e1a\u8bed\u6599\u77e9\u9635',"], ["NOW(), 'UDD??????????');", "NOW(), 'UDD\u884c\u4e1a\u8bed\u6599\u77e9\u9635');"], ['-- 29966 UDD?????????', '-- 29966 UDD \u6df1\u5ea6\u5bf9\u8bdd\u8c03\u8bd5\u83dc\u5355'], ["VALUES (29966, '?????????',", "VALUES (29966, '\u6df1\u5ea6\u5bf9\u8bdd\u8c03\u8bd5',"], ["NOW(), 'UDD???/???/???????');", "NOW(), 'UDD\u610f\u56fe/\u68c0\u7d22/\u751f\u6210\u8c03\u8bd5');"], ], }, { path: join(root, 'fs-agent/src/main/resources/db/migration/tenant/V20260727_01__lobster_menu_canonical_sync.sql'), pairs: [ ['-- A.1 ???????????????????', '-- A.1 \u6e05\u7406\u89d2\u8272\u5173\u8054\u4e2d\u7684\u975e\u767d\u540d\u5355\u83dc\u5355'], ['-- A.2 ???????????', '-- A.2 \u5220\u9664\u975e\u767d\u540d\u5355\u83dc\u5355\u9879'], ['-- A.3 ??? sys_menu??UNHEX ?????????', '-- A.3 \u91cd\u5efa sys_menu\uff08UNHEX \u4fdd\u8bc1\u4e2d\u6587\u540d\u79f0\uff09'], ['-- A.4 ??? company_menu??????????????', '-- A.4 \u540c\u6b65 company_menu\uff08\u9500\u552e\u7aef\u5b50\u96c6\uff09'], ['-- A.5 ??????', '-- A.5 \u8865\u5168\u89d2\u8272\u6388\u6743'], ], }, ]; const canonicalHeader = `-- ============================================================================ -- \u9f99\u8679\u5f15\u64ce\u83dc\u5355\u89c4\u8303\u540c\u6b65\u521d\u59cb\u5316\u811a\u672c\uff082026-06-27\uff09 -- \u4e0e fs-agent V20260727_01 / ApplyLobsterCanonicalMenus \u914d\u5957 -- -- \u9500\u552e\u7aef company_menu / tenant_company_menu \u4fdd\u7559 8 \u9879 + \u8282\u70b9\u8be6\u60c5 29926 \u7b49\uff1a -- 32481,29949,29905,29950,29934,29906,3008,29912 -- \u7ba1\u7406\u7aef sys_menu / tenant_sys_menu \u989d\u5916\u4fdd\u7559\u7ba1\u7406\u4e13\u5c5e\u5b50\u83dc\u5355\uff1a -- 29933,29925,29963,29964,29951,29907,29908,29909,29965,29966 -- \u4e0b\u7ebf\u5197\u4f59/\u91cd\u590d\u83dc\u5355\uff1a29937,29939,29947,29938,29944,29936,29946, -- 29948,29922,29920,29941,29923,29924,29940,29942,29943,29945,3006,3007 \u7b49 -- -- \u4f7f\u7528\u8bf4\u660e\uff1a -- \u4e3b\u5e93\u6a21\u677f\u5e93\u6267\u884c PART A -- \u79df\u6237\u5e93 ylrz_saas \u9010\u79df\u6237\u6267\u884c PART B -- ============================================================================ -- ###################################################################### -- PART A \uff1a\u4e3b\u5e93 sys_menu + company_menu -- ###################################################################### `; { const path = join(root, 'sql/lobster_menu_canonical_init.sql'); let text = readFileSync(path, 'utf8').replace(/\r\n/g, '\n'); const start = text.indexOf('-- ============================================================================'); const end = text.indexOf('-- A.1'); if (start >= 0 && end > start) { text = canonicalHeader + text.slice(end); } text = text .replace('-- A.1 ???????????????????', '-- A.1 \u6e05\u7406\u89d2\u8272\u5173\u8054\u4e2d\u7684\u975e\u767d\u540d\u5355\u83dc\u5355') .replace('-- A.2 ???????????', '-- A.2 \u5220\u9664\u975e\u767d\u540d\u5355\u83dc\u5355\u9879'); writeUtf8(path, text); console.log('sql fixed lobster_menu_canonical_init.sql'); } for (const { path, pairs } of sqlPatches) { let text = readFileSync(path, 'utf8').replace(/\r\n/g, '\n'); for (const [from, to] of pairs) { if (!text.includes(from)) { console.warn('sql patch skip:', path.split(/[/\\]/).pop(), from.slice(0, 40)); continue; } text = text.replace(from, to); } writeUtf8(path, text); console.log('sql fixed', path.split(/[/\\]/).pop()); } console.log('lobster utf8 fix done');