@khanglvm/relay 0.10.0 → 0.10.1
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 +2 -1
- package/docs/AGENT.md +7 -0
- package/package.json +1 -1
- package/skills/relay/SKILL.md +32 -2
- package/src/cli.js +48 -11
package/README.md
CHANGED
|
@@ -35,7 +35,8 @@ That's it. Next time your agent needs a decision or wants to show you a plan,
|
|
|
35
35
|
it opens a board like the ones above and waits for your Submit.
|
|
36
36
|
|
|
37
37
|
Keep relay current with **`rly upgrade`** — it installs the latest CLI and
|
|
38
|
-
refreshes the skill
|
|
38
|
+
refreshes the skill (via `npx skills`, falling back to the bundled copy) in one
|
|
39
|
+
step, leaving any boards you have open untouched.
|
|
39
40
|
|
|
40
41
|
## What it improves
|
|
41
42
|
|
package/docs/AGENT.md
CHANGED
|
@@ -544,7 +544,14 @@ call rather than calling it repeatedly in a loop.
|
|
|
544
544
|
comments and reopen the board as a conversation thread.
|
|
545
545
|
- Use `rly update <id>` to push spec changes to a running board — the page
|
|
546
546
|
reloads and answers survive via draft autosave. Batch updates; do not spam.
|
|
547
|
+
- When the user asks to *see* code changes — "show me the diff", "show me git
|
|
548
|
+
diff", "review these changes" — capture `git diff` (or `git show <sha>`) and
|
|
549
|
+
render it in a `diff` block instead of printing it to the terminal; for a
|
|
550
|
+
brand-new file use a `code` block. Point them at a file to inspect with a
|
|
551
|
+
clickable local path in markdown.
|
|
547
552
|
- For sensitive PlantUML diagrams, set `"server": "https://your-server"` to avoid
|
|
548
553
|
sending source to the public plantuml.com server.
|
|
549
554
|
- Bundled universal skill (Claude Code, Codex, any SKILL.md-aware agent):
|
|
550
555
|
`rly skill install` — or `npx skills add khanglvm/relay --skill relay --all`.
|
|
556
|
+
`rly upgrade` refreshes the CLI **and** the skill (via npx skills, falling back
|
|
557
|
+
to the bundled copy) in one step.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanglvm/relay",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Browser-based 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, wait for submit, read answers as JSON.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
package/skills/relay/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: relay
|
|
3
|
-
description: "The tool for collecting user requirements, decisions, and answers (choice, yes-no, text, scale
|
|
3
|
+
description: "The tool for collecting user requirements, decisions, and answers (choice, yes-no, text, scale) and for presenting prototypes, plans, structures, code changes, or reports with rich visuals - mermaid/graphviz/plantuml diagrams, charts, tables, code, diffs, video, custom HTML, clickable file-links - plus inline comments on any element. Opens a browser board, waits for Submit, returns JSON answers, comments, and edited diagrams. Use PROACTIVELY instead of (a) native ask-user tools for 2+ answers or options needing explanation, (b) ASCII trees/tables/diagrams in the terminal or prose for structures/designs/plans, (c) hand-rolled HTML demos. Triggers: collect requirements, ask the user, get decisions/feedback, present a prototype, plan/design review, show me the structure/file tree, architecture or dependency graph, visualize, diagram, chart, table, compare alternatives, survey, edit the diagram, show me the diff / git diff, video walkthrough, open a file. Skip for a single trivial yes/no confirmation."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# relay (`rly`)
|
|
@@ -28,6 +28,9 @@ Schema).** The essentials are below.
|
|
|
28
28
|
| Present a prototype / demo an idea | **rly show** — never hand-roll an HTML file + server |
|
|
29
29
|
| Gather requirements / plan approval / feedback round | **rly** |
|
|
30
30
|
| Architecture or flow that benefits from a diagram | **rly** (mermaid block) |
|
|
31
|
+
| "Show me the diff" / git diff / code changes / before-after | **rly** (`diff` block — run `git diff`, render it; never dump it in the terminal) |
|
|
32
|
+
| A demo, screen recording or walkthrough | **rly** (`video` block) |
|
|
33
|
+
| Point the user at a file to open (log, capture, report) | **rly** (a clickable local file-link in markdown) |
|
|
31
34
|
| Something you can decide yourself from context | neither — just decide |
|
|
32
35
|
|
|
33
36
|
Once the user has answered one board in a session, prefer boards for later
|
|
@@ -119,7 +122,17 @@ single/multi question.
|
|
|
119
122
|
{ "type": "table", "columns": ["A","B"], "rows": [["x","y"]], "sortable": true }
|
|
120
123
|
// ^ use a `table` block for tabular data — sortable + per-cell comments.
|
|
121
124
|
// (markdown blocks render GFM pipe tables too, but those are display-only.)
|
|
122
|
-
{ "type": "code", "lang": "js", "code": "const x = 1;" }
|
|
125
|
+
{ "type": "code", "lang": "js", "code": "const x = 1;", "filename": "demo.js" }
|
|
126
|
+
{ "type": "code", "codeFile": "src/server.js" } // load text from a local file
|
|
127
|
+
{ "type": "diff", "lang": "js", "filename": "src/auth.js", "view": "split",
|
|
128
|
+
"diff": "@@ -1,3 +1,3 @@\n ctx\n-old line\n+new line\n ctx" }
|
|
129
|
+
// ^ a unified / `git diff` text rendered as a colored, line-numbered comparison
|
|
130
|
+
// (no git needed — just paste the diff). "view":"split" = side-by-side; the
|
|
131
|
+
// viewer also has a live Unified⇄Split toggle. "diffFile" loads it from a file.
|
|
132
|
+
{ "type": "video", "src": "https://youtu.be/dQw4w9WgXcQ", "title": "Demo walkthrough" }
|
|
133
|
+
{ "type": "video", "src": "recordings/demo.mp4", "title": "Local capture", "height": 360 }
|
|
134
|
+
// ^ YouTube/Vimeo URL embeds a player; an http(s) media URL or a local video
|
|
135
|
+
// file (mp4/webm/ogv/mov/mkv/m4v) plays inline (local files stream, not embedded).
|
|
123
136
|
{ "type": "html", "html": "<p>hi</p>", "height": 360 }
|
|
124
137
|
{ "type": "html", "htmlFile": "viz.html", "height": 400 }
|
|
125
138
|
{ "type": "image", "src": "screenshot.png" } // local file, URL, or data URI
|
|
@@ -154,6 +167,15 @@ stays dependency-free. PlantUML uses the public plantuml.com server by default;
|
|
|
154
167
|
pass `"server"` for a self-hosted instance. Legacy `"html"` / `"htmlFile"` /
|
|
155
168
|
`"htmlHeight"` on root or questions are still accepted and normalised automatically.
|
|
156
169
|
|
|
170
|
+
### Local file links — clickable, open in the default app
|
|
171
|
+
|
|
172
|
+
Write a local path in any markdown (the `intro` or a `markdown` block) — `~/clip.mp4`,
|
|
173
|
+
`./src/app.ts`, `/abs/report.pdf`, a `file://` URL, or a backtick-wrapped path — and it
|
|
174
|
+
renders as a click-to-open link that opens the file in the user's OS default app
|
|
175
|
+
(editor, video player, viewer …); `[label](~/path)` works too. Only paths you actually
|
|
176
|
+
wrote on the board can be opened (same-origin + allowlist guarded). Surface a real
|
|
177
|
+
clickable path instead of telling the user to paste it into a terminal.
|
|
178
|
+
|
|
157
179
|
## Annotations
|
|
158
180
|
|
|
159
181
|
Users can hover chart points, diagram nodes (mermaid + graphviz), table cells,
|
|
@@ -210,6 +232,14 @@ urgency, `textarea` for constraints.
|
|
|
210
232
|
`html`/`image` block rendering that variant (see Visual options above); `scale`
|
|
211
233
|
for confidence; `textarea` for what's missing from both.
|
|
212
234
|
|
|
235
|
+
**Show a git diff / code changes** — when the user says "show me the diff" /
|
|
236
|
+
"show me git diff" / "review these changes": capture `git diff` (or `git diff
|
|
237
|
+
<ref>`, `git show <sha>`) and present it in a `diff` block — set `"view":
|
|
238
|
+
"split"` for side-by-side — instead of dumping it in the terminal. Pair it with
|
|
239
|
+
a `yesno` "Apply these changes?" and a `textarea` for feedback; users can select
|
|
240
|
+
diff text to comment on a specific line. For a brand-new file prefer a `code` block; for a
|
|
241
|
+
recorded walkthrough of the change add a `video` block.
|
|
242
|
+
|
|
213
243
|
**Metrics review** — board-level `chart` block (bar or line) showing the key
|
|
214
244
|
numbers, followed by a `table` block for the raw data; at least one question
|
|
215
245
|
asking what to act on. In the intro, tell the user they can click chart points
|
package/src/cli.js
CHANGED
|
@@ -773,6 +773,25 @@ function removeLegacySkills() {
|
|
|
773
773
|
return removed;
|
|
774
774
|
}
|
|
775
775
|
|
|
776
|
+
// Stamps the current CLI version into every installed skill dir's .rly-version.
|
|
777
|
+
// `rly skill install` writes this itself, but an `npx skills add` refresh does
|
|
778
|
+
// not — so after any refresh we re-stamp the dirs that now have a SKILL.md,
|
|
779
|
+
// keeping skillFreshnessWarning() from nagging about a just-refreshed skill.
|
|
780
|
+
function stampSkillVersion() {
|
|
781
|
+
const stamped = [];
|
|
782
|
+
for (const dir of Object.values(KNOWN_SKILL_DIRS())) {
|
|
783
|
+
try {
|
|
784
|
+
if (fs.existsSync(path.join(dir, 'SKILL.md'))) {
|
|
785
|
+
fs.writeFileSync(path.join(dir, '.rly-version'), VERSION);
|
|
786
|
+
stamped.push(dir);
|
|
787
|
+
}
|
|
788
|
+
} catch {
|
|
789
|
+
// best effort — a marker we couldn't write just re-triggers the nudge
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return stamped;
|
|
793
|
+
}
|
|
794
|
+
|
|
776
795
|
// Short instruction block for an agent's main instruction file (CLAUDE.md,
|
|
777
796
|
// AGENTS.md, …). A skill is only a tier-1 hint that agents can ignore; these
|
|
778
797
|
// rules, appended to the instructions the agent always reads, enforce usage.
|
|
@@ -783,8 +802,12 @@ const SKILL_RULES = `## relay — ask & show in the browser, not the terminal
|
|
|
783
802
|
beyond one trivial yes/no)? Do NOT ask in plain terminal text. Build a board
|
|
784
803
|
spec and run: \`rly ask --file spec.json --detach\`, then \`rly wait <boardId>\`.
|
|
785
804
|
- Presenting a plan, structure, architecture, data, or a prototype? Show a
|
|
786
|
-
relay board with mermaid/graphviz/chart/table/image/html
|
|
787
|
-
ASCII diagrams or walls of prose.
|
|
805
|
+
relay board with mermaid/graphviz/chart/table/code/diff/video/image/html
|
|
806
|
+
blocks — never ASCII diagrams or walls of prose.
|
|
807
|
+
- "Show me the diff / git diff / these changes"? Run \`git diff\` (or \`git show\`)
|
|
808
|
+
and render the output in a \`diff\` block — never paste a raw diff in the
|
|
809
|
+
terminal. Point the user at a file with a clickable local path in a markdown
|
|
810
|
+
block, and embed a screen recording with a \`video\` block.
|
|
788
811
|
- When answer choices are visual (designs, layouts, variants), give each
|
|
789
812
|
option its own visual (\`options[].blocks\`) so the user picks by looking.
|
|
790
813
|
- Read the result JSON from stdout; treat \`comment\` and \`annotations\` as
|
|
@@ -1031,8 +1054,9 @@ function cmdAgent() {
|
|
|
1031
1054
|
return 0;
|
|
1032
1055
|
}
|
|
1033
1056
|
|
|
1034
|
-
// `rly upgrade` — install the latest CLI globally AND refresh the
|
|
1035
|
-
//
|
|
1057
|
+
// `rly upgrade` — install the latest CLI globally AND refresh the skill (via the
|
|
1058
|
+
// npx-skills package manager, falling back to the bundled copy) in one shot.
|
|
1059
|
+
// (`update` is taken by the live-mutate command, so this is
|
|
1036
1060
|
// `upgrade` / `self-update`.) Running boards are surfaced and handled: a global
|
|
1037
1061
|
// reinstall overwrites relay's files, but live detached servers snapshot their
|
|
1038
1062
|
// UI at first request and serve from memory, so they keep working on their own
|
|
@@ -1051,7 +1075,7 @@ async function cmdUpgrade(args) {
|
|
|
1051
1075
|
if (args.dryRun === true) {
|
|
1052
1076
|
printJson({
|
|
1053
1077
|
dryRun: true,
|
|
1054
|
-
wouldRun: [wantCli && `npm install -g ${PKG_NAME}@latest`, wantSkill && '
|
|
1078
|
+
wouldRun: [wantCli && `npm install -g ${PKG_NAME}@latest`, wantSkill && 'npx skills add khanglvm/relay --skill relay --all'].filter(Boolean),
|
|
1055
1079
|
runningBoards: running.map((r) => r.id),
|
|
1056
1080
|
runningHandling: running.length
|
|
1057
1081
|
? doStop
|
|
@@ -1108,17 +1132,30 @@ async function cmdUpgrade(args) {
|
|
|
1108
1132
|
}
|
|
1109
1133
|
|
|
1110
1134
|
if (wantSkill) {
|
|
1111
|
-
//
|
|
1112
|
-
//
|
|
1113
|
-
|
|
1114
|
-
|
|
1135
|
+
// Refresh the skill through the npx-skills package manager — the same channel
|
|
1136
|
+
// the skill is normally managed by (skills-lock.json, ~/.agents, ~/.claude, …)
|
|
1137
|
+
// — so the global install stays in sync and pulls the freshest skill for
|
|
1138
|
+
// khanglvm/relay. `npx -y` so the one-off download needs no prompt.
|
|
1139
|
+
process.stderr.write('\nRefreshing the relay skill (npx skills add khanglvm/relay --skill relay --all)\n');
|
|
1140
|
+
let r = spawnSync('npx', ['-y', 'skills', 'add', 'khanglvm/relay', '--skill', 'relay', '--all'], { stdio: 'inherit', shell: true });
|
|
1141
|
+
let how = 'npx-skills';
|
|
1142
|
+
if (r.error || r.status !== 0) {
|
|
1143
|
+
// Fallback: install the skill bundled with the CLI we just upgraded. Works
|
|
1144
|
+
// offline / when the skills CLI is unreachable, and matches this version.
|
|
1145
|
+
process.stderr.write('\nnpx skills unavailable — falling back to the bundled skill (rly skill install)\n');
|
|
1146
|
+
r = spawnSync('rly', ['skill', 'install'], { stdio: 'inherit', shell: true });
|
|
1147
|
+
how = 'bundled';
|
|
1148
|
+
}
|
|
1115
1149
|
if (r.error || r.status !== 0) {
|
|
1116
1150
|
process.stderr.write(
|
|
1117
1151
|
`Skill refresh did not complete${r.error ? ` (${r.error.message})` : ` (exit ${r.status})`} — ` +
|
|
1118
|
-
'run `
|
|
1152
|
+
'run `npx skills add khanglvm/relay --skill relay --all` (or `rly skill install`) yourself.\n'
|
|
1119
1153
|
);
|
|
1120
1154
|
} else {
|
|
1121
|
-
|
|
1155
|
+
// Keep the freshness marker accurate however the skill landed, so the next
|
|
1156
|
+
// `rly` run doesn't nag that the just-refreshed skill is stale.
|
|
1157
|
+
stampSkillVersion();
|
|
1158
|
+
did.skill = how;
|
|
1122
1159
|
}
|
|
1123
1160
|
}
|
|
1124
1161
|
|