@khanglvm/relay 0.14.1 → 0.15.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.
package/README.md CHANGED
@@ -80,10 +80,11 @@ unchanged; pick whichever surface fits.
80
80
  | "Type *done* when finished reviewing" | A Submit button; answers, notes, and inline comments returned as JSON |
81
81
  | Feedback = another wall of text | Click any chart point, diagram node, table cell, or sentence to comment — the agent replies and the thread grows on the board |
82
82
 
83
- Everything autosaves in real time (drafts survive timeouts), multiple boards
84
- run at once, and the package has **zero npm runtime dependencies** — plain
85
- Node ≥ 18. Browser-side Chart.js, Mermaid, and Viz.js assets are vendored in
86
- the package and lazy-loaded offline when a board actually needs them.
83
+ Everything autosaves in real time, detached board links keep serving after
84
+ agent timeouts, multiple boards run at once, and the package has **zero npm
85
+ runtime dependencies** — plain Node ≥ 18. Browser-side Chart.js, Mermaid, and
86
+ Viz.js assets are vendored in the package and lazy-loaded offline when a board
87
+ actually needs them.
87
88
 
88
89
  ## Learn more
89
90
 
@@ -92,7 +93,7 @@ the package and lazy-loaded offline when a board actually needs them.
92
93
  | `rly help` | every command at a glance |
93
94
  | `rly git pick` / `rly git cherry-pick` | choose commit actions and rank the order directly on a board; add `--code` to cherry-pick with split code review and per-hunk Apply/Skip/Hold |
94
95
  | `rly git conflict [files…]` | auto-detect unmerged conflict files, or open specific local paths, and return resolved content in `result.blockEdits` |
95
- | `rly share <board-id>` | activate/list/revoke same-Wi-Fi reviewer or collaborator links for a running browser board |
96
+ | `rly share <board-id>` | activate/list/revoke same-Wi-Fi collaborator, reference-only reviewer, or read-only links for a running browser board |
96
97
  | `rly view <file.md> …` | open a quick read-only board that renders local markdown file(s), data files, or PDFs — library-free; great for plans, READMEs, reports, quotes |
97
98
  | `rly install --target <agent>` | write relay's rules into an agent's instruction file — `claude` `codex` `cursor` `copilot` `kiro` `windsurf` `cline` `gemini` `opencode` `droid` `agents`; `--all`, `--scope`, `--print`, `--list` |
98
99
  | `rly upgrade` | update the CLI **and** refresh the skill in one step (safe around open boards; `--dry-run`, `--cli-only`, `--skill-only`) |
@@ -171,9 +172,13 @@ npm test # smoke tests with no external services (spawns real servers, fake-
171
172
  embedded in the payload.
172
173
  - **`pdf` block** — render local `.pdf` files or PDF URLs inline. Local PDFs
173
174
  stream from the board server and are never embedded in the page payload.
174
- - **Durable drafts / rescue** — every autosave mirrors to `localStorage`; a
175
- board whose connection drops blocks further input instead of losing it, and
176
- `rly rescue <id>` re-serves on the same port so an open tab reconnects.
175
+ - **Durable boards / rescue** — detached boards keep serving after timeout
176
+ until Submit or `rly stop`; every autosave mirrors to `localStorage`; a board
177
+ whose connection drops blocks further input instead of losing it, and
178
+ `rly rescue <id>` re-serves on the same port so an open tab reconnects. Active
179
+ same-Wi-Fi share links stay tied to the board and survive a same-port re-serve
180
+ until revoked. Reviewer submissions are isolated, reference-only side reviews
181
+ that never finish the owner's board; read-only links cannot mutate feedback.
177
182
  - Still **zero npm runtime dependencies**, offline, and cross-platform. Vendored
178
183
  browser libraries are loaded only for boards that need them.
179
184
 
@@ -201,8 +206,8 @@ npm test # smoke tests with no external services (spawns real servers, fake-
201
206
  - **Markdown blocks render GFM tables**; element comments moved to an
202
207
  Outline-style right sidebar with inline highlights on commented text.
203
208
  - **Seamless timeouts** — a detached board that runs past its deadline keeps
204
- serving so you can still submit (it lands as `submitted`); the page shows a
205
- calm note instead of disconnecting.
209
+ serving until Submit or explicit stop, so you can still submit (it lands as
210
+ `submitted`); the page shows a calm note instead of disconnecting.
206
211
  - **`rly upgrade`** — install the latest CLI and refresh the skill in one step.
207
212
  - Per-question notes are multi-line textboxes.
208
213
 
package/docs/AGENT.md CHANGED
@@ -75,23 +75,28 @@ results), so partial input is never lost.
75
75
 
76
76
  Browser boards are local-owner only by default. A same-Wi-Fi phone/tablet/other
77
77
  laptop gets a locked page until sharing is explicitly activated. The owner can
78
- click **Share** at the bottom of the board, or you can manage the same links for
79
- the user:
78
+ click the topbar **Share** icon, or you can manage the same links for the user:
80
79
 
81
80
  ```sh
82
81
  rly share b-xxxxx # list active share roles
83
- rly share b-xxxxx --role review # reviewer: add comments only
84
- rly share b-xxxxx --role collab # collaborator: edit/comment/submit
82
+ rly share b-xxxxx --role review # reviewer: answer/comment + submit a side review
83
+ rly share b-xxxxx --role collab # collaborator: edit/comment/final-submit as owner-authorized
84
+ rly share b-xxxxx --role read # read-only viewer: no answers/comments/submit
85
85
  rly share b-xxxxx --role review --revoke # revoke one role
86
86
  rly share b-xxxxx --revoke --all # revoke all active links
87
87
  ```
88
88
 
89
- Use `review` unless the user explicitly wants the other device to submit as the
90
- owner. Reviewers cannot change answers, submit, edit comments, or delete
91
- comments; their autosaves merge new comments into the existing draft.
92
- Collaborators can edit answers, comment, open allowed local file links, and
93
- submit. Shared viewers refresh from the live draft when another viewer saves,
94
- deferred while someone is typing/commenting.
89
+ Use `review` for independent feedback: each browser gets an isolated review
90
+ draft and may answer, comment, and submit, but the submission is stored as a
91
+ **reference-only side review**. It does not finish the board, wake the agent, or
92
+ complete `rly wait`; the owner (or an owner-authorized collaborator) must still
93
+ submit the final answer. `rly result <id>` exposes current side-review drafts and
94
+ submissions on demand under `sideReviews`, clearly marked `referenceOnly:true`.
95
+ Use `read` when the other device should only view the board and existing
96
+ feedback. Read-only viewers cannot answer, comment, edit blocks, open local file
97
+ links, or submit. Collaborators retain owner-authorized edit/comment/final-submit
98
+ permission. Active links keep the same token across a same-port
99
+ `rly reopen`/`rly rescue` until revoked.
95
100
 
96
101
  ## Inline mode — relay as an MCP App (Claude & Codex apps)
97
102
 
@@ -672,12 +677,13 @@ raising `--timeout`.
672
677
  For a **detached** board, the `timeout` deadline is *soft*: it hands you a
673
678
  `timeout` result (with the autosaved draft) so you regain control, but the
674
679
  server stays up and the board stays fully usable — the user can keep
675
- commenting and still hit Submit. The page tells them you stopped waiting and
676
- to prompt you afterward. So if you got a `timeout` and the user might still be
677
- working: re-check later with `rly result <id>` (its status flips to
678
- `submitted` once they finish), or pass `--on-result` so a late submit
679
- push-wakes you. A blocking `rly ask` (no `--detach`) still ends hard on
680
- timeout, since there's no separate waiter to hand back to.
680
+ commenting and still hit Submit. It stays on the same port until Submit or an
681
+ explicit `rly stop`, so don't reopen just because your wait timed out. The page
682
+ tells them you stopped waiting and to prompt you afterward. So if you got a
683
+ `timeout` and the user might still be working: re-check later with `rly result
684
+ <id>` (its status flips to `submitted` once they finish), or pass `--on-result`
685
+ so a late submit push-wakes you. A blocking `rly ask` (no `--detach`) still ends
686
+ hard on timeout, since there's no separate waiter to hand back to.
681
687
 
682
688
  ## Push-wake — get notified instead of polling
683
689
 
@@ -745,7 +751,9 @@ rly rm <id> | --all # delete saved board(s)
745
751
  ```
746
752
 
747
753
  Multiple boards can run at once (each gets its own port on 127.0.0.1).
748
- Storage lives in `~/.relay` (override with `RLY_HOME`).
754
+ Detached boards are durable: they keep serving past timeout, `reopen`/`rescue`
755
+ prefer the last port, and active same-Wi-Fi share links keep the same token until
756
+ revoked. Storage lives in `~/.relay` (override with `RLY_HOME`).
749
757
 
750
758
  ## Live board mutation — `rly update`
751
759
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanglvm/relay",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "Question boards with rich blocks (markdown, charts, mermaid, tables, code, diffs, video, sandboxed HTML), clickable local file-links, and element-level annotations for AI coding agents (Claude Code, Codex, …): ask users structured questions, present interactive visuals, collect inline comments, read answers as JSON — in a local browser board OR rendered INLINE inside the Claude & Codex apps as an MCP App (SEP-1865).",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -135,6 +135,10 @@ rly wait b-xxxxx --timeout 550 # blocks until submit, prints result JSON
135
135
  rly result b-xxxxx # non-blocking peek (includes live draft)
136
136
  ```
137
137
 
138
+ Detached boards are durable: their own timeout hands the agent a `timeout`
139
+ result but keeps the same URL/port serving until Submit or `rly stop`. Do not
140
+ create a new board just because a wait timed out.
141
+
138
142
  For long waits prefer presence-aware waiting over a huge --timeout:
139
143
 
140
144
  ```sh
@@ -178,23 +182,31 @@ answers and any annotations written so far.
178
182
 
179
183
  Browser boards are local-owner only by default. A phone/tablet/other laptop on
180
184
  the same Wi-Fi gets a locked page until sharing is explicitly activated. The
181
- owner can click **Share** at the bottom of the board, or an agent can manage the
182
- same links with `rly share`:
185
+ owner can click the topbar **Share** icon, or an agent can manage the same links
186
+ with `rly share`:
183
187
 
184
188
  ```sh
185
189
  rly share b-xxxxx # list active share roles
186
190
  rly share b-xxxxx --role review # activate a reviewer link
187
191
  rly share b-xxxxx --role collab # activate a collaborator link
192
+ rly share b-xxxxx --role read # activate a read-only link
188
193
  rly share b-xxxxx --role review --revoke # revoke one role
189
194
  rly share b-xxxxx --revoke --all # revoke all active share links
190
195
  ```
191
196
 
192
- Use `review` when the other device should add comments only. Reviewers cannot
193
- change answers, submit, edit comments, or delete comments; their autosaves merge
194
- new comments into the existing draft. Use `collab` only when the user explicitly
197
+ Use `review` for independent feedback. Each reviewer browser gets an isolated
198
+ draft and can answer, comment, and submit a **reference-only side review**. That
199
+ submission never finishes the board or wakes/completes the waiting agent; the
200
+ owner (or owner-authorized collaborator) must still provide the final answer.
201
+ When the owner asks for current reviewer input, run `rly result <id>` and inspect
202
+ `sideReviews.submissions` plus `sideReviews.drafts`; both are explicitly marked
203
+ reference-only. Use `read` for a view-only link with no answers, comments, block
204
+ edits, local-file opening, or submit. Use `collab` only when the user explicitly
195
205
  wants that device to act as the owner: collaborators can edit answers, comment,
196
- open allowed local file links, and submit. Shared viewers refresh from the live
197
- draft when another viewer saves, deferred while someone is typing/commenting.
206
+ open allowed local file links, and final-submit. Shared viewers refresh from the
207
+ relevant live draft when another viewer in the same role/session saves.
208
+ Active share links are durable too: they keep the same token across a same-port
209
+ `rly reopen`/`rly rescue` until `rly share --revoke` disables them.
198
210
 
199
211
  ## Minimal spec
200
212
 
@@ -534,7 +546,8 @@ one yesno "Does this match your mental model?" + a textarea for notes.
534
546
  answers prefilled) · `rly reopen <id> --replies file.json` (add agent replies) ·
535
547
  `rly rescue <id>` (re-serve a dropped board on its ORIGINAL port) ·
536
548
  `rly list` / `rly open` / `rly stop <id>` · `rly rm <id>`.
537
- Multiple boards can run concurrently.
549
+ Multiple boards can run concurrently. Detached boards keep serving past timeout;
550
+ use `rly stop` when you actually want to close one.
538
551
 
539
552
  ### Continue a board — reconnect, NEVER recreate it
540
553
 
package/src/cli.js CHANGED
@@ -761,21 +761,27 @@ async function cmdWaitLoop(id, deadline, opts) {
761
761
 
762
762
  async function cmdResult(args) {
763
763
  const record = mustLoad(args._[0]);
764
+ const sideReviews = {
765
+ referenceOnly: true,
766
+ note: 'Side reviews are reference only. Wait for the board owner (or owner-authorized collaborator) to submit the final answer.',
767
+ submissions: Array.isArray(record.sideReviews) ? record.sideReviews : [],
768
+ drafts: record.reviewDrafts && typeof record.reviewDrafts === 'object' ? record.reviewDrafts : {},
769
+ };
764
770
  if (record.result && record.result.finishedAt) {
765
- printResult(record.result);
771
+ printResult({ ...record.result, sideReviews });
766
772
  return exitCodeFor(record.result.status);
767
773
  }
768
774
  const running = loadRunning(record.id);
769
775
  if (running && isAlive(running.pid)) {
770
776
  // While open, expose the real-time autosaved draft so agents can peek, plus
771
777
  // best-effort presence (whether the user is still viewing/focused/active).
772
- const out = { status: 'open', boardId: record.id, url: running.url, draft: record.draft ?? null };
778
+ const out = { status: 'open', boardId: record.id, url: running.url, draft: record.draft ?? null, sideReviews };
773
779
  const presence = await fetchPresence(running.url);
774
780
  if (presence) out.presence = presence;
775
781
  printResult(out); // draft can hold many annotations — sidecar it too
776
782
  return 0;
777
783
  }
778
- printResult({ status: 'lost', boardId: record.id, draft: record.draft ?? null });
784
+ printResult({ status: 'lost', boardId: record.id, draft: record.draft ?? null, sideReviews });
779
785
  return 5;
780
786
  }
781
787
 
@@ -785,9 +791,10 @@ async function cmdShare(args) {
785
791
  if (!running || !isAlive(running.pid)) {
786
792
  throw new CliError(`board "${record.id}" is not running. Use \`rly reopen ${record.id} --detach\` first.`, 5);
787
793
  }
788
- const role = args.all ? 'all' : args.role;
789
- if (role !== undefined && !['collab', 'review', 'all'].includes(role)) {
790
- throw new CliError('--role must be collab or review.', 4);
794
+ let role = args.all ? 'all' : args.role;
795
+ if (role === 'readonly' || role === 'read-only') role = 'read';
796
+ if (role !== undefined && !['collab', 'review', 'read', 'all'].includes(role)) {
797
+ throw new CliError('--role must be collab, review, or read.', 4);
791
798
  }
792
799
  const shareUrl = new URL('/api/share', running.url);
793
800
  let res;
@@ -1084,6 +1091,9 @@ the user should view — put it in relay instead of printing it.**
1084
1091
  if it is still open and the user may continue, run \`rly wait\` again. Do not
1085
1092
  use \`--on-result\` as the primary Codex return path; normal Codex CLI sessions
1086
1093
  do not expose a portable inbound API that wakes the current agent turn.
1094
+ Detached boards are durable: a board timeout hands the agent a \`timeout\`
1095
+ result but keeps the same URL/port serving until Submit or \`rly stop\`. Do
1096
+ not create a new board just because a wait timed out.
1087
1097
  - **A plan, structure, architecture, data, or prototype** → a relay board with
1088
1098
  diagram/chart/table/code/image/html blocks — never ASCII diagrams or walls of prose.
1089
1099
  - **"Show me the diff / git diff / these changes"** → \`rly diff\` (runs git diff →
@@ -1097,8 +1107,12 @@ the user should view — put it in relay instead of printing it.**
1097
1107
  option its own visual (\`options[].blocks\`) so the user picks by looking.
1098
1108
  - Same-Wi-Fi sharing is locked by default. When the user wants another device to
1099
1109
  review or co-fill a running board, manage explicit links with \`rly share <id>\`:
1100
- \`--role review\` creates a comments-only reviewer link, \`--role collab\` creates
1101
- an edit/comment/submit link, and \`--revoke\` disables active links.
1110
+ \`--role review\` creates an answer/comment link whose submissions are reference-only
1111
+ side reviews (\`rly result\` exposes them but they never complete \`rly wait\`),
1112
+ \`--role collab\` creates an owner-authorized edit/comment/final-submit link,
1113
+ \`--role read\` creates a view-only link, and \`--revoke\` disables active links. Active
1114
+ share links are durable across same-port \`rly reopen\`/\`rly rescue\` until
1115
+ revoked.
1102
1116
  - **There's a purpose-built component for most content — use the MOST SPECIFIC one,
1103
1117
  never plain prose when a block fits.** Blocks: \`table\` (sortable/filterable/CSV,
1104
1118
  load from .csv/.json), \`chart\`, \`kpi\` (stat cards), \`mermaid\`/\`graphviz\`/\`plantuml\`,
@@ -1568,8 +1582,8 @@ async function cmdServeInternal(args) {
1568
1582
  open: args.open !== false,
1569
1583
  timeoutSec: args.timeout !== undefined ? Math.max(0, Number.parseInt(args.timeout, 10) || 0) : 1800,
1570
1584
  quiet: true,
1571
- // Detached board: timeout hands back to the agent but keeps serving so the
1572
- // user can keep commenting and still submit (seamless past the deadline).
1585
+ // Detached board: timeout hands back to the agent but keeps the same
1586
+ // URL/port serving until Submit or explicit stop.
1573
1587
  keepAliveOnTimeout: true,
1574
1588
  });
1575
1589
  await done;
@@ -1605,10 +1619,12 @@ USAGE
1605
1619
  read that file if your shell truncates stdout; never pipe to head/tail
1606
1620
  rly result <id> result/status now (includes live autosaved draft + presence while open)
1607
1621
  rly share <id> list active same-Wi-Fi share links for a running board
1608
- rly share <id> --role review activate a reviewer link (comments only)
1609
- rly share <id> --role collab activate a collaborator link (edit/comment/submit)
1622
+ rly share <id> --role review reviewer: answer/comment/submit a reference-only side review
1623
+ rly share <id> --role collab collaborator: edit/comment/final-submit as owner-authorized
1624
+ rly share <id> --role read activate a read-only viewer link
1610
1625
  rly share <id> --role review --revoke
1611
1626
  revoke one share role; use --revoke --all to disable all roles
1627
+ active links survive same-port reopen/rescue until revoked
1612
1628
  rly list [--json] running boards
1613
1629
  rly open [id] re-open the browser tab of a running board
1614
1630
  rly reopen <id> [--replies f.json] serve a saved board again, prefilled with saved answers
@@ -1643,7 +1659,8 @@ COMMON FLAGS
1643
1659
 
1644
1660
  EXIT CODES 0 submitted/acknowledged · 2 timeout · 3 cancelled · 4 usage · 5 not found
1645
1661
 
1646
- NOTES answers & annotations autosave in real time (drafts survive timeout/cancel);
1662
+ NOTES detached boards keep serving after timeout until Submit or stop;
1663
+ answers & annotations autosave in real time (drafts survive timeout/cancel);
1647
1664
  submitting auto-closes the tab and unblocks the CLI.
1648
1665
 
1649
1666
  AI AGENTS run \`rly agent\` for the complete machine-oriented guide.