@polderlabs/bizar-omp 0.4.0 → 0.4.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.
- package/README.md +38 -12
- package/dist/cli/agents-ink.d.ts +22 -0
- package/dist/cli/agents-ink.d.ts.map +1 -0
- package/dist/cli/agents-ink.js +177 -0
- package/dist/cli/agents-ink.js.map +1 -0
- package/dist/cli/agents.d.ts +14 -0
- package/dist/cli/agents.d.ts.map +1 -0
- package/dist/cli/agents.js +198 -0
- package/dist/cli/agents.js.map +1 -0
- package/dist/cli/doctor.d.ts +4 -4
- package/dist/cli/install.d.ts +6 -2
- package/dist/cli/install.d.ts.map +1 -1
- package/dist/cli/install.js +21 -6
- package/dist/cli/install.js.map +1 -1
- package/dist/cli/main.js +15 -4
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/omb-invocation.d.ts +7 -0
- package/dist/cli/omb-invocation.d.ts.map +1 -0
- package/dist/cli/omb-invocation.js +27 -0
- package/dist/cli/omb-invocation.js.map +1 -0
- package/dist/cli/omb.js +19 -2
- package/dist/cli/omb.js.map +1 -1
- package/dist/extension.d.ts +3 -0
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +28 -4
- package/dist/extension.js.map +1 -1
- package/dist/omp/autonomous-settings.d.ts.map +1 -1
- package/dist/omp/autonomous-settings.js +6 -0
- package/dist/omp/autonomous-settings.js.map +1 -1
- package/dist/omp/compatibility.d.ts +5 -5
- package/dist/omp/compatibility.d.ts.map +1 -1
- package/dist/omp/compatibility.js +2 -2
- package/dist/omp/compatibility.js.map +1 -1
- package/dist/omp/model-role-assignment.d.ts +5 -0
- package/dist/omp/model-role-assignment.d.ts.map +1 -1
- package/dist/omp/model-role-assignment.js +18 -10
- package/dist/omp/model-role-assignment.js.map +1 -1
- package/dist/omp/omb-sessions.d.ts +30 -0
- package/dist/omp/omb-sessions.d.ts.map +1 -0
- package/dist/omp/omb-sessions.js +225 -0
- package/dist/omp/omb-sessions.js.map +1 -0
- package/dist/omp/omb-settings.d.ts +10 -0
- package/dist/omp/omb-settings.d.ts.map +1 -0
- package/dist/omp/omb-settings.js +34 -0
- package/dist/omp/omb-settings.js.map +1 -0
- package/dist/omp/tmux.d.ts +14 -3
- package/dist/omp/tmux.d.ts.map +1 -1
- package/dist/omp/tmux.js +133 -9
- package/dist/omp/tmux.js.map +1 -1
- package/docs/compatibility/baseline.json +28 -4
- package/docs/compatibility/supported-surfaces.json +30 -4
- package/docs/releases/0.4.1.md +13 -0
- package/docs/releases/0.4.2.md +9 -0
- package/docs/releases/native-stable.md +1 -1
- package/docs/releases/support-matrix.md +1 -1
- package/package.json +10 -2
- package/rules/bizar-native-omp.md +1 -0
- package/skills/bizar-omp/SKILL.md +8 -3
- package/skills/omp-native-development/SKILL.md +1 -1
- package/skills/omp-native-development/references/accuracy-and-versioning.md +2 -2
- package/skills/omp-native-development/references/source-manifest.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BizarHarness OMP
|
|
2
2
|
|
|
3
|
-
Release `0.4.
|
|
3
|
+
Release `0.4.2` is the current release target; it will be published on [npm](https://www.npmjs.com/package/@polderlabs/bizar-omp) and available as a [GitHub release](https://github.com/PolderLabsVOF/BizarHarness-OMP/releases/tag/v0.4.2) after the final release gate.
|
|
4
4
|
|
|
5
5
|
BizarHarness OMP is a ground-up, native [oh-my-pi](https://github.com/can1357/oh-my-pi) extension for engineering workflows. It owns workflow intent, acceptance contracts, evidence freshness, and integration admission. OMP owns sessions, models, credentials, tools, workers, isolation, and conversation state.
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ The package has no Claude Code, AO, Claude Agent SDK, MCP server, second worker
|
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
Requires Node 22+, Bun 1.3.14+, and OMP **18.2.
|
|
11
|
+
Requires Node 22+, Bun 1.3.14+, and OMP **18.2.6** on PATH (18.2.5 and 18.2.4 remain regression-qualified).
|
|
12
12
|
|
|
13
13
|
The recommended installation is through OMP's native plugin manager:
|
|
14
14
|
|
|
@@ -19,6 +19,14 @@ omp
|
|
|
19
19
|
|
|
20
20
|
This loads the extension, eight Bizar specialist agents, the default `bizar-omp` orientation skill plus specialized skills, rules, prompts, and the native model-role command. The main OMP session is the Bizar Orchestrator by default. Bizar also enables OMP's native Advisor and configures a visible `bizar_advisor` role for passive independent review. The skill explains Bizar's ownership boundaries, workflow/evidence tools, model-role command, and `omp` versus `omb` launcher contract. On session start, Bizar applies its autonomous OMP preset, enables background task execution, and enables steerable Collab. The ordinary `omp` command remains untouched; use `omb` when you want a durable tmux-backed host.
|
|
21
21
|
|
|
22
|
+
OMP's plugin manager owns the extension and all OMP-discoverable assets. It cannot place npm executables into your shell `PATH`, so `omb` and `bizar-omp` need the explicit all-in-one setup fallback:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npx --yes @polderlabs/bizar-omp@0.4.2 setup
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`setup` installs the exact package version globally for both commands, installs that same version through `omp plugin install`, applies the autonomous settings with a recoverable receipt, and leaves credentials and explicit user policies intact. If you only need the OMP extension, `omp plugin install @polderlabs/bizar-omp` remains the primary path.
|
|
29
|
+
|
|
22
30
|
The companion CLI is optional for diagnostics and repair:
|
|
23
31
|
|
|
24
32
|
```sh
|
|
@@ -27,11 +35,11 @@ bizar-omp install-doctor
|
|
|
27
35
|
omb
|
|
28
36
|
```
|
|
29
37
|
|
|
30
|
-
`bizar-omp install` remains available when a host-level repair is needed. The plugin path is the normal path and applies the same autonomous settings from the loaded extension. Worker patches are retained for explicit parent integration rather than automatically applied. Credentials, selected providers/models, explicit deny/prompt policies, and project overrides are preserved.
|
|
38
|
+
`bizar-omp install` remains available when a host-level repair is needed; `bizar-omp setup` is the one-command fallback when you need both the plugin and shell commands. The plugin path is the normal path and applies the same autonomous settings from the loaded extension. Worker patches are retained for explicit parent integration rather than automatically applied. Credentials, selected providers/models, explicit deny/prompt policies, and project overrides are preserved.
|
|
31
39
|
|
|
32
40
|
Use only in trusted projects. OMP extensions and shell commands are not an OS security sandbox. Review changes with `bizar-omp install --dry-run`; isolate configuration with `bizar-omp install --profile bizar`, then launch `omp --profile bizar`. A new profile needs its own OMP login/model configuration.
|
|
33
41
|
|
|
34
|
-
Restart OMP after plugin installation. `bizar-omp uninstall` removes the plugin
|
|
42
|
+
Restart OMP after plugin installation. `bizar-omp uninstall` removes the plugin installation created by the CLI installer and restores settings it changed, preserving later user edits. Add the same `--profile` for profile-scoped commands. The global package install supplies the `omb` and `bizar-omp` shell commands; the plugin itself is still installed and updated through `omp plugin install`.
|
|
35
43
|
|
|
36
44
|
## Development
|
|
37
45
|
|
|
@@ -44,7 +52,7 @@ npm run verify:package
|
|
|
44
52
|
|
|
45
53
|
Try the extension from the checkout with `omp --extension ./dist/extension.js`. For an installed package use `omp plugin link /path/to/bizaromp`; the `omp.extensions` manifest points at `dist/extension.js`.
|
|
46
54
|
|
|
47
|
-
The development contract is documented in `CONTRIBUTING.md`: work from feature branches, pass CI before merging to `main`, use Conventional Commits, and cut exact SemVer tags. CI runs on Node 22/24 and Bun 1.3.14, including packed-package and registry-plugin installation against OMP 18.2.
|
|
55
|
+
The development contract is documented in `CONTRIBUTING.md`: work from feature branches, pass CI before merging to `main`, use Conventional Commits, and cut exact SemVer tags. CI runs on Node 22/24 and Bun 1.3.14, including packed-package and registry-plugin installation against OMP 18.2.6. Repository-plan limitations currently prevent enforced GitHub branch protection. Tagged builds publish to npm through trusted publishing and create a GitHub release artifact; see [release setup](docs/releases/npm-publishing.md).
|
|
48
56
|
|
|
49
57
|
## Commands and tools
|
|
50
58
|
|
|
@@ -58,7 +66,7 @@ The main Orchestrator chooses the method tier automatically. Focused fixes use d
|
|
|
58
66
|
|
|
59
67
|
## Persistent agent sessions and the Agent Hub
|
|
60
68
|
|
|
61
|
-
OMP's native Agent Hub is the control surface for Bizar's background agents. With `async.enabled` enabled, task agents run in the background and can be inspected from the hub. Open
|
|
69
|
+
OMP's native Agent Hub is the control surface for Bizar's background agents. With `async.enabled` enabled, task agents run in the background and can be inspected from the hub. Bizar sets `display.pinnedAgents=full`, so every active task agent is visible in the live session as well as the hub. Open the hub with `Alt+A` or `Ctrl+S`; it can inspect live agents, open their transcripts, interrupt them, send follow-up instructions, and revive parked agents. Agent definitions and model roles are not running sessions: they appear in the hub only after the orchestrator actually spawns them, so installation does not waste model calls by starting every specialist.
|
|
62
70
|
|
|
63
71
|
For a session that must keep running after its visible terminal closes, start OMP with `omb`. `omb` starts the interactive OMP host inside a persistent tmux session from the first process. A terminal window is only the client; the host process is what owns the model turn and workers:
|
|
64
72
|
|
|
@@ -67,9 +75,27 @@ For a session that must keep running after its visible terminal closes, start OM
|
|
|
67
75
|
omb
|
|
68
76
|
```
|
|
69
77
|
|
|
70
|
-
`omp` remains the normal direct launcher and never starts, attaches to, or hands off to tmux. This separation keeps terminal ownership deterministic and prevents raw-mode probe responses from leaking between OMP processes. `omb`
|
|
78
|
+
`omp` remains the normal direct launcher and never starts, attaches to, or hands off to tmux. This separation keeps terminal ownership deterministic and prevents raw-mode probe responses from leaking between OMP processes. Plain `omb` reconnects to the most recently active live Bizar session in the current directory; if none exists, it creates the stable default session for that directory. The launcher enables tmux mouse mode before attaching, so wheel scrolling stays pane scrolling instead of becoming OMP prompt-history input. Inside an existing tmux session, `omb` runs OMP directly to avoid nested tmux clients. Noninteractive invocations such as `omb --print` also run directly.
|
|
79
|
+
|
|
80
|
+
Run multiple durable OMP conversations in the same project with a session id, or create a fresh generated session:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
omb new "Investigate the API timeout"
|
|
84
|
+
omb --session api-retries
|
|
85
|
+
omb --new
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`omb new` always creates a fresh session. `omb --session <id>` creates or reconnects to a named session, while plain `omb` returns to the latest active session for the current directory.
|
|
89
|
+
|
|
90
|
+
Use the cross-project session switcher to see every Bizar-owned host, attach to one, or dispatch a new host from an interactive prompt:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
omb agents
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The hub is a full-screen Ink TUI with a workspace rail, grouped live-session list, selected-session inspector, status counts, and modal Settings, Help, and Delete views. It remains keyboard-first: use Up/Down (or `j`/`k`) to select, Enter to attach, `n` to choose a project directory, task, and session name, `e` to rename, `d` to delete after confirmation, `s` to open Settings, `r` to refresh, `?` for help, and `q` to leave the hub. Settings persist the latest-session reconnect preference, mouse scrolling, and whether stopped sessions are shown. Each Bizar host gets an isolated native OMP session journal, so the hub shows OMP's configured or auto-generated session title. Before OMP has generated a title, it derives a stable label from the first task; the project/id remains visible as secondary identity. Sessions are identified by their project path and Bizar session id, so several sessions in one project remain independent. The hub only reads and controls tmux sessions created by Bizar; unrelated tmux sessions are not displayed or changed.
|
|
71
97
|
|
|
72
|
-
Run the objective in that host, then detach
|
|
98
|
+
Run the objective in that host, then use `Ctrl-d` or `Ctrl-c` to leave the client and return to the Bizar agents hub. Both keys are private to the Bizar tmux client, so they detach the view without sending EOF or interrupt input into OMP; the host and background work continue. The standard tmux sequence `Ctrl-b d` remains available too. Mouse scrolling is enabled by default and can be changed from Settings. If the host pane is already dead, the next `omb` detects it, respawns the host, and reconnects to the same project session. Closing the terminal window or detaching does not stop the tmux host. Bizar automatically enables `collab.autoStart=control` so the host is discoverable and steerable. Later, discover and reconnect to the live host:
|
|
73
99
|
|
|
74
100
|
```sh
|
|
75
101
|
omp collab list
|
|
@@ -79,18 +105,18 @@ omp join "<control-link>"
|
|
|
79
105
|
|
|
80
106
|
The joined OMP client receives the live transcript and Agent Hub roster. Press `Alt+A` or `Ctrl+S` to steer the running agents. Closing the joined client is safe; it only disconnects that guest. Use the project-specific session shown by `tmux ls` to return to the original host, or kill that session when the work should stop. `omb` is the supported way to start or reconnect; no extension callback performs a process handoff.
|
|
81
107
|
|
|
82
|
-
`collab.autoStart=control` publishes a capability-bearing control link through the configured Collab relay. Treat the link like a credential and share it only with intended operators. Use `collab.autoStart=view` for monitoring without steering. If the host process itself is killed, its live task agents cannot continue; OMP persists the session transcript for later resume, but it does not turn a terminated model process into a running background job. OMP's native `hub` tool can also launch a persistent host with `persist: true` and `pty: true`; `omp ps` then lists and controls that supervised process.
|
|
108
|
+
`collab.autoStart=control` publishes a capability-bearing control link through the configured Collab relay. Treat the link like a credential and share it only with intended operators. Use `collab.autoStart=view` for monitoring without steering. The install preset hides thinking blocks and model tool activity while preserving the reasoning itself, keeping the chat readable; use OMP's display settings when you need the detailed trace. If the host process itself is killed, its live task agents cannot continue; OMP persists the session transcript for later resume, but it does not turn a terminated model process into a running background job. OMP's native `hub` tool can also launch a persistent host with `persist: true` and `pty: true`; `omp ps` then lists and controls that supervised process.
|
|
83
109
|
|
|
84
110
|
## Support boundary
|
|
85
111
|
|
|
86
|
-
The supported native baseline is OMP 18.2.
|
|
112
|
+
The supported native baseline is OMP 18.2.6 (release commit `78b753124d11f8dd3ae73e2524125890ff7c977e`) and Bun >=1.3.14; OMP 18.2.5 and 18.2.4 remain separately tested compatibility versions. The extension API is trusted in-process code; OMP task isolation protects the child workspace/settings but is not an OS sandbox for extension code. See `docs/compatibility/` and `docs/security/` for the qualified matrix.
|
|
87
113
|
|
|
88
114
|
## Model roles
|
|
89
115
|
|
|
90
|
-
Bizar ships semantic native roles for orchestration, advisory review, coordination, research, planning, architecture, implementation, review, security, verification, and documentation. Installing the plugin registers visible, namespaced `bizar_*` roles in OMP's model menu and preserves operator-owned role mappings. To have
|
|
116
|
+
Bizar ships semantic native roles for orchestration, advisory review, coordination, research, planning, architecture, implementation, review, security, verification, and documentation. Installing the plugin registers visible, namespaced `bizar_*` roles in OMP's model menu and preserves operator-owned role mappings. To have Bizar inspect the authenticated models currently available to OMP, assign the best selectors using its bounded local scorer, validate every assignment, and report unresolved roles, run:
|
|
91
117
|
|
|
92
118
|
```text
|
|
93
119
|
/bizar-models
|
|
94
120
|
```
|
|
95
121
|
|
|
96
|
-
`/bizar model-roles` remains a compatibility alias, and `/bizar-models health` validates the configured selectors without changing settings. The assignment command
|
|
122
|
+
`/bizar model-roles` remains a compatibility alias, and `/bizar-models health` validates the configured selectors without changing settings. The assignment command uses OMP 18.2.6's native authenticated model catalog directly in the extension, normalizes irregular thinking metadata safely, chooses assignments using actual capability metadata, preserves non-Bizar roles, validates native resolution, and reports any role it could not assign. It is intentionally bounded and does not start a long planning or research turn. The plugin registers safe Bizar defaults so the roles are visible immediately; `/bizar-models` can replace those defaults with concrete available selectors.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type OmbSessionInfo } from "../omp/omb-sessions.js";
|
|
2
|
+
import type { OmbSettings } from "../omp/omb-settings.js";
|
|
3
|
+
export type AgentsHubAction = {
|
|
4
|
+
type: "quit";
|
|
5
|
+
} | {
|
|
6
|
+
type: "attach";
|
|
7
|
+
session: OmbSessionInfo;
|
|
8
|
+
} | {
|
|
9
|
+
type: "new";
|
|
10
|
+
selected?: OmbSessionInfo;
|
|
11
|
+
} | {
|
|
12
|
+
type: "rename";
|
|
13
|
+
session: OmbSessionInfo;
|
|
14
|
+
} | {
|
|
15
|
+
type: "delete";
|
|
16
|
+
session: OmbSessionInfo;
|
|
17
|
+
} | {
|
|
18
|
+
type: "settings";
|
|
19
|
+
settings: OmbSettings;
|
|
20
|
+
};
|
|
21
|
+
export declare function runInkAgentsHub(cwd: string, env: NodeJS.ProcessEnv, sessions: OmbSessionInfo[], settings: OmbSettings): Promise<AgentsHubAction>;
|
|
22
|
+
//# sourceMappingURL=agents-ink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-ink.d.ts","sourceRoot":"","sources":["../../src/cli/agents-ink.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA0C,KAAK,cAAc,EAAwB,MAAM,wBAAwB,CAAC;AAC3H,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,CAAC;AA6ThD,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAOtJ"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { Box, Text, useApp, useInput, useWindowSize, render } from "ink";
|
|
4
|
+
import { listOmbSessions, ombSessionDisplayName } from "../omp/omb-sessions.js";
|
|
5
|
+
const statusLabel = (state) => state === "attached" ? "CONNECTED" : state === "detached" ? "DISCONNECTED" : "STOPPED";
|
|
6
|
+
const statusColor = (state) => state === "attached" ? "green" : state === "detached" ? "yellow" : "gray";
|
|
7
|
+
const statusMark = (state) => state === "attached" ? "●" : state === "detached" ? "◌" : "○";
|
|
8
|
+
const short = (value, width) => value.length <= width ? value : width <= 1 ? value.slice(0, width) : `${value.slice(0, width - 1)}…`;
|
|
9
|
+
function age(session) {
|
|
10
|
+
const timestamp = session.lastAttachedAt ?? session.createdAt;
|
|
11
|
+
if (!timestamp)
|
|
12
|
+
return "age unknown";
|
|
13
|
+
const seconds = Math.max(0, Math.floor(Date.now() / 1000) - timestamp);
|
|
14
|
+
if (seconds < 60)
|
|
15
|
+
return "just now";
|
|
16
|
+
if (seconds < 3600)
|
|
17
|
+
return `${Math.floor(seconds / 60)}m ago`;
|
|
18
|
+
if (seconds < 86400)
|
|
19
|
+
return `${Math.floor(seconds / 3600)}h ago`;
|
|
20
|
+
return `${Math.floor(seconds / 86400)}d ago`;
|
|
21
|
+
}
|
|
22
|
+
function projectCounts(sessions) {
|
|
23
|
+
const counts = new Map();
|
|
24
|
+
for (const session of sessions)
|
|
25
|
+
counts.set(session.project, (counts.get(session.project) ?? 0) + 1);
|
|
26
|
+
return [...counts.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
27
|
+
}
|
|
28
|
+
function visibleSessions(allSessions, settings) {
|
|
29
|
+
return settings.showStoppedSessions ? allSessions : allSessions.filter(session => session.state !== "dead");
|
|
30
|
+
}
|
|
31
|
+
function Header({ cwd, sessions }) {
|
|
32
|
+
const connected = sessions.filter(session => session.state === "attached").length;
|
|
33
|
+
const disconnected = sessions.filter(session => session.state === "detached").length;
|
|
34
|
+
const stopped = sessions.filter(session => session.state === "dead").length;
|
|
35
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { bold: true, color: "cyan", children: "\u25C6 BIZAR / AGENTS HUB" }), _jsx(Text, { dimColor: true, children: short(cwd, 44) })] }), _jsxs(Box, { marginTop: 1, gap: 2, children: [_jsxs(Text, { color: "green", children: ["\u25CF ", connected, " connected"] }), _jsxs(Text, { color: "yellow", children: ["\u25CC ", disconnected, " disconnected"] }), _jsxs(Text, { color: "gray", children: ["\u25CB ", stopped, " stopped"] })] })] }));
|
|
36
|
+
}
|
|
37
|
+
function WorkspaceRail({ sessions, selected }) {
|
|
38
|
+
const projects = projectCounts(sessions);
|
|
39
|
+
return (_jsxs(Box, { width: "28%", minWidth: 24, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "WORKSPACES" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: "white", bold: true, children: ["\u203A ALL SESSIONS ", _jsx(Text, { dimColor: true, children: sessions.length })] }), projects.length === 0 ? _jsx(Text, { dimColor: true, children: " No active projects" }) : projects.map(([project, count]) => (_jsxs(Text, { color: selected?.project === project ? "cyan" : undefined, children: [selected?.project === project ? " › " : " ", short(project, 18), " ", _jsx(Text, { dimColor: true, children: count })] }, project)))] }), _jsxs(Box, { marginTop: 2, flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { bold: true, color: "yellow", children: "LIVE VIEW" }), _jsx(Text, { dimColor: true, children: "Updates every few seconds." }), _jsx(Text, { dimColor: true, children: "Only bizar-* sessions" }), _jsx(Text, { dimColor: true, children: "are shown or changed." })] })] }));
|
|
40
|
+
}
|
|
41
|
+
function SessionRow({ session, selected, width }) {
|
|
42
|
+
const color = statusColor(session.state);
|
|
43
|
+
const displayName = ombSessionDisplayName(session);
|
|
44
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, backgroundColor: selected ? "blue" : undefined, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Text, { color: selected ? "white" : color, bold: selected, children: [selected ? "›" : " ", " ", statusMark(session.state), " ", short(displayName, Math.max(18, width - 28))] }), _jsx(Text, { color: selected ? "white" : color, dimColor: !selected, children: statusLabel(session.state) })] }), _jsxs(Box, { paddingLeft: 4, justifyContent: "space-between", children: [_jsx(Text, { dimColor: true, children: short(`${session.project}/${session.id} · ${session.cwd}`, Math.max(20, width - 20)) }), _jsx(Text, { dimColor: true, children: age(session) })] })] }));
|
|
45
|
+
}
|
|
46
|
+
function SessionList({ sessions, selected, rows, width }) {
|
|
47
|
+
const visibleCount = Math.max(4, rows - 7);
|
|
48
|
+
const start = Math.max(0, Math.min(Math.max(0, sessions.length - visibleCount), selected - Math.floor(visibleCount / 2)));
|
|
49
|
+
const visible = sessions.slice(start, start + visibleCount);
|
|
50
|
+
let previous;
|
|
51
|
+
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { bold: true, color: "cyan", children: "SESSIONS" }), _jsx(Text, { dimColor: true, children: sessions.length ? `${start + 1}-${Math.min(start + visibleCount, sessions.length)} of ${sessions.length}` : "empty" })] }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: visible.length === 0 ? (_jsxs(Box, { flexDirection: "column", paddingY: 2, children: [_jsx(Text, { color: "yellow", children: "No Bizar sessions are running." }), _jsx(Text, { dimColor: true, children: "Press n to dispatch a new agent session." })] })) : visible.map((session, offset) => {
|
|
52
|
+
const index = start + offset;
|
|
53
|
+
const heading = session.state !== previous;
|
|
54
|
+
previous = session.state;
|
|
55
|
+
return (_jsxs(Box, { flexDirection: "column", children: [heading && _jsxs(Text, { color: statusColor(session.state), bold: true, children: [statusMark(session.state), " ", statusLabel(session.state)] }), _jsx(SessionRow, { session: session, selected: index === selected, width: width })] }, session.name));
|
|
56
|
+
}) })] }));
|
|
57
|
+
}
|
|
58
|
+
function Inspector({ session }) {
|
|
59
|
+
return (_jsxs(Box, { width: "29%", minWidth: 25, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "SELECTED SESSION" }), !session ? _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Select a session to inspect it." }) }) : (_jsxs(Box, { marginTop: 1, flexDirection: "column", gap: 1, children: [_jsxs(Text, { bold: true, color: statusColor(session.state), children: [statusMark(session.state), " ", statusLabel(session.state)] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "NAME" }), _jsx(Text, { children: ombSessionDisplayName(session) }), _jsx(Text, { dimColor: true, children: session.nativeName ? "OMP session title" : "Generated from task or project" })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "PROJECT" }), _jsx(Text, { children: short(session.cwd, 30) })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "COMMAND" }), _jsx(Text, { children: short(session.command || "omp", 30) })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "LAST ACTIVITY" }), _jsx(Text, { children: age(session) })] })] }))] }));
|
|
60
|
+
}
|
|
61
|
+
function Footer() {
|
|
62
|
+
return (_jsxs(Box, { marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, justifyContent: "space-between", children: [_jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "Enter" }), " attach ", _jsx(Text, { color: "cyan", children: "n" }), " new ", _jsx(Text, { color: "cyan", children: "e" }), " rename ", _jsx(Text, { color: "cyan", children: "d" }), " delete"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "s" }), " settings ", _jsx(Text, { color: "cyan", children: "r" }), " refresh ", _jsx(Text, { color: "cyan", children: "?" }), " help ", _jsx(Text, { color: "cyan", children: "q" }), " quit"] })] }));
|
|
63
|
+
}
|
|
64
|
+
function Modal({ title, children, width, columns }) {
|
|
65
|
+
return (_jsxs(Box, { position: "absolute", top: 2, left: Math.max(0, Math.floor((columns - width) / 2)), width: width, flexDirection: "column", borderStyle: "double", borderColor: "cyan", backgroundColor: "black", paddingX: 2, paddingY: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: title }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: children })] }));
|
|
66
|
+
}
|
|
67
|
+
function SettingsModal({ settings, selected, columns, onToggle, onSave, onClose }) {
|
|
68
|
+
const options = [
|
|
69
|
+
["Attach plain omb to latest live session", settings.autoAttachLatest],
|
|
70
|
+
["Enable mouse scrolling in OMB sessions", settings.mouseScrolling],
|
|
71
|
+
["Show stopped sessions in this view", settings.showStoppedSessions],
|
|
72
|
+
];
|
|
73
|
+
return (_jsxs(Modal, { title: "OMB SETTINGS", width: Math.min(70, Math.max(46, columns - 6)), columns: columns, children: [options.map(([label, enabled], index) => (_jsxs(Text, { color: index === selected ? "white" : undefined, backgroundColor: index === selected ? "blue" : undefined, children: [index === selected ? "›" : " ", " [", enabled ? "on " : "off", "] ", label] }, label))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "Up/Down select Space/Enter toggle s save Esc cancel" }), _jsx(Text, { color: "yellow", children: selected === 1 ? "Mouse mode applies to existing OMB sessions when saved." : "" }), _jsx(Text, { children: selected >= 0 ? "" : "" }), _jsx(SettingsKeyHandler, { onToggle: onToggle, onSave: onSave, onClose: onClose })] }));
|
|
74
|
+
}
|
|
75
|
+
function SettingsKeyHandler({ onToggle, onSave, onClose }) {
|
|
76
|
+
useInput((input, key) => {
|
|
77
|
+
if (key.upArrow || key.downArrow)
|
|
78
|
+
return;
|
|
79
|
+
if (key.escape)
|
|
80
|
+
onClose();
|
|
81
|
+
else if (input === " " || key.return)
|
|
82
|
+
onToggle();
|
|
83
|
+
else if (input === "s")
|
|
84
|
+
onSave();
|
|
85
|
+
});
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
function HelpModal({ columns, onClose }) {
|
|
89
|
+
useInput((input, key) => { if (key.escape || key.return || input === "q")
|
|
90
|
+
onClose(); });
|
|
91
|
+
return (_jsxs(Modal, { title: "OMB AGENTS SHORTCUTS", width: Math.min(64, Math.max(42, columns - 6)), columns: columns, children: [_jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "Enter" }), " attach to the selected session"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "n" }), " create a new session"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "e" }), " rename the selected session"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "d" }), " delete after confirmation"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "s" }), " open launcher settings"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "r" }), " refresh the session list"] }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "q / Esc" }), " leave this view"] }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "Only tmux sessions with the bizar- prefix are managed." }), _jsx(Text, { dimColor: true, children: "Press Enter or Esc to return." })] }));
|
|
92
|
+
}
|
|
93
|
+
function DeleteModal({ session, columns, onConfirm, onClose }) {
|
|
94
|
+
useInput((input, key) => {
|
|
95
|
+
if (input.toLowerCase() === "y")
|
|
96
|
+
onConfirm();
|
|
97
|
+
else if (key.escape || key.return || input.length > 0)
|
|
98
|
+
onClose();
|
|
99
|
+
});
|
|
100
|
+
return (_jsxs(Modal, { title: "DELETE SESSION?", width: Math.min(64, Math.max(42, columns - 6)), columns: columns, children: [_jsxs(Text, { bold: true, children: [session.project, "/", session.id] }), _jsx(Text, { dimColor: true, children: short(session.cwd, 54) }), _jsx(Text, { children: " " }), _jsx(Text, { color: "yellow", children: "This stops OMP and removes the tmux session." }), _jsxs(Text, { children: ["Press ", _jsx(Text, { color: "red", bold: true, children: "y" }), " to delete, any other key to cancel."] })] }));
|
|
101
|
+
}
|
|
102
|
+
function AgentsApp({ cwd, env, sessions: initialSessions, settings: initialSettings, onAction }) {
|
|
103
|
+
const { columns, rows } = useWindowSize();
|
|
104
|
+
const [allSessions, setAllSessions] = useState(initialSessions);
|
|
105
|
+
const [settings, setSettings] = useState(initialSettings);
|
|
106
|
+
const [selected, setSelected] = useState(0);
|
|
107
|
+
const [overlay, setOverlay] = useState();
|
|
108
|
+
const [overlaySelected, setOverlaySelected] = useState(0);
|
|
109
|
+
const [draftSettings, setDraftSettings] = useState(initialSettings);
|
|
110
|
+
const { exit } = useApp();
|
|
111
|
+
const sessions = useMemo(() => visibleSessions(allSessions, settings), [allSessions, settings]);
|
|
112
|
+
const selectedSession = sessions[selected];
|
|
113
|
+
const refresh = async () => setAllSessions(await listOmbSessions(cwd, env));
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
const timer = setInterval(() => { void refresh(); }, 3000);
|
|
116
|
+
return () => clearInterval(timer);
|
|
117
|
+
}, [cwd, env]);
|
|
118
|
+
useEffect(() => { setSelected(value => Math.min(value, Math.max(0, sessions.length - 1))); }, [sessions.length]);
|
|
119
|
+
const finish = (action) => { onAction(action); exit(); };
|
|
120
|
+
useInput((input, key) => {
|
|
121
|
+
if (overlay)
|
|
122
|
+
return;
|
|
123
|
+
if (key.ctrl && input === "c") {
|
|
124
|
+
finish({ type: "quit" });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (key.escape || input === "q") {
|
|
128
|
+
finish({ type: "quit" });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (key.upArrow || input === "k")
|
|
132
|
+
setSelected(value => Math.max(0, value - 1));
|
|
133
|
+
else if (key.downArrow || input === "j")
|
|
134
|
+
setSelected(value => Math.min(Math.max(0, sessions.length - 1), value + 1));
|
|
135
|
+
else if (key.return && selectedSession)
|
|
136
|
+
finish({ type: "attach", session: selectedSession });
|
|
137
|
+
else if (input === "n")
|
|
138
|
+
finish({ type: "new", selected: selectedSession });
|
|
139
|
+
else if (input === "e" && selectedSession)
|
|
140
|
+
finish({ type: "rename", session: selectedSession });
|
|
141
|
+
else if (input === "d" && selectedSession) {
|
|
142
|
+
setOverlay("delete");
|
|
143
|
+
}
|
|
144
|
+
else if (input === "r") {
|
|
145
|
+
void refresh();
|
|
146
|
+
}
|
|
147
|
+
else if (input === "?")
|
|
148
|
+
setOverlay("help");
|
|
149
|
+
else if (input === "s") {
|
|
150
|
+
setDraftSettings(settings);
|
|
151
|
+
setOverlaySelected(0);
|
|
152
|
+
setOverlay("settings");
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return (_jsxs(Box, { flexDirection: "column", width: "100%", minHeight: Math.max(12, rows - 1), paddingX: 1, children: [_jsx(Header, { cwd: cwd, sessions: sessions }), _jsxs(Box, { flexGrow: 1, marginTop: 1, gap: 1, children: [_jsx(WorkspaceRail, { sessions: sessions, selected: selectedSession }), _jsx(SessionList, { sessions: sessions, selected: selected, rows: rows, width: Math.max(34, Math.floor(columns * 0.42)) }), _jsx(Inspector, { session: selectedSession })] }), _jsx(Footer, {}), overlay === "help" && _jsx(HelpModal, { columns: columns, onClose: () => setOverlay(undefined) }), overlay === "delete" && selectedSession && _jsx(DeleteModal, { session: selectedSession, columns: columns, onConfirm: () => finish({ type: "delete", session: selectedSession }), onClose: () => setOverlay(undefined) }), overlay === "settings" && (_jsx(SettingsModal, { settings: draftSettings, selected: overlaySelected, columns: columns, onToggle: () => {
|
|
156
|
+
const field = overlaySelected === 0 ? "autoAttachLatest" : overlaySelected === 1 ? "mouseScrolling" : "showStoppedSessions";
|
|
157
|
+
setDraftSettings(value => ({ ...value, [field]: !value[field] }));
|
|
158
|
+
}, onSave: () => finish({ type: "settings", settings: draftSettings }), onClose: () => setOverlay(undefined) })), overlay === "settings" && _jsx(SettingsNavigation, { selected: overlaySelected, onChange: setOverlaySelected })] }));
|
|
159
|
+
}
|
|
160
|
+
function SettingsNavigation({ selected, onChange }) {
|
|
161
|
+
useInput((_input, key) => {
|
|
162
|
+
if (key.upArrow)
|
|
163
|
+
onChange(Math.max(0, selected - 1));
|
|
164
|
+
else if (key.downArrow)
|
|
165
|
+
onChange(Math.min(2, selected + 1));
|
|
166
|
+
});
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
export async function runInkAgentsHub(cwd, env, sessions, settings) {
|
|
170
|
+
let action = { type: "quit" };
|
|
171
|
+
const app = render(_jsx(AgentsApp, { cwd: cwd, env: env, sessions: sessions, settings: settings, onAction: value => { action = value; } }), {
|
|
172
|
+
alternateScreen: true,
|
|
173
|
+
});
|
|
174
|
+
await app.waitUntilExit();
|
|
175
|
+
return action;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=agents-ink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-ink.js","sourceRoot":"","sources":["../../src/cli/agents-ink.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type OmbSettings } from "../omp/omb-settings.js";
|
|
3
|
+
import { type OmbSessionInfo } from "../omp/omb-sessions.js";
|
|
4
|
+
interface HubRenderOptions {
|
|
5
|
+
currentCwd?: string;
|
|
6
|
+
maxVisible?: number;
|
|
7
|
+
notice?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function renderAgentsHub(sessions: OmbSessionInfo[], selected: number, options?: HubRenderOptions): string;
|
|
10
|
+
export declare function renderSettingsOverlay(settings: OmbSettings, selected: number): string;
|
|
11
|
+
/** Run the keyboard-first cross-project session manager. */
|
|
12
|
+
export declare function runAgentsHub(cwd?: string, _args?: string[], env?: NodeJS.ProcessEnv): Promise<number>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/cli/agents.ts"],"names":[],"mappings":";AAeA,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC5F,OAAO,EAA0C,KAAK,cAAc,EAAwB,MAAM,wBAAwB,CAAC;AAG3H,UAAU,gBAAgB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiDD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EAAE,EAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAoCR;AAiBD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYrF;AA0DD,4DAA4D;AAC5D,wBAAsB,YAAY,CAChC,GAAG,SAAgB,EACnB,KAAK,GAAE,MAAM,EAAO,EACpB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { existsSync, statSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
7
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
8
|
+
import { attachOmbSession, deleteOmbSession, launchOmb, ombSessionName, renameOmbSession, setOmbSessionMouse, } from "../omp/tmux.js";
|
|
9
|
+
import { loadOmbSettings, saveOmbSettings } from "../omp/omb-settings.js";
|
|
10
|
+
import { listOmbSessions, ombSessionDisplayName } from "../omp/omb-sessions.js";
|
|
11
|
+
import { runInkAgentsHub } from "./agents-ink.js";
|
|
12
|
+
const RESET = "\u001b[0m";
|
|
13
|
+
const DIM = "\u001b[2m";
|
|
14
|
+
const BOLD = "\u001b[1m";
|
|
15
|
+
const REVERSE = "\u001b[7m";
|
|
16
|
+
function generatedSessionId() {
|
|
17
|
+
return `s-${Date.now().toString(36)}-${randomBytes(2).toString("hex")}`;
|
|
18
|
+
}
|
|
19
|
+
function statusLabel(state) {
|
|
20
|
+
return state === "attached" ? "connected" : state === "detached" ? "disconnected" : "stopped";
|
|
21
|
+
}
|
|
22
|
+
function sessionAge(session) {
|
|
23
|
+
const timestamp = session.lastAttachedAt ?? session.createdAt;
|
|
24
|
+
if (!timestamp)
|
|
25
|
+
return "age ?";
|
|
26
|
+
const seconds = Math.max(0, Math.floor(Date.now() / 1000) - timestamp);
|
|
27
|
+
if (seconds < 60)
|
|
28
|
+
return "now";
|
|
29
|
+
if (seconds < 3600)
|
|
30
|
+
return `${Math.floor(seconds / 60)}m`;
|
|
31
|
+
if (seconds < 86400)
|
|
32
|
+
return `${Math.floor(seconds / 3600)}h`;
|
|
33
|
+
return `${Math.floor(seconds / 86400)}d`;
|
|
34
|
+
}
|
|
35
|
+
function truncate(value, width) {
|
|
36
|
+
if (value.length <= width)
|
|
37
|
+
return value;
|
|
38
|
+
if (width <= 1)
|
|
39
|
+
return value.slice(0, width);
|
|
40
|
+
return `${value.slice(0, width - 1)}…`;
|
|
41
|
+
}
|
|
42
|
+
function sessionSummary(session, currentCwd, terminalWidth) {
|
|
43
|
+
const project = truncate(ombSessionDisplayName(session), 28).padEnd(28);
|
|
44
|
+
const location = session.cwd === currentCwd ? "current project" : session.cwd;
|
|
45
|
+
const locationWidth = Math.max(18, Math.min(44, terminalWidth - 28 - 12 - 8));
|
|
46
|
+
return `${project} ${statusLabel(session.state).padEnd(12)} ${truncate(location, locationWidth).padEnd(locationWidth)} ${sessionAge(session)}`;
|
|
47
|
+
}
|
|
48
|
+
function counts(sessions) {
|
|
49
|
+
const connected = sessions.filter(session => session.state === "attached").length;
|
|
50
|
+
const disconnected = sessions.filter(session => session.state === "detached").length;
|
|
51
|
+
const stopped = sessions.filter(session => session.state === "dead").length;
|
|
52
|
+
return `${sessions.length} session${sessions.length === 1 ? "" : "s"} · ${connected} connected · ${disconnected} disconnected · ${stopped} stopped`;
|
|
53
|
+
}
|
|
54
|
+
function sectionName(state) {
|
|
55
|
+
return state === "attached" ? "Connected" : state === "detached" ? "Disconnected" : "Stopped";
|
|
56
|
+
}
|
|
57
|
+
export function renderAgentsHub(sessions, selected, options = {}) {
|
|
58
|
+
const currentCwd = options.currentCwd || process.cwd();
|
|
59
|
+
const terminalWidth = Math.max(60, output.columns || 90);
|
|
60
|
+
const maxVisible = Math.max(4, options.maxVisible ?? Math.max(4, (output.rows || 24) - 10));
|
|
61
|
+
const start = Math.max(0, Math.min(Math.max(0, sessions.length - maxVisible), selected - Math.floor(maxVisible / 2)));
|
|
62
|
+
const visible = sessions.slice(start, start + maxVisible);
|
|
63
|
+
const lines = [
|
|
64
|
+
`${BOLD}Bizar Agents${RESET}`,
|
|
65
|
+
counts(sessions),
|
|
66
|
+
`${DIM}${truncate(currentCwd, terminalWidth - 2)}${RESET}`,
|
|
67
|
+
"",
|
|
68
|
+
`${DIM}Enter attach n new e rename d delete s settings r refresh ? help q quit${RESET}`,
|
|
69
|
+
"",
|
|
70
|
+
];
|
|
71
|
+
if (sessions.length === 0) {
|
|
72
|
+
lines.push("No Bizar sessions are running.", "", "Press n to dispatch a new session.");
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
let previousState;
|
|
76
|
+
for (const [offset, session] of visible.entries()) {
|
|
77
|
+
const index = start + offset;
|
|
78
|
+
if (session.state !== previousState) {
|
|
79
|
+
lines.push(`${BOLD}${sectionName(session.state)}${RESET}`);
|
|
80
|
+
previousState = session.state;
|
|
81
|
+
}
|
|
82
|
+
const row = `${index === selected ? ">" : " "} ${sessionSummary(session, currentCwd, terminalWidth)}`;
|
|
83
|
+
lines.push(index === selected ? `${REVERSE}${row}${RESET}` : row);
|
|
84
|
+
}
|
|
85
|
+
if (start > 0 || start + visible.length < sessions.length) {
|
|
86
|
+
lines.push(`${DIM}Showing ${start + 1}-${start + visible.length} of ${sessions.length}. Use Up/Down to scroll.${RESET}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (options.notice)
|
|
90
|
+
lines.push("", `${options.notice}`);
|
|
91
|
+
lines.push("", `${DIM}Bizar owns only sessions with the bizar- prefix; unrelated tmux sessions are untouched.${RESET}`);
|
|
92
|
+
return `${lines.join("\n")}\n`;
|
|
93
|
+
}
|
|
94
|
+
function boxed(title, body, width = 58) {
|
|
95
|
+
const inner = width - 2;
|
|
96
|
+
const top = `┌${"─".repeat(inner)}┐`;
|
|
97
|
+
const bottom = `└${"─".repeat(inner)}┘`;
|
|
98
|
+
const rows = [`│ ${BOLD}${title}${RESET}${" ".repeat(Math.max(0, inner - title.length - 1))}│`];
|
|
99
|
+
const ansi = /\u001b\[[0-9;]*m/g;
|
|
100
|
+
for (const line of body) {
|
|
101
|
+
const visible = line.replace(ansi, "");
|
|
102
|
+
const clipped = truncate(visible, inner - 1);
|
|
103
|
+
const content = visible.length > inner - 1 ? clipped : line;
|
|
104
|
+
rows.push(`│ ${content}${" ".repeat(Math.max(0, inner - 1 - clipped.length))}│`);
|
|
105
|
+
}
|
|
106
|
+
return [top, ...rows, bottom].join("\n");
|
|
107
|
+
}
|
|
108
|
+
export function renderSettingsOverlay(settings, selected) {
|
|
109
|
+
const options = [
|
|
110
|
+
["Attach plain omb to latest live session", settings.autoAttachLatest],
|
|
111
|
+
["Enable mouse scrolling in OMB sessions", settings.mouseScrolling],
|
|
112
|
+
["Show stopped sessions in this view", settings.showStoppedSessions],
|
|
113
|
+
];
|
|
114
|
+
const body = options.map(([label, enabled], index) => {
|
|
115
|
+
const row = `${index === selected ? ">" : " "} [${enabled ? "on " : "off"}] ${label}`;
|
|
116
|
+
return index === selected ? `${REVERSE}${row}${RESET}` : row;
|
|
117
|
+
});
|
|
118
|
+
body.push("", `${DIM}Up/Down select Space/Enter toggle s save Esc cancel${RESET}`);
|
|
119
|
+
return boxed("OMB Settings", body);
|
|
120
|
+
}
|
|
121
|
+
async function promptLine(prompt) {
|
|
122
|
+
// Ink unrefs stdin when it leaves raw mode. Re-ref it before handing the
|
|
123
|
+
// terminal to readline so an unanswered prompt keeps the CLI alive.
|
|
124
|
+
input.ref?.();
|
|
125
|
+
input.setRawMode?.(false);
|
|
126
|
+
input.resume();
|
|
127
|
+
const readline = createInterface({ input, output });
|
|
128
|
+
try {
|
|
129
|
+
return await readline.question(prompt);
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
readline.close();
|
|
133
|
+
input.setRawMode?.(true);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function restoreTerminal() {
|
|
137
|
+
input.setRawMode?.(false);
|
|
138
|
+
input.pause();
|
|
139
|
+
output.write(`${RESET}\u001b[?25h\n`);
|
|
140
|
+
}
|
|
141
|
+
async function dispatchSession(currentCwd, selected, env) {
|
|
142
|
+
const defaultCwd = selected?.cwd && selected.cwd !== "?" ? selected.cwd : currentCwd;
|
|
143
|
+
const requestedCwd = (await promptLine(`Project directory [${defaultCwd}]: `)).trim() || defaultCwd;
|
|
144
|
+
const expandedCwd = requestedCwd === "~" ? homedir() : requestedCwd.startsWith("~/") ? resolve(homedir(), requestedCwd.slice(2)) : requestedCwd;
|
|
145
|
+
const projectCwd = resolve(expandedCwd);
|
|
146
|
+
if (!existsSync(projectCwd) || !statSync(projectCwd).isDirectory()) {
|
|
147
|
+
output.write(`omb agents: not a directory: ${projectCwd}\n`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const task = (await promptLine("Describe a task for the new session (optional): ")).trim();
|
|
151
|
+
const requestedId = (await promptLine("Session name (blank=generated): ")).trim();
|
|
152
|
+
restoreTerminal();
|
|
153
|
+
await launchOmb(projectCwd, task ? [task] : [], env, requestedId || generatedSessionId());
|
|
154
|
+
}
|
|
155
|
+
async function renameSession(session, env) {
|
|
156
|
+
const requestedId = (await promptLine(`New name for ${session.id} [${session.id}]: `)).trim() || session.id;
|
|
157
|
+
const projectCwd = session.cwd === "?" ? process.cwd() : session.cwd;
|
|
158
|
+
const nextName = ombSessionName(projectCwd, requestedId);
|
|
159
|
+
if (nextName === session.name)
|
|
160
|
+
return "Session name unchanged.";
|
|
161
|
+
const code = await renameOmbSession(session.name, nextName, projectCwd, env);
|
|
162
|
+
return code === 0 ? `Renamed session to ${requestedId}.` : "Could not rename that session.";
|
|
163
|
+
}
|
|
164
|
+
async function applySavedSettings(previous, next, sessions, cwd, env) {
|
|
165
|
+
saveOmbSettings(next, env);
|
|
166
|
+
if (previous.mouseScrolling !== next.mouseScrolling) {
|
|
167
|
+
await Promise.all(sessions.map(session => setOmbSessionMouse(session.name, next.mouseScrolling, cwd, env)));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** Run the keyboard-first cross-project session manager. */
|
|
171
|
+
export async function runAgentsHub(cwd = process.cwd(), _args = [], env = process.env) {
|
|
172
|
+
if (!input.isTTY || !output.isTTY) {
|
|
173
|
+
output.write("omb agents requires an interactive terminal.\n");
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
176
|
+
let settings = loadOmbSettings(env);
|
|
177
|
+
while (true) {
|
|
178
|
+
const allSessions = await listOmbSessions(cwd, env);
|
|
179
|
+
const sessions = settings.showStoppedSessions ? allSessions : allSessions.filter(session => session.state !== "dead");
|
|
180
|
+
const action = await runInkAgentsHub(cwd, env, sessions, settings);
|
|
181
|
+
if (action.type === "quit")
|
|
182
|
+
return 0;
|
|
183
|
+
if (action.type === "settings") {
|
|
184
|
+
await applySavedSettings(settings, action.settings, allSessions, cwd, env);
|
|
185
|
+
settings = action.settings;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (action.type === "attach")
|
|
189
|
+
await attachOmbSession(action.session.name, action.session.cwd === "?" ? cwd : action.session.cwd, env);
|
|
190
|
+
else if (action.type === "new")
|
|
191
|
+
await dispatchSession(cwd, action.selected, env);
|
|
192
|
+
else if (action.type === "rename")
|
|
193
|
+
await renameSession(action.session, env);
|
|
194
|
+
else if (action.type === "delete")
|
|
195
|
+
await deleteOmbSession(action.session.name, cwd, env);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=agents.js.map
|