diff --git a/console-ui/public/portal/index.html b/console-ui/public/portal/index.html
index 6fefeac..6c41341 100644
--- a/console-ui/public/portal/index.html
+++ b/console-ui/public/portal/index.html
@@ -674,11 +674,19 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return {
if (!location.hash) location.hash = '#/' + HOME;
route();
}
- function dropSession() {
+ // t161(leo 07-31 實撞:「實際上根本沒連上任何庫,清單空白」):session 過期時
+ // 舊行為=靜默清 token 跳回登入頁,**畫面不說任何原因** ⇒ 用戶以為「庫不見了/系統壞了」。
+ // 友善=前端:踢回登入頁時一定要說「為什麼」,用戶才知道下一步做什麼(重新登入即可,資料都在)。
+ function dropSession(reason) {
S.token = '';
S.profile = null;
try { localStorage.removeItem('arcrun_portal_session'); } catch (e) { /* noop */ }
showAuth();
+ var msg = reason || '你的登入已過期,請重新登入(你的資料都還在,不會遺失)。';
+ try {
+ var el = $('login-status');
+ if (el) el.textContent = msg;
+ } catch (e) { /* 登入殼還沒渲染就算了 */ }
}
function boot() {
if (!S.token) { showAuth(); return; }
diff --git a/cypher-executor/src/routes/health.ts b/cypher-executor/src/routes/health.ts
index 5485639..7d09505 100644
--- a/cypher-executor/src/routes/health.ts
+++ b/cypher-executor/src/routes/health.ts
@@ -3,9 +3,19 @@ import type { Bindings } from '../types';
export const healthRouter = new Hono<{ Bindings: Bindings }>();
-healthRouter.get('/health', (c) =>
- c.json({ ok: true })
-);
+// t162(leo 07-31 實撞:「小幫手一直顯示知識庫需要更新…重新更新後並不會消失」):
+// daemon cloudVersionStale() 讀 /health 的 `bundle_version` 判斷是否過舊——
+// 但本端點過去只回 {ok:true},**從沒吐這個欄位** ⇒ daemon 恆讀到空字串
+// ⇒ 恆判 stale ⇒ 假警報永遠不消失(安裝器其實一直有注入 ARCRUN_BUNDLE_VERSION var,
+// 只是沒有人把它吐出來)。修=誠實回報本實例的 bundle 版本。
+// 未注入(本地 dev/很舊的實例)就省略該欄——daemon 對空字串仍判 stale,
+// 那是**正確的**(真的是老實例,該更新)。
+healthRouter.get('/health', (c) => {
+ const bundleVersion = c.env.ARCRUN_BUNDLE_VERSION;
+ return c.json(
+ bundleVersion ? { ok: true, bundle_version: bundleVersion } : { ok: true },
+ );
+});
healthRouter.get('/', (c) =>
c.json({
diff --git a/cypher-executor/src/types.ts b/cypher-executor/src/types.ts
index 94efb72..c0ce895 100644
--- a/cypher-executor/src/types.ts
+++ b/cypher-executor/src/types.ts
@@ -68,6 +68,13 @@ export type Bindings = {
// 必填:cypher-executor 用此組出 component worker URL(避開同 zone 自循環死鎖,見 P0 #9)
// self-hosted fork 必須改 wrangler.toml [vars] 為自己的帳號 subdomain
WORKER_SUBDOMAIN: string;
+ /**
+ * t162:本實例安裝時的 bundle 版本(格式 `YYYY-MM-DD+`)。
+ * 由安裝器 deployBundledWorker 注入(worker.js:805),**給 daemon 比對用**——
+ * daemon `/health` 讀不到就恆判「需要更新」(假警報迴圈,leo 07-31 實撞)。
+ * 未注入(本地 dev/舊實例)= undefined,/health 省略該欄。
+ */
+ ARCRUN_BUNDLE_VERSION?: string;
// Platform telemetry api_key(可選,wrangler secret)
// 對應 SDD .agents/specs/llm-interface/ M1.2
// 設了會把 agent-telemetry block 都聚集在 platform_telemetry user_id 下