@khanglvm/relay 0.9.1 → 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 +31 -1
- package/docs/AGENT.md +42 -3
- package/package.json +2 -2
- package/skills/relay/SKILL.md +32 -2
- package/src/cli.js +89 -11
- package/src/open.js +12 -0
- package/src/server.js +193 -0
- package/src/spec.js +126 -8
- package/src/store.js +4 -0
- package/src/ui/app.js +288 -30
- package/src/ui/blocks.css +144 -2
- package/src/ui/blocks.js +406 -59
- package/src/ui/style.css +41 -0
package/src/ui/blocks.css
CHANGED
|
@@ -79,6 +79,42 @@
|
|
|
79
79
|
.blk-markdown .md .md-tablewrap { overflow-x: auto; margin: 12px 0; }
|
|
80
80
|
.blk-markdown .md .md-table { margin: 0; }
|
|
81
81
|
|
|
82
|
+
/* Click-to-open local file links. Rendered wherever markdown runs (intro, md
|
|
83
|
+
blocks, table cells). A small file glyph + accent text signals "openable",
|
|
84
|
+
distinct from a plain web link. The whole chip is the click target. */
|
|
85
|
+
.rly-filelink {
|
|
86
|
+
display: inline-flex; align-items: baseline; gap: 0.3em;
|
|
87
|
+
color: var(--accent); cursor: pointer; text-decoration: none;
|
|
88
|
+
border-bottom: 1px solid transparent;
|
|
89
|
+
border-radius: 4px;
|
|
90
|
+
transition: border-color 150ms var(--ease), background 150ms var(--ease);
|
|
91
|
+
}
|
|
92
|
+
.rly-filelink:hover { border-bottom-color: var(--accent); }
|
|
93
|
+
.rly-filelink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
94
|
+
.rly-filelink .rly-filelink-ico {
|
|
95
|
+
flex: none; align-self: center;
|
|
96
|
+
width: 0.92em; height: 0.92em;
|
|
97
|
+
background: currentColor;
|
|
98
|
+
/* a document glyph drawn via mask, so it inherits the accent color */
|
|
99
|
+
-webkit-mask: var(--rly-file-mask) center / contain no-repeat;
|
|
100
|
+
mask: var(--rly-file-mask) center / contain no-repeat;
|
|
101
|
+
opacity: 0.85;
|
|
102
|
+
}
|
|
103
|
+
:root {
|
|
104
|
+
--rly-file-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zm8 1.5V8h4.5L14 3.5z'/%3E%3C/svg%3E");
|
|
105
|
+
}
|
|
106
|
+
.rly-filelink.rly-filelink-code .rly-filelink-txt {
|
|
107
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
108
|
+
font-size: 0.86em;
|
|
109
|
+
background: var(--bg-sunken);
|
|
110
|
+
border: 1px solid var(--border);
|
|
111
|
+
border-radius: 5px;
|
|
112
|
+
padding: 1px 5px;
|
|
113
|
+
}
|
|
114
|
+
.rly-filelink.is-opening { opacity: 0.55; pointer-events: none; }
|
|
115
|
+
/* Error-tone toast for a failed open (success reuses the plain .toast). */
|
|
116
|
+
.toast.toast-err { background: var(--danger); color: var(--danger-fg); }
|
|
117
|
+
|
|
82
118
|
/* ---------- code block ---------- */
|
|
83
119
|
.blk-pre {
|
|
84
120
|
background: var(--bg-sunken);
|
|
@@ -87,24 +123,130 @@
|
|
|
87
123
|
padding: 14px 16px;
|
|
88
124
|
overflow-x: auto;
|
|
89
125
|
margin: 0;
|
|
90
|
-
|
|
91
|
-
|
|
126
|
+
/* Pin font metrics on the <pre> itself: its line-box strut uses the pre's
|
|
127
|
+
own font-size, so leaving it inherited (≈16px) makes lines taller than the
|
|
128
|
+
0.85rem gutter and the numbers drift. Match them exactly. */
|
|
92
129
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
93
130
|
font-size: 0.85rem;
|
|
94
131
|
line-height: 1.55;
|
|
132
|
+
}
|
|
133
|
+
.blk-pre code {
|
|
134
|
+
font-family: inherit;
|
|
135
|
+
font-size: inherit;
|
|
136
|
+
line-height: inherit;
|
|
95
137
|
color: var(--fg);
|
|
96
138
|
white-space: pre;
|
|
97
139
|
}
|
|
98
140
|
/* subtle tinter colors via theme vars only */
|
|
99
141
|
.blk-pre .tok-kw,
|
|
142
|
+
.blk-difftable .tok-kw,
|
|
100
143
|
.blk-markdown .md .tok-kw { color: var(--accent); }
|
|
101
144
|
.blk-pre .tok-str,
|
|
145
|
+
.blk-difftable .tok-str,
|
|
102
146
|
.blk-markdown .md .tok-str { color: var(--ok); }
|
|
103
147
|
.blk-pre .tok-com,
|
|
148
|
+
.blk-difftable .tok-com,
|
|
104
149
|
.blk-markdown .md .tok-com { color: var(--muted); font-style: italic; }
|
|
105
150
|
.blk-pre .tok-num,
|
|
151
|
+
.blk-difftable .tok-num,
|
|
106
152
|
.blk-markdown .md .tok-num { color: var(--fg-2); }
|
|
107
153
|
|
|
154
|
+
/* code block: file-name / language header above the card */
|
|
155
|
+
.blk-codehead {
|
|
156
|
+
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
157
|
+
padding: 6px 12px; margin-bottom: -1px;
|
|
158
|
+
background: var(--bg-sunken);
|
|
159
|
+
border: 1px solid var(--border); border-bottom: 0;
|
|
160
|
+
border-radius: 10px 10px 0 0;
|
|
161
|
+
font-size: 0.74rem; color: var(--muted);
|
|
162
|
+
}
|
|
163
|
+
.blk-codehead .blk-codename {
|
|
164
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
165
|
+
color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
166
|
+
}
|
|
167
|
+
.blk-codehead .blk-codelang { text-transform: uppercase; letter-spacing: 0.05em; flex: none; }
|
|
168
|
+
.blk-codehead:empty,
|
|
169
|
+
.blk-codehead .blk-codename:empty,
|
|
170
|
+
.blk-codehead .blk-codelang:empty { display: none; }
|
|
171
|
+
.blk-codehead:has(.blk-codename:empty) { justify-content: flex-end; }
|
|
172
|
+
|
|
173
|
+
/* code block: line-number gutter + code column share one bordered card */
|
|
174
|
+
.blk-coderow {
|
|
175
|
+
display: flex; align-items: stretch;
|
|
176
|
+
background: var(--bg-sunken);
|
|
177
|
+
border: 1px solid var(--border);
|
|
178
|
+
border-radius: 10px;
|
|
179
|
+
overflow: hidden;
|
|
180
|
+
}
|
|
181
|
+
.blk-codehead + .blk-coderow { border-radius: 0 0 10px 10px; }
|
|
182
|
+
.blk-gutter {
|
|
183
|
+
flex: none; user-select: none; -webkit-user-select: none;
|
|
184
|
+
padding: 14px 10px 14px 14px; text-align: right;
|
|
185
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
186
|
+
font-size: 0.85rem; line-height: 1.55;
|
|
187
|
+
color: var(--muted); white-space: pre;
|
|
188
|
+
border-right: 1px solid var(--border);
|
|
189
|
+
}
|
|
190
|
+
.blk-coderow .blk-pre {
|
|
191
|
+
flex: 1 1 auto; border: 0; border-radius: 0; background: none;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* ---------- diff (unified / git diff) ---------- */
|
|
195
|
+
.blk-diffscroll { overflow-x: auto; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-sunken); }
|
|
196
|
+
.blk-codehead + .blk-diffscroll { border-radius: 0 0 10px 10px; }
|
|
197
|
+
.blk-difftable {
|
|
198
|
+
border-collapse: collapse; width: 100%;
|
|
199
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
200
|
+
font-size: 0.84rem; line-height: 1.5;
|
|
201
|
+
}
|
|
202
|
+
.blk-difftable td { padding: 0 8px; vertical-align: top; }
|
|
203
|
+
.blk-difftable .diff-no {
|
|
204
|
+
width: 1%; white-space: nowrap; text-align: right;
|
|
205
|
+
color: var(--muted); user-select: none; -webkit-user-select: none;
|
|
206
|
+
padding: 0 6px; border-right: 1px solid var(--border);
|
|
207
|
+
}
|
|
208
|
+
.blk-difftable .diff-sign {
|
|
209
|
+
width: 1ch; text-align: center; color: var(--muted);
|
|
210
|
+
user-select: none; -webkit-user-select: none; padding: 0 4px;
|
|
211
|
+
}
|
|
212
|
+
.blk-difftable .diff-code { width: 100%; white-space: pre; }
|
|
213
|
+
.blk-difftable .diff-code code { font: inherit; color: var(--fg); background: none; }
|
|
214
|
+
.blk-difftable .diff-add { background: rgba(77, 138, 102, 0.16); }
|
|
215
|
+
.blk-difftable .diff-add .diff-sign { color: var(--ok); }
|
|
216
|
+
.blk-difftable .diff-del { background: rgba(188, 68, 52, 0.15); }
|
|
217
|
+
.blk-difftable .diff-del .diff-sign { color: var(--danger); }
|
|
218
|
+
.blk-difftable .diff-hunk td { color: var(--accent); background: var(--accent-soft); padding-top: 2px; padding-bottom: 2px; }
|
|
219
|
+
.blk-difftable .diff-meta td { color: var(--muted); font-style: italic; }
|
|
220
|
+
.blk-difftable .diff-hunk .diff-code code,
|
|
221
|
+
.blk-difftable .diff-meta .diff-code code { color: inherit; }
|
|
222
|
+
|
|
223
|
+
/* diff: side-by-side (split) view — old | new. Long lines grow the table and
|
|
224
|
+
the wrapper scrolls horizontally; short code splits ~50/50. */
|
|
225
|
+
.blk-difftable-split .diff-code { width: 50%; }
|
|
226
|
+
.blk-difftable-split .diff-newside { border-left: 2px solid var(--border-strong); }
|
|
227
|
+
.blk-difftable .diff-fill {
|
|
228
|
+
background-color: var(--bg-sunken);
|
|
229
|
+
background-image: repeating-linear-gradient(45deg, transparent 0, transparent 6px, rgba(128, 128, 128, 0.07) 6px, rgba(128, 128, 128, 0.07) 12px);
|
|
230
|
+
}
|
|
231
|
+
/* Unified/Split view toggle in the diff header */
|
|
232
|
+
.blk-difftoggle {
|
|
233
|
+
flex: none; cursor: pointer; font: inherit; font-size: 0.72rem;
|
|
234
|
+
color: var(--fg-2); background: var(--card);
|
|
235
|
+
border: 1px solid var(--border); border-radius: 6px; padding: 2px 8px;
|
|
236
|
+
transition: color 150ms var(--ease), border-color 150ms var(--ease);
|
|
237
|
+
}
|
|
238
|
+
.blk-difftoggle:hover { color: var(--accent); border-color: var(--accent); }
|
|
239
|
+
|
|
240
|
+
/* ---------- video (iframe embed / local stream / direct URL) ---------- */
|
|
241
|
+
.blk-videowrap { margin: 0; }
|
|
242
|
+
.blk-video, .blk-video-embed {
|
|
243
|
+
display: block; width: 100%; border: 0;
|
|
244
|
+
border-radius: 10px; background: #000;
|
|
245
|
+
}
|
|
246
|
+
.blk-video { max-height: 70vh; }
|
|
247
|
+
.blk-video-embed { aspect-ratio: 16 / 9; height: auto; }
|
|
248
|
+
.blk-videocap { margin-top: 8px; font-size: 0.84rem; color: var(--muted); text-align: center; }
|
|
249
|
+
|
|
108
250
|
/* ---------- table ---------- */
|
|
109
251
|
.blk-table {
|
|
110
252
|
width: 100%;
|