@dylanpiercey/work 0.0.145 → 0.0.147

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 (80) hide show
  1. package/dist/_Bv4lCw13.js +2 -0
  2. package/dist/{_RdvbSrnZ.js → _DGEhqy7E.js} +186 -32
  3. package/dist/index.mjs +5950 -5873
  4. package/dist/public/assets/_2xuRGdn_.js +1 -0
  5. package/dist/public/assets/_B12ZGJAK.js +1 -0
  6. package/dist/public/assets/_BJJj6Bgs.js +1 -0
  7. package/dist/public/assets/_BONsa0p1.js +1 -0
  8. package/dist/public/assets/_BaWHj3BA.js +1 -0
  9. package/dist/public/assets/_Bbw6USJg.js +1 -0
  10. package/dist/public/assets/_BlpiJD5o.js +1 -0
  11. package/dist/public/assets/_C9l_aW0n.js +1 -0
  12. package/dist/public/assets/{_Dy1DNuXx.js → _CbHNdeDU.js} +4 -4
  13. package/dist/public/assets/_CbHNdeDU.js.br +0 -0
  14. package/dist/public/assets/_Cr0wBZa1.js +1 -0
  15. package/dist/public/assets/_Cr0wBZa1.js.br +0 -0
  16. package/dist/public/assets/_DIXWDGWP.js +1 -0
  17. package/dist/public/assets/_D_3kwekz.js +1 -0
  18. package/dist/public/assets/_Ddu-G-hH.js +1 -0
  19. package/dist/public/assets/{_DQ3bjKhC.js → _DsOQV4Jf.js} +20 -20
  20. package/dist/public/assets/_DsOQV4Jf.js.br +0 -0
  21. package/dist/public/assets/_DxNtl6PJ.js +1 -0
  22. package/dist/public/assets/_IH_dHn2Z.js +1 -0
  23. package/dist/public/assets/_NutY1vka.js +1 -0
  24. package/dist/public/assets/_Q11TJ5W0.js +1 -0
  25. package/dist/public/assets/_SRRkeWJi.js +1 -0
  26. package/dist/public/assets/_a5rTuRF3.js +1 -0
  27. package/dist/public/assets/_kv7st39T.js +1 -0
  28. package/dist/public/assets/_okmh0c7M.js +1 -0
  29. package/dist/public/assets/app-page-CS4w1M-v.css +1 -0
  30. package/dist/public/assets/app-page-CS4w1M-v.css.br +0 -0
  31. package/dist/public/assets/diff-view-BcgXlDbY.css +1 -0
  32. package/dist/public/assets/diff-view-BcgXlDbY.css.br +0 -0
  33. package/dist/public/assets/diff-view-YLo1KhOq.js +2 -0
  34. package/dist/public/assets/icon-arrow-down-CYif_Qat.css +1 -0
  35. package/dist/public/assets/icon-arrow-down-CYif_Qat.css.br +0 -0
  36. package/dist/public/assets/new-B000kC3p.js +1 -0
  37. package/dist/public/assets/settings-B000kC3p.js +1 -0
  38. package/dist/public/assets/w-B000kC3p.js +1 -0
  39. package/dist/public/assets/w._-B000kC3p.js +1 -0
  40. package/dist/public/assets/w._-CE1vFHA1.js +1 -0
  41. package/lib/setup/doctor.d.mts +1 -1
  42. package/lib/setup/doctor.mjs +32 -5
  43. package/package.json +1 -1
  44. package/scripts/migrate.mjs +1 -1
  45. package/dist/_BF-bl9wz.js +0 -2
  46. package/dist/public/assets/_21mgW-1Z.js +0 -1
  47. package/dist/public/assets/_B9sRUkZv.js +0 -1
  48. package/dist/public/assets/_BQDnrQES.js +0 -1
  49. package/dist/public/assets/_BgCHTkW2.js +0 -1
  50. package/dist/public/assets/_BvOfxkzU.js +0 -1
  51. package/dist/public/assets/_C448NmFH.js +0 -1
  52. package/dist/public/assets/_C4_-B9wF.js +0 -1
  53. package/dist/public/assets/_C7gmftFo.js +0 -1
  54. package/dist/public/assets/_C7gmftFo.js.br +0 -0
  55. package/dist/public/assets/_CEw_Mye5.js +0 -1
  56. package/dist/public/assets/_CFi5anE6.js +0 -1
  57. package/dist/public/assets/_CGcmWQOb.js +0 -1
  58. package/dist/public/assets/_CeGQErY4.js +0 -1
  59. package/dist/public/assets/_D2C1S8zb.js +0 -1
  60. package/dist/public/assets/_D5RLfyQD.js +0 -1
  61. package/dist/public/assets/_DBeqA_AC.js +0 -1
  62. package/dist/public/assets/_DFvgQmuO.js +0 -1
  63. package/dist/public/assets/_DQ3bjKhC.js.br +0 -0
  64. package/dist/public/assets/_DQO13XHH.js +0 -1
  65. package/dist/public/assets/_DsCpEqH5.js +0 -1
  66. package/dist/public/assets/_Dy1DNuXx.js.br +0 -0
  67. package/dist/public/assets/_VnRbDdk0.js +0 -1
  68. package/dist/public/assets/_bVO2SjRK.js +0 -1
  69. package/dist/public/assets/app-page-k1J1kX4l.css +0 -1
  70. package/dist/public/assets/app-page-k1J1kX4l.css.br +0 -0
  71. package/dist/public/assets/diff-view-Ch_De7qH.css +0 -1
  72. package/dist/public/assets/diff-view-Ch_De7qH.css.br +0 -0
  73. package/dist/public/assets/diff-view-D7PqjZCP.js +0 -2
  74. package/dist/public/assets/icon-arrow-down-CMd0RUdb.css +0 -1
  75. package/dist/public/assets/icon-arrow-down-CMd0RUdb.css.br +0 -0
  76. package/dist/public/assets/new-ieyLBknO.js +0 -1
  77. package/dist/public/assets/settings-ieyLBknO.js +0 -1
  78. package/dist/public/assets/w-ieyLBknO.js +0 -1
  79. package/dist/public/assets/w._-DRZmWqrE.js +0 -1
  80. package/dist/public/assets/w._-ieyLBknO.js +0 -1
@@ -0,0 +1,2 @@
1
+ import { m as notifySessionsChanged } from "./_DGEhqy7E.js";
2
+ export { notifySessionsChanged };
@@ -72,7 +72,7 @@ var tmux = (args, env) => run$1("tmux", [
72
72
  "-L",
73
73
  TMUX_SOCKET,
74
74
  ...args
75
- ], void 0, utf8Locale(env ?? process.env));
75
+ ], os.homedir(), utf8Locale(env ?? process.env));
76
76
  /** launchd starts the service with no locale at all, and under a non-UTF-8
77
77
  * locale tmux replaces characters it deems unprintable in format output —
78
78
  * including the \t separators sessionStates and the scraper split on, which
@@ -426,6 +426,20 @@ function setupPath(base = process.env.PATH || "") {
426
426
  const seen = /* @__PURE__ */ new Set();
427
427
  return [...base.split(path.delimiter), ...extra].filter((p) => p && !seen.has(p) && seen.add(p)).join(path.delimiter);
428
428
  }
429
+ /** setupPath() split once per PATH value: `which` runs for every tool on
430
+ * every probe and rebuilt the list each time. */
431
+ var dirsFor = {
432
+ base: void 0,
433
+ dirs: []
434
+ };
435
+ function setupDirs() {
436
+ const base = process.env.PATH || "";
437
+ if (dirsFor.base !== base) dirsFor = {
438
+ base,
439
+ dirs: setupPath(base).split(path.delimiter)
440
+ };
441
+ return dirsFor.dirs;
442
+ }
429
443
  /** `~/…` for anything under the home directory — every path here is for
430
444
  * display (Settings rows, `work doctor`), never re-used to exec. */
431
445
  function tilde(p) {
@@ -434,7 +448,7 @@ function tilde(p) {
434
448
  }
435
449
  /** Absolute path of `bin` on setupPath(), or null. */
436
450
  function which(bin) {
437
- for (const dir of setupPath().split(path.delimiter)) {
451
+ for (const dir of setupDirs()) {
438
452
  const full = path.join(dir, bin);
439
453
  try {
440
454
  if (fs.statSync(full).isFile()) return full;
@@ -500,14 +514,29 @@ function ghKnownHosts() {
500
514
  }
501
515
  return [...text.matchAll(/^([A-Za-z0-9.-]+):\s*$/gm)].map((m) => m[1]);
502
516
  }
517
+ /** Agent scan memo. Every app page render, skills scan and session
518
+ * create asks; the answer only moves when something is installed, and
519
+ * the doctor probe (which every install runs) refreshes it. */
520
+ var AGENTS_MEMO_MS = 3e4;
521
+ var agentsMemo = null;
503
522
  /**
504
523
  * Every agent CLI instance on PATH, per family: the plain binary and any
505
524
  * numeric-suffixed siblings (`claude1`, `cursor-agent2`). Sync — a PATH
506
525
  * scan is cheap and the boot handler needs it without awaiting. First hit
507
- * on PATH wins per name, like the shell.
526
+ * on PATH wins per name, like the shell. `fresh` rescans regardless of
527
+ * the memo.
508
528
  */
509
- function discoverAgents() {
510
- const dirs = setupPath().split(path.delimiter);
529
+ function discoverAgents(fresh = false) {
530
+ if (!fresh && agentsMemo && Date.now() - agentsMemo.at < AGENTS_MEMO_MS) return agentsMemo.value;
531
+ const value = scanAgents();
532
+ agentsMemo = {
533
+ at: Date.now(),
534
+ value
535
+ };
536
+ return value;
537
+ }
538
+ function scanAgents() {
539
+ const dirs = setupDirs();
511
540
  const seenDirs = /* @__PURE__ */ new Set();
512
541
  const seen = /* @__PURE__ */ new Map();
513
542
  for (const dir of dirs) {
@@ -614,7 +643,7 @@ async function doctor(opts = {}) {
614
643
  mise: t.mise
615
644
  };
616
645
  });
617
- const agents = discoverAgents();
646
+ const agents = discoverAgents(true);
618
647
  const missing = [];
619
648
  for (const t of tools) if (t.required && !t.installed) missing.push(t.id);
620
649
  if (!github.some((h) => h.authed)) missing.push("github-auth");
@@ -705,12 +734,108 @@ function preferredAgent(enabled = enabledAgents()) {
705
734
  return enabled[0] || "shell";
706
735
  }
707
736
  //#endregion
737
+ //#region src/server/cache.ts
738
+ /** Keyed stale-while-revalidate cache: a cached value is served immediately
739
+ * (revalidating in the background when older than `ttlMs`); loads are deduped
740
+ * per key, and `refresh` bypasses both the cache and any in-flight load. */
741
+ function swr(ttlMs, load, seed) {
742
+ const cache = /* @__PURE__ */ new Map();
743
+ const inflight = /* @__PURE__ */ new Map();
744
+ function start(key, refresh) {
745
+ const startedAt = Date.now();
746
+ const promise = load(key, refresh).then((value) => {
747
+ const existing = cache.get(key);
748
+ if (!existing || existing.at <= startedAt) cache.set(key, {
749
+ at: Date.now(),
750
+ value
751
+ });
752
+ return value;
753
+ }).finally(() => {
754
+ if (inflight.get(key)?.promise === promise) inflight.delete(key);
755
+ });
756
+ inflight.set(key, {
757
+ promise,
758
+ refresh
759
+ });
760
+ return promise;
761
+ }
762
+ const read = (key, refresh = false) => {
763
+ if (refresh) {
764
+ const current = inflight.get(key);
765
+ return current?.refresh ? current.promise : start(key, true);
766
+ }
767
+ let cached = cache.get(key);
768
+ if (!cached && seed) {
769
+ cached = seed(key);
770
+ if (cached) cache.set(key, cached);
771
+ }
772
+ if (cached) {
773
+ if (Date.now() - cached.at >= ttlMs && !inflight.has(key)) start(key, false).catch(() => {});
774
+ return Promise.resolve(cached.value);
775
+ }
776
+ return inflight.get(key)?.promise ?? start(key, false);
777
+ };
778
+ /** Inject an externally fetched value (e.g. from a batched load). */
779
+ read.set = (key, value) => {
780
+ cache.set(key, {
781
+ at: Date.now(),
782
+ value
783
+ });
784
+ };
785
+ /** Current cached value, if any — used when a batch update must merge
786
+ * with a richer per-key load rather than replace it. */
787
+ read.get = (key) => cache.get(key)?.value;
788
+ return read;
789
+ }
790
+ /** Serialize async work per key: calls for one key run in submission order,
791
+ * each starting only after the previous settled. The stored tail is the
792
+ * all-settled form, so a rejection neither blocks the next caller nor leaves
793
+ * the entry behind — the map holds only keys with work still in flight. */
794
+ var locks = /* @__PURE__ */ new Map();
795
+ function withLock(key, fn) {
796
+ const run = (locks.get(key) ?? Promise.resolve()).then(fn);
797
+ const tail = run.then(() => {}, () => {});
798
+ locks.set(key, tail);
799
+ tail.then(() => {
800
+ if (locks.get(key) === tail) locks.delete(key);
801
+ });
802
+ return run;
803
+ }
804
+ /** One load at a time, and a short reuse window: callers join the in-flight
805
+ * load, and a result younger than `ttlMs` is served without one. For an
806
+ * expensive process sweep (lsof, ps, list-panes) whose answer does not
807
+ * change within the window — `ttlMs` of 0 still collapses concurrent
808
+ * callers onto a single spawn. */
809
+ function shared(fn, ttlMs) {
810
+ let inflight = null;
811
+ let last = null;
812
+ return () => {
813
+ if (last && Date.now() - last.at < ttlMs) return Promise.resolve(last.value);
814
+ if (!inflight) inflight = fn().then((value) => {
815
+ last = {
816
+ at: Date.now(),
817
+ value
818
+ };
819
+ return value;
820
+ }).finally(() => {
821
+ inflight = null;
822
+ });
823
+ return inflight;
824
+ };
825
+ }
826
+ //#endregion
708
827
  //#region src/server/events.ts
709
828
  var listeners = /* @__PURE__ */ new Set();
710
829
  function publish(type, data) {
830
+ publishJson(type, data === void 0 ? void 0 : JSON.stringify(data), data);
831
+ }
832
+ /** Publish with the payload already serialized (a producer that had to
833
+ * stringify it anyway, e.g. for change detection, hands the string in). */
834
+ function publishJson(type, dataJson, data) {
711
835
  const event = {
712
836
  type,
713
- data
837
+ data,
838
+ frame: dataJson === void 0 ? JSON.stringify({ type }) : `{"type":${JSON.stringify(type)},"data":${dataJson}}`
714
839
  };
715
840
  for (const listener of [...listeners]) try {
716
841
  listener(event);
@@ -6599,7 +6724,7 @@ function publishChange(sessionId) {
6599
6724
  const row = get("SELECT workspace_id FROM sessions WHERE id = ?", sessionId);
6600
6725
  if (row?.workspace_id) {
6601
6726
  const workspaceId = row.workspace_id;
6602
- import("./_BF-bl9wz.js").then((m) => m.notifySessionsChanged(workspaceId));
6727
+ import("./_Bv4lCw13.js").then((m) => m.notifySessionsChanged(workspaceId));
6603
6728
  return;
6604
6729
  }
6605
6730
  publish("sessions.changed");
@@ -8126,6 +8251,7 @@ async function disposeSession(id) {
8126
8251
  "-t",
8127
8252
  tmuxName(id)
8128
8253
  ]).catch(() => {});
8254
+ forgetPanes();
8129
8255
  clearTmuxStarted(id);
8130
8256
  clearAgentPhase(id);
8131
8257
  db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
@@ -8144,9 +8270,18 @@ function tmuxWasStarted(id) {
8144
8270
  function clearTmuxStarted(id) {
8145
8271
  tmuxStarted.delete(id);
8146
8272
  }
8147
- /** SSE payload: session rows + live tmux/hook state so clients don't refetch. */
8273
+ /** SSE payload: session rows + live tmux/hook state so clients don't refetch.
8274
+ * Coalesced per workspace: a turn boundary lands as a burst of phase
8275
+ * transitions (hook, then scrape), and each one cost a list-panes spawn
8276
+ * and a broadcast for a list that came out the same. */
8277
+ var EMIT_DEBOUNCE_MS = 50;
8278
+ var pendingEmits = /* @__PURE__ */ new Map();
8148
8279
  function notifySessionsChanged(workspaceId) {
8149
- emitSessionsChanged(workspaceId);
8280
+ clearTimeout(pendingEmits.get(workspaceId));
8281
+ pendingEmits.set(workspaceId, setTimeout(() => {
8282
+ pendingEmits.delete(workspaceId);
8283
+ emitSessionsChanged(workspaceId);
8284
+ }, EMIT_DEBOUNCE_MS));
8150
8285
  }
8151
8286
  async function emitSessionsChanged(workspaceId) {
8152
8287
  try {
@@ -8172,13 +8307,13 @@ async function sendToSession(id, text, size) {
8172
8307
  const wsPath = workspacePath(session.workspace_id);
8173
8308
  if (!wsPath) throw new Error("unknown workspace");
8174
8309
  const name = tmuxName(id);
8175
- await ensureTmuxServer();
8176
8310
  const env = cleanEnv();
8177
8311
  if (!await tmux([
8178
8312
  "has-session",
8179
8313
  "-t",
8180
8314
  name
8181
8315
  ], env).then(() => true, () => false)) {
8316
+ await ensureTmuxServer();
8182
8317
  if (promptAsArgv(session.agent)) {
8183
8318
  await tmux(newSessionArgs(session, wsPath, "-d", text, size), env);
8184
8319
  markTmuxStarted(id);
@@ -8219,33 +8354,52 @@ async function sendToSession(id, text, size) {
8219
8354
  * started, so a shell someone ran `claude` inside still reads as "shell". */
8220
8355
  async function sessionStates() {
8221
8356
  const result = {};
8222
- const out = await tmux([
8223
- "list-panes",
8224
- "-a",
8225
- "-F",
8226
- "#{session_name} #{pane_current_command}"
8227
- ]).catch(() => "");
8228
- for (const line of out.split("\n")) {
8229
- const [name, command] = line.split(" ");
8230
- if (!name?.startsWith("wk-")) continue;
8231
- const id = name.slice(3);
8232
- result[id] = {
8233
- alive: true,
8234
- phase: agentPhase(id),
8235
- command: command || ""
8236
- };
8237
- }
8357
+ for (const { id, command } of await listPanes() || []) if (id) result[id] = {
8358
+ alive: true,
8359
+ phase: agentPhase(id),
8360
+ command
8361
+ };
8238
8362
  return result;
8239
8363
  }
8240
8364
  /** Root pids of every tmux pane (the agent/shell each session runs). */
8241
8365
  async function panePids() {
8366
+ return new Set((await listPanes() || []).map((p) => p.pid));
8367
+ }
8368
+ /** Every tmux pane, one `list-panes` for everyone who wants one: session
8369
+ * state, pane pids, the activity scraper and every phase transition ask
8370
+ * within a short span, and a field costs tmux nothing while a spawn costs
8371
+ * ~10 ms on macOS. The reuse window sits well under the scraper's 2 s
8372
+ * cadence; the one reader that must not see a stale answer — a
8373
+ * kill-session followed by a state read — drops the window with
8374
+ * `forgetPanes`. Null when tmux did not answer (server down, transient
8375
+ * failure): callers that clear state on "no panes" must not clear it on
8376
+ * "no answer". */
8377
+ var PANES_REUSE_MS = 400;
8378
+ var panesShared = shared(listPanesNow, PANES_REUSE_MS);
8379
+ var listPanes = () => panesShared();
8380
+ function forgetPanes() {
8381
+ panesShared = shared(listPanesNow, PANES_REUSE_MS);
8382
+ }
8383
+ async function listPanesNow() {
8242
8384
  const out = await tmux([
8243
8385
  "list-panes",
8244
8386
  "-a",
8245
8387
  "-F",
8246
- "#{pane_pid}"
8247
- ]).catch(() => "");
8248
- return new Set(out.split("\n").filter(Boolean).map(Number));
8388
+ "#{session_name} #{pane_current_command} #{pane_pid} #{window_activity}"
8389
+ ]).catch(() => null);
8390
+ if (out === null) return null;
8391
+ const panes = [];
8392
+ for (const line of out.split("\n")) {
8393
+ if (!line) continue;
8394
+ const [name, command, pid, stamp] = line.split(" ");
8395
+ panes.push({
8396
+ id: name?.startsWith("wk-") ? name.slice(3) : void 0,
8397
+ command: command || "",
8398
+ pid: Number(pid),
8399
+ activityAt: Number(stamp) * 1e3
8400
+ });
8401
+ }
8402
+ return panes;
8249
8403
  }
8250
8404
  /** Cleared once per process — boot already runs this, and a server we
8251
8405
  * create below never has PORT set, so re-running on every attach only
@@ -8283,7 +8437,7 @@ async function ensureTmuxServer() {
8283
8437
  "work-keeper",
8284
8438
  "sleep",
8285
8439
  "infinity"
8286
- ]).catch(() => {});
8440
+ ], os.homedir()).catch(() => {});
8287
8441
  }
8288
8442
  /** Full tmux command (options + new-session) for creating/attaching a
8289
8443
  * session's tmux; `mode` is "-d" (create detached) or "-A" (attach-or-create). */
@@ -8537,4 +8691,4 @@ function sleep(ms) {
8537
8691
  return new Promise((resolve) => setTimeout(resolve, ms));
8538
8692
  }
8539
8693
  //#endregion
8540
- export { setSetting as $, setScrapedPhase as A, saveSubscription as B, agentBadge as C, agentMeta as D, agentLabel as E, manifest as F, agentChoices as G, subscribe as H, normalizeAccent as I, enabledAgents as J, allPrefs as K, setInstance as L, ACCENT_RE as M, getInstance as N, clearAgentPhase as O, iconSvg as P, setPref as Q, deleteSubscription as R, blankRow as S, agentFromCommand as T, subscriberCount as U, publish as V, subscriberJoins as W, preferredAgent as X, getSetting as Y, setDisabledAgents as Z, tmuxName as _, gh as _t, ensureTmuxServer as a, setupPath as at, readHookPayload as b, tmux as bt, killWorkspaceSessions as c, TOOLS as ct, newSessionArgs as d, toolById as dt, discoverAgents as et, notifySessionsChanged as f, all as ft, sessionStates as g, TMUX_SOCKET as gt, sendToSession as h, workspacePath as ht, disposeSessions as i, miseVersions as it, setSessionViewers as j, setAgentPhase as k, listSessions as l, agentById as lt, renameSession as m, get as mt, clearTmuxStarted as n, ghKnownHosts as nt, getSession as o, which as ot, panePids as p, db as pt, disabledAgents as q, createSession as r, miseInstalls as rt, killSession as s, DEFAULT_GITHUB_HOST as st, cleanEnv as t, doctor as tt, markTmuxStarted as u, agentLabel$1 as ut, tmuxWasStarted as v, git as vt, agentFamily as w, reportsWorking as x, config as xt, AGENTS as y, run$1 as yt, pushPublicKey as z };
8694
+ export { disabledAgents as $, clearAgentPhase as A, deleteSubscription as B, reportsWorking as C, gh as Ct, agentFromCommand as D, config as Dt, agentFamily as E, tmux as Et, getInstance as F, subscribe as G, saveSubscription as H, iconSvg as I, shared as J, subscriberCount as K, manifest as L, setScrapedPhase as M, setSessionViewers as N, agentLabel as O, ACCENT_RE as P, allPrefs as Q, normalizeAccent as R, readHookPayload as S, TMUX_SOCKET as St, agentBadge as T, run$1 as Tt, publish as U, pushPublicKey as V, publishJson as W, withLock as X, swr as Y, agentChoices as Z, sendToSession as _, toolById as _t, ensureTmuxServer as a, setSetting as at, tmuxWasStarted as b, get as bt, killSession as c, ghKnownHosts as ct, listSessions as d, setupPath as dt, enabledAgents as et, markTmuxStarted as f, which as ft, renameSession as g, agentLabel$1 as gt, panePids as h, agentById as ht, disposeSessions as i, setPref as it, setAgentPhase as j, agentMeta as k, killWorkspaceSessions as l, miseInstalls as lt, notifySessionsChanged as m, TOOLS as mt, clearTmuxStarted as n, preferredAgent as nt, forgetPanes as o, discoverAgents as ot, newSessionArgs as p, DEFAULT_GITHUB_HOST as pt, subscriberJoins as q, createSession as r, setDisabledAgents as rt, getSession as s, doctor as st, cleanEnv as t, getSetting as tt, listPanes as u, miseVersions as ut, sessionStates as v, all as vt, blankRow as w, git as wt, AGENTS as x, workspacePath as xt, tmuxName as y, db as yt, setInstance as z };