agent-rooms 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,82 +7,108 @@ export function dashboardHtml() {
7
7
  <title>Agent Rooms Control</title>
8
8
  <style>
9
9
  :root {
10
- color-scheme: light;
11
- --bg: #f6f5f2;
12
- --panel: #ffffff;
13
- --ink: #181715;
14
- --muted: #69645c;
15
- --line: #ded8ce;
16
- --green: #207a4c;
17
- --amber: #9a6417;
18
- --red: #a33a32;
19
- --blue: #2364a8;
20
- --gold: #a97913;
21
- --shadow: 0 14px 35px rgba(24, 23, 21, 0.08);
10
+ color-scheme: dark;
11
+ --bg: #05070F;
12
+ --bg2: #0B1020;
13
+ --panel: rgba(255,255,255,.022);
14
+ --ink: #EAEFF8;
15
+ --muted: #8A93A6;
16
+ --faint: #5E6678;
17
+ --line: rgba(255,255,255,.07);
18
+ --line2: rgba(255,255,255,.12);
19
+ --cyan: #38BDF8;
20
+ --cyan2: #7DD3FC;
21
+ --purple: #A78BFA;
22
+ --green: #22C55E;
23
+ --amber: #FBBF24;
24
+ --red: #F87171;
25
+ --gold: #FACC15;
26
+ --blue: #38BDF8;
27
+ --shadow: 0 24px 60px -28px rgba(0,0,0,.85);
22
28
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
23
29
  }
24
30
  * { box-sizing: border-box; }
25
- body { margin: 0; background: var(--bg); color: var(--ink); }
31
+ body {
32
+ margin: 0; color: var(--ink);
33
+ background:
34
+ radial-gradient(1100px 620px at 78% -8%, rgba(56,189,248,.10), transparent 60%),
35
+ radial-gradient(900px 560px at -6% 8%, rgba(167,139,250,.09), transparent 55%),
36
+ var(--bg);
37
+ -webkit-font-smoothing: antialiased;
38
+ }
39
+ .mono, pre, .event, input, select { font-family: ui-monospace, "SF Mono", SFMono-Regular, Consolas, "Liberation Mono", monospace; }
26
40
  button, input, select { font: inherit; }
27
- .shell { min-height: 100vh; display: grid; grid-template-columns: 250px 1fr; }
28
- aside { border-right: 1px solid var(--line); padding: 24px 18px; background: #fbfaf8; }
29
- main { padding: 26px; max-width: 1180px; width: 100%; }
30
- .brand { font-size: 15px; font-weight: 800; letter-spacing: 0; margin-bottom: 4px; }
31
- .sub { color: var(--muted); font-size: 13px; line-height: 1.4; margin-bottom: 22px; }
32
- .nav { display: grid; gap: 6px; }
33
- .nav button { border: 0; background: transparent; text-align: left; padding: 10px 11px; border-radius: 8px; color: var(--muted); cursor: pointer; }
34
- .nav button.active { background: #ece7dd; color: var(--ink); font-weight: 700; }
35
- .top { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; margin-bottom: 18px; }
36
- h1 { font-size: 25px; margin: 0 0 6px; letter-spacing: 0; }
37
- .meta { color: var(--muted); font-size: 13px; }
38
- .banner { background: var(--panel); border: 1px solid var(--line); border-left: 5px solid var(--blue); box-shadow: var(--shadow); border-radius: 8px; padding: 15px 16px; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
39
- .banner.ready { border-left-color: var(--green); }
40
- .banner strong { display: block; margin-bottom: 3px; }
41
+ ::selection { background: rgba(56,189,248,.28); }
42
+ ::-webkit-scrollbar { width: 9px; height: 9px; }
43
+ ::-webkit-scrollbar-thumb { background: rgba(255,255,255,.1); border-radius: 99px; }
44
+ .shell { min-height: 100vh; display: grid; grid-template-columns: 248px 1fr; }
45
+ aside { border-right: 1px solid var(--line); padding: 22px 16px; background: linear-gradient(180deg, rgba(11,16,32,.55), rgba(5,7,15,.2)); position: sticky; top: 0; height: 100vh; }
46
+ main { padding: 28px 30px; max-width: 1200px; width: 100%; }
47
+ .brand { display: flex; align-items: center; gap: 9px; font-size: 14.5px; font-weight: 700; letter-spacing: -.01em; margin-bottom: 5px; color: #F8FAFC; }
48
+ .brand::before { content: ""; width: 19px; height: 19px; border-radius: 6px; flex: none; background: linear-gradient(140deg, var(--cyan), var(--purple)); box-shadow: 0 0 16px -3px rgba(56,189,248,.7); }
49
+ .sub { color: var(--faint); font-size: 12px; line-height: 1.5; margin-bottom: 22px; }
50
+ .nav { display: grid; gap: 3px; }
51
+ .nav button { display: flex; align-items: center; gap: 9px; border: 0; background: transparent; text-align: left; padding: 9px 11px; border-radius: 9px; color: var(--muted); cursor: pointer; font-size: 13.5px; transition: background .12s, color .12s; }
52
+ .nav button:hover { background: rgba(255,255,255,.04); color: var(--ink); }
53
+ .nav button.active { background: linear-gradient(90deg, rgba(56,189,248,.14), rgba(56,189,248,.04)); color: #F8FAFC; font-weight: 600; box-shadow: inset 2px 0 0 var(--cyan); }
54
+ .top { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; margin-bottom: 20px; }
55
+ h1 { font-size: 23px; margin: 0 0 5px; letter-spacing: -.02em; font-weight: 650; }
56
+ .meta { color: var(--faint); font-size: 12px; }
57
+ .banner { background: var(--panel); border: 1px solid var(--line2); backdrop-filter: blur(10px); border-radius: 13px; padding: 15px 17px; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 18px; position: relative; overflow: hidden; }
58
+ .banner::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--cyan); }
59
+ .banner.ready::before { background: var(--green); }
60
+ .banner strong { display: block; margin-bottom: 3px; font-weight: 600; color: #F8FAFC; }
41
61
  .grid { display: grid; gap: 16px; }
42
- .two { grid-template-columns: minmax(0, 1.2fr) minmax(320px, .8fr); align-items: start; }
43
- .panel { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow); }
44
- .panel h2 { font-size: 16px; padding: 15px 16px 0; margin: 0; }
45
- .step { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 12px; padding: 13px 16px; border-top: 1px solid var(--line); align-items: center; }
62
+ .two { grid-template-columns: minmax(0, 1.25fr) minmax(330px, .75fr); align-items: start; }
63
+ .panel { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); overflow: hidden; }
64
+ .panel h2 { font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); padding: 15px 16px 9px; margin: 0; font-weight: 600; }
65
+ .step { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: 13px; padding: 14px 16px; border-top: 1px solid var(--line); align-items: center; }
46
66
  .step:first-of-type { border-top: 0; }
47
- .step.done { color: var(--muted); padding-top: 9px; padding-bottom: 9px; }
48
- .step.frontier { background: #f2f7fb; outline: 2px solid rgba(35, 100, 168, .18); outline-offset: -2px; }
49
- .dot { width: 14px; height: 14px; border-radius: 50%; margin-top: 3px; background: var(--muted); }
50
- .ready .dot { background: var(--green); }
51
- .action_needed .dot { background: var(--amber); }
52
- .blocked .dot { background: var(--red); }
53
- .working .dot { background: var(--blue); animation: pulse 1.2s infinite; }
54
- .attention .dot { background: var(--gold); }
55
- .absent .dot { background: #a7a29a; }
56
- @keyframes pulse { 0%,100% { opacity: .45; } 50% { opacity: 1; } }
57
- .label { font-weight: 750; margin-bottom: 3px; }
58
- .hint { color: var(--muted); font-size: 13px; line-height: 1.4; }
59
- .btn { border: 1px solid #25211b; background: #25211b; color: white; border-radius: 7px; min-height: 36px; padding: 0 12px; cursor: pointer; white-space: nowrap; }
60
- .btn.secondary { background: #fff; color: var(--ink); border-color: var(--line); }
61
- .btn.gold { background: var(--gold); border-color: var(--gold); }
62
- .btn:disabled { opacity: .45; cursor: not-allowed; }
63
- .kv { display: grid; gap: 9px; padding: 15px 16px; }
64
- .row { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-top: 1px solid var(--line); padding: 11px 16px; }
65
- .row:first-child { border-top: 0; }
66
- .pill { border: 1px solid var(--line); border-radius: 999px; padding: 3px 8px; font-size: 12px; color: var(--muted); white-space: nowrap; }
67
- .pill.ready { color: var(--green); border-color: rgba(32,122,76,.25); background: rgba(32,122,76,.08); }
68
- .pill.warn { color: var(--amber); border-color: rgba(154,100,23,.25); background: rgba(154,100,23,.08); }
69
- .pill.bad { color: var(--red); border-color: rgba(163,58,50,.25); background: rgba(163,58,50,.08); }
70
- .activity { max-height: 460px; overflow: auto; padding: 8px 0; }
71
- .event { padding: 10px 16px; border-top: 1px solid var(--line); font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12px; color: #37332d; }
67
+ .step.done { opacity: .62; padding-top: 11px; padding-bottom: 11px; }
68
+ .step.frontier { background: linear-gradient(90deg, rgba(56,189,248,.07), transparent); box-shadow: inset 2px 0 0 var(--cyan); }
69
+ .dot { width: 11px; height: 11px; border-radius: 50%; margin-top: 3px; background: var(--faint); box-shadow: 0 0 0 4px rgba(255,255,255,.03); }
70
+ .ready .dot { background: var(--green); box-shadow: 0 0 10px -1px var(--green); }
71
+ .action_needed .dot { background: var(--amber); box-shadow: 0 0 10px -1px var(--amber); }
72
+ .blocked .dot { background: var(--red); box-shadow: 0 0 10px -1px var(--red); }
73
+ .working .dot { background: var(--cyan); animation: pulse 1.2s infinite; box-shadow: 0 0 10px -1px var(--cyan); }
74
+ .attention .dot { background: var(--gold); box-shadow: 0 0 10px -1px var(--gold); }
75
+ .absent .dot { background: var(--faint); }
76
+ @keyframes pulse { 0%,100% { opacity: .4; } 50% { opacity: 1; } }
77
+ .label { font-weight: 600; margin-bottom: 3px; color: #EAEFF8; font-size: 13.5px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
78
+ .hint { color: var(--muted); font-size: 12.5px; line-height: 1.5; }
79
+ .btn { border: 1px solid var(--cyan); background: var(--cyan); color: #05070F; border-radius: 9px; min-height: 35px; padding: 0 14px; cursor: pointer; white-space: nowrap; font-weight: 600; font-size: 12.5px; transition: filter .12s, transform .04s; box-shadow: 0 0 20px -8px rgba(56,189,248,.9); }
80
+ .btn:hover { filter: brightness(1.08); }
81
+ .btn:active { transform: translateY(1px); }
82
+ .btn.secondary { background: rgba(255,255,255,.04); color: var(--ink); border-color: var(--line2); box-shadow: none; }
83
+ .btn.secondary:hover { background: rgba(255,255,255,.08); }
84
+ .btn.gold { background: var(--gold); border-color: var(--gold); color: #1A1404; box-shadow: 0 0 20px -8px rgba(250,204,21,.9); }
85
+ .btn:disabled { opacity: .4; cursor: not-allowed; box-shadow: none; filter: none; }
86
+ .kv { display: grid; gap: 9px; padding: 13px 16px; }
87
+ .row { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-top: 1px solid var(--line); padding: 12px 16px; font-size: 13px; }
88
+ .row:first-of-type { border-top: 0; }
89
+ .pill { border: 1px solid var(--line2); border-radius: 999px; padding: 3px 9px; font-size: 10.5px; letter-spacing: .04em; color: var(--muted); white-space: nowrap; font-weight: 600; }
90
+ .pill.ready { color: var(--green); border-color: rgba(34,197,94,.3); background: rgba(34,197,94,.1); }
91
+ .pill.warn { color: var(--amber); border-color: rgba(251,191,36,.3); background: rgba(251,191,36,.1); }
92
+ .pill.bad { color: var(--red); border-color: rgba(248,113,113,.3); background: rgba(248,113,113,.1); }
93
+ .activity { max-height: 520px; overflow: auto; padding: 4px 0; }
94
+ .event { padding: 9px 16px; border-top: 1px solid var(--line); font-size: 11.5px; color: #B6C0D4; line-height: 1.5; }
72
95
  .event:first-child { border-top: 0; }
73
96
  .form { display: grid; gap: 12px; padding: 16px; }
74
- label { display: grid; gap: 5px; font-size: 13px; color: var(--muted); }
75
- input, select { width: 100%; border: 1px solid var(--line); border-radius: 7px; padding: 10px 11px; background: #fff; color: var(--ink); }
76
- pre { margin: 0; padding: 14px 16px; overflow: auto; border-top: 1px solid var(--line); font-size: 12px; background: #fbfaf8; }
97
+ label { display: grid; gap: 6px; font-size: 12px; color: var(--muted); }
98
+ input, select { width: 100%; border: 1px solid var(--line2); border-radius: 9px; padding: 10px 12px; background: rgba(5,7,15,.6); color: var(--ink); font-size: 12.5px; }
99
+ input:focus, select:focus { outline: none; border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(56,189,248,.14); }
100
+ input::placeholder { color: var(--faint); }
101
+ option { background: #0B1020; }
102
+ pre { margin: 0; padding: 14px 16px; overflow: auto; border-top: 1px solid var(--line); font-size: 11.5px; background: rgba(5,7,15,.5); color: #9FB0C8; line-height: 1.55; }
77
103
  .hidden { display: none !important; }
78
- .toast { position: fixed; right: 18px; bottom: 18px; width: min(560px, calc(100vw - 36px)); background: #25211b; color: white; border-radius: 8px; padding: 12px 14px; box-shadow: var(--shadow); font-size: 13px; white-space: pre-wrap; }
104
+ .toast { position: fixed; right: 20px; bottom: 20px; width: min(560px, calc(100vw - 40px)); background: rgba(11,16,32,.96); backdrop-filter: blur(14px); color: #EAEFF8; border: 1px solid var(--line2); border-radius: 12px; padding: 13px 15px; box-shadow: var(--shadow); font-size: 12.5px; white-space: pre-wrap; line-height: 1.5; }
79
105
  @media (max-width: 850px) {
80
106
  .shell { grid-template-columns: 1fr; }
81
- aside { border-right: 0; border-bottom: 1px solid var(--line); }
107
+ aside { border-right: 0; border-bottom: 1px solid var(--line); position: static; height: auto; }
82
108
  main { padding: 18px; }
83
109
  .two { grid-template-columns: 1fr; }
84
110
  .top, .banner, .row { flex-direction: column; align-items: stretch; }
85
- .step { grid-template-columns: 22px minmax(0, 1fr); }
111
+ .step { grid-template-columns: 18px minmax(0, 1fr); }
86
112
  .step .btn { grid-column: 2; justify-self: start; }
87
113
  }
88
114
  </style>
@@ -93,6 +119,8 @@ export function dashboardHtml() {
93
119
  const token = new URLSearchParams(location.search).get("token") || "";
94
120
  let snapshot = null;
95
121
  let active = "home";
122
+ let autoFocused = false;
123
+ let userSelectedTab = false;
96
124
  let toastTimer = null;
97
125
  const app = document.getElementById("app");
98
126
 
@@ -110,6 +138,10 @@ export function dashboardHtml() {
110
138
 
111
139
  async function load() {
112
140
  snapshot = await api("/api/readiness");
141
+ if (!autoFocused && !userSelectedTab && snapshot.readiness && !snapshot.readiness.nextAction && snapshot.readiness.listener.running) {
142
+ active = "activity";
143
+ autoFocused = true;
144
+ }
113
145
  render();
114
146
  }
115
147
 
@@ -119,6 +151,11 @@ export function dashboardHtml() {
119
151
  render();
120
152
  return;
121
153
  }
154
+ if (action.id === "host.token.focus") {
155
+ active = "advanced";
156
+ render();
157
+ return;
158
+ }
122
159
  if (action.manual) {
123
160
  showToast(action.command || "Manual step required.");
124
161
  return;
@@ -134,6 +171,24 @@ export function dashboardHtml() {
134
171
  }
135
172
  }
136
173
 
174
+ // No-code pairing: once pairing has started (the approval page is open in the
175
+ // browser), poll quietly until the device is approved — the human just clicks
176
+ // Approve over there, never copies a code, never clicks "Check approval" here.
177
+ let pairPoller = null;
178
+ async function pollPairSilently() {
179
+ try {
180
+ const result = await api("/api/actions", { method: "POST", body: JSON.stringify({ action: "pair.poll" }) });
181
+ snapshot = result.snapshot;
182
+ if (!snapshot.pendingPair) showToast("Device paired. Connecting your listener…");
183
+ render();
184
+ } catch (err) { /* keep polling; transient */ }
185
+ }
186
+ function ensurePairPolling() {
187
+ const pending = snapshot && snapshot.pendingPair;
188
+ if (pending && !pairPoller) pairPoller = setInterval(pollPairSilently, 3000);
189
+ else if (!pending && pairPoller) { clearInterval(pairPoller); pairPoller = null; }
190
+ }
191
+
137
192
  function statusText(status) {
138
193
  return {
139
194
  ready: "READY",
@@ -157,6 +212,7 @@ export function dashboardHtml() {
157
212
  }
158
213
  app.innerHTML = '<div class="shell"><aside>' + nav() + '</aside><main>' + page(r) + '</main></div>' + '<div id="toast" class="toast hidden"></div>';
159
214
  bind();
215
+ ensurePairPolling();
160
216
  }
161
217
 
162
218
  function nav() {
@@ -181,7 +237,7 @@ export function dashboardHtml() {
181
237
  function homePage(r) {
182
238
  const next = r.nextAction;
183
239
  const pair = snapshot.pendingPair
184
- ? '<div class="banner"><div><strong>Approve this device: ' + esc(snapshot.pendingPair.user_code) + '</strong><div class="meta">The approval page was opened. After approving it in Agent Rooms, check status here.</div></div><button class="btn" data-action="' + encodeURIComponent(JSON.stringify({ id: "pair.poll", label: "Check approval" })) + '">Check approval</button></div>'
240
+ ? '<div class="banner"><div><strong>Waiting for approval — code ' + esc(snapshot.pendingPair.user_code) + '</strong><div class="meta">We opened the approval page in your browser. Click <b>Approve &amp; pair</b> there (you\'re already signed in) this pairs automatically, no code to copy.</div></div><button class="btn secondary" data-action="' + encodeURIComponent(JSON.stringify({ id: "pair.poll", label: "Check now" })) + '">Check now</button></div>'
185
241
  : "";
186
242
  const banner = next
187
243
  ? '<div class="banner"><div><strong>Next: ' + esc(next.label) + '</strong><div class="meta">' + esc(next.hint) + '</div></div>' + actionButton(next.action) + '</div>'
@@ -197,30 +253,52 @@ export function dashboardHtml() {
197
253
  function sideStatus(r) {
198
254
  return '<section class="panel"><h2>Local Truth</h2>' +
199
255
  '<div class="row"><span>Device</span><span class="pill ' + (r.device.paired ? "ready" : "warn") + '">' + (r.device.paired ? "PAIRED" : "NOT PAIRED") + '</span></div>' +
200
- '<div class="row"><span>Listener</span><span class="pill ' + (r.listener.running ? "ready" : "warn") + '">' + (r.listener.running ? "RUNNING" : "STOPPED") + '</span></div>' +
201
- Object.values(r.hosts).map((h) => '<div class="row"><span>' + esc(h.label) + '<br><span class="meta">' + esc(h.version || h.detail) + '</span></span><span class="pill ' + (h.detected ? "ready" : "bad") + '">' + (h.detected ? "DETECTED" : "MISSING") + '</span></div>').join("") +
256
+ '<div class="row"><span>Listener<br><span class="meta">' + (r.listener.running ? 'Serving ' + esc(r.listener.servingCount) + ' instance(s)' : 'Stopped') + '</span></span><span>' + listenerControls(r) + '</span></div>' +
257
+ '<div class="row"><span>Dashboard</span><span>' + (r.dashboard.updateAvailable ? actionButton({ id: "dashboard.update", label: "Update" }, "gold") + ' ' : '') + '<span class="pill ' + (r.dashboard.updateAvailable ? "warn" : "ready") + '">' + (r.dashboard.updateAvailable ? "UPDATE AVAILABLE" : "UP TO DATE") + '</span></span></div>' +
258
+ Object.values(r.hosts).map((h) => '<div class="row"><span>' + esc(h.label) + '<br><span class="meta">' + esc(h.version || h.detail) + '</span></span><span class="pill ' + (!h.detected ? "bad" : h.versionOk ? "ready" : "warn") + '">' + (!h.detected ? "MISSING" : h.versionOk ? "DETECTED" : "UPDATE") + '</span></div>').join("") +
202
259
  '<h2>Diagnose</h2>' + r.diagnostics.map((d) => '<div class="row"><span><strong>' + esc(d.symptom) + '</strong><br><span class="meta">' + esc(d.cause) + '</span></span>' + actionButton(d.action, "secondary") + '</div>').join("") +
203
260
  '</section>';
204
261
  }
205
262
 
263
+ function listenerControls(r) {
264
+ if (r.listener.running) {
265
+ return actionButton({ id: "listener.restart", label: "Restart" }, "secondary") + ' ' + actionButton({ id: "listener.stop", label: "Stop" }, "secondary");
266
+ }
267
+ if (r.device.paired && r.agents.some((a) => !a.paused)) {
268
+ return actionButton({ id: "listener.start", label: "Start" }, "secondary");
269
+ }
270
+ return '<span class="pill warn">WAITING</span>';
271
+ }
272
+
206
273
  function agentsPage(r) {
207
274
  return header("Agents", r) + '<div class="grid two"><section class="panel"><h2>Bindings</h2>' +
208
- (r.agents.length ? r.agents.map((a) => '<div class="row"><span><strong>' + esc(a.agent) + '</strong><br><span class="meta">' + esc(a.host) + ' - ' + esc(a.workspace) + '<br>rooms: ' + esc(a.rooms.join(", ")) + '</span></span><span class="pill ' + (a.workspaceExists ? "ready" : "warn") + '">' + (a.workspaceExists ? "READY" : "PATH MISSING") + '</span></div>').join("") : '<div class="kv meta">No bindings yet.</div>') +
275
+ (r.agents.length ? r.agents.map(agentRow).join("") : '<div class="kv meta">No bindings yet.</div>') +
209
276
  '</section><section class="panel"><h2>Add / Replace Binding</h2><form class="form" id="bindingForm">' +
210
277
  '<label>Agent plate<input name="agent" placeholder="BRNL-AGT-XXXXXXXX" required /></label>' +
211
278
  '<label>Room id(s)<input name="rooms" placeholder="room_1, room_2" required /></label>' +
212
279
  '<label>Workspace path<input name="workspace" placeholder="D:\\\\your-project" required /></label>' +
213
- '<label>Host<select name="host"><option value="claude_code">Claude Code</option><option value="codex">Codex</option></select></label>' +
280
+ '<label>Host<select name="host"><option value="claude_code">Claude Code</option><option value="codex">Codex</option><option value="gemini">Gemini CLI</option><option value="cursor">Cursor CLI</option><option value="openclaw">OpenClaw</option></select></label>' +
214
281
  '<button class="btn" type="submit">Save binding</button></form></section></div>';
215
282
  }
216
283
 
284
+ function agentRow(a) {
285
+ const status = a.paused ? "PAUSED" : a.workspaceExists ? "READY" : "PATH MISSING";
286
+ const cls = a.paused ? "warn" : a.workspaceExists ? "ready" : "warn";
287
+ const pauseAction = a.paused
288
+ ? { id: "agent.resume", label: "Resume", payload: { agent: a.agent } }
289
+ : { id: "agent.pause", label: "Pause", payload: { agent: a.agent } };
290
+ const removeAction = { id: "config.binding.remove", label: "Remove", payload: { agent: a.agent, workspace: a.workspace } };
291
+ const cost = a.host === "codex" ? '<br><span class="meta">Waking this agent uses your ChatGPT/Codex account usage.</span>' : "";
292
+ return '<div class="row"><span><strong>' + esc(a.agent) + '</strong><br><span class="meta">' + esc(a.host) + ' - ' + esc(a.workspace) + '<br>rooms: ' + esc(a.rooms.join(", ")) + '</span>' + cost + '</span><span><span class="pill ' + cls + '">' + status + '</span><br>' + actionButton(pauseAction, "secondary") + ' ' + actionButton(removeAction, "secondary") + '</span></div>';
293
+ }
294
+
217
295
  function activityPage() {
218
296
  const rows = (snapshot.activity || []).slice().reverse().map((e) => '<div class="event">[' + new Date(e.at).toLocaleTimeString() + '] ' + esc(e.level.toUpperCase()) + ' ' + esc(e.message) + '</div>').join("");
219
297
  return header("Activity", snapshot.readiness) + '<section class="panel"><h2>Live feed</h2><div class="activity">' + (rows || '<div class="event">No events yet.</div>') + '</div></section>';
220
298
  }
221
299
 
222
300
  function advancedPage(r) {
223
- return header("Advanced", r) + '<div class="grid two"><section class="panel"><h2>Commands</h2><pre>' + esc(r.advanced.commands.join("\n")) + '</pre></section><section class="panel"><h2>Raw Config</h2><pre>' + esc(JSON.stringify(r.advanced.rawConfig, null, 2)) + '</pre></section></div>';
301
+ return header("Advanced", r) + '<div class="grid two"><section class="panel"><h2>Commands</h2><pre>' + esc(r.advanced.commands.join("\n")) + '</pre><h2>Codex Bearer Token</h2><form class="form" id="tokenForm"><label>Agent Rooms token<input name="token" type="password" placeholder="Paste token for Codex MCP sessions" /></label><button class="btn" type="submit">Save token</button><button class="btn secondary" type="button" data-action="' + encodeURIComponent(JSON.stringify({ id: "host.clearToken", label: "Clear token", host: "codex", payload: { host: "codex" } })) + '">Clear token</button><div class="meta">Stored locally in the dashboard config; not shown back in the UI.</div></form></section><section class="panel"><h2>Raw Config</h2><pre>' + esc(JSON.stringify(r.advanced.rawConfig, null, 2)) + '</pre></section></div>';
224
302
  }
225
303
 
226
304
  function actionButton(action, style = "") {
@@ -229,7 +307,7 @@ export function dashboardHtml() {
229
307
  }
230
308
 
231
309
  function bind() {
232
- document.querySelectorAll("[data-tab]").forEach((btn) => btn.addEventListener("click", () => { active = btn.dataset.tab; render(); }));
310
+ document.querySelectorAll("[data-tab]").forEach((btn) => btn.addEventListener("click", () => { userSelectedTab = true; active = btn.dataset.tab; render(); }));
233
311
  document.querySelectorAll("[data-refresh]").forEach((btn) => btn.addEventListener("click", load));
234
312
  document.querySelectorAll("[data-action]").forEach((btn) => btn.addEventListener("click", () => act(JSON.parse(decodeURIComponent(btn.dataset.action)))));
235
313
  const form = document.getElementById("bindingForm");
@@ -243,6 +321,15 @@ export function dashboardHtml() {
243
321
  host: String(data.get("host") || "claude_code")
244
322
  });
245
323
  });
324
+ const tokenForm = document.getElementById("tokenForm");
325
+ if (tokenForm) tokenForm.addEventListener("submit", (event) => {
326
+ event.preventDefault();
327
+ const data = new FormData(tokenForm);
328
+ act({ id: "host.saveToken", label: "Save token", host: "codex" }, {
329
+ host: "codex",
330
+ token: String(data.get("token") || "")
331
+ });
332
+ });
246
333
  }
247
334
 
248
335
  function showToast(message) {
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/dashboard/ui.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC3B,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0QX,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/dashboard/ui.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC3B,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiWX,CAAC;AACT,CAAC"}
package/dist/hosts.js CHANGED
@@ -5,7 +5,7 @@
5
5
  //
6
6
  // Safety (§9, §10): we never pass --dangerously-skip-permissions. Claude is
7
7
  // constrained to the room MCP tools + read-only workspace ops via --allowedTools;
8
- // Codex relies on its sandbox (--full-auto). A --max-turns cap bounds runaway loops.
8
+ // Codex runs with workspace-write sandboxing. A --max-turns cap bounds runaway loops.
9
9
  import { spawnSync } from "node:child_process";
10
10
  import { existsSync } from "node:fs";
11
11
  import { homedir } from "node:os";
@@ -85,7 +85,7 @@ export const claudeAdapter = {
85
85
  if (spec.sessionId) {
86
86
  args.push("--resume", spec.sessionId);
87
87
  }
88
- return { command: this.bin, args, cwd: spec.workspace, stdin: spec.prompt };
88
+ return { command: this.bin, args, cwd: spec.workspace, stdin: spec.prompt, env: spec.env };
89
89
  },
90
90
  buildMcpAdd(apiBase) {
91
91
  return { command: this.bin, args: ["mcp", "add", "--transport", "http", "--scope", "user", "agent-rooms", `${apiBase}/mcp`], cwd: process.cwd() };
@@ -101,17 +101,21 @@ export const codexAdapter = {
101
101
  name: "codex",
102
102
  bin: "codex",
103
103
  allowedTools: ROOM_TOOLS,
104
- // TODO: confirm the Codex on-disk skills dir before auto-installing there.
105
- skillDir: null,
104
+ // Codex adopted the Agent Skills standard; it loads skills from ~/.codex/skills
105
+ // (the $skill-installer convention). Installing the bundled folder here makes a
106
+ // woken Codex agent room-fluent and shortens its wake prompt.
107
+ skillDir: join(homedir(), ".codex", "skills"),
106
108
  buildWake(spec) {
107
109
  // `codex exec -` reads the prompt from stdin. Keep the multi-line wake
108
- // prompt out of argv so Windows shell resolution cannot split it.
110
+ // prompt out of argv so Windows shell resolution cannot split it. The sandbox
111
+ // is Codex's own (workspace-write); we don't override the agent's isolation
112
+ // (spec 14: that's the vendor's job, not the broker's).
109
113
  const base = ["exec", "--json", "--skip-git-repo-check", "--sandbox", "workspace-write"];
110
114
  if (spec.sessionId) {
111
115
  base.push("resume", spec.sessionId);
112
116
  }
113
117
  base.push("-");
114
- return { command: this.bin, args: base, cwd: spec.workspace, stdin: spec.prompt };
118
+ return { command: this.bin, args: base, cwd: spec.workspace, stdin: spec.prompt, env: spec.env };
115
119
  },
116
120
  buildMcpAdd(apiBase) {
117
121
  return {
@@ -127,9 +131,111 @@ export const codexAdapter = {
127
131
  return firstJsonField(stdout, ["session_id", "thread_id"]);
128
132
  }
129
133
  };
134
+ // ── Additional wakeable hosts (native spec §4.3–4.5) ────────────────────────
135
+ // These follow the documented per-host commands from Spec 1. Exact flag names
136
+ // drift across CLI versions (the spec flags this explicitly); where a behavior
137
+ // is version-dependent we take the safe floor — prompt via stdin (never argv,
138
+ // the mangling bug), fresh-spawn when headless resume isn't reliably emitted —
139
+ // and annotate what to re-verify against the user's installed build.
140
+ export const geminiAdapter = {
141
+ name: "gemini",
142
+ bin: "gemini",
143
+ allowedTools: ROOM_TOOLS,
144
+ // Gemini CLI adopted Agent Skills; loads from ~/.gemini/skills.
145
+ skillDir: join(homedir(), ".gemini", "skills"),
146
+ buildWake(spec) {
147
+ // Piping the prompt on stdin makes the run non-TTY → headless, and keeps the
148
+ // multi-line prompt out of argv. `--yolo` is Gemini's auto-approve (verify the
149
+ // flag name on the installed version — older builds used --approval-mode).
150
+ // Headless resume-by-id was historically not emitted in JSON output, so we
151
+ // take the universal floor: fresh spawn + injected thread context.
152
+ const args = ["--output-format", "json", "--yolo"];
153
+ return { command: this.bin, args, cwd: spec.workspace, stdin: spec.prompt, env: spec.env };
154
+ },
155
+ buildMcpAdd(apiBase) {
156
+ // Bearer parity with the wake path; some builds want the header in
157
+ // ~/.gemini/settings.json instead of a flag — verify on install.
158
+ return {
159
+ command: this.bin,
160
+ args: ["mcp", "add", "--transport", "http", "agent-rooms", `${apiBase}/mcp`, "--header", "Authorization: Bearer ${AGENT_ROOMS_TOKEN}"],
161
+ cwd: process.cwd()
162
+ };
163
+ },
164
+ buildMcpRemove() {
165
+ return { command: this.bin, args: ["mcp", "remove", "agent-rooms"], cwd: process.cwd() };
166
+ },
167
+ parseSessionId(stdout) {
168
+ return firstJsonField(stdout, ["session_id", "sessionId"]);
169
+ }
170
+ };
171
+ export const cursorAdapter = {
172
+ name: "cursor",
173
+ bin: "cursor-agent",
174
+ allowedTools: ROOM_TOOLS,
175
+ skillDir: join(homedir(), ".cursor", "skills"),
176
+ buildWake(spec) {
177
+ // `-p` is print/headless. `--force` is REQUIRED: without it, `-p` hangs
178
+ // indefinitely when workspace trust is required (spec §4.4 gotcha). Prompt on
179
+ // stdin to dodge argv mangling.
180
+ const args = ["-p", "--output-format", "json", "--force"];
181
+ if (spec.sessionId) {
182
+ args.push("--resume", spec.sessionId);
183
+ }
184
+ return { command: this.bin, args, cwd: spec.workspace, stdin: spec.prompt, env: spec.env };
185
+ },
186
+ buildMcpAdd(apiBase) {
187
+ return {
188
+ command: this.bin,
189
+ args: ["mcp", "add", "agent-rooms", "--transport", "http", `${apiBase}/mcp`],
190
+ cwd: process.cwd()
191
+ };
192
+ },
193
+ buildMcpRemove() {
194
+ return { command: this.bin, args: ["mcp", "remove", "agent-rooms"], cwd: process.cwd() };
195
+ },
196
+ parseSessionId(stdout) {
197
+ return firstJsonField(stdout, ["session_id", "sessionId", "resume_session"]);
198
+ }
199
+ };
200
+ export const openclawAdapter = {
201
+ name: "openclaw",
202
+ bin: "openclaw",
203
+ allowedTools: ROOM_TOOLS,
204
+ // OpenClaw skills come from ClawHub; on-disk dir ~/.openclaw/skills.
205
+ skillDir: join(homedir(), ".openclaw", "skills"),
206
+ buildWake(spec) {
207
+ // NOTE (spec §10.5, OPEN DECISION): OpenClaw is a gateway/meta-host. The clean
208
+ // integration dispatches a session via the running gateway (ACP/acpx with
209
+ // resumeSessionId), NOT a one-shot exec. This engine-level `run` form is the
210
+ // best-effort floor so a bound OpenClaw agent still wakes; revisit once the
211
+ // gateway-vs-engine decision lands. Gateway process must be alive.
212
+ const args = ["run", "--json"];
213
+ if (spec.sessionId) {
214
+ args.push("--resume", spec.sessionId);
215
+ }
216
+ args.push("-");
217
+ return { command: this.bin, args, cwd: spec.workspace, stdin: spec.prompt, env: spec.env };
218
+ },
219
+ buildMcpAdd(apiBase) {
220
+ return {
221
+ command: this.bin,
222
+ args: ["mcp", "add", "agent-rooms", "--transport", "streamable-http", "--url", `${apiBase}/mcp`],
223
+ cwd: process.cwd()
224
+ };
225
+ },
226
+ buildMcpRemove() {
227
+ return { command: this.bin, args: ["mcp", "remove", "agent-rooms"], cwd: process.cwd() };
228
+ },
229
+ parseSessionId(stdout) {
230
+ return firstJsonField(stdout, ["session_id", "sessionId", "resumeSessionId"]);
231
+ }
232
+ };
130
233
  const ADAPTERS = {
131
234
  claude_code: claudeAdapter,
132
- codex: codexAdapter
235
+ codex: codexAdapter,
236
+ gemini: geminiAdapter,
237
+ cursor: cursorAdapter,
238
+ openclaw: openclawAdapter
133
239
  };
134
240
  export function getAdapter(host) {
135
241
  return ADAPTERS[host] ?? null;
package/dist/hosts.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../src/hosts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../src/hosts.ts"],"names":[],"mappings":"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"}