e744ad1f96
事故鏈(07-31 深夜,leo 刷新撞到):t159 重打包 staging bundle 時,build-ui-bundle 吃了 feat/step3 分支的 console-ui/public/——該分支基底早於 maind7fab7c「拿掉登記新庫」,public 停在舊世代 ⇒ youlin 實例 UI 被打回被淘汰的 「登記新庫」人工表單典範(07-27 mistakes 已記帳的 src/public 雙世代債, 這次由「分支副本停舊代」路徑引爆——債沒還,任何一個部署路徑都會引爆它)。 刪掉的(舊世代,git rm 實體刪除): - console-ui/src/(console.ts/console-dashboard.ts/portal-ui.ts)=07-22 從 cypher-executor 搬出的 renderer 快照,自 07-27 起與 public/ 真身脫鉤、只會 重產舊 UI - console-ui/scripts/build.mjs=從上述舊 renderer 重產 public 的 build 步驟 (deploy.mjs 原自動跑它=引爆器本體) - cypher POST /portal/admin/libraries(人工建庫端點)=死端點(e28e190 起 UI 零呼叫;leo 規格「要直通 daemon,同步,沒有登記這回事」)。GET 列表/PATCH 管理/t159 daemon 自動登記照舊 新唯一源:console-ui/public/=手改演進的真身(本 commit 同步到 maine28e190世代+註解字樣改寫達成「登記新庫」全檔 0 命中);deploy.mjs 改為直接託管 public(無 build 步)+世代閘(缺「不需要人工新增」或含「登記新庫」拒部署)。 驗:tsc 全綠;deploy.mjs node --check 過;重打 ui bundle 242KB 過世代閘, 指紋「登記新庫」=0/「不需要人工新增」=1。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
50 lines
3.0 KiB
JavaScript
50 lines
3.0 KiB
JavaScript
import fs from 'node:fs';
|
|
const html = fs.readFileSync(new URL('./index.html', import.meta.url).pathname,'utf8');
|
|
// 抽出 daemonPick 相關函式(從 DAEMON_BASE_DEFAULT 到 daemonHint 結尾)
|
|
const start = html.indexOf('var DAEMON_BASE_DEFAULT');
|
|
const endMark = "return '(封測版未簽章,第一次請右鍵→打開)';\n }";
|
|
const end = html.indexOf(endMark) + endMark.length;
|
|
if (start < 0 || end < start) throw new Error('抽不到函式區塊');
|
|
const src = html.slice(start, end);
|
|
|
|
const cases = [
|
|
['Windows', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36'],
|
|
['Mac', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/605.1.15'],
|
|
['iPhone', 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Safari/604.1'],
|
|
['Linux', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120 Safari/537.36'],
|
|
];
|
|
let pass=0, fail=0;
|
|
const chk=(l,c,extra='')=>{ if(c){console.log('PASS:',l);pass++;} else {console.log('FAIL:',l,extra);fail++;} };
|
|
|
|
for (const [name, ua] of cases) {
|
|
const fn = new Function('navigator','window', src + '; return {daemonPick:daemonPick, daemonHint:daemonHint, daemonBase:daemonBase};');
|
|
const api = fn({userAgent: ua}, {});
|
|
const d = api.daemonPick();
|
|
const label = d.sure ? d.pick.label : '(兩個都給)';
|
|
const url = d.sure ? d.pick.url : d.mac.url + ' + ' + d.win.url;
|
|
console.log(`\n[${name}] sure=${d.sure} → ${label}`);
|
|
console.log(` url: ${url}`);
|
|
if (name==='Windows') {
|
|
chk('Windows 給 win zip', d.sure && d.pick.url.endsWith('ArcrunRAG-win-unsigned.zip'), d.pick&&d.pick.url);
|
|
chk('Windows 另一版是 Mac', d.other && d.other.url.endsWith('mac-unsigned.zip'));
|
|
chk('Windows 話術提 藍色視窗', api.daemonHint('win').includes('仍要執行'));
|
|
}
|
|
if (name==='Mac') {
|
|
chk('Mac 給 mac zip', d.sure && d.pick.url.endsWith('ArcrunRAG-mac-unsigned.zip'));
|
|
chk('Mac 另一版是 Windows', d.other && d.other.url.endsWith('win-unsigned.zip'));
|
|
chk('Mac 話術提 右鍵打開', api.daemonHint('mac').includes('右鍵'));
|
|
}
|
|
if (name==='iPhone' || name==='Linux') {
|
|
// iPhone 含 "Mac OS X" 但不是桌機 Mac;Linux 兩者皆非 → 都該落在「不確定=兩個都給」
|
|
if (name==='Linux') chk('Linux 判不出來→兩個都給', d.sure===false);
|
|
if (name==='iPhone') chk('iPhone 不該被判成 Mac(手機→兩個都給)', d.sure===false, 'sure='+d.sure);
|
|
}
|
|
}
|
|
// 舊 key 相容
|
|
const fn2 = new Function('navigator','window', src + '; return daemonBase();');
|
|
console.log('\n[相容] daemonDownload 舊 key →', fn2({userAgent:''},{ARCRUN_CONFIG:{daemonDownload:'https://x.dev/d/ArcrunRAG-mac-unsigned.zip'}}));
|
|
chk('舊 key 推得出目錄', fn2({userAgent:''},{ARCRUN_CONFIG:{daemonDownload:'https://x.dev/d/ArcrunRAG-mac-unsigned.zip'}})==='https://x.dev/d/');
|
|
chk('daemonBase 新 key 優先', fn2({userAgent:''},{ARCRUN_CONFIG:{daemonBase:'https://y.dev/z'}})==='https://y.dev/z/');
|
|
console.log(`\n=== ${pass} passed, ${fail} failed ===`);
|
|
process.exit(fail?1:0);
|