fleetlens 1.0.0 → 1.0.2

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 (107) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/app-path-routes-manifest.json +1 -0
  3. package/app/apps/web/.next/build-manifest.json +3 -3
  4. package/app/apps/web/.next/prerender-manifest.json +3 -3
  5. package/app/apps/web/.next/routes-manifest.json +6 -0
  6. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  7. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  8. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  14. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/app/apps/web/.next/server/app/agent/page.js.nft.json +1 -1
  16. package/app/apps/web/.next/server/app/agent/page_client-reference-manifest.js +1 -1
  17. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route.js.nft.json +1 -1
  18. package/app/apps/web/.next/server/app/api/agent/index/route.js.nft.json +1 -1
  19. package/app/apps/web/.next/server/app/api/agent/mcp/route.js +3 -3
  20. package/app/apps/web/.next/server/app/api/agent/mcp/route.js.nft.json +1 -1
  21. package/app/apps/web/.next/server/app/api/agent/suggestions/route.js.nft.json +1 -1
  22. package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
  23. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  24. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  26. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  27. package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/api/health/route/app-paths-manifest.json +3 -0
  29. package/app/apps/web/.next/server/app/api/health/route/build-manifest.json +9 -0
  30. package/app/apps/web/.next/server/app/api/health/route/server-reference-manifest.json +4 -0
  31. package/app/apps/web/.next/server/app/api/health/route.js +7 -0
  32. package/app/apps/web/.next/server/app/api/health/route.js.map +5 -0
  33. package/app/apps/web/.next/server/app/api/health/route.js.nft.json +1 -0
  34. package/app/apps/web/.next/server/app/api/health/route_client-reference-manifest.js +3 -0
  35. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
  36. package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.nft.json +1 -1
  37. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  38. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  39. package/app/apps/web/.next/server/app/api/settings/credentials/route.js.nft.json +1 -1
  40. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  41. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
  42. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  43. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  44. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  45. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  46. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  47. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  48. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  49. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  50. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  51. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  52. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  53. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  54. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  55. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  56. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  57. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  58. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  59. package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
  60. package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
  61. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  62. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  63. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  64. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  65. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  66. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  67. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  68. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  69. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  70. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  71. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  72. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  73. package/app/apps/web/.next/server/app/team/onboarding/page.js.nft.json +1 -1
  74. package/app/apps/web/.next/server/app/team/onboarding/page_client-reference-manifest.js +1 -1
  75. package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
  76. package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
  77. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  78. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  79. package/app/apps/web/.next/server/app-paths-manifest.json +1 -0
  80. package/app/apps/web/.next/server/chunks/[root-of-the-server]__02.51sr._.js +3 -0
  81. package/app/apps/web/.next/server/chunks/[root-of-the-server]__06irs4z._.js +3 -0
  82. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_health_route_actions_08i7v0h.js +3 -0
  83. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0sr4wr_.js +3 -3
  84. package/app/apps/web/.next/server/chunks/ssr/_0k8yioi._.js +1 -1
  85. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
  86. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
  87. package/app/apps/web/.next/server/functions-config-manifest.json +1 -0
  88. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  89. package/app/apps/web/.next/server/middleware-manifest.json +5 -5
  90. package/app/apps/web/.next/server/pages/500.html +1 -1
  91. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  92. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  93. package/app/apps/web/.next/static/chunks/0dqhn7-3.038l.js +14 -0
  94. package/app/apps/web/app/api/health/route.ts +12 -0
  95. package/app/apps/web/lib/changelog-data.generated.ts +1 -1
  96. package/app/apps/web/package.json +1 -1
  97. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  98. package/dist/daemon-worker.js +296 -18
  99. package/dist/index.js +46 -15
  100. package/menubar/Fleetlens.app/Contents/Info.plist +2 -2
  101. package/menubar/Fleetlens.app/Contents/MacOS/FleetlensMenubar +0 -0
  102. package/package.json +1 -1
  103. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0sbhe0s._.js +0 -3
  104. package/app/apps/web/.next/static/chunks/18c7gd5.b8gfc.js +0 -14
  105. /package/app/apps/web/.next/static/{mSM83A_ktoKiZ6y_p7wNk → zyhoVMC9iNC5vofPFRY6z}/_buildManifest.js +0 -0
  106. /package/app/apps/web/.next/static/{mSM83A_ktoKiZ6y_p7wNk → zyhoVMC9iNC5vofPFRY6z}/_clientMiddlewareManifest.js +0 -0
  107. /package/app/apps/web/.next/static/{mSM83A_ktoKiZ6y_p7wNk → zyhoVMC9iNC5vofPFRY6z}/_ssgManifest.js +0 -0
@@ -6860,11 +6860,204 @@ var init_file_probe = __esm({
6860
6860
  }
6861
6861
  });
6862
6862
 
6863
- // src/daemon-worker.ts
6863
+ // src/pid.ts
6864
+ import { readFileSync as readFileSync21, writeFileSync as writeFileSync15, mkdirSync as mkdirSync14, unlinkSync as unlinkSync5 } from "node:fs";
6865
+ import { execFileSync as execFileSync3 } from "node:child_process";
6866
+ import { dirname as dirname12 } from "node:path";
6867
+ function writePid(filePath, pid, port, version) {
6868
+ mkdirSync14(dirname12(filePath), { recursive: true });
6869
+ let content = String(pid);
6870
+ if (port != null) {
6871
+ content += `:${port}`;
6872
+ if (version) content += `:${version}`;
6873
+ }
6874
+ writeFileSync15(filePath, content, "utf8");
6875
+ }
6876
+ function readPid(filePath) {
6877
+ try {
6878
+ const content = readFileSync21(filePath, "utf8").trim();
6879
+ const [pidStr, portStr, versionStr] = content.split(":");
6880
+ const pid = parseInt(pidStr, 10);
6881
+ if (Number.isNaN(pid)) return null;
6882
+ const port = portStr ? parseInt(portStr, 10) : void 0;
6883
+ return {
6884
+ pid,
6885
+ port: Number.isNaN(port) ? void 0 : port,
6886
+ version: versionStr || void 0
6887
+ };
6888
+ } catch {
6889
+ return null;
6890
+ }
6891
+ }
6892
+ function isProcessAlive(pid, markers) {
6893
+ try {
6894
+ process.kill(pid, 0);
6895
+ } catch {
6896
+ return false;
6897
+ }
6898
+ if (!markers || markers.length === 0) return true;
6899
+ try {
6900
+ const cmd = execFileSync3("ps", ["-p", String(pid), "-o", "command="], {
6901
+ encoding: "utf8"
6902
+ }).trim();
6903
+ return markers.some((m) => cmd.includes(m));
6904
+ } catch {
6905
+ return false;
6906
+ }
6907
+ }
6908
+ function cleanStalePid(filePath, markers) {
6909
+ const entry = readPid(filePath);
6910
+ if (entry === null) return false;
6911
+ if (isProcessAlive(entry.pid, markers)) return false;
6912
+ try {
6913
+ unlinkSync5(filePath);
6914
+ } catch {
6915
+ }
6916
+ return true;
6917
+ }
6918
+ function removePid(filePath) {
6919
+ try {
6920
+ unlinkSync5(filePath);
6921
+ } catch {
6922
+ }
6923
+ }
6924
+ var init_pid = __esm({
6925
+ "src/pid.ts"() {
6926
+ "use strict";
6927
+ }
6928
+ });
6929
+
6930
+ // src/server.ts
6864
6931
  import { spawn as spawn3 } from "node:child_process";
6865
- import { closeSync, existsSync as existsSync19, mkdirSync as mkdirSync14, openSync, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "node:fs";
6866
- import { dirname as dirname12, join as join13 } from "node:path";
6932
+ import { join as join13, dirname as dirname13 } from "node:path";
6867
6933
  import { fileURLToPath } from "node:url";
6934
+ import { existsSync as existsSync19, realpathSync as realpathSync3, readFileSync as readFileSync22 } from "node:fs";
6935
+ import { homedir as homedir6 } from "node:os";
6936
+ function appDir() {
6937
+ const here = dirname13(fileURLToPath(import.meta.url));
6938
+ return join13(here, "..", "app", "apps", "web");
6939
+ }
6940
+ function cliBinRealPath() {
6941
+ const argv1 = process.argv[1] ?? "";
6942
+ try {
6943
+ return realpathSync3(argv1);
6944
+ } catch {
6945
+ return argv1;
6946
+ }
6947
+ }
6948
+ function onDiskVersion() {
6949
+ try {
6950
+ const here = dirname13(fileURLToPath(import.meta.url));
6951
+ const pkg = JSON.parse(readFileSync22(join13(here, "..", "package.json"), "utf8"));
6952
+ return pkg.version ?? "1.0.2";
6953
+ } catch {
6954
+ return "1.0.2";
6955
+ }
6956
+ }
6957
+ function getServerStatus() {
6958
+ cleanStalePid(PID_FILE, SERVER_MARKERS);
6959
+ const entry = readPid(PID_FILE);
6960
+ if (entry !== null && isProcessAlive(entry.pid, SERVER_MARKERS)) {
6961
+ return { running: true, pid: entry.pid, port: entry.port ?? DEFAULT_PORT, version: entry.version };
6962
+ }
6963
+ return { running: false };
6964
+ }
6965
+ async function startServer(opts = {}) {
6966
+ const port = opts.port ?? (parseInt(process.env.CCLENS_PORT ?? "", 10) || DEFAULT_PORT);
6967
+ const serverJs = join13(appDir(), "server.js");
6968
+ if (!existsSync19(serverJs)) {
6969
+ throw new Error(`Server not found at ${serverJs}. Reinstall with: npm install -g fleetlens`);
6970
+ }
6971
+ const portInUse = await checkPort(port);
6972
+ if (portInUse) {
6973
+ throw new Error(`Port ${port} is in use. Use --port to specify a different port.`);
6974
+ }
6975
+ const dataDir = join13(homedir6(), ".claude", "projects");
6976
+ const child = spawn3(process.execPath, [serverJs], {
6977
+ detached: true,
6978
+ stdio: "ignore",
6979
+ env: {
6980
+ ...process.env,
6981
+ PORT: String(port),
6982
+ HOSTNAME: "localhost",
6983
+ CCLENS_DATA_DIR: dataDir,
6984
+ FLEETLENS_CLI_BIN: cliBinRealPath(),
6985
+ FLEETLENS_WEB_START_DAEMON: opts.autoStartDaemon === false ? "0" : "1"
6986
+ },
6987
+ cwd: appDir()
6988
+ });
6989
+ child.unref();
6990
+ const pid = child.pid;
6991
+ writePid(PID_FILE, pid, port, onDiskVersion());
6992
+ await waitForHealth(`http://localhost:${port}`, 3e4);
6993
+ return { pid, port };
6994
+ }
6995
+ async function probeServerHealth(port, timeoutMs) {
6996
+ try {
6997
+ await fetch(`http://localhost:${port}/api/health`, {
6998
+ signal: AbortSignal.timeout(timeoutMs)
6999
+ });
7000
+ return true;
7001
+ } catch {
7002
+ return false;
7003
+ }
7004
+ }
7005
+ async function restartWedgedServer(pid, port) {
7006
+ try {
7007
+ process.kill(pid, "SIGKILL");
7008
+ } catch {
7009
+ }
7010
+ removePid(PID_FILE);
7011
+ await waitForPortFree(port, 5e3);
7012
+ return startServer({ port });
7013
+ }
7014
+ async function checkPort(port) {
7015
+ const { createServer } = await import("node:net");
7016
+ return new Promise((resolve4) => {
7017
+ const server = createServer();
7018
+ server.once("error", () => resolve4(true));
7019
+ server.once("listening", () => {
7020
+ server.close(() => resolve4(false));
7021
+ });
7022
+ server.listen(port, "localhost");
7023
+ });
7024
+ }
7025
+ async function waitForPortFree(port, timeoutMs) {
7026
+ const start = Date.now();
7027
+ while (Date.now() - start < timeoutMs) {
7028
+ if (!await checkPort(port)) return;
7029
+ await new Promise((r) => setTimeout(r, 200));
7030
+ }
7031
+ }
7032
+ async function waitForHealth(url, timeoutMs) {
7033
+ const start = Date.now();
7034
+ while (Date.now() - start < timeoutMs) {
7035
+ try {
7036
+ const res = await fetch(url);
7037
+ if (res.ok) return;
7038
+ } catch {
7039
+ }
7040
+ await new Promise((r) => setTimeout(r, 500));
7041
+ }
7042
+ throw new Error(`Server did not become healthy within ${timeoutMs / 1e3}s`);
7043
+ }
7044
+ var PID_FILE, DEFAULT_PORT, SERVER_MARKERS;
7045
+ var init_server = __esm({
7046
+ "src/server.ts"() {
7047
+ "use strict";
7048
+ init_pid();
7049
+ init_fs();
7050
+ PID_FILE = cclensPath("pid");
7051
+ DEFAULT_PORT = 3321;
7052
+ SERVER_MARKERS = ["next-server", "server.js"];
7053
+ }
7054
+ });
7055
+
7056
+ // src/daemon-worker.ts
7057
+ import { spawn as spawn4 } from "node:child_process";
7058
+ import { closeSync, existsSync as existsSync20, mkdirSync as mkdirSync15, openSync, readFileSync as readFileSync23, writeFileSync as writeFileSync16 } from "node:fs";
7059
+ import { dirname as dirname14, join as join14 } from "node:path";
7060
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
6868
7061
 
6869
7062
  // src/usage/token.ts
6870
7063
  import { execFileSync } from "node:child_process";
@@ -7192,8 +7385,8 @@ async function refreshAccessToken(entry) {
7192
7385
  break;
7193
7386
  }
7194
7387
  }
7195
- const { writeFileSync: writeFileSync16 } = await import("node:fs");
7196
- writeFileSync16(p, JSON.stringify(raw, null, 2), "utf8");
7388
+ const { writeFileSync: writeFileSync17 } = await import("node:fs");
7389
+ writeFileSync17(p, JSON.stringify(raw, null, 2), "utf8");
7197
7390
  } catch {
7198
7391
  }
7199
7392
  return j.access_token;
@@ -9111,7 +9304,7 @@ function buildIngestPayload(inputs) {
9111
9304
  return {
9112
9305
  ingestId: randomUUID(),
9113
9306
  observedAt: (/* @__PURE__ */ new Date()).toISOString(),
9114
- cliVersion: "1.0.0",
9307
+ cliVersion: "1.0.2",
9115
9308
  ...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
9116
9309
  ...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
9117
9310
  ...richRollup ? { richRollup } : {},
@@ -14492,10 +14685,10 @@ exec ${shellEscape(claudeBin)} \\
14492
14685
  "$USR"
14493
14686
  `, { mode: 493 });
14494
14687
  const existingBefore = snapshotAllTranscripts();
14495
- const spawn4 = spawnSync(tmuxBin, ["new-session", "-d", "-s", sessionName, "-x", "140", "-y", "50", "-c", cwd, wrapper], { encoding: "utf8" });
14496
- if (spawn4.status !== 0) {
14688
+ const spawn5 = spawnSync(tmuxBin, ["new-session", "-d", "-s", sessionName, "-x", "140", "-y", "50", "-c", cwd, wrapper], { encoding: "utf8" });
14689
+ if (spawn5.status !== 0) {
14497
14690
  cleanup(cwd, runId, tmuxBin, sessionName);
14498
- throw new TmuxRunError(`tmux new-session failed: ${spawn4.stderr.trim()}`);
14691
+ throw new TmuxRunError(`tmux new-session failed: ${spawn5.stderr.trim()}`);
14499
14692
  }
14500
14693
  const onAbort = () => {
14501
14694
  try {
@@ -18045,30 +18238,73 @@ async function getUpdateAvailability() {
18045
18238
  if (isDevMode()) return null;
18046
18239
  const latest = await fetchLatestVersion();
18047
18240
  if (latest === null) return {
18048
- current: "1.0.0",
18241
+ current: "1.0.2",
18049
18242
  latest: null,
18050
18243
  updateAvailable: false
18051
18244
  };
18052
18245
  return {
18053
- current: "1.0.0",
18246
+ current: "1.0.2",
18054
18247
  latest,
18055
- updateAvailable: shouldUpdate("1.0.0", latest)
18248
+ updateAvailable: shouldUpdate("1.0.2", latest)
18056
18249
  };
18057
18250
  }
18058
18251
 
18252
+ // src/daemon-worker.ts
18253
+ init_server();
18254
+
18255
+ // src/watchdog.ts
18256
+ var FAILURE_THRESHOLD = 3;
18257
+ var MAX_RESTARTS_PER_WINDOW = 3;
18258
+ var WINDOW_MS = 60 * 60 * 1e3;
18259
+ var ServerWatchdog = class {
18260
+ failures = 0;
18261
+ restartsAt = [];
18262
+ /** A different pid is serving now. The failure run belongs to the old
18263
+ * process — a fresh server gets full grace — but the restart cap stays:
18264
+ * watchdog restarts change the pid too, and clearing the cap on every
18265
+ * one would disarm the flap guard entirely. */
18266
+ noteNewInstance() {
18267
+ this.failures = 0;
18268
+ }
18269
+ /** No tracked server at all (pid file gone). Watchdog restarts never pass
18270
+ * through this state — only an operator stop (or a cycle the watchdog
18271
+ * happens to observe mid-gap) does — so a human is at the wheel and the
18272
+ * restart budget re-arms in full. */
18273
+ noteServerGone() {
18274
+ this.failures = 0;
18275
+ this.restartsAt = [];
18276
+ }
18277
+ onProbe(ok, nowMs) {
18278
+ if (ok) {
18279
+ this.failures = 0;
18280
+ return "ok";
18281
+ }
18282
+ this.failures = Math.min(this.failures + 1, FAILURE_THRESHOLD);
18283
+ if (this.failures < FAILURE_THRESHOLD) return "failing";
18284
+ this.restartsAt = this.restartsAt.filter((t) => nowMs - t < WINDOW_MS);
18285
+ if (this.restartsAt.length >= MAX_RESTARTS_PER_WINDOW) return "gave-up";
18286
+ this.restartsAt.push(nowMs);
18287
+ this.failures = 0;
18288
+ return "restart";
18289
+ }
18290
+ };
18291
+
18059
18292
  // src/daemon-worker.ts
18060
18293
  var USAGE_LOG3 = cclensPath("usage.jsonl");
18061
18294
  var DAEMON_LOG = cclensPath("daemon.log");
18062
18295
  var UPDATE_STATE = cclensPath("daemon-update.json");
18063
18296
  var WATCHDOG_INTERVAL_MS = 5 * 1e3;
18064
18297
  var AUTO_UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1e3;
18065
- mkdirSync14(dirname12(USAGE_LOG3), { recursive: true });
18298
+ var SERVER_HEALTH_INTERVAL_MS = 60 * 1e3;
18299
+ var SERVER_HEALTH_TIMEOUT_MS = 10 * 1e3;
18300
+ mkdirSync15(dirname14(USAGE_LOG3), { recursive: true });
18066
18301
  function log2(level, message) {
18067
18302
  appendDaemonLogLine(level, message);
18068
18303
  }
18069
18304
  var nextPollAtMs = 0;
18070
18305
  var nextAuxPollAtMs = 0;
18071
18306
  var nextTeamSyncAtMs = 0;
18307
+ var nextServerHealthAtMs = 0;
18072
18308
  var firstTeamSync = true;
18073
18309
  var currentIntervalMs = BASE_INTERVAL_MS;
18074
18310
  var waitingForRefresh = false;
@@ -18101,14 +18337,14 @@ var perceptionHandle = setInterval(async () => {
18101
18337
  }, PERCEPTION_INTERVAL_MS);
18102
18338
  function readUpdateState() {
18103
18339
  try {
18104
- return JSON.parse(readFileSync21(UPDATE_STATE, "utf8"));
18340
+ return JSON.parse(readFileSync23(UPDATE_STATE, "utf8"));
18105
18341
  } catch {
18106
18342
  return null;
18107
18343
  }
18108
18344
  }
18109
18345
  function writeUpdateState(state) {
18110
18346
  try {
18111
- writeFileSync15(UPDATE_STATE, JSON.stringify(state, null, 2), { mode: 384 });
18347
+ writeFileSync16(UPDATE_STATE, JSON.stringify(state, null, 2), { mode: 384 });
18112
18348
  } catch {
18113
18349
  }
18114
18350
  }
@@ -18121,7 +18357,7 @@ function nextUpdateCheckFromState(nowMs) {
18121
18357
  }
18122
18358
  var nextUpdateCheckAtMs = nextUpdateCheckFromState(Date.now());
18123
18359
  function cliEntryPath() {
18124
- return join13(dirname12(fileURLToPath(import.meta.url)), "index.js");
18360
+ return join14(dirname14(fileURLToPath2(import.meta.url)), "index.js");
18125
18361
  }
18126
18362
  async function runDaemonUpdateCheck() {
18127
18363
  if (process.env.FLEETLENS_DAEMON_AUTO_UPDATE === "0") {
@@ -18153,7 +18389,7 @@ async function runDaemonUpdateCheck() {
18153
18389
  return;
18154
18390
  }
18155
18391
  const entry = cliEntryPath();
18156
- if (!existsSync19(entry)) {
18392
+ if (!existsSync20(entry)) {
18157
18393
  log2("warn", `update check found ${availability.latest}, but CLI entry is missing at ${entry}`);
18158
18394
  return;
18159
18395
  }
@@ -18162,7 +18398,7 @@ async function runDaemonUpdateCheck() {
18162
18398
  logFd = openSync(DAEMON_LOG, "a");
18163
18399
  } catch {
18164
18400
  }
18165
- const child = spawn3(process.execPath, [entry, "update"], {
18401
+ const child = spawn4(process.execPath, [entry, "update"], {
18166
18402
  detached: true,
18167
18403
  stdio: ["ignore", logFd, logFd],
18168
18404
  env: { ...process.env, FLEETLENS_UPDATE_SOURCE: "daemon" }
@@ -18192,6 +18428,44 @@ async function runDaemonUpdateCheck() {
18192
18428
  nextUpdateCheckAtMs = Date.now() + AUTO_UPDATE_INTERVAL_MS;
18193
18429
  }
18194
18430
  }
18431
+ var serverWatchdog = new ServerWatchdog();
18432
+ var lastServerVerdict = "ok";
18433
+ var lastServerPid = null;
18434
+ async function runServerHealthCheck() {
18435
+ const status = getServerStatus();
18436
+ if (!status.running) {
18437
+ if (lastServerPid !== null) {
18438
+ serverWatchdog.noteServerGone();
18439
+ lastServerPid = null;
18440
+ }
18441
+ return;
18442
+ }
18443
+ if (status.pid !== lastServerPid) {
18444
+ serverWatchdog.noteNewInstance();
18445
+ lastServerPid = status.pid;
18446
+ }
18447
+ const ok = await probeServerHealth(status.port, SERVER_HEALTH_TIMEOUT_MS);
18448
+ const verdict = serverWatchdog.onProbe(ok, Date.now());
18449
+ if (verdict === "failing") {
18450
+ log2("warn", `[watchdog] server pid=${status.pid} not answering on port ${status.port}`);
18451
+ } else if (verdict === "restart") {
18452
+ log2("warn", `[watchdog] server pid=${status.pid} wedged; force-restarting on port ${status.port}`);
18453
+ try {
18454
+ const fresh = await restartWedgedServer(status.pid, status.port);
18455
+ log2("info", `[watchdog] server restarted (pid=${fresh.pid}, port=${fresh.port})`);
18456
+ } catch (err) {
18457
+ log2("error", `[watchdog] restart failed: ${err.message}`);
18458
+ }
18459
+ } else if (verdict === "gave-up" && lastServerVerdict !== "gave-up") {
18460
+ log2(
18461
+ "error",
18462
+ `[watchdog] server keeps wedging after 3 restarts within the hour; standing down \u2014 run 'fleetlens start' to restart manually`
18463
+ );
18464
+ } else if (verdict === "ok" && lastServerVerdict !== "ok") {
18465
+ log2("info", `[watchdog] server responding again (pid=${status.pid})`);
18466
+ }
18467
+ lastServerVerdict = verdict;
18468
+ }
18195
18469
  async function pollAuxiliaryUsage() {
18196
18470
  for (const source of agentSources) {
18197
18471
  if (source.kind === "claude-code") continue;
@@ -18353,6 +18627,10 @@ async function runLoop() {
18353
18627
  if (Date.now() >= nextUpdateCheckAtMs) {
18354
18628
  await runDaemonUpdateCheck();
18355
18629
  }
18630
+ if (Date.now() >= nextServerHealthAtMs) {
18631
+ await runServerHealthCheck();
18632
+ nextServerHealthAtMs = Date.now() + SERVER_HEALTH_INTERVAL_MS;
18633
+ }
18356
18634
  await sleep2(WATCHDOG_INTERVAL_MS);
18357
18635
  }
18358
18636
  }
package/dist/index.js CHANGED
@@ -6217,6 +6217,8 @@ __export(server_exports, {
6217
6217
  getServerStatus: () => getServerStatus,
6218
6218
  isServerStale: () => isServerStale,
6219
6219
  openBrowser: () => openBrowser,
6220
+ probeServerHealth: () => probeServerHealth,
6221
+ restartWedgedServer: () => restartWedgedServer,
6220
6222
  startServer: () => startServer,
6221
6223
  stopServer: () => stopServer
6222
6224
  });
@@ -6241,9 +6243,9 @@ function onDiskVersion() {
6241
6243
  try {
6242
6244
  const here = dirname3(fileURLToPath(import.meta.url));
6243
6245
  const pkg = JSON.parse(readFileSync5(join3(here, "..", "package.json"), "utf8"));
6244
- return pkg.version ?? "1.0.0";
6246
+ return pkg.version ?? "1.0.2";
6245
6247
  } catch {
6246
- return "1.0.0";
6248
+ return "1.0.2";
6247
6249
  }
6248
6250
  }
6249
6251
  function getServerStatus() {
@@ -6255,7 +6257,7 @@ function getServerStatus() {
6255
6257
  return { running: false };
6256
6258
  }
6257
6259
  function isServerStale(status2) {
6258
- return status2.running === true && status2.version !== "1.0.0";
6260
+ return status2.running === true && status2.version !== "1.0.2";
6259
6261
  }
6260
6262
  async function ensureCurrentServer(opts = {}) {
6261
6263
  const status2 = getServerStatus();
@@ -6316,6 +6318,25 @@ async function startServer(opts = {}) {
6316
6318
  await waitForHealth(`http://localhost:${port}`, 3e4);
6317
6319
  return { pid, port };
6318
6320
  }
6321
+ async function probeServerHealth(port, timeoutMs) {
6322
+ try {
6323
+ await fetch(`http://localhost:${port}/api/health`, {
6324
+ signal: AbortSignal.timeout(timeoutMs)
6325
+ });
6326
+ return true;
6327
+ } catch {
6328
+ return false;
6329
+ }
6330
+ }
6331
+ async function restartWedgedServer(pid, port) {
6332
+ try {
6333
+ process.kill(pid, "SIGKILL");
6334
+ } catch {
6335
+ }
6336
+ removePid(PID_FILE);
6337
+ await waitForPortFree(port, 5e3);
6338
+ return startServer({ port });
6339
+ }
6319
6340
  function stopServer() {
6320
6341
  cleanStalePid(PID_FILE, SERVER_MARKERS);
6321
6342
  const entry = readPid(PID_FILE);
@@ -6617,10 +6638,12 @@ function runNpmInstall() {
6617
6638
  try {
6618
6639
  execSync(`npm install -g ${PACKAGE_NAME}@latest --prefer-online`, {
6619
6640
  stdio: "pipe",
6620
- timeout: 6e4
6641
+ timeout: 3e5
6621
6642
  });
6622
6643
  return true;
6623
- } catch {
6644
+ } catch (err) {
6645
+ const msg = err instanceof Error ? err.message : String(err);
6646
+ console.error(` (npm install failed: ${msg.split("\n")[0]})`);
6624
6647
  return false;
6625
6648
  }
6626
6649
  }
@@ -6695,9 +6718,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
6695
6718
  console.warn(
6696
6719
  ` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
6697
6720
  );
6698
- } else if (verify.installedVersion !== "1.0.0") {
6721
+ } else if (verify.installedVersion !== "1.0.2") {
6699
6722
  console.log(
6700
- ` \u2192 This process is still running ${"1.0.0"}. Next invocation will use ${verify.installedVersion}.`
6723
+ ` \u2192 This process is still running ${"1.0.2"}. Next invocation will use ${verify.installedVersion}.`
6701
6724
  );
6702
6725
  }
6703
6726
  }
@@ -6732,14 +6755,14 @@ async function getUpdateAvailability() {
6732
6755
  if (isDevMode()) return null;
6733
6756
  const latest = await fetchLatestVersion();
6734
6757
  if (latest === null) return {
6735
- current: "1.0.0",
6758
+ current: "1.0.2",
6736
6759
  latest: null,
6737
6760
  updateAvailable: false
6738
6761
  };
6739
6762
  return {
6740
- current: "1.0.0",
6763
+ current: "1.0.2",
6741
6764
  latest,
6742
- updateAvailable: shouldUpdate("1.0.0", latest)
6765
+ updateAvailable: shouldUpdate("1.0.2", latest)
6743
6766
  };
6744
6767
  }
6745
6768
  async function checkForUpdate() {
@@ -6829,7 +6852,7 @@ async function restartServices(state) {
6829
6852
  }
6830
6853
  async function forceUpdate() {
6831
6854
  const latest = await fetchLatestVersion();
6832
- const current = "1.0.0";
6855
+ const current = "1.0.2";
6833
6856
  if (latest === null) {
6834
6857
  console.error("Could not reach npm registry. Check your network.");
6835
6858
  process.exit(1);
@@ -7239,10 +7262,18 @@ async function status() {
7239
7262
  if (server.running) {
7240
7263
  const url = `http://localhost:${server.port}`;
7241
7264
  const ver = server.version ?? "unknown";
7242
- console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
7265
+ const responsive = await probeServerHealth(server.port, 3e3);
7266
+ if (responsive) {
7267
+ console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
7268
+ } else {
7269
+ console.log(`Server: running but UNRESPONSIVE on ${url} (PID ${server.pid}, v${ver})`);
7270
+ console.log(
7271
+ " \u26A0 process is alive but not answering HTTP \u2014 a running daemon's watchdog force-restarts a wedged server ('fleetlens daemon logs' shows its verdicts), or run 'fleetlens start' now"
7272
+ );
7273
+ }
7243
7274
  if (isServerStale(server)) {
7244
7275
  console.log(
7245
- ` \u26A0 serving stale ${ver} (CLI is ${"1.0.0"}) \u2014 run 'fleetlens start' to restart on the current version`
7276
+ ` \u26A0 serving stale ${ver} (CLI is ${"1.0.2"}) \u2014 run 'fleetlens start' to restart on the current version`
7246
7277
  );
7247
7278
  }
7248
7279
  } else {
@@ -19935,7 +19966,7 @@ function buildIngestPayload(inputs) {
19935
19966
  return {
19936
19967
  ingestId: randomUUID2(),
19937
19968
  observedAt: (/* @__PURE__ */ new Date()).toISOString(),
19938
- cliVersion: "1.0.0",
19969
+ cliVersion: "1.0.2",
19939
19970
  ...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
19940
19971
  ...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
19941
19972
  ...richRollup ? { richRollup } : {},
@@ -21979,7 +22010,7 @@ async function main() {
21979
22010
  case "version":
21980
22011
  case "--version":
21981
22012
  case "-v":
21982
- console.log(`fleetlens ${"1.0.0"}`);
22013
+ console.log(`fleetlens ${"1.0.2"}`);
21983
22014
  break;
21984
22015
  case "help":
21985
22016
  case "--help":
@@ -10,8 +10,8 @@
10
10
  <key>CFBundleName</key><string>Fleetlens</string>
11
11
  <key>CFBundleDisplayName</key><string>Fleetlens</string>
12
12
  <key>CFBundlePackageType</key><string>APPL</string>
13
- <key>CFBundleShortVersionString</key><string>1.0.0</string>
14
- <key>CFBundleVersion</key><string>1.0.0</string>
13
+ <key>CFBundleShortVersionString</key><string>1.0.2</string>
14
+ <key>CFBundleVersion</key><string>1.0.2</string>
15
15
  <key>LSApplicationCategoryType</key><string>public.app-category.developer-tools</string>
16
16
  <key>LSMinimumSystemVersion</key><string>14.0</string>
17
17
  <key>LSUIElement</key><true/>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetlens",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "fleetlens — local-only dashboard and usage tracker for Claude Code sessions and agent fleets",
5
5
  "license": "MIT",
6
6
  "author": "cowcow02",
@@ -1,3 +0,0 @@
1
- module.exports=[93695,(e,t,s)=>{t.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},18622,(e,t,s)=>{t.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(e,t,s)=>{t.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(e,t,s)=>{t.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},70406,(e,t,s)=>{t.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},50227,(e,t,s)=>{t.exports=e.x("node:path",()=>require("node:path"))},2157,(e,t,s)=>{t.exports=e.x("node:fs",()=>require("node:fs"))},60526,(e,t,s)=>{t.exports=e.x("node:os",()=>require("node:os"))},66680,(e,t,s)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},27174,e=>{"use strict";e.i(39587),e.s([])},86040,e=>{"use strict";e.i(27174);var t=e.i(36521);let s=/\[request interrupted|interrupted by user/i,r=/rate.?limit|overloaded_error|api error|Error sending message/i,n=/<command-name>(\/[^<\s]+)<\/command-name>(?:[\s\S]*?<command-args>([\s\S]*?)<\/command-args>)?/,o=/<task-notification>/;function i(e){for(let t of e)if(t?.type==="text")return t.text}function a(e){return e<1e3?String(e):e<1e4?(e/1e3).toFixed(1)+"k":e<1e6?Math.round(e/1e3)+"k":e<1e7?(e/1e6).toFixed(2)+"M":(e/1e6).toFixed(1)+"M"}function u(e){if(void 0===e||e<0)return"—";let t=Math.floor(e/1e3),s=Math.floor(t/3600),r=String(Math.floor(t%3600/60)).padStart(2,"0"),n=String(t%60).padStart(2,"0");return`${s}:${r}:${n}`}function l(e){if(void 0===e)return"—";if(e<1e3)return`${e}ms`;let t=Math.round(e/1e3);if(t<60)return`${t}s`;let s=Math.floor(t/60),r=t%60;if(s<60)return r?`${s}m ${r}s`:`${s}m`;let n=Math.floor(s/60),o=s%60;return o?`${n}h ${o}m`:`${n}h`}function f(e,t){if(!e)return"";let s=e.replace(/\s+/g," ").trim();return s.length>t?s.slice(0,t-1)+"…":s}e.s(["summarizeSessionForAI",0,function(e){let p,d=function(e){let a=new Map;for(let t of e){if(!t.messageId)continue;let e=a.get(t.messageId)??[];e.push(t),a.set(t.messageId,e)}let u=e.filter(e=>{if("system"===e.role||"meta"===e.role||"tool-result"===e.role||"agent-thinking"===e.role)return!1;if("user"===e.role){let s=i(e.blocks)??"";if(0===e.blocks.length||!s.trim())return!1;if(n.test(s)||o.test(s))return!0;if((0,t.isFrameworkInjectedUserInput)(s))return!1}return!0}),l=[];for(let e=0;e<u.length;e++){let t=u[e];if("tool-call"===t.role){let t=e;for(;e+1<u.length&&"tool-call"===u[e+1].role;)e++;let s=u.slice(t,e+1),r=[],n=new Map;for(let e of s){let t=e.toolName??"tool";n.has(t)||r.push(t),n.set(t,(n.get(t)??0)+1)}let o=r.map(e=>({name:e,count:n.get(e)??1}));l.push({kind:"tool-group",toolNames:o,count:s.length,events:s,tOffsetMs:s[0].tOffsetMs,gapMs:s[0].gapMs});continue}if("user"===t.role){let e=i(t.blocks)??"",r=function(e){if(!o.test(e))return null;let t=t=>{let s=e.match(RegExp(`<${t}>([\\s\\S]*?)<\\/${t}>`));return s?s[1].trim():void 0},s=(t("status")??"").toLowerCase(),r="unknown";return"success"===s||"ok"===s||"done"===s||"completed"===s?r="success":"failed"===s||"error"===s||"fail"===s?r="failed":("running"===s||"in_progress"===s)&&(r="running"),{status:r,summary:t("summary")??"Background task notification",taskId:t("task-id"),toolUseId:t("tool-use-id"),outputFile:t("output-file")}}(e);if(r){l.push({kind:"task-notification",event:t,status:r.status,summary:r.summary,taskId:r.taskId,toolUseId:r.toolUseId,outputFile:r.outputFile,tOffsetMs:t.tOffsetMs,gapMs:t.gapMs});continue}if(s.test(e)){l.push({kind:"interrupt",event:t,tOffsetMs:t.tOffsetMs,gapMs:t.gapMs});continue}let a=e.match(n);if(a){let e=a[1],s=(a[2]??"").trim(),r=s?`${e} ${s}`:e;l.push({kind:"user",event:t,displayPreview:r,displayBlocks:[{type:"text",text:r}],tOffsetMs:t.tOffsetMs,gapMs:t.gapMs});continue}l.push({kind:"user",event:t,tOffsetMs:t.tOffsetMs,gapMs:t.gapMs});continue}if("agent"===t.role){let e=i(t.blocks)??"";if(function(e){if(!e.usage)return!1;let t=e.usage;return 0===t.input&&0===t.output&&0===t.cacheRead&&0===t.cacheWrite}(t)){l.push({kind:"model",event:t,tOffsetMs:t.tOffsetMs,gapMs:t.gapMs}),r.test(e)&&e.length<500&&l.push({kind:"error",event:t,message:e,tOffsetMs:t.tOffsetMs,gapMs:0});continue}if(r.test(e)&&e.length<500){l.push({kind:"error",event:t,message:e,tOffsetMs:t.tOffsetMs,gapMs:t.gapMs});continue}let s=t.messageId?a.get(t.messageId)??[t]:[t];l.push({kind:"agent",event:t,groupedEvents:s,tOffsetMs:t.tOffsetMs,gapMs:t.gapMs});continue}}return l}(e.events),c=function(e){let t=[],s=[],r=null,n=()=>{let e,n;if(0===s.length)return;let o=0,i=0,a=0,u=new Map,l=new Set,f={input:0,output:0,cacheRead:0,cacheWrite:0};for(let t=0;t<s.length;t++){let r=s[t];if("agent"===r.kind){o++,void 0===e&&(e=t);let s=r.event.messageId,n=r.event.usage;s&&!l.has(s)&&n&&(l.add(s),f.input+=n.input,f.output+=n.output,f.cacheRead+=n.cacheRead,f.cacheWrite+=n.cacheWrite)}else if("tool-group"===r.kind)for(let e of(i+=r.count,r.toolNames))u.set(e.name,(u.get(e.name)??0)+e.count);else"error"===r.kind&&a++}for(let e=s.length-1;e>=0;e--){if("agent"!==s[e].kind)continue;let t=s[e-1];if(t?.kind!=="task-notification"){n=e;break}}if(void 0===n){for(let e=s.length-1;e>=0;e--)if("agent"===s[e].kind){n=e;break}}let p=void 0!==e&&"agent"===s[e].kind?s[e].event.preview:void 0,d=void 0!==n&&"agent"===s[n].kind?s[n].event.preview:void 0,c=Array.from(u.entries()).sort((e,t)=>t[1]-e[1]).map(([e,t])=>({name:e,count:t})),m=s[0],g=s[s.length-1],h=r?.tOffsetMs??m.tOffsetMs,k=g.tOffsetMs;t.push({kind:"turn",rows:s,firstPrimaryIndex:"tool-group"===m.kind?m.events[0].index:m.event.index,tOffsetMs:h,durationMs:void 0!==h&&void 0!==k&&k>=h?k-h:void 0,summary:{agentMessages:o,toolCalls:i,errors:a,firstAgentPreview:p,finalAgentPreview:d,firstAgentIndex:e,finalAgentIndex:n,toolNames:c,totalTokens:f}}),s=[]};for(let o of e)"user"===o.kind||"interrupt"===o.kind?(n(),t.push(o),r=o):s.push(o);return n(),t}(d),m=e.totalUsage.input+e.totalUsage.cacheRead+e.totalUsage.cacheWrite,g=e.totalUsage.cacheRead+e.totalUsage.cacheWrite,h=new Map;for(let e of d)if("tool-group"===e.kind)for(let t of e.toolNames)h.set(t.name,(h.get(t.name)??0)+t.count);let k=Array.from(h.entries()).sort((e,t)=>t[1]-e[1]).slice(0,8).map(([e,t])=>`${e}\xd7${t}`).join(", "),v=d.find(e=>"user"===e.kind&&!e.event.preview.startsWith("<command-name>")&&!e.event.preview.startsWith("Base directory for this skill:")),M=v?.kind==="user"?v.displayBlocks?.[0]?.type==="text"?v.displayBlocks[0].text:(p=v.event.blocks.find(e=>e?.type==="text"),p?.text??v.event.preview):"",x=d.filter(e=>"error"===e.kind),$=x.length>0?`${x.length} errors, first: "${f(x[0].message,160)}"`:"none",y=[],w=e.durationMs??0;for(let t of e.events){if("tool-call"!==t.role||"Bash"!==t.toolName)continue;let e=t.blocks.find(e=>e&&"tool_use"===e.type),s="string"==typeof e?.input?.command?e.input.command:"";if(!/gh\s+pr\s+create\b/i.test(s))continue;let r=s.match(/--title\s+["']([^"']+)["']/),n=r?.[1]??s.replace(/^gh pr create /,"").slice(0,120),o=w>0&&void 0!==t.tOffsetMs?Math.round(t.tOffsetMs/w*100):0;y.push({offsetPct:o,titleOrCmd:n})}let O="";for(let e=c.length-1;e>=0;e--){let t=c[e];if("turn"!==t.kind)continue;let s=t.summary.finalAgentIndex;if(void 0!==s){let e=t.rows[s];if(e?.kind==="agent"){let t=e.event.blocks.find(e=>e&&"text"===e.type);O=t?.text??e.event.preview;break}}}let b=[];for(let e of c){if(b.length>=40){b.push({offset:"...",line:`(+${c.length-b.length} more rows)`});break}if("user"===e.kind){let t=f(function(e){switch(e.kind){case"user":return e.displayPreview??e.event.preview;case"agent":return e.event.preview;case"tool-group":return e.toolNames.slice(0,4).map(e=>e.count>1?`${e.name} \xd7${e.count}`:e.name).join(", ");case"interrupt":return"[interrupted]";case"model":return"[zero-usage response]";case"error":return`ERROR: ${e.message}`;case"task-notification":return`BG task ${e.status}: ${e.summary}`;default:return""}}(e),180);t.startsWith("<command-name>")||b.push({offset:u(e.tOffsetMs),line:`USER: ${t}`})}else if("turn"===e.kind){let t=e.summary,s=t.firstAgentPreview?f(t.firstAgentPreview,180):"",r=t.finalAgentPreview?f(t.finalAgentPreview,180):"",n=s&&r&&s===r,o=t.toolNames.slice(0,3).map(e=>e.count>1?`${e.name}\xd7${e.count}`:e.name).join(", "),i=`${t.agentMessages} msg, ${t.toolCalls} tools${t.errors>0?`, ${t.errors} err`:""}`,a=n||!r?s:`${s} → ${r}`;b.push({offset:u(e.tOffsetMs),line:`TURN (${i}${o?`, ${o}`:""}): ${a}`})}else"interrupt"===e.kind&&b.push({offset:u(e.tOffsetMs),line:"INTERRUPT"})}let I=[];for(let t of(I.push(`# Session ${e.id}`),I.push(`project: ${e.projectName}`),e.model&&I.push(`model: ${e.model}`),I.push(`duration: ${l(e.durationMs)} | active: ${l(e.airTimeMs??e.durationMs)}`),I.push(`events: ${e.eventCount} | tokens: ${a(m)} in / ${a(e.totalUsage.output)} out${g>0?` (+${a(g)} cached)`:""}`),I.push(`tool calls: ${e.toolCallCount??0}${k?` (${k})`:""}`),I.push(`turns: ${e.turnCount??0}`),e.firstTimestamp&&I.push(`started: ${e.firstTimestamp}`),I.push(""),M&&(I.push("## First user message"),I.push(f(M,1200)),I.push("")),I.push("## Timeline"),b))I.push(`[${t.offset}] ${t.line}`);if(I.push(""),y.length>0){for(let e of(I.push("## PRs shipped"),y))I.push(`- at ${e.offsetPct}% into session: ${f(e.titleOrCmd,160)}`);I.push("")}return I.push("## Errors encountered"),I.push($),I.push(""),O&&(I.push("## Final agent message"),I.push(f(O,800))),I.join("\n")}],86040)}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0sbhe0s._.js.map