readyroom 0.1.5 → 0.1.7

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 CHANGED
@@ -57,7 +57,7 @@ These words are used exactly, in code, comments, tool descriptions, and docs. No
57
57
  - **ticket** — one pending request: `{ id, stream, question, options, context, urgency, status, created_at, expires_at }`.
58
58
  - **stream** — which agent asked. Defaults to `$READYROOM_STREAM`, else `basename(cwd)`.
59
59
  - **drain** — the human answering tickets from the page.
60
- - **heads-up page** — the single HTML page served at `GET /`.
60
+ - **readyroom page** — the single HTML page served at `GET /`.
61
61
 
62
62
  The tool names (`ask_human`, `wait_for_answer`, `list_pending`, `cancel_ticket`) are the
63
63
  agent-facing contract and do not change with the product name. The product name is a separate
@@ -222,7 +222,7 @@ handles `SIGTERM`.
222
222
 
223
223
  ### Cloudflare Worker
224
224
 
225
- Always-on, reachable from anywhere, no box to patch. The Worker serves the heads-up page and
225
+ Always-on, reachable from anywhere, no box to patch. The Worker serves the readyroom page and
226
226
  the Streamable HTTP MCP endpoint from the same origin, backed by one SQLite Durable Object
227
227
  instance.
228
228
 
@@ -526,7 +526,7 @@ The Worker has no state dir, no bind address, and no daemon role. Three conseque
526
526
  1. **The token is mandatory.** There is no loopback and no safe fallback, so a token-less
527
527
  request to any `/api/*` route is rejected. (On the Node target, a missing token is an allow —
528
528
  the bind refusal rule guarantees a token-less server is only reachable on loopback.)
529
- 2. **`/api/events` returns `501`** with a short plain-text body. The heads-up page's polling
529
+ 2. **`/api/events` returns `501`** with a short plain-text body. The readyroom page's polling
530
530
  fallback carries the Worker target; no Durable-Object-held stream fleet is built for v1.
531
531
  3. **`wait_for_answer` clamps its timeout** to a short window (5 seconds) and returns
532
532
  `status: "pending"` promptly rather than erroring. This is the **one place the three targets
@@ -534,7 +534,7 @@ The Worker has no state dir, no bind address, and no daemon role. Three conseque
534
534
  protocol — call again later — is already the correct handling, so no agent needs to know
535
535
  which target it is talking to.
536
536
 
537
- ## The heads-up page
537
+ ## The readyroom page
538
538
 
539
539
  The page is a **status board**, not a chat log. It shows what is waiting and clears when you
540
540
  have answered — which is why there is no markdown parser and no message history.
@@ -552,7 +552,7 @@ network otherwise cut. It is inlined at build time into each target's bundle.
552
552
  option buttons, a free-text field, and an Answer button.
553
553
  - **Keyboard-first.** `j`/`k` move between tickets, `1`-`5` pick an option, `Enter` submits, `u`
554
554
  undoes the last answer. Draining a queue with a mouse is the slow path.
555
- - **Tab title carries the count.** `(3) heads-up`.
555
+ - **Tab title carries the count.** `(3) readyroom`.
556
556
  - **No colour-only signalling.** Urgency and status are carried by text and borders as well as
557
557
  hue, so the page is legible on an e-ink display and in grayscale print.
558
558
  - **No animation on the critical path.** Respects `prefers-reduced-motion`. No hover-only
@@ -570,7 +570,7 @@ network otherwise cut. It is inlined at build time into each target's bundle.
570
570
 
571
571
  ```
572
572
  GET /healthz -> 200, body "ok"
573
- GET / -> the heads-up page (index.html)
573
+ GET / -> the readyroom page (index.html)
574
574
  GET /api/tickets -> { tickets: Ticket[] } pending + last 5 min of answered
575
575
  GET /api/events -> text/event-stream of ticket changes (501 on the Worker)
576
576
  POST /api/answer -> { id, answer, answered_by? } -> 200 | 404 | 409 already answered
package/dist/server.mjs CHANGED
@@ -7506,7 +7506,7 @@ var public_default = `<!DOCTYPE html>
7506
7506
  <head>
7507
7507
  <meta charset="utf-8">
7508
7508
  <meta name="viewport" content="width=device-width, initial-scale=1">
7509
- <title>heads-up</title>
7509
+ <title>readyroom</title>
7510
7510
  <style>
7511
7511
  /* No external fonts, no external origins, no images fetched over the network.
7512
7512
  Everything below is self-contained so the page renders with the network cut. */
@@ -7660,7 +7660,7 @@ var public_default = `<!DOCTYPE html>
7660
7660
  </head>
7661
7661
  <body>
7662
7662
  <header>
7663
- <h1>heads-up</h1>
7663
+ <h1>readyroom</h1>
7664
7664
  <p class="sub">Drain the queue. <kbd>j</kbd>/<kbd>k</kbd> move &middot; <kbd>1</kbd>-<kbd>5</kbd> pick &middot; <kbd>Enter</kbd> answer &middot; <kbd>u</kbd> undo</p>
7665
7665
  <div id="status" class="banner" role="status" aria-live="polite">
7666
7666
  <span class="tag">Status:</span> <span id="status-text">starting</span>
@@ -8155,7 +8155,7 @@ var public_default = `<!DOCTYPE html>
8155
8155
  var recent = recentTickets();
8156
8156
 
8157
8157
  /* requirement 5: tab title carries the count */
8158
- document.title = pending.length > 0 ? "(" + pending.length + ") heads-up" : "heads-up";
8158
+ document.title = pending.length > 0 ? "(" + pending.length + ") readyroom" : "readyroom";
8159
8159
 
8160
8160
  /* status line */
8161
8161
  var statusText = "idle";
@@ -21259,21 +21259,22 @@ async function attachStdio(server) {
21259
21259
  await server.connect(transport);
21260
21260
  return transport;
21261
21261
  }
21262
- async function attachStreamableHttp(server, options) {
21262
+ async function attachStreamableHttp(serverFactory, options) {
21263
21263
  const log4 = options.log ?? ((message) => process.stderr.write(`readyroom: ${message}
21264
21264
  `));
21265
- const transport = new StreamableHTTPServerTransport({
21266
- sessionIdGenerator: void 0,
21267
- enableJsonResponse: true
21268
- });
21269
- await server.connect(transport);
21270
21265
  const handle = async (req, res) => {
21271
21266
  if (!checkOrigin(req, options.allowedOrigins)) {
21272
21267
  res.writeHead(403, { "content-type": "text/plain; charset=utf-8" });
21273
21268
  res.end("Forbidden: missing or disallowed Origin");
21274
21269
  return;
21275
21270
  }
21271
+ const server = serverFactory();
21272
+ const transport = new StreamableHTTPServerTransport({
21273
+ sessionIdGenerator: void 0,
21274
+ enableJsonResponse: true
21275
+ });
21276
21276
  try {
21277
+ await server.connect(transport);
21277
21278
  await transport.handleRequest(req, res);
21278
21279
  } catch (error2) {
21279
21280
  log4(`mcp transport error on port ${options.port}: ${error2 instanceof Error ? error2.message : String(error2)}`);
@@ -21281,12 +21282,17 @@ async function attachStreamableHttp(server, options) {
21281
21282
  res.writeHead(500, { "content-type": "text/plain; charset=utf-8" });
21282
21283
  res.end("Internal Server Error");
21283
21284
  }
21285
+ } finally {
21286
+ await transport.close().catch(() => {
21287
+ });
21288
+ await server.close().catch(() => {
21289
+ });
21284
21290
  }
21285
21291
  };
21286
21292
  return {
21287
- transport,
21288
21293
  handle,
21289
- close: () => transport.close()
21294
+ close: async () => {
21295
+ }
21290
21296
  };
21291
21297
  }
21292
21298
 
@@ -21462,7 +21468,7 @@ async function runDaemon(config2, defaultStream) {
21462
21468
  await store.load();
21463
21469
  const deps = { store, defaultStream, now };
21464
21470
  const allowedOrigins = buildAllowedOrigins(config2.port, config2.allowedOrigins);
21465
- const mcp = await attachStreamableHttp(createMcpServer(deps), {
21471
+ const mcp = await attachStreamableHttp(() => createMcpServer(deps), {
21466
21472
  port: config2.port,
21467
21473
  allowedOrigins,
21468
21474
  log: log3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "readyroom",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "An MCP server that lets coding agents request a human decision without hijacking whichever window is focused. Agents enqueue a ticket; the human drains the queue from one page when they choose to.",
5
5
  "type": "module",
6
6
  "keywords": [