@modelzen/feishu-codex-bridge 0.6.6 → 0.6.7-test.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +210 -17
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8509,7 +8509,7 @@ function withCodexHooksFeature(text) {
8509
8509
  }
8510
8510
 
8511
8511
  // src/service/update.ts
8512
- import { existsSync as existsSync8, readFileSync as readFileSync4 } from "fs";
8512
+ import { existsSync as existsSync9, readFileSync as readFileSync4 } from "fs";
8513
8513
  import { dirname as dirname9, join as join15, resolve as resolve6 } from "path";
8514
8514
  import { fileURLToPath as fileURLToPath4 } from "url";
8515
8515
 
@@ -8523,7 +8523,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
8523
8523
 
8524
8524
  // src/service/common.ts
8525
8525
  init_paths();
8526
- import { createReadStream, statSync as statSync2 } from "fs";
8526
+ import { appendFileSync, createReadStream, statSync as statSync2 } from "fs";
8527
8527
  import { appendFile, mkdir as mkdir7, readFile as readFile9 } from "fs/promises";
8528
8528
  import { dirname as dirname6, join as join11, resolve as resolve4 } from "path";
8529
8529
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -8538,6 +8538,13 @@ async function ensureLogFiles() {
8538
8538
  await appendFile(serviceStdoutPath(), "");
8539
8539
  await appendFile(serviceStderrPath(), "");
8540
8540
  }
8541
+ function appendServiceErr(tag, line) {
8542
+ try {
8543
+ appendFileSync(serviceStderrPath(), `[${(/* @__PURE__ */ new Date()).toISOString()}] [${tag}] ${line}
8544
+ `);
8545
+ } catch {
8546
+ }
8547
+ }
8541
8548
  function resolveCliBinPath() {
8542
8549
  const distDir = dirname6(fileURLToPath2(import.meta.url));
8543
8550
  return resolve4(distDir, "..", "bin", "feishu-codex-bridge.mjs");
@@ -8747,9 +8754,10 @@ function launchctlError(command, result) {
8747
8754
  // src/service/win-startup.ts
8748
8755
  init_paths();
8749
8756
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
8750
- import { openSync, readFileSync as readFileSync3, rmSync, writeFileSync } from "fs";
8757
+ import { existsSync as existsSync7, openSync, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync } from "fs";
8751
8758
  import { mkdir as mkdir9, writeFile as writeFile8 } from "fs/promises";
8752
8759
  import { join as join13 } from "path";
8760
+ var RELAUNCH_TASK_NAME = "feishu-codex-bridge-relaunch";
8753
8761
  var RUN_KEY_PATH = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
8754
8762
  var RUN_KEY_NAME = "feishu-codex-bridge";
8755
8763
  var SERVICE_ENV_FLAG = "FEISHU_CODEX_BRIDGE_SERVICE";
@@ -8779,14 +8787,16 @@ function buildLauncherVbs() {
8779
8787
  ""
8780
8788
  ].join("\r\n");
8781
8789
  }
8782
- function startNow() {
8790
+ function startNow(envPath) {
8783
8791
  const out = openSync(serviceStdoutPath(), "a");
8784
8792
  const err = openSync(serviceStderrPath(), "a");
8793
+ const overrides = { [SERVICE_ENV_FLAG]: "1" };
8794
+ if (envPath) overrides.PATH = envPath;
8785
8795
  const child = spawn3(process.execPath, [resolveCliBinPath(), "run"], {
8786
8796
  detached: true,
8787
8797
  windowsHide: true,
8788
8798
  stdio: ["ignore", out, err],
8789
- env: mergeProcessEnv(process.env, { [SERVICE_ENV_FLAG]: "1" })
8799
+ env: mergeProcessEnv(process.env, overrides)
8790
8800
  });
8791
8801
  if (child.pid) writeFileSync(servicePidFile(), String(child.pid), "utf8");
8792
8802
  child.unref();
@@ -8817,10 +8827,150 @@ async function restartWinStartup() {
8817
8827
  throw new Error("\u767B\u5F55\u81EA\u542F\u672A\u5B89\u88C5\uFF08\u5148\u8FD0\u884C `feishu-codex-bridge start`\uFF09\u3002");
8818
8828
  }
8819
8829
  await ensureLogFiles();
8820
- killService();
8821
- startNow();
8830
+ const oldPid = readServicePid();
8831
+ if (oldPid === null || !pidAlive(oldPid)) {
8832
+ startNow();
8833
+ return statusWinStartup();
8834
+ }
8835
+ writeRelaunchRequest({ oldPid, envPath: process.env.PATH ?? "", nonce: `${process.pid}-${Date.now()}` });
8836
+ if (!spawnTreeFreeRelauncher()) {
8837
+ clearRelaunchRequest();
8838
+ appendServiceErr("relaunch", `no tree-free backend (powershell/schtasks); kept old pid=${oldPid} running, did NOT restart`);
8839
+ throw new Error("\u65E0\u6CD5\u62C9\u8D77\u300C\u6811\u5916\u300D\u91CD\u542F\u8FDB\u7A0B\uFF08powershell \u4E0E schtasks \u5747\u4E0D\u53EF\u7528\uFF09\uFF1B\u5DF2\u4FDD\u7559\u65E7\u670D\u52A1\u7EE7\u7EED\u8FD0\u884C\uFF0C\u672A\u91CD\u542F\u3002");
8840
+ }
8841
+ appendServiceErr("relaunch", `submitted async relaunch for oldPid=${oldPid}`);
8822
8842
  return statusWinStartup();
8823
8843
  }
8844
+ function relaunchRequestFile() {
8845
+ return join13(paths.appDir, "relaunch.json");
8846
+ }
8847
+ function writeRelaunchRequest(req) {
8848
+ writeFileSync(relaunchRequestFile(), JSON.stringify(req), "utf8");
8849
+ }
8850
+ function clearRelaunchRequest() {
8851
+ rmSync(relaunchRequestFile(), { force: true });
8852
+ }
8853
+ function relaunchClaimFile() {
8854
+ return `${relaunchRequestFile()}.claim.${process.pid}`;
8855
+ }
8856
+ function claimRelaunchRequest() {
8857
+ const claim = relaunchClaimFile();
8858
+ try {
8859
+ renameSync(relaunchRequestFile(), claim);
8860
+ } catch {
8861
+ return null;
8862
+ }
8863
+ try {
8864
+ const r = JSON.parse(readFileSync3(claim, "utf8"));
8865
+ if (typeof r.oldPid === "number" && Number.isFinite(r.oldPid)) {
8866
+ return {
8867
+ oldPid: r.oldPid,
8868
+ envPath: typeof r.envPath === "string" ? r.envPath : "",
8869
+ nonce: String(r.nonce ?? "")
8870
+ };
8871
+ }
8872
+ } catch {
8873
+ }
8874
+ return null;
8875
+ }
8876
+ function clearRelaunchClaim() {
8877
+ rmSync(relaunchClaimFile(), { force: true });
8878
+ }
8879
+ function buildRelauncherPowershell(binPath = resolveCliBinPath(), nodePath = process.execPath) {
8880
+ const inner = `"${nodePath}" "${binPath}" __win-relaunch`;
8881
+ const lit = `'${inner.replace(/'/g, "''")}'`;
8882
+ return `$c=${lit}; try { Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine=$c } -ErrorAction Stop | Out-Null } catch { schtasks /create /tn ${RELAUNCH_TASK_NAME} /tr $c /sc ONCE /st 00:00 /f | Out-Null; schtasks /run /tn ${RELAUNCH_TASK_NAME} | Out-Null }`;
8883
+ }
8884
+ function powershellPath() {
8885
+ const root = process.env.SystemRoot || process.env.windir || "C:\\Windows";
8886
+ const p = join13(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
8887
+ return existsSync7(p) ? p : null;
8888
+ }
8889
+ function spawnTreeFreeRelauncher() {
8890
+ const ps = powershellPath();
8891
+ if (ps) {
8892
+ const errFd = openSync(serviceStderrPath(), "a");
8893
+ const child = spawn3(
8894
+ ps,
8895
+ ["-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden", "-Command", buildRelauncherPowershell()],
8896
+ { detached: true, windowsHide: true, stdio: ["ignore", errFd, errFd] }
8897
+ );
8898
+ child.on("error", (e) => appendServiceErr("relaunch", `powershell spawn error: ${e.message}`));
8899
+ child.unref();
8900
+ return true;
8901
+ }
8902
+ appendServiceErr("relaunch", "powershell.exe not found; trying schtasks fallback");
8903
+ return spawnSchtasksRelauncher();
8904
+ }
8905
+ function spawnSchtasksRelauncher() {
8906
+ const tr = `"${process.execPath}" "${resolveCliBinPath()}" __win-relaunch`;
8907
+ const create = spawnSync2(
8908
+ "schtasks",
8909
+ ["/create", "/tn", RELAUNCH_TASK_NAME, "/tr", tr, "/sc", "ONCE", "/st", "00:00", "/f"],
8910
+ { encoding: "utf8", windowsHide: true }
8911
+ );
8912
+ if (create.status !== 0) {
8913
+ appendServiceErr("relaunch", `schtasks /create failed exit=${create.status ?? "?"} ${(create.stderr || "").trim()}`);
8914
+ return false;
8915
+ }
8916
+ const run = spawnSync2("schtasks", ["/run", "/tn", RELAUNCH_TASK_NAME], { encoding: "utf8", windowsHide: true });
8917
+ if (run.status !== 0) {
8918
+ appendServiceErr("relaunch", `schtasks /run failed exit=${run.status ?? "?"} ${(run.stderr || "").trim()}`);
8919
+ return false;
8920
+ }
8921
+ return true;
8922
+ }
8923
+ function defaultTaskkill(pid) {
8924
+ const r = spawnSync2("taskkill", ["/pid", String(pid), "/T", "/F"], { encoding: "utf8", windowsHide: true });
8925
+ return { status: r.status, stderr: (r.stderr || "").toString() };
8926
+ }
8927
+ async function runWinRelaunch(deps = {}) {
8928
+ const claim = deps.claimRequest ?? claimRelaunchRequest;
8929
+ const clearClaim = deps.clearRequest ?? clearRelaunchClaim;
8930
+ const alive = deps.pidAlive ?? pidAlive;
8931
+ const kill = deps.taskkill ?? defaultTaskkill;
8932
+ const start = deps.start ?? startNow;
8933
+ const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
8934
+ const graceMs = deps.graceMs ?? 15e3;
8935
+ const pollMs = deps.pollMs ?? 200;
8936
+ const now = deps.now ?? (() => Date.now());
8937
+ const ensureLogs = deps.ensureLogs ?? ensureLogFiles;
8938
+ const logLine = deps.logLine ?? ((line) => appendServiceErr("relaunch", line));
8939
+ await ensureLogs();
8940
+ const req = claim();
8941
+ if (!req) {
8942
+ logLine("no relaunch request to claim (already handled by another relauncher, or none)");
8943
+ return;
8944
+ }
8945
+ try {
8946
+ logLine(`start oldPid=${req.oldPid} self=${process.pid}`);
8947
+ if (alive(req.oldPid)) {
8948
+ const r = kill(req.oldPid);
8949
+ logLine(`taskkill oldPid=${req.oldPid} exit=${r.status ?? "?"} ${r.stderr.trim()}`.trim());
8950
+ }
8951
+ const deadline = now() + graceMs;
8952
+ while (now() < deadline && alive(req.oldPid)) {
8953
+ await sleep(pollMs);
8954
+ }
8955
+ if (alive(req.oldPid)) {
8956
+ logLine(
8957
+ `ABORT: oldPid=${req.oldPid} still alive after ${graceMs}ms (elevated / access denied?); not starting new to avoid double instance`
8958
+ );
8959
+ return;
8960
+ }
8961
+ await sleep(300);
8962
+ start(req.envPath);
8963
+ logLine(`relaunched; new service.pid=${readServicePid() ?? "?"}`);
8964
+ } finally {
8965
+ clearClaim();
8966
+ if (process.platform === "win32") {
8967
+ try {
8968
+ spawnSync2("schtasks", ["/delete", "/tn", RELAUNCH_TASK_NAME, "/f"], { stdio: "ignore", windowsHide: true });
8969
+ } catch {
8970
+ }
8971
+ }
8972
+ }
8973
+ }
8824
8974
  function statusWinStartup() {
8825
8975
  const installed = isInstalled();
8826
8976
  const pid = readServicePid();
@@ -8880,12 +9030,15 @@ function pidAlive(pid) {
8880
9030
  function killService() {
8881
9031
  const pid = readServicePid();
8882
9032
  if (pid === null || !pidAlive(pid)) return;
8883
- spawnSync2("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore" });
9033
+ const r = spawnSync2("taskkill", ["/pid", String(pid), "/T", "/F"], { encoding: "utf8", windowsHide: true });
9034
+ if (r.status !== 0) {
9035
+ appendServiceErr("kill", `taskkill pid=${pid} exit=${r.status ?? "?"} ${(r.stderr || "").toString().trim()}`);
9036
+ }
8884
9037
  }
8885
9038
 
8886
9039
  // src/service/systemd.ts
8887
9040
  import { spawnSync as spawnSync3 } from "child_process";
8888
- import { existsSync as existsSync7 } from "fs";
9041
+ import { existsSync as existsSync8 } from "fs";
8889
9042
  import { mkdir as mkdir10, rm as rm4, writeFile as writeFile9 } from "fs/promises";
8890
9043
  import { homedir as homedir5 } from "os";
8891
9044
  import { dirname as dirname8, join as join14 } from "path";
@@ -8989,7 +9142,7 @@ function statusSystemd() {
8989
9142
  };
8990
9143
  }
8991
9144
  function unitExists() {
8992
- return existsSync7(systemdUnitPath());
9145
+ return existsSync8(systemdUnitPath());
8993
9146
  }
8994
9147
  function systemdActive() {
8995
9148
  const r = spawnSync3("systemctl", ["--user", "is-active", SYSTEMD_UNIT_NAME], {
@@ -9064,7 +9217,7 @@ function packageName() {
9064
9217
  return pkgJson().name ?? "@modelzen/feishu-codex-bridge";
9065
9218
  }
9066
9219
  function isDevSource() {
9067
- return existsSync8(join15(pkgRoot(), ".git"));
9220
+ return existsSync9(join15(pkgRoot(), ".git"));
9068
9221
  }
9069
9222
  function isNewer(a, b) {
9070
9223
  const pa = a.split(".").map((n) => Number.parseInt(n, 10) || 0);
@@ -9779,7 +9932,7 @@ init_paths();
9779
9932
  init_paths();
9780
9933
  init_logger();
9781
9934
  import { mkdir as mkdir11 } from "fs/promises";
9782
- import { existsSync as existsSync9 } from "fs";
9935
+ import { existsSync as existsSync10 } from "fs";
9783
9936
  import { isAbsolute as isAbsolute2, join as join17, resolve as resolve7 } from "path";
9784
9937
 
9785
9938
  // src/project/announcement.ts
@@ -9972,7 +10125,7 @@ function assertBackendUsable(backend, mode) {
9972
10125
  async function resolveCwd(name, existingPath) {
9973
10126
  if (existingPath) {
9974
10127
  const cwd2 = isAbsolute2(existingPath) ? existingPath : resolve7(existingPath);
9975
- if (!existsSync9(cwd2)) throw new Error(`\u6587\u4EF6\u5939\u4E0D\u5B58\u5728\uFF1A${cwd2}`);
10128
+ if (!existsSync10(cwd2)) throw new Error(`\u6587\u4EF6\u5939\u4E0D\u5B58\u5728\uFF1A${cwd2}`);
9976
10129
  return { cwd: cwd2, blank: false };
9977
10130
  }
9978
10131
  const cwd = join17(paths.projectsRootDir, name);
@@ -14737,16 +14890,22 @@ async function doUpdate() {
14737
14890
  }
14738
14891
  const res = await installLatest();
14739
14892
  log.info("daemon-control", "update-installed", { ok: res.ok });
14740
- if (!res.ok) return;
14893
+ appendServiceErr("daemon-control", `update-installed ok=${res.ok}`);
14894
+ if (!res.ok) {
14895
+ appendServiceErr("daemon-control", "install failed \u2014 keeping old version, not restarting");
14896
+ return;
14897
+ }
14741
14898
  await doRestart("update");
14742
14899
  }
14743
14900
  async function doRestart(phase) {
14744
14901
  if (!isServiceRunning()) {
14745
14902
  log.info("daemon-control", "restart-skipped-no-service", { phase });
14903
+ appendServiceErr("daemon-control", `restart-skipped-no-service (phase=${phase}); service.pid \u672A\u6307\u5411\u5728\u8DD1\u7684 daemon`);
14746
14904
  return;
14747
14905
  }
14748
14906
  await getServiceAdapter().restart();
14749
14907
  log.info("daemon-control", "restart-issued", { phase });
14908
+ appendServiceErr("daemon-control", `restart-issued (phase=${phase})`);
14750
14909
  }
14751
14910
 
14752
14911
  // src/web/mount.ts
@@ -15495,6 +15654,9 @@ ${UI_PURE_JS}
15495
15654
  var daemon = null; // /api/daemon
15496
15655
  var diag = null; // /api/diagnosis \u7ED3\u679C\uFF08\u5F53\u524D bot \u7684\u63A2\u6D4B\uFF1B\u5207 Tab \u5FC5\u6E05\uFF09
15497
15656
  var catalog = null; // /api/backends \u7F13\u5B58\uFF08\u540E\u7AEF\u7BA1\u7406\u5361 + \u9879\u76EE picker \u590D\u7528\uFF09
15657
+ var lastUpdate = null; // /api/update/check \u7ED3\u679C\u7F13\u5B58\uFF1A\u603B\u89C8 5s \u91CD\u6E32\u4E0D\u91CD\u67E5\uFF08\u6BCF\u6B21\u67E5\u90FD spawn npm view\uFF09
15658
+ var updateCheckedAt = 0; // \u4E0A\u6B21\u68C0\u67E5\u65F6\u95F4\u6233\uFF1B\u62FF\u5230\u7ED3\u679C\u8D85 30min\u3001\u8F6F\u5931\u8D25\u8D85 ~2min \u624D\u968F\u91CD\u6E32\u81EA\u52A8\u590D\u67E5
15659
+ var updateChecking = false;// in-flight \u95F8\uFF1Anpm view \u53EF\u80FD\u6570\u79D2~20s\uFF0C\u671F\u95F4 5s \u91CD\u6E32\u4E0D\u53E0\u53D1\u7B2C\u4E8C\u4E2A\u8BF7\u6C42
15498
15660
  var drawerProject = null; // \u62BD\u5C49\u91CC\u6253\u5F00\u7684\u9879\u76EE\u540D
15499
15661
  var diagBotId = null; // diag \u5C5E\u4E8E\u54EA\u4E2A bot\uFF08\u9632\u4E32\u53F0\uFF09
15500
15662
  var bkDetailId = null; // \u540E\u7AEF Agent \u8BE6\u60C5\u89C6\u56FE\u5F53\u524D\u5C55\u5F00\u7684\u540E\u7AEF id\uFF08null=\u5217\u8868\uFF09
@@ -15693,6 +15855,14 @@ ${UI_PURE_JS}
15693
15855
  fetch('/api/daemon').then(function (r) { return r.json(); })
15694
15856
  .then(function (d) {
15695
15857
  daemon = d;
15858
+ // \u8FD0\u884C\u4E2D\u7684\u5B9E\u9645\u7248\u672C\u4E00\u65E6\u8DDF\u7248\u672C\u68C0\u67E5\u7F13\u5B58\u91CC\u7684 current \u5BF9\u4E0D\u4E0A\uFF08\u591A\u534A\u662F\u521A\u66F4\u65B0+\u91CD\u542F\u5B8C\u6210\uFF09\uFF0C
15859
+ // \u5C31\u4F5C\u5E9F\u7F13\u5B58\u5E76\u5F53\u573A\u8865\u67E5\u4E00\u6B21\uFF08\u82E5\u5728\u603B\u89C8\u9875\uFF09\uFF0C\u628A\u300C\u6709\u65B0\u7248\u300D\u7ACB\u523B\u7FFB\u6210\u300C\u5DF2\u662F\u6700\u65B0\u7248\u300D\u2014\u2014\u4E0D\u7B49
15860
+ // \u4E0B\u4E00\u8F6E renderRoute\uFF0C\u6D88\u9664 loadState/loadDaemon \u540C\u5468\u671F\u7ADE\u6001\u5BFC\u81F4\u7684 ~10s \u5EF6\u8FDF\u4E0E\u6A2A\u5E45\u6B8B\u7559\u3002
15861
+ // \u53EA\u5728\u7248\u672C\u771F\u53D8\u65F6\u624D\u67E5\uFF08\u7A33\u6001 d.version===current\uFF09\uFF0C\u65E2\u7559\u4F4F\u66F4\u65B0\u540E\u7684\u5373\u65F6\u53CD\u9988\uFF0C\u53C8\u4E0D\u56DE\u5230 5s \u7A7A\u8F6C\u3002
15862
+ if (lastUpdate && d.version && d.version !== lastUpdate.current) {
15863
+ lastUpdate = null; updateCheckedAt = 0;
15864
+ if (parseRoute(location.hash).tab === 'overview') { var ub = $('updateBody'); if (ub) loadUpdate(ub); }
15865
+ }
15696
15866
  if (parseRoute(location.hash).tab === 'overview') { var b = $('daemonBody'); if (b) renderDaemon(b); }
15697
15867
  renderSidebarFoot();
15698
15868
  renderGlobalSummary();
@@ -16006,7 +16176,14 @@ ${UI_PURE_JS}
16006
16176
  daemonCard.appendChild(updateBody);
16007
16177
  root.appendChild(daemonCard);
16008
16178
  renderDaemon(daemonBody);
16009
- loadUpdate(updateBody);
16179
+ // \u7248\u672C\u68C0\u67E5\u4F1A\u5728\u670D\u52A1\u7AEF spawn\u300Cnpm view\u300D\uFF0C\u4E0D\u80FD\u8DDF\u7740 5s \u91CD\u6E32\u6BCF\u6B21\u90FD\u8DD1\uFF1A\u6709\u7F13\u5B58\u5C31\u76F4\u63A5\u6E32\uFF0C
16180
+ // \u53EA\u5728\u9996\u6B21\u6216\u7F13\u5B58\u8FC7\u671F\uFF0830min\uFF09\u65F6\u624D\u771F\u67E5\u4E00\u6B21\u3002\u624B\u52A8\u300C\u68C0\u67E5\u66F4\u65B0\u300D\u6309\u94AE\u4ECD\u5F3A\u5236\u5237\u65B0\u3002
16181
+ if (lastUpdate) {
16182
+ renderUpdate(updateBody, lastUpdate);
16183
+ if (Date.now() - updateCheckedAt > 30 * 60 * 1000) loadUpdate(updateBody);
16184
+ } else {
16185
+ loadUpdate(updateBody);
16186
+ }
16010
16187
 
16011
16188
  // \u{1F916} \u673A\u5668\u4EBA\uFF08\u5728 Feishu Bridge \u5361\u4E0B\u9762\uFF0C\u5404\u81EA\u5360\u6EE1\u5BBD\u5EA6\uFF09
16012
16189
  var botsCard = el('div', 'card');
@@ -16365,9 +16542,19 @@ ${UI_PURE_JS}
16365
16542
  }
16366
16543
 
16367
16544
  function loadUpdate(box) {
16545
+ if (updateChecking) return; // \u5728\u9014\u5C31\u4E0D\u53E0\u53D1\uFF1A\u6162\u68C0\u67E5\uFF08npm view \u6700\u957F 20s\uFF09\u671F\u95F4 5s \u91CD\u6E32\u4E0D\u91CD\u590D spawn
16546
+ updateChecking = true;
16547
+ updateCheckedAt = Date.now(); // \u4E50\u89C2\u5360\u4F4D\uFF1Ain-flight \u671F\u95F4 30min \u8FB9\u754C\u4E0D\u518D\u88AB\u53CD\u590D\u5224\u771F
16368
16548
  fetch('/api/update/check').then(function (r) { return r.json(); })
16369
- .then(function (u) { renderUpdate(box, u); })
16370
- .catch(function () { box.textContent = '\u26A0\uFE0F \u7248\u672C\u68C0\u67E5\u5931\u8D25\uFF08\u7F51\u7EDC\u6216 npm registry\uFF09'; });
16549
+ .then(function (u) {
16550
+ lastUpdate = u;
16551
+ // \u8F6F\u5931\u8D25\uFF1A\u975E dev \u5374\u6CA1\u62FF\u5230 latest\uFF08\u591A\u534A registry \u4E0D\u53EF\u8FBE/\u8D85\u65F6\uFF0C\u670D\u52A1\u7AEF\u4ECD\u56DE 200\uFF09\uFF0C\u53EA\u7F13\u5B58 ~2min
16552
+ // \u4FBF\u81EA\u52A8\u590D\u67E5\uFF0C\u522B\u628A\u300C\u67E5\u8BE2\u5931\u8D25\u300D\u9489\u4F4F 30min\uFF1B\u62FF\u5230 latest \u6216 dev \u6A21\u5F0F\u624D\u6309\u5B8C\u6574 30min TTL\u3002
16553
+ updateCheckedAt = (u && (u.dev || u.latest)) ? Date.now() : Date.now() - 28 * 60 * 1000;
16554
+ renderUpdate(box, u);
16555
+ })
16556
+ .catch(function () { box.textContent = '\u26A0\uFE0F \u7248\u672C\u68C0\u67E5\u5931\u8D25\uFF08\u7F51\u7EDC\u6216 npm registry\uFF09'; })
16557
+ .then(function () { updateChecking = false; }); // finally\uFF1A\u65E0\u8BBA\u6210\u8D25\u90FD\u677E\u95F8
16371
16558
  }
16372
16559
  function renderUpdate(box, u) {
16373
16560
  box.textContent = '';
@@ -18141,6 +18328,7 @@ async function runSupervisor(bots) {
18141
18328
  const supervisorStartedAt = Date.now();
18142
18329
  const cliEntry = process.argv[1];
18143
18330
  if (!cliEntry) throw new Error("supervisor: \u65E0\u6CD5\u89E3\u6790 CLI \u5165\u53E3\uFF08process.argv[1] \u4E3A\u7A7A\uFF09");
18331
+ recordServicePid();
18144
18332
  const childEnv = { ...process.env };
18145
18333
  delete childEnv[SERVICE_ENV_FLAG];
18146
18334
  let shuttingDown = false;
@@ -18407,6 +18595,7 @@ async function runOnboardingConsole() {
18407
18595
  releaseLock = acquireSingleInstanceLock("__onboarding__");
18408
18596
  } catch (err) {
18409
18597
  if (err instanceof BridgeAlreadyRunningError) {
18598
+ clearServicePid();
18410
18599
  console.error(`\u2717 ${err.message}`);
18411
18600
  process.exitCode = 1;
18412
18601
  return;
@@ -18475,6 +18664,7 @@ async function runSingle(botName) {
18475
18664
  releaseLock = acquireSingleInstanceLock(cfg.accounts.app.id);
18476
18665
  } catch (err) {
18477
18666
  if (err instanceof BridgeAlreadyRunningError) {
18667
+ clearServicePid();
18478
18668
  console.error(`\u2717 ${err.message}`);
18479
18669
  log.info("run", "already-running", { pid: err.pid });
18480
18670
  process.exitCode = 1;
@@ -19030,6 +19220,9 @@ program.command("web").description("\u672C\u673A Web \u63A7\u5236\u53F0\uFF08\u5
19030
19220
  program.command("__daemon-control <action>", { hidden: true }).action(async (action) => {
19031
19221
  await runDaemonControl(action);
19032
19222
  });
19223
+ program.command("__win-relaunch", { hidden: true }).action(async () => {
19224
+ await runWinRelaunch();
19225
+ });
19033
19226
  var bot = program.command("bot").description("\u98DE\u4E66\u673A\u5668\u4EBA\u7BA1\u7406\uFF08\u591A\u673A\u5668\u4EBA\uFF09");
19034
19227
  bot.command("init [name]").description("\u6CE8\u518C\u4E00\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA\u5E76\u6388\u6743\uFF08\u53EF\u9009\u77ED\u540D\uFF09").action(async (name) => {
19035
19228
  await runBotInit(name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelzen/feishu-codex-bridge",
3
- "version": "0.6.6",
3
+ "version": "0.6.7-test.0",
4
4
  "description": "Bridge Feishu/Lark messenger with local Codex via app-server (project=group, thread=session)",
5
5
  "type": "module",
6
6
  "bin": {