@polderlabs/bizar-omp 0.4.8 → 0.4.9

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 (64) hide show
  1. package/README.md +52 -3
  2. package/dist/cli/agents-ink.d.ts.map +1 -1
  3. package/dist/cli/agents-ink.js +54 -18
  4. package/dist/cli/agents-ink.js.map +1 -1
  5. package/dist/cli/agents.d.ts.map +1 -1
  6. package/dist/cli/agents.js +15 -13
  7. package/dist/cli/agents.js.map +1 -1
  8. package/dist/cli/directory-selector.d.ts.map +1 -1
  9. package/dist/cli/directory-selector.js +3 -1
  10. package/dist/cli/directory-selector.js.map +1 -1
  11. package/dist/cli/doctor.d.ts +6 -0
  12. package/dist/cli/doctor.d.ts.map +1 -1
  13. package/dist/cli/doctor.js +17 -1
  14. package/dist/cli/doctor.js.map +1 -1
  15. package/dist/cli/main.js +0 -0
  16. package/dist/cli/omb-daemon.d.ts +2 -0
  17. package/dist/cli/omb-daemon.d.ts.map +1 -0
  18. package/dist/cli/omb-daemon.js +113 -0
  19. package/dist/cli/omb-daemon.js.map +1 -0
  20. package/dist/cli/omb-dashboard.d.ts +12 -0
  21. package/dist/cli/omb-dashboard.d.ts.map +1 -0
  22. package/dist/cli/omb-dashboard.js +103 -0
  23. package/dist/cli/omb-dashboard.js.map +1 -0
  24. package/dist/cli/omb.js +8 -0
  25. package/dist/cli/omb.js.map +1 -1
  26. package/dist/cli/process.d.ts.map +1 -1
  27. package/dist/cli/process.js +5 -1
  28. package/dist/cli/process.js.map +1 -1
  29. package/dist/cli/setup-ui.js +1 -1
  30. package/dist/cli/setup-ui.js.map +1 -1
  31. package/dist/extension.d.ts.map +1 -1
  32. package/dist/extension.js +51 -0
  33. package/dist/extension.js.map +1 -1
  34. package/dist/omp/daemon-service.d.ts +24 -0
  35. package/dist/omp/daemon-service.d.ts.map +1 -0
  36. package/dist/omp/daemon-service.js +272 -0
  37. package/dist/omp/daemon-service.js.map +1 -0
  38. package/dist/omp/daemon.d.ts +48 -0
  39. package/dist/omp/daemon.d.ts.map +1 -0
  40. package/dist/omp/daemon.js +193 -0
  41. package/dist/omp/daemon.js.map +1 -0
  42. package/dist/omp/dashboard-html.d.ts +9 -0
  43. package/dist/omp/dashboard-html.d.ts.map +1 -0
  44. package/dist/omp/dashboard-html.js +594 -0
  45. package/dist/omp/dashboard-html.js.map +1 -0
  46. package/dist/omp/model-role-assignment.d.ts +3 -0
  47. package/dist/omp/model-role-assignment.d.ts.map +1 -1
  48. package/dist/omp/model-role-assignment.js +28 -6
  49. package/dist/omp/model-role-assignment.js.map +1 -1
  50. package/dist/omp/omb-sessions.d.ts +47 -2
  51. package/dist/omp/omb-sessions.d.ts.map +1 -1
  52. package/dist/omp/omb-sessions.js +236 -108
  53. package/dist/omp/omb-sessions.js.map +1 -1
  54. package/dist/omp/session-activity.d.ts +71 -0
  55. package/dist/omp/session-activity.d.ts.map +1 -0
  56. package/dist/omp/session-activity.js +361 -0
  57. package/dist/omp/session-activity.js.map +1 -0
  58. package/dist/omp/tmux.d.ts +24 -0
  59. package/dist/omp/tmux.d.ts.map +1 -1
  60. package/dist/omp/tmux.js +168 -49
  61. package/dist/omp/tmux.js.map +1 -1
  62. package/docs/compatibility/baseline.json +1 -1
  63. package/docs/releases/0.4.9.md +6 -0
  64. package/package.json +1 -1
@@ -38,11 +38,11 @@ export const BIZAR_ROLE_PROFILES = [
38
38
  { role: "bizar_research", purpose: "evidence-grounded investigation", preference: "balanced", minContextWindow: 128_000, requiresReasoning: true },
39
39
  { role: "bizar_plan", purpose: "dependencies and acceptance planning", preference: "strong", minContextWindow: 128_000, requiresReasoning: true },
40
40
  { role: "bizar_architect", purpose: "cross-component design and tradeoffs", preference: "strong", minContextWindow: 128_000, requiresReasoning: true },
41
- { role: "bizar_build", purpose: "focused implementation", preference: "balanced", minContextWindow: 64_000, requiresReasoning: true },
41
+ { role: "bizar_build", purpose: "focused implementation", preference: "balanced", minContextWindow: 64_000, requiresReasoning: true, providerPreference: "local" },
42
42
  { role: "bizar_review", purpose: "independent correctness review", preference: "strong", minContextWindow: 128_000, requiresReasoning: true, preferDistinctFrom: "bizar_build" },
43
43
  { role: "bizar_security", purpose: "security and trust-boundary review", preference: "strong", minContextWindow: 128_000, requiresReasoning: true, preferDistinctFrom: "bizar_build" },
44
- { role: "bizar_verify", purpose: "reproducible checks and evidence", preference: "fast", minContextWindow: 32_000, requiresReasoning: true },
45
- { role: "bizar_docs", purpose: "documentation and release alignment", preference: "fast", minContextWindow: 32_000, requiresReasoning: false },
44
+ { role: "bizar_verify", purpose: "reproducible checks and evidence", preference: "fast", minContextWindow: 32_000, requiresReasoning: true, providerPreference: "local" },
45
+ { role: "bizar_docs", purpose: "documentation and release alignment", preference: "fast", minContextWindow: 32_000, requiresReasoning: false, providerPreference: "local" },
46
46
  ];
47
47
  /**
48
48
  * Kept as a small compatibility fallback for older OMP hosts that do not expose
@@ -78,17 +78,39 @@ const maxThinkingRank = (model) => {
78
78
  return Math.max(0, ...thinkingLevels(model.thinking).map(level => THINKING_LEVELS.indexOf(level)));
79
79
  };
80
80
  const hourlyCost = (model) => (model.cost?.input ?? 0) + (model.cost?.output ?? 0);
81
+ /**
82
+ * Providers that serve models from the local machine. Used to bias role
83
+ * assignment: locally hosted models cost nothing per token and keep work
84
+ * on-device, but they must never disqualify a capable cloud fallback.
85
+ */
86
+ const LOCAL_PROVIDERS = {
87
+ "llama.cpp": true,
88
+ llamacpp: true,
89
+ ollama: true,
90
+ lmstudio: true,
91
+ "lm-studio": true,
92
+ vllm: true,
93
+ jan: true,
94
+ gpt4all: true,
95
+ };
96
+ export function isLocalModel(model) {
97
+ return LOCAL_PROVIDERS[model.provider.toLowerCase()] === true;
98
+ }
81
99
  function qualityScore(model, profile) {
82
100
  const context = Math.min(2, Math.log10(Math.max(1, model.contextWindow ?? 0)) / 6);
83
101
  const output = Math.min(1, Math.log10(Math.max(1, model.maxTokens ?? 0)) / 6);
84
102
  const reasoning = model.reasoning ? 1 : 0;
85
103
  const thinking = maxThinkingRank(model) / 5;
86
104
  const costPenalty = Math.min(1, Math.log10(1 + hourlyCost(model)) / 3);
105
+ // A role may prefer locally hosted models (free per token, on-device).
106
+ // The bonus is additive and opt-in per profile: a local model that fits
107
+ // overtakes comparable cloud models, while a mismatch still falls back.
108
+ const providerBias = profile.providerPreference === "local" && isLocalModel(model) ? 0.15 : 0;
87
109
  if (profile.preference === "fast")
88
- return context * 0.2 + output * 0.1 + reasoning * 0.2 + thinking * 0.1 - costPenalty * 0.4;
110
+ return providerBias + context * 0.2 + output * 0.1 + reasoning * 0.2 + thinking * 0.1 - costPenalty * 0.4;
89
111
  if (profile.preference === "strong")
90
- return context * 0.25 + output * 0.15 + reasoning * 0.3 + thinking * 0.3 - costPenalty * 0.05;
91
- return context * 0.25 + output * 0.15 + reasoning * 0.25 + thinking * 0.2 - costPenalty * 0.2;
112
+ return providerBias + context * 0.25 + output * 0.15 + reasoning * 0.3 + thinking * 0.3 - costPenalty * 0.05;
113
+ return providerBias + context * 0.25 + output * 0.15 + reasoning * 0.25 + thinking * 0.2 - costPenalty * 0.2;
92
114
  }
93
115
  function familyOf(query, model) {
94
116
  return query.family?.(model) ?? model.provider.toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"model-role-assignment.js","sourceRoot":"","sources":["../../src/omp/model-role-assignment.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model-role-assignment.js","sourceRoot":"","sources":["../../src/omp/model-role-assignment.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,29 @@
1
+ import { type OmbSessionActivity } from "./session-activity.js";
1
2
  export declare const BIZAR_SESSION_PREFIX = "bizar-";
2
- export type OmbSessionState = "attached" | "detached" | "dead";
3
+ /**
4
+ * Connection and activity state of one Bizar-owned session.
5
+ *
6
+ * `working` and `waiting` describe what the agent is doing, `connected` and
7
+ * `disconnected` describe whether an interactive client is attached to an idle
8
+ * session, and `stopped` means no host is observed and the journal is silent.
9
+ */
10
+ export type OmbSessionState = "working" | "waiting" | "connected" | "disconnected" | "stopped";
3
11
  export interface OmbSessionInfo {
4
12
  name: string;
5
13
  cwd: string;
6
14
  project: string;
7
15
  id: string;
8
16
  state: OmbSessionState;
17
+ /** Privacy-safe live activity, when the session journal exposes it. */
18
+ activity?: OmbSessionActivity;
19
+ /**
20
+ * True when tmux currently hosts this session.
21
+ *
22
+ * A live OMP process whose host `omb` never created, or whose host died
23
+ * while the agent kept working, has no attachable tmux session. Absent for
24
+ * synthetic records, which are treated as hosted.
25
+ */
26
+ hosted?: boolean;
9
27
  command: string;
10
28
  pid: string;
11
29
  /** Native OMP session id, when its journal is available. */
@@ -19,12 +37,39 @@ export interface OmbSessionInfo {
19
37
  createdAt?: number;
20
38
  lastAttachedAt?: number;
21
39
  }
40
+ export interface ListOmbSessionsOptions {
41
+ /** Include Bizar sessions whose tmux host exited and whose journal is silent. Defaults to false. */
42
+ includeStopped?: boolean;
43
+ }
22
44
  /** Keep native OMP journals separate so each durable `omb` host has one exact session. */
23
45
  export declare function ombSessionDir(session: string, env?: NodeJS.ProcessEnv): string;
24
46
  /** Native OMP title first, then a deterministic prompt/project fallback. */
25
47
  export declare function ombSessionDisplayName(session: Pick<OmbSessionInfo, "project" | "id" | "nativeName" | "firstMessage" | "nativeSessionAvailable">): string;
48
+ /**
49
+ * Resolve the tmux-compatible multiplexer binary. `BIZAR_TMUX_BIN` always
50
+ * wins. On Windows, psmux is the supported native multiplexer (it ships a
51
+ * `tmux` command alias, but resolving `tmux` on PATH could pick unrelated
52
+ * binaries), so prefer `psmux` and fall back to the generic `tmux` name;
53
+ * elsewhere the standard `tmux` binary is used.
54
+ */
55
+ export declare function resolveMultiplexerBin(env?: NodeJS.ProcessEnv): string;
56
+ /**
57
+ * Resolve the hub state from tmux liveness, client attachment, and journal
58
+ * activity.
59
+ *
60
+ * Work wins over attachment: a detached client must never hide an agent that
61
+ * is still processing, which is the failure this hub exists to prevent.
62
+ * `waiting` refines an attached session that finished its turn, `connected`
63
+ * covers an attached session with no structured activity yet, and
64
+ * `disconnected` covers a live session with no client and no work in flight.
65
+ */
66
+ export declare function ombSessionState(input: {
67
+ dead: boolean;
68
+ attached: boolean;
69
+ activity?: OmbSessionActivity;
70
+ }): OmbSessionState;
26
71
  /** Discover Bizar-owned tmux sessions without touching unrelated tmux sessions. */
27
- export declare function listOmbSessions(cwd?: string, env?: NodeJS.ProcessEnv): Promise<OmbSessionInfo[]>;
72
+ export declare function listOmbSessions(cwd?: string, env?: NodeJS.ProcessEnv, options?: ListOmbSessionsOptions): Promise<OmbSessionInfo[]>;
28
73
  /** Return the most recently attached live session for one exact project path. */
29
74
  export declare function findLastOmbSession(cwd: string, env?: NodeJS.ProcessEnv): Promise<OmbSessionInfo | undefined>;
30
75
  //# sourceMappingURL=omb-sessions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"omb-sessions.d.ts","sourceRoot":"","sources":["../../src/omp/omb-sessions.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAUD,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAG3F;AAoID,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,IAAI,GAAG,YAAY,GAAG,cAAc,GAAG,wBAAwB,CAAC,GAAG,MAAM,CAOxJ;AAsCD,mFAAmF;AACnF,wBAAsB,eAAe,CACnC,GAAG,SAAgB,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,cAAc,EAAE,CAAC,CAwD3B;AAED,iFAAiF;AACjF,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAKrC"}
1
+ {"version":3,"file":"omb-sessions.d.ts","sourceRoot":"","sources":["../../src/omp/omb-sessions.ts"],"names":[],"mappings":"AAIA,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAK7C;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,SAAS,CAAC;AAE/F,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,oGAAoG;IACpG,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA2BD,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE3F;AAuJD,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,IAAI,GAAG,YAAY,GAAG,cAAc,GAAG,wBAAwB,CAAC,GAAG,MAAM,CAOxJ;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGlF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,eAAe,CAM3H;AAkKD,mFAAmF;AACnF,wBAAsB,eAAe,CACnC,GAAG,SAAgB,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,cAAc,EAAE,CAAC,CAkB3B;AAED,iFAAiF;AACjF,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAOrC"}
@@ -1,12 +1,18 @@
1
1
  import { spawn } from "node:child_process";
2
- import { readdir, readFile } from "node:fs/promises";
2
+ import { readdir, stat } from "node:fs/promises";
3
3
  import { basename, join, relative, resolve } from "node:path";
4
4
  import { homedir, tmpdir } from "node:os";
5
+ import { deriveSessionActivity, listSessionJournals, readJournalHead, readJournalTail, } from "./session-activity.js";
5
6
  export const BIZAR_SESSION_PREFIX = "bizar-";
7
+ /** Most recent stopped sessions to surface when stopped sessions are enabled. */
8
+ const STOPPED_SESSION_LIMIT = 6;
9
+ function nativeSessionRoot(env) {
10
+ const stateHome = env.XDG_STATE_HOME || join(env.HOME || homedir(), ".local", "state");
11
+ return join(stateHome, "bizar-omp", "native-sessions");
12
+ }
6
13
  /** Keep native OMP journals separate so each durable `omb` host has one exact session. */
7
14
  export function ombSessionDir(session, env = process.env) {
8
- const stateHome = env.XDG_STATE_HOME || join(env.HOME || homedir(), ".local", "state");
9
- return join(stateHome, "bizar-omp", "native-sessions", session);
15
+ return join(nativeSessionRoot(env), session);
10
16
  }
11
17
  function ompAgentDir(env) {
12
18
  if (env.PI_CODING_AGENT_DIR)
@@ -38,86 +44,101 @@ function cleanText(value) {
38
44
  .trim();
39
45
  return cleaned || undefined;
40
46
  }
41
- async function readNativeSessionFile(file) {
42
- try {
43
- const content = await readFile(file, "utf8");
44
- const lines = content.split("\n");
45
- const header = JSON.parse(lines[0] || "");
46
- if (header.type !== "session")
47
- return undefined;
48
- let firstMessage;
49
- let latestTitle = cleanText(header.title);
50
- for (const line of lines.slice(1)) {
51
- if (!line.trim())
52
- continue;
53
- try {
54
- const entry = JSON.parse(line);
55
- if (entry.type === "title" || entry.type === "title_change")
56
- latestTitle = cleanText(entry.title) || latestTitle;
57
- if (!firstMessage && entry.type === "message" && entry.message && typeof entry.message === "object") {
58
- const message = entry.message;
59
- if (message.role === "user") {
60
- if (typeof message.content === "string")
61
- firstMessage = cleanText(message.content);
62
- else if (Array.isArray(message.content)) {
63
- const text = message.content
64
- .filter(item => typeof item === "object" && item !== null && item.type === "text")
65
- .map(item => item.text)
66
- .filter((item) => typeof item === "string")
67
- .join(" ");
68
- firstMessage = cleanText(text);
69
- }
70
- }
71
- }
72
- }
73
- catch {
74
- // A partially written final JSONL line should not hide a valid header/title.
75
- }
47
+ function asRecord(value) {
48
+ return typeof value === "object" && value !== null ? value : undefined;
49
+ }
50
+ /**
51
+ * Parse one journal's session header, title, and first user prompt.
52
+ *
53
+ * Current journals open with a `title` entry that is rewritten in place, so
54
+ * the session header is the first `session` entry rather than the first line.
55
+ */
56
+ async function readNativeSessionFile(journal) {
57
+ const content = await readJournalHead(journal);
58
+ if (!content)
59
+ return undefined;
60
+ let header;
61
+ const entries = [];
62
+ for (const line of content.split("\n")) {
63
+ const trimmed = line.trim();
64
+ if (!trimmed || trimmed[0] !== "{")
65
+ continue;
66
+ let entry;
67
+ try {
68
+ entry = JSON.parse(trimmed);
69
+ }
70
+ catch {
71
+ // A partially written final line must not hide the entries before it.
72
+ continue;
73
+ }
74
+ if (!header && entry.type === "session") {
75
+ header = entry;
76
+ continue;
76
77
  }
77
- const timestamp = typeof header.timestamp === "string" ? Date.parse(header.timestamp) : NaN;
78
- return {
79
- id: cleanText(header.id),
80
- title: latestTitle,
81
- cwd: cleanText(header.cwd),
82
- firstMessage,
83
- createdAt: Number.isFinite(timestamp) ? Math.floor(timestamp / 1000) : undefined,
84
- };
78
+ entries.push(entry);
85
79
  }
86
- catch {
80
+ if (!header)
87
81
  return undefined;
82
+ let latestTitle = cleanText(header.title);
83
+ let firstMessage;
84
+ for (const entry of entries) {
85
+ if (entry.type === "title" || entry.type === "title_change")
86
+ latestTitle = cleanText(entry.title) || latestTitle;
87
+ if (firstMessage || entry.type !== "message")
88
+ continue;
89
+ const message = asRecord(entry.message);
90
+ if (message?.role !== "user")
91
+ continue;
92
+ if (typeof message.content === "string")
93
+ firstMessage = cleanText(message.content);
94
+ else if (Array.isArray(message.content)) {
95
+ firstMessage = cleanText(message.content
96
+ .filter(item => asRecord(item)?.type === "text")
97
+ .map(item => asRecord(item)?.text)
98
+ .filter((item) => typeof item === "string")
99
+ .join(" "));
100
+ }
88
101
  }
102
+ const timestamp = typeof header.timestamp === "string" ? Date.parse(header.timestamp) : NaN;
103
+ return {
104
+ id: cleanText(header.id),
105
+ title: latestTitle,
106
+ cwd: cleanText(header.cwd),
107
+ firstMessage,
108
+ createdAt: Number.isFinite(timestamp) ? Math.floor(timestamp / 1000) : undefined,
109
+ };
89
110
  }
90
- async function readNativeSessionMetadata(sessionDir) {
91
- let files;
92
- try {
93
- files = (await readdir(sessionDir, { withFileTypes: true }))
94
- .filter(entry => entry.isFile() && entry.name.endsWith(".jsonl"))
95
- .map(entry => join(sessionDir, entry.name));
96
- }
97
- catch {
98
- return undefined;
111
+ /** Metadata plus live activity for a Bizar-owned native session directory. */
112
+ async function readNativeSessionSnapshot(sessionDir, now) {
113
+ const journals = await listSessionJournals(sessionDir);
114
+ const newest = journals.at(-1);
115
+ if (!newest)
116
+ return {};
117
+ const [entries, modifiedAt, ...candidates] = await Promise.all([
118
+ readJournalTail(newest),
119
+ stat(newest).then(file => file.mtimeMs).catch(() => undefined),
120
+ ...journals.slice(-3).reverse().map(journal => readNativeSessionFile(journal)),
121
+ ]);
122
+ let metadata;
123
+ for (const candidate of candidates) {
124
+ if (candidate) {
125
+ metadata = candidate;
126
+ break;
127
+ }
99
128
  }
100
- const candidates = await Promise.all(files.map(async (file) => ({ file, metadata: await readNativeSessionFile(file) })));
101
- const valid = candidates.filter((candidate) => Boolean(candidate.metadata));
102
- if (valid.length === 0)
103
- return undefined;
104
- valid.sort((a, b) => a.file.localeCompare(b.file));
105
- return valid.at(-1)?.metadata;
129
+ return {
130
+ metadata,
131
+ activity: entries.length > 0 ? deriveSessionActivity(entries, { now, fallbackUpdatedAt: modifiedAt }) : undefined,
132
+ };
106
133
  }
107
134
  async function readLegacyNativeSessionMetadata(cwd, sessionCreatedAt, env) {
108
135
  const sessionDir = defaultOmpSessionDir(cwd, env);
109
- let files;
110
- try {
111
- files = (await readdir(sessionDir, { withFileTypes: true }))
112
- .filter(entry => entry.isFile() && entry.name.endsWith(".jsonl"))
113
- .map(entry => join(sessionDir, entry.name));
114
- }
115
- catch {
136
+ const journals = await listSessionJournals(sessionDir);
137
+ if (journals.length === 0)
116
138
  return undefined;
117
- }
118
- const candidates = (await Promise.all(files.map(async (file) => {
119
- const metadata = await readNativeSessionFile(file);
120
- return metadata ? { file, metadata } : undefined;
139
+ const candidates = (await Promise.all(journals.map(async (journal) => {
140
+ const metadata = await readNativeSessionFile(journal);
141
+ return metadata ? { journal, metadata } : undefined;
121
142
  }))).filter((candidate) => Boolean(candidate));
122
143
  if (candidates.length === 0)
123
144
  return undefined;
@@ -154,6 +175,45 @@ export function ombSessionDisplayName(session) {
154
175
  return `New ${session.project} session`;
155
176
  return `${session.project}/${session.id || "main"}`;
156
177
  }
178
+ /**
179
+ * Resolve the tmux-compatible multiplexer binary. `BIZAR_TMUX_BIN` always
180
+ * wins. On Windows, psmux is the supported native multiplexer (it ships a
181
+ * `tmux` command alias, but resolving `tmux` on PATH could pick unrelated
182
+ * binaries), so prefer `psmux` and fall back to the generic `tmux` name;
183
+ * elsewhere the standard `tmux` binary is used.
184
+ */
185
+ export function resolveMultiplexerBin(env = process.env) {
186
+ if (env.BIZAR_TMUX_BIN)
187
+ return env.BIZAR_TMUX_BIN;
188
+ return process.platform === "win32" ? "psmux" : "tmux";
189
+ }
190
+ /**
191
+ * Resolve the hub state from tmux liveness, client attachment, and journal
192
+ * activity.
193
+ *
194
+ * Work wins over attachment: a detached client must never hide an agent that
195
+ * is still processing, which is the failure this hub exists to prevent.
196
+ * `waiting` refines an attached session that finished its turn, `connected`
197
+ * covers an attached session with no structured activity yet, and
198
+ * `disconnected` covers a live session with no client and no work in flight.
199
+ */
200
+ export function ombSessionState(input) {
201
+ if (input.dead)
202
+ return "stopped";
203
+ const activity = input.activity;
204
+ if (activity && activity.phase !== "unknown" && !activity.awaitingInput)
205
+ return "working";
206
+ if (!input.attached)
207
+ return "disconnected";
208
+ return activity?.awaitingInput ? "waiting" : "connected";
209
+ }
210
+ const STATE_RANK = {
211
+ working: 0,
212
+ waiting: 1,
213
+ connected: 2,
214
+ disconnected: 3,
215
+ stopped: 4,
216
+ };
157
217
  function exitCode(code, signal) {
158
218
  if (code !== null)
159
219
  return code;
@@ -165,7 +225,15 @@ function readTmux(command, args, cwd, env) {
165
225
  child.stdout?.setEncoding("utf8");
166
226
  child.stdout?.on("data", chunk => { output += chunk; });
167
227
  return new Promise((resolve, reject) => {
168
- child.once("error", reject);
228
+ // A missing multiplexer binary means "no sessions", not a crash:
229
+ // discovery callers treat any nonzero code as an empty listing. Any
230
+ // other spawn failure (EACCES, EPERM, ...) is still a hard error.
231
+ child.once("error", (error) => {
232
+ if (error.code === "ENOENT" || error.code === "EINVAL")
233
+ resolve({ code: 127, output: "" });
234
+ else
235
+ reject(error);
236
+ });
169
237
  child.once("close", (code, signal) => resolve({ code: exitCode(code, signal), output }));
170
238
  });
171
239
  }
@@ -173,6 +241,11 @@ function sessionId(name) {
173
241
  const match = name.match(/-[a-f0-9]{10}(?:-(.*))?$/);
174
242
  return match?.[1] || "main";
175
243
  }
244
+ /** Project slug encoded in the Bizar session name, without the digest. */
245
+ function sessionProject(name) {
246
+ const trimmed = name.slice(BIZAR_SESSION_PREFIX.length);
247
+ return trimmed.replace(/-[a-f0-9]{10}(?:-.*)?$/, "") || trimmed || "session";
248
+ }
176
249
  function parsePane(output) {
177
250
  const [dead, cwd, command, pid] = output.trim().split("\t");
178
251
  return {
@@ -182,14 +255,8 @@ function parsePane(output) {
182
255
  pid: pid || "?",
183
256
  };
184
257
  }
185
- /** Discover Bizar-owned tmux sessions without touching unrelated tmux sessions. */
186
- export async function listOmbSessions(cwd = process.cwd(), env = process.env) {
187
- const tmux = env.BIZAR_TMUX_BIN || "tmux";
188
- const childEnv = { ...env, BIZAR_OMP_NO_TMUX: "1" };
189
- const sessions = await readTmux(tmux, ["list-sessions", "-F", "#{session_name}\t#{session_created}\t#{session_last_attached}\t#{session_attached}"], cwd, childEnv);
190
- if (sessions.code !== 0)
191
- return [];
192
- const names = sessions.output
258
+ function parseSessionList(output) {
259
+ return output
193
260
  .split("\n")
194
261
  .map(line => line.trim())
195
262
  .filter(Boolean)
@@ -201,38 +268,99 @@ export async function listOmbSessions(cwd = process.cwd(), env = process.env) {
201
268
  lastAttachedAt: Number.isFinite(Number(parts[2])) ? Number(parts[2]) : undefined,
202
269
  attached: parts[3] !== "0",
203
270
  }));
204
- const records = await Promise.all(names.map(async (session) => {
205
- const pane = await readTmux(tmux, ["list-panes", "-t", session.name, "-F", "#{pane_dead}\t#{pane_current_path}\t#{pane_current_command}\t#{pane_pid}"], cwd, childEnv);
206
- const details = parsePane(pane.output);
207
- const nativeDir = ombSessionDir(session.name, env);
208
- const native = await readNativeSessionMetadata(nativeDir);
209
- const legacyNative = native ?? await readLegacyNativeSessionMetadata(details.cwd, session.createdAt, env);
210
- return {
211
- name: session.name,
212
- cwd: details.cwd,
213
- project: details.cwd === "?" ? session.name.slice(BIZAR_SESSION_PREFIX.length) : basename(details.cwd),
214
- id: sessionId(session.name),
215
- state: details.dead ? "dead" : session.attached ? "attached" : "detached",
216
- command: details.command,
217
- pid: details.pid,
218
- nativeId: legacyNative?.id,
219
- nativeName: legacyNative?.title,
220
- firstMessage: legacyNative?.firstMessage,
221
- nativeSessionAvailable: Boolean(native || legacyNative),
222
- createdAt: session.createdAt,
223
- lastAttachedAt: session.lastAttachedAt,
224
- };
225
- }));
226
- return records.sort((a, b) => {
227
- const stateRank = (state) => state === "dead" ? 2 : state === "attached" ? 0 : 1;
228
- return stateRank(a.state) - stateRank(b.state) || a.project.localeCompare(b.project) || a.name.localeCompare(b.name);
271
+ }
272
+ function sessionRecord(name, fields) {
273
+ return {
274
+ name,
275
+ project: fields.cwd === "?" ? sessionProject(name) : basename(fields.cwd),
276
+ id: sessionId(name),
277
+ ...fields,
278
+ };
279
+ }
280
+ async function describeLiveSession(tmux, session, cwd, childEnv, env, now) {
281
+ const pane = await readTmux(tmux, ["list-panes", "-t", session.name, "-F", "#{pane_dead}\t#{pane_current_path}\t#{pane_current_command}\t#{pane_pid}"], cwd, childEnv);
282
+ const details = parsePane(pane.output);
283
+ const nativeDir = ombSessionDir(session.name, env);
284
+ const snapshot = await readNativeSessionSnapshot(nativeDir, now);
285
+ const native = snapshot.metadata ?? await readLegacyNativeSessionMetadata(details.cwd, session.createdAt, env);
286
+ return sessionRecord(session.name, {
287
+ cwd: details.cwd,
288
+ state: ombSessionState({ dead: details.dead, attached: session.attached, activity: snapshot.activity }),
289
+ activity: snapshot.activity,
290
+ hosted: true,
291
+ command: details.command,
292
+ pid: details.pid,
293
+ nativeId: native?.id,
294
+ nativeName: native?.title,
295
+ firstMessage: native?.firstMessage,
296
+ nativeSessionAvailable: Boolean(snapshot.metadata || native),
297
+ createdAt: session.createdAt ?? native?.createdAt,
298
+ lastAttachedAt: session.lastAttachedAt,
229
299
  });
230
300
  }
301
+ /**
302
+ * Bizar sessions that tmux no longer hosts.
303
+ *
304
+ * tmux removes a session as soon as its pane exits, so a terminated session
305
+ * only remains discoverable through the native state directory that `omb`
306
+ * gives every durable host. A journal written inside the stale window proves
307
+ * the agent is still running — a host started outside `omb`, or one whose pane
308
+ * died while the agent kept working — so those sessions stay live instead of
309
+ * being reported as stopped.
310
+ */
311
+ async function listUnhostedSessions(env, liveNames, now) {
312
+ let entries;
313
+ try {
314
+ entries = await readdir(nativeSessionRoot(env), { withFileTypes: true });
315
+ }
316
+ catch {
317
+ return [];
318
+ }
319
+ const unhosted = (await Promise.all(entries.map(async (entry) => {
320
+ if (!entry.isDirectory() || !entry.name.startsWith(BIZAR_SESSION_PREFIX) || liveNames.has(entry.name))
321
+ return undefined;
322
+ const snapshot = await readNativeSessionSnapshot(join(nativeSessionRoot(env), entry.name), now);
323
+ const activity = snapshot.activity;
324
+ const alive = Boolean(activity && !activity.stale);
325
+ return sessionRecord(entry.name, {
326
+ cwd: snapshot.metadata?.cwd ?? "?",
327
+ state: alive ? ombSessionState({ dead: false, attached: false, activity }) : "stopped",
328
+ activity,
329
+ hosted: false,
330
+ command: alive ? "unattached" : "exited",
331
+ pid: "?",
332
+ nativeId: snapshot.metadata?.id,
333
+ nativeName: snapshot.metadata?.title,
334
+ firstMessage: snapshot.metadata?.firstMessage,
335
+ nativeSessionAvailable: Boolean(snapshot.metadata),
336
+ createdAt: snapshot.metadata?.createdAt,
337
+ });
338
+ }))).filter((session) => Boolean(session));
339
+ unhosted.sort((a, b) => (b.activity?.updatedAt ?? 0) - (a.activity?.updatedAt ?? 0));
340
+ const live = unhosted.filter(session => session.state !== "stopped");
341
+ return [...live, ...unhosted.filter(session => session.state === "stopped").slice(0, STOPPED_SESSION_LIMIT)];
342
+ }
343
+ /** Discover Bizar-owned tmux sessions without touching unrelated tmux sessions. */
344
+ export async function listOmbSessions(cwd = process.cwd(), env = process.env, options = {}) {
345
+ const tmux = resolveMultiplexerBin(env);
346
+ const childEnv = { ...env, BIZAR_OMP_NO_TMUX: "1" };
347
+ const now = Date.now();
348
+ const sessions = await readTmux(tmux, ["list-sessions", "-F", "#{session_name}\t#{session_created}\t#{session_last_attached}\t#{session_attached}"], cwd, childEnv);
349
+ const live = sessions.code === 0 ? parseSessionList(sessions.output) : [];
350
+ const records = await Promise.all(live.map(session => describeLiveSession(tmux, session, cwd, childEnv, env, now)));
351
+ const unhosted = await listUnhostedSessions(env, new Set(live.map(session => session.name)), now);
352
+ const stopped = options.includeStopped ? unhosted.filter(session => session.state === "stopped") : [];
353
+ return [...records, ...unhosted.filter(session => session.state !== "stopped"), ...stopped].sort((a, b) => STATE_RANK[a.state] - STATE_RANK[b.state] ||
354
+ a.project.localeCompare(b.project) ||
355
+ a.name.localeCompare(b.name));
356
+ }
231
357
  /** Return the most recently attached live session for one exact project path. */
232
358
  export async function findLastOmbSession(cwd, env = process.env) {
233
359
  const sessions = await listOmbSessions(cwd, env);
234
360
  return sessions
235
- .filter(session => session.cwd === cwd && session.state !== "dead")
361
+ // Only a session tmux still hosts can be reattached. Resuming a live but
362
+ // unhosted session would put a second writer on its journal.
363
+ .filter(session => session.cwd === cwd && session.state !== "stopped" && session.hosted !== false)
236
364
  .sort((a, b) => (b.lastAttachedAt ?? b.createdAt ?? 0) - (a.lastAttachedAt ?? a.createdAt ?? 0))[0];
237
365
  }
238
366
  //# sourceMappingURL=omb-sessions.js.map