ework-web 0.10.109 → 0.10.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ework-web",
3
- "version": "0.10.109",
3
+ "version": "0.10.110",
4
4
  "type": "module",
5
5
  "description": "ework-web — standalone multi-project issue tracker. Local SQLite-backed, no external API dependency. Bun + TypeScript + SSR HTML.",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@ interface RouterDaemonRow {
36
36
 
37
37
  let routerCache: { at: number; rows: RouterDaemonRow[] } | null = null;
38
38
 
39
- async function routerDaemons(): Promise<RouterDaemonRow[]> {
39
+ export async function routerDaemons(): Promise<RouterDaemonRow[]> {
40
40
  if (routerCache && Date.now() - routerCache.at < 15_000) return routerCache.rows;
41
41
  try {
42
42
  const cfg = await loadConfig();
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@ import { homedir } from "os";
8
8
  import { loadConfig, DB_OVERRIDABLE, parseOverride, resolveTtsBackend } from "./config";
9
9
  import type { Config } from "./config";
10
10
  import { setConfig, deleteConfig, getConfigAll, initDB, getDB } from "./db";
11
- import { getActiveDaemons, listAllDaemons, getSessionDaemonMap, resolveDaemonEndpoint, getRunningSessionsForProject, resolveSessionUid } from "./coordination";
11
+ import { getActiveDaemons, listAllDaemons, getSessionDaemonMap, resolveDaemonEndpoint, getRunningSessionsForProject, resolveSessionUid, routerDaemons } from "./coordination";
12
12
  import { testMysqlConnection, migrateSqliteToMysql, writeMysqlEnv, migrateMysqlToSqlite, writeSqliteEnv, migrateDaemonSqliteToMysql, generateMysqlDDL } from "./db-admin";
13
13
  import type { MysqlTargetOpts } from "./db-admin";
14
14
  import { checkAuth, makeAuthCookieHeader, clearAuthCookieHeader, loginHTML, sanitizeNext, ensureBootstrapAdmin, ensureBootstrapSystem, isReservedSystemLogin } from "./auth";
@@ -758,6 +758,23 @@ async function handle(req: Request, url: URL, ip: string, ctx: { authed: boolean
758
758
  const limit = Math.min(5000, Math.max(1, Number(url.searchParams.get("limit")) || 30));
759
759
  const daemonEp = url.searchParams.get("daemon");
760
760
  const daemonIdParam = url.searchParams.get("daemon_id");
761
+ // daemon_id is only a hint: ids churn across daemon reinstalls and the
762
+ // {{d_*}} mirror tables exist only in split-DB mysql deployments, so a
763
+ // stale hint must fall back to scanning daemons that hold the session.
764
+ const tryAllDaemons = async (): Promise<Response | null> => {
765
+ if (!/^ses_[0-9A-Za-z]{8,}/.test(sid)) return null;
766
+ let registry: Array<{ endpoint?: string }> = [];
767
+ try { registry = await routerDaemons(); } catch { registry = []; }
768
+ for (const d of registry) {
769
+ if (!d.endpoint) continue;
770
+ try {
771
+ const c = new RemoteOpencodeClient(d.endpoint);
772
+ const { html: body } = await buildSessionView(c, sid, desc, cfg.collapseLines, limit, all);
773
+ return html(body);
774
+ } catch { /* daemon does not hold this session — try next */ }
775
+ }
776
+ return null;
777
+ };
761
778
  if (!daemonEp && daemonIdParam) {
762
779
  const id = Number(daemonIdParam);
763
780
  if (Number.isFinite(id) && id > 0) {
@@ -776,6 +793,8 @@ async function handle(req: Request, url: URL, ip: string, ctx: { authed: boolean
776
793
  } catch (e) {
777
794
  const status = e instanceof OpencodeError ? e.status : 500;
778
795
  if (status === 404) {
796
+ const scanned = await tryAllDaemons();
797
+ if (scanned) return scanned;
779
798
  return html(errorPage(
780
799
  "会话不在该 daemon 上",
781
800
  `会话 ${sid} 在 daemon ${effectiveId} (${ep}) 上找不到 (HTTP ${status})。\n\n` +
@@ -786,6 +805,9 @@ async function handle(req: Request, url: URL, ip: string, ctx: { authed: boolean
786
805
  }
787
806
  throw e;
788
807
  }
808
+ } else {
809
+ const scanned = await tryAllDaemons();
810
+ if (scanned) return scanned;
789
811
  }
790
812
  }
791
813
  }