@vllm-sr/dsh 0.4.1 → 0.5.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 +62 -15
- package/package.json +2 -2
- package/src/client.js +13 -5
- package/src/index.js +232 -76
- package/src/keys.js +40 -3
- package/src/questions.js +31 -0
- package/src/shield.js +116 -40
- package/src/spans.js +216 -0
- package/web/client.js +150 -15
package/web/client.js
CHANGED
|
@@ -30,7 +30,7 @@ window.__ModuleLoader__.load({
|
|
|
30
30
|
const FRESH_MS = 20000
|
|
31
31
|
const ROWS_SHOWN = 4
|
|
32
32
|
|
|
33
|
-
const REFLEX = { triage: 'Triage', guard: 'Guard', shield: 'Shield', done: 'Done-check', tool: 'Batch' }
|
|
33
|
+
const REFLEX = { triage: 'Triage', guard: 'Guard', shield: 'Shield', privacy: 'Privacy', done: 'Done-check', tool: 'Batch' }
|
|
34
34
|
const KINDS = { code: 'Code', data: 'Data', research: 'Research', writing: 'Writing', ops: 'Ops', chat: 'Chat' }
|
|
35
35
|
const EFFORT = ['Trivial', 'Small', 'Medium', 'Large']
|
|
36
36
|
const RISK = ['Safe', 'Normal', 'Dangerous', 'Critical']
|
|
@@ -59,12 +59,14 @@ window.__ModuleLoader__.load({
|
|
|
59
59
|
waiting: { label: 'Waiting on you', tone: 'info' },
|
|
60
60
|
unfinished: { label: 'Sent back', tone: 'warn' },
|
|
61
61
|
unchecked: { label: 'Sent back to verify', tone: 'warn' },
|
|
62
|
+
unsupported: { label: 'Sent back to re-verify', tone: 'warn' },
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
const num = value => (typeof value === 'number' && Number.isFinite(value) ? value : undefined)
|
|
65
66
|
const p2 = value => (num(value) === undefined ? '?' : value.toFixed(2))
|
|
66
67
|
const secs = ms => (num(ms) === undefined ? '' : `${(ms / 1000).toFixed(2)} s`)
|
|
67
|
-
|
|
68
|
+
// System One's models are vllm-sr's; the name always shows its owner, whatever form the answer gave it in
|
|
69
|
+
const fullModel = model => (typeof model === 'string' && model ? (model.includes('/') ? model : `vllm-sr/${model}`) : '')
|
|
68
70
|
const plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`
|
|
69
71
|
const clamp01 = value => Math.min(1, Math.max(0, value))
|
|
70
72
|
const level = (labels, score) => labels[Math.min(labels.length - 1, Math.max(0, Math.round(score)))]
|
|
@@ -82,12 +84,12 @@ window.__ModuleLoader__.load({
|
|
|
82
84
|
return data && typeof data === 'object' && data.v === 1 && typeof data.reflex === 'string' ? data : undefined
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
// one card per triage of a turn, per guard or
|
|
87
|
+
// one card per triage of a turn, per guard, shield or privacy step (parallel calls share it), per done-check
|
|
86
88
|
function groupOf(data, seq) {
|
|
87
89
|
const turn = Number.isSafeInteger(data.turn) ? data.turn : undefined
|
|
88
90
|
const step = Number.isSafeInteger(data.step) ? data.step : undefined
|
|
89
91
|
if (data.reflex === 'triage' && turn !== undefined) return `t${turn}:triage`
|
|
90
|
-
if (
|
|
92
|
+
if (['guard', 'shield', 'privacy'].includes(data.reflex) && turn !== undefined && step !== undefined) return `t${turn}:s${step}:${data.reflex}`
|
|
91
93
|
return `r${seq}`
|
|
92
94
|
}
|
|
93
95
|
|
|
@@ -197,8 +199,9 @@ window.__ModuleLoader__.load({
|
|
|
197
199
|
if (risk !== undefined) facts.push({ id: 'risk', label: 'Risk', value: `${level(RISK, Math.min(3, risk))} · ${risk.toFixed(2)} of 3`, bar: risk / 3, tone: risk >= 2.5 ? 'bad' : risk >= 1.8 ? 'warn' : 'ok' })
|
|
198
200
|
if (leaks !== undefined) facts.push({ id: 'leaks', label: 'Leaks secrets', value: p2(leaks), bar: leaks, tone: leaks >= 0.7 ? 'bad' : undefined })
|
|
199
201
|
if (onTask !== undefined) facts.push({ id: 'on-task', label: 'On task', value: p2(onTask), bar: onTask, tone: onTask < 0.15 ? 'warn' : undefined })
|
|
202
|
+
const danger = Array.isArray(row.danger) ? row.danger.filter(span => typeof span?.text === 'string' && span.text) : []
|
|
200
203
|
return {
|
|
201
|
-
verdict: row.verdict, ...verdict, subject, facts, outcome, outcomeKey: outcome ? row.outcome : undefined, verdictTone: verdict.tone,
|
|
204
|
+
verdict: row.verdict, ...verdict, subject: danger.length ? { ...subject, marks: danger, kind: 'dangerous' } : subject, facts, outcome, outcomeKey: outcome ? row.outcome : undefined, verdictTone: verdict.tone,
|
|
202
205
|
tone: outcome && SEVERITY[outcome.tone] > SEVERITY[verdict.tone] ? outcome.tone : verdict.tone,
|
|
203
206
|
note: row.verdict !== 'allow' && row.why ? `Because ${row.why}.` : undefined,
|
|
204
207
|
}
|
|
@@ -208,14 +211,33 @@ window.__ModuleLoader__.load({
|
|
|
208
211
|
if (row.error) return errorView(row, { text: 'so the result was passed on unscreened', tone: 'muted' })
|
|
209
212
|
const verdict = SHIELD[row.verdict] ?? SHIELD.clean
|
|
210
213
|
const lines = num(row.removedLines) ?? 0
|
|
214
|
+
const spans = num(row.removedSpans) ?? 0
|
|
215
|
+
const what = spans ? `${plural(spans, 'span')} of text (${plural(num(row.removedChars) ?? 0, 'character')})` : plural(lines, 'line')
|
|
211
216
|
return {
|
|
212
217
|
verdict: row.verdict, ...verdict, subject: { tool: row.tool, text: row.call },
|
|
213
218
|
facts: [
|
|
214
219
|
{ id: 'passages', label: 'Passages', value: String(num(row.passages) ?? '?') },
|
|
215
220
|
{ id: 'injection', label: 'Injection', value: p2(row.maxP), bar: num(row.maxP), tone: row.maxP >= 0.5 ? 'bad' : 'ok' },
|
|
221
|
+
...(spans ? [{ id: 'spans', label: 'Spans removed', value: String(spans) }] : []),
|
|
216
222
|
],
|
|
217
|
-
|
|
218
|
-
|
|
223
|
+
excerpts: Array.isArray(row.excerpts) ? { list: row.excerpts, kind: 'removed' } : undefined,
|
|
224
|
+
note: row.verdict === 'removed' ? `Removed ${what} that gave orders to AI agents before System Two read the result${spans ? '; the text around it stayed' : ''}.`
|
|
225
|
+
: row.verdict === 'flagged' ? `Found ${what} that give orders to AI agents; the result was withheld.` : undefined,
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function privacyView(row) {
|
|
230
|
+
if (row.error) return errorView(row, { text: 'so the result went to System Two unmasked', tone: 'warn' })
|
|
231
|
+
const masked = num(row.masked) ?? 0
|
|
232
|
+
const labels = row.labels && typeof row.labels === 'object' ? Object.entries(row.labels).filter(([, n]) => num(n)) : []
|
|
233
|
+
return {
|
|
234
|
+
verdict: 'masked', label: 'Masked', short: 'masked', tone: 'info',
|
|
235
|
+
headline: `${plural(masked, 'personal detail')} masked${row.tool ? ` · ${row.tool}` : ''}`,
|
|
236
|
+
subject: row.call ? { tool: row.tool, text: row.call } : undefined,
|
|
237
|
+
facts: [{ id: 'masked', label: 'Masked', value: String(masked) }],
|
|
238
|
+
labels: labels.map(([label, n]) => ({ label, n })),
|
|
239
|
+
excerpts: Array.isArray(row.excerpts) ? { list: row.excerpts, kind: 'masked' } : undefined,
|
|
240
|
+
note: 'System Two read [LABEL] placeholders instead of these details.',
|
|
219
241
|
}
|
|
220
242
|
}
|
|
221
243
|
|
|
@@ -225,6 +247,7 @@ window.__ModuleLoader__.load({
|
|
|
225
247
|
const why = DONE[row.why] ? row.why : row.verdict === 'continue' ? 'unfinished' : 'complete'
|
|
226
248
|
const verdict = DONE[why]
|
|
227
249
|
const round = `${num(row.steers) ?? '?'} of ${num(row.maxSteers) ?? '?'}`
|
|
250
|
+
const unsupported = num(row.unsupported) ?? 0
|
|
228
251
|
return {
|
|
229
252
|
verdict: row.verdict === 'continue' ? 'continue' : 'stop', ...verdict, why, short: verdict.label.toLowerCase(),
|
|
230
253
|
headline: row.verdict === 'continue' ? `${verdict.label} to System Two (${round})` : why === 'waiting' ? 'Waiting on you' : 'The work is done',
|
|
@@ -232,9 +255,13 @@ window.__ModuleLoader__.load({
|
|
|
232
255
|
{ id: 'complete', label: 'Complete', value: p2(yesOf(a.complete)), bar: yesOf(a.complete), tone: yesOf(a.complete) < 0.5 ? 'warn' : 'ok' },
|
|
233
256
|
{ id: 'checked', label: 'Checked', value: p2(yesOf(a.checked)), bar: yesOf(a.checked) },
|
|
234
257
|
{ id: 'waiting', label: 'Waiting on you', value: p2(yesOf(a.waiting)), bar: yesOf(a.waiting) },
|
|
258
|
+
...(row.spanModel ? [{ id: 'unsupported', label: 'Unsupported', value: String(unsupported), tone: unsupported ? 'warn' : 'ok' }] : []),
|
|
235
259
|
],
|
|
260
|
+
excerpts: unsupported && Array.isArray(row.excerpts) ? { list: row.excerpts, kind: 'unsupported' } : undefined,
|
|
236
261
|
note: why === 'unfinished' ? `Not finished yet, so System Two goes back to work (${round}).`
|
|
237
|
-
: why === 'unchecked' ? `The changes were not checked, so System Two goes back to verify them (${round}).`
|
|
262
|
+
: why === 'unchecked' ? `The changes were not checked, so System Two goes back to verify them (${round}).`
|
|
263
|
+
: why === 'unsupported' ? `Nothing System Two read supports ${plural(unsupported, 'claim')} in its answer, so it goes back to re-verify just ${unsupported === 1 ? 'that one' : 'those'} (${round}).`
|
|
264
|
+
: unsupported ? `Nothing System Two read supports ${plural(unsupported, 'claim')} in its answer.` : undefined,
|
|
238
265
|
}
|
|
239
266
|
}
|
|
240
267
|
|
|
@@ -244,6 +271,7 @@ window.__ModuleLoader__.load({
|
|
|
244
271
|
case 'guard': return guardView(row)
|
|
245
272
|
case 'shield': return shieldView(row)
|
|
246
273
|
case 'done': return doneView(row)
|
|
274
|
+
case 'privacy': return privacyView(row)
|
|
247
275
|
default: return row.error ? errorView(row) : { verdict: 'unknown', label: 'Decision', short: 'decision', tone: 'muted', facts: [] }
|
|
248
276
|
}
|
|
249
277
|
}
|
|
@@ -264,7 +292,7 @@ window.__ModuleLoader__.load({
|
|
|
264
292
|
const key = view.outcome?.short ?? view.short
|
|
265
293
|
counts.set(key, (counts.get(key) ?? 0) + 1)
|
|
266
294
|
}
|
|
267
|
-
const noun = reflex === 'guard' ? 'call' : reflex === 'shield' ? 'result' : 'decision'
|
|
295
|
+
const noun = reflex === 'guard' ? 'call' : reflex === 'shield' || reflex === 'privacy' ? 'result' : 'decision'
|
|
268
296
|
return [plural(views.length, noun), ...[...counts].map(([short, n]) => `${n} ${short}`)].join(' · ')
|
|
269
297
|
}
|
|
270
298
|
|
|
@@ -273,7 +301,7 @@ window.__ModuleLoader__.load({
|
|
|
273
301
|
const label = view.outcome ? `${view.label} → ${view.outcome.label}` : view.label
|
|
274
302
|
const rest = []
|
|
275
303
|
if (view.subject?.text) rest.push(`${view.subject.tool ?? ''} ${view.subject.text}`.trim())
|
|
276
|
-
const lead = view.facts.find(fact => ['risk', 'injection', 'complete', 'effort'].includes(fact.id))
|
|
304
|
+
const lead = view.facts.find(fact => ['risk', 'injection', 'complete', 'effort', 'masked'].includes(fact.id))
|
|
277
305
|
if (lead) rest.push(`${lead.label.toLowerCase()} ${lead.value}`)
|
|
278
306
|
if (view.error) rest.push(view.error)
|
|
279
307
|
return { label, tone: view.tone, rest: rest.join(' · ') }
|
|
@@ -319,6 +347,43 @@ window.__ModuleLoader__.load({
|
|
|
319
347
|
secs(ms) ? h('span', { className: 'vsr-s1__ms', 'data-system-one-part': 'latency' }, secs(ms)) : null)
|
|
320
348
|
}
|
|
321
349
|
|
|
350
|
+
function Model({ model, also }) {
|
|
351
|
+
const names = [...new Set([fullModel(model), fullModel(also)].filter(Boolean))]
|
|
352
|
+
return names.length ? h('b', { className: 'vsr-s1__model', 'data-system-one-part': 'model', title: names.join(' + ') }, names.join(' + ')) : null
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// what a span model marked: removed injections, masked personal data (only its label), unsupported claims
|
|
356
|
+
function Mark({ mark, kind }) {
|
|
357
|
+
const p = num(mark.probability)
|
|
358
|
+
return h('mark', {
|
|
359
|
+
className: cx('vsr-s1__span', `vsr-s1__span--${kind}`),
|
|
360
|
+
'data-system-one-part': 'span',
|
|
361
|
+
'data-system-one-span-label': text(mark.label) || undefined,
|
|
362
|
+
'data-system-one-probability': p === undefined ? undefined : String(p),
|
|
363
|
+
title: [text(mark.label), p === undefined ? '' : p.toFixed(2)].filter(Boolean).join(' · '),
|
|
364
|
+
}, kind === 'masked' ? text(mark.label) || 'PII' : text(mark.text))
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function Excerpts({ excerpts }) {
|
|
368
|
+
return h('div', { className: 'vsr-s1__excerpts', 'data-system-one-part': 'excerpts' },
|
|
369
|
+
excerpts.list.slice(0, 3).map((parts, index) => h('div', { key: index, className: 'vsr-s1__excerpt', 'data-system-one-part': 'excerpt' },
|
|
370
|
+
(Array.isArray(parts) ? parts : []).map((part, at) => (part?.mark ? h(Mark, { key: at, mark: part.mark, kind: excerpts.kind }) : h('span', { key: at }, text(part?.text)))))))
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// the subject with each marked text highlighted where it first occurs
|
|
374
|
+
function Marked({ value, marks, kind }) {
|
|
375
|
+
const pieces = []
|
|
376
|
+
let rest = value
|
|
377
|
+
for (const mark of marks) {
|
|
378
|
+
const at = rest.indexOf(mark.text)
|
|
379
|
+
if (at < 0) continue
|
|
380
|
+
if (at > 0) pieces.push(rest.slice(0, at))
|
|
381
|
+
pieces.push(h(Mark, { key: pieces.length, mark, kind }))
|
|
382
|
+
rest = rest.slice(at + mark.text.length)
|
|
383
|
+
}
|
|
384
|
+
return [...pieces, rest]
|
|
385
|
+
}
|
|
386
|
+
|
|
322
387
|
function Pill({ tone, children, arrow, part }) {
|
|
323
388
|
return h('span', { className: cx('vsr-s1__pill', `vsr-s1__pill--${tone}`, arrow && 'vsr-s1__pill--then'), 'data-system-one-part': part }, children)
|
|
324
389
|
}
|
|
@@ -344,8 +409,12 @@ window.__ModuleLoader__.load({
|
|
|
344
409
|
h('div', { className: 'vsr-s1__main' },
|
|
345
410
|
view.subject?.text ? h('div', { className: 'vsr-s1__subject', 'data-system-one-part': 'subject' },
|
|
346
411
|
view.subject.tool ? h('span', { className: 'vsr-s1__tool' }, view.subject.tool) : null,
|
|
347
|
-
h('code', { className: 'vsr-s1__code', title: view.subject.text }, view.subject.text)) : null,
|
|
412
|
+
h('code', { className: 'vsr-s1__code', title: view.subject.text }, view.subject.marks ? h(Marked, { value: view.subject.text, marks: view.subject.marks, kind: view.subject.kind }) : view.subject.text)) : null,
|
|
413
|
+
view.subject?.marks && view.subject.marks.some(mark => !view.subject.text.includes(mark.text))
|
|
414
|
+
? h('div', { className: 'vsr-s1__note', 'data-system-one-part': 'note' }, 'The dangerous part: ', view.subject.marks.map((mark, index) => h(Mark, { key: index, mark, kind: view.subject.kind }))) : null,
|
|
348
415
|
view.facts.length ? h('div', { className: 'vsr-s1__facts', 'data-system-one-part': 'facts' }, view.facts.map(fact => h(Fact, { key: fact.id, ...fact }))) : null,
|
|
416
|
+
view.labels?.length ? h('div', { className: 'vsr-s1__labels', 'data-system-one-part': 'labels' }, view.labels.map(entry => h('span', { key: entry.label, className: 'vsr-s1__label', 'data-system-one-span-label': entry.label }, entry.label, h('b', null, String(entry.n))))) : null,
|
|
417
|
+
view.excerpts?.list?.length ? h(Excerpts, { excerpts: view.excerpts }) : null,
|
|
349
418
|
view.note ? h('div', { className: 'vsr-s1__note', 'data-system-one-part': 'note' }, view.note) : null),
|
|
350
419
|
!single && secs(row.ms) ? h('span', { className: 'vsr-s1__rowms', 'data-system-one-part': 'latency' }, secs(row.ms)) : null)
|
|
351
420
|
}
|
|
@@ -360,6 +429,12 @@ window.__ModuleLoader__.load({
|
|
|
360
429
|
|
|
361
430
|
const whole = value => (Number.isSafeInteger(value) ? String(value) : undefined)
|
|
362
431
|
|
|
432
|
+
// how many spans a span model marked in an element's decisions
|
|
433
|
+
function spanCount(state) {
|
|
434
|
+
const n = state.rows.reduce((sum, row) => sum + (num(row.removedSpans) ?? 0) + (num(row.masked) ?? 0) + (num(row.unsupported) ?? 0) + (Array.isArray(row.danger) ? row.danger.length : 0), 0)
|
|
435
|
+
return n ? String(n) : undefined
|
|
436
|
+
}
|
|
437
|
+
|
|
363
438
|
// a public contract (README.md, "Selectors"); React leaves out an attribute whose value is undefined
|
|
364
439
|
function attributes(kind, state, worst) {
|
|
365
440
|
return {
|
|
@@ -372,6 +447,9 @@ window.__ModuleLoader__.load({
|
|
|
372
447
|
'data-system-one-count': String(state.rows.length),
|
|
373
448
|
'data-system-one-turn': whole(state.rows[0].turn),
|
|
374
449
|
'data-system-one-step': state.reflex === 'guard' || state.reflex === 'shield' ? whole(state.rows[0].step) : undefined,
|
|
450
|
+
'data-system-one-model': fullModel(state.rows[state.rows.length - 1].model) || undefined,
|
|
451
|
+
'data-system-one-span-model': fullModel(state.rows.find(row => row.spanModel)?.spanModel) || undefined,
|
|
452
|
+
'data-system-one-spans': spanCount(state) || undefined,
|
|
375
453
|
}
|
|
376
454
|
}
|
|
377
455
|
|
|
@@ -393,7 +471,7 @@ window.__ModuleLoader__.load({
|
|
|
393
471
|
h(Badge, { key: idOf(last), id: idOf(last), ms: last.ms, time: last.time }),
|
|
394
472
|
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, reflex),
|
|
395
473
|
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: headline }, headline),
|
|
396
|
-
|
|
474
|
+
h(Model, { model: last.model, also: state.rows.find(row => row.spanModel)?.spanModel })),
|
|
397
475
|
h(Rows, { reflex: state.reflex, rows: state.rows, views }))
|
|
398
476
|
}
|
|
399
477
|
|
|
@@ -423,15 +501,48 @@ window.__ModuleLoader__.load({
|
|
|
423
501
|
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: said },
|
|
424
502
|
h('span', { className: cx('vsr-s1__verdict', line.tone && `vsr-s1__verdict--${line.tone}`), 'data-system-one-part': 'verdict' }, line.label),
|
|
425
503
|
line.rest ? ` · ${line.rest}` : null),
|
|
504
|
+
open ? h(Model, { model: last.model, also: state.rows.find(row => row.spanModel)?.spanModel }) : null,
|
|
426
505
|
h(Chevron)),
|
|
427
506
|
open ? h(Rows, { reflex: state.reflex, rows: state.rows, views }) : null)
|
|
428
507
|
}
|
|
429
508
|
|
|
509
|
+
function KeyGlyph() {
|
|
510
|
+
return h('svg', { className: 'vsr-s1__glyph', viewBox: '0 0 16 16', width: 12, height: 12, 'aria-hidden': true },
|
|
511
|
+
h('circle', { cx: 5.5, cy: 8, r: 3, fill: 'none', stroke: 'currentColor', strokeWidth: 1.6 }),
|
|
512
|
+
h('path', { d: 'M8.5 8H14M12 8v2.5M14 8v2', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round' }))
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// The free key a start fetched, or why it could not: one line under the request, in either mode.
|
|
516
|
+
function KeyNotice({ state }) {
|
|
517
|
+
const row = state.rows[state.rows.length - 1]
|
|
518
|
+
const created = row.verdict === 'created'
|
|
519
|
+
const fresh = useFresh(`key:${idOf(row)}`, row.time)
|
|
520
|
+
const site = text(row.site) || 'app.vllm-sr.ai'
|
|
521
|
+
const said = created
|
|
522
|
+
? `Free API key created for ${site}, saved in ${text(row.saved) || '~/.dsh/.env'}`
|
|
523
|
+
: `No free API key from ${site}: ${text(row.error?.message) || 'the site refused'}. Get one at ${site} and save it as ${text(row.ref) || 'VLLM_SR_API_KEY'}.`
|
|
524
|
+
const link = (href, label) => (typeof href === 'string' && /^https:\/\//.test(href) ? h('a', { className: 'vsr-s1__link', href, target: '_blank', rel: 'noreferrer' }, label) : null)
|
|
525
|
+
return h('div', {
|
|
526
|
+
className: cx('vsr-s1', 'vsr-s1--notice', created ? 'vsr-s1--ok' : 'vsr-s1--bad', fresh && 'vsr-s1--fresh'),
|
|
527
|
+
role: 'note',
|
|
528
|
+
'aria-label': `System Duo: ${said}`,
|
|
529
|
+
'data-system-one': 'notice',
|
|
530
|
+
'data-system-one-reflex': 'key',
|
|
531
|
+
'data-system-one-verdict': created ? 'created' : 'failed',
|
|
532
|
+
'data-system-one-tone': created ? 'ok' : 'bad',
|
|
533
|
+
'data-system-one-turn': whole(row.turn),
|
|
534
|
+
},
|
|
535
|
+
h('span', { className: cx('vsr-s1__duo', fresh && 'vsr-s1__badge--fresh'), 'data-system-one-part': 'badge' }, h(KeyGlyph), 'System Duo'),
|
|
536
|
+
h('span', { className: cx('vsr-s1__summary', !created && 'vsr-s1__summary--bad'), 'data-system-one-part': 'summary', title: said }, said),
|
|
537
|
+
created && (row.terms || row.privacy) ? h('span', { className: 'vsr-s1__links', 'data-system-one-part': 'links' }, link(row.terms, 'Terms'), link(row.privacy, 'Privacy')) : null)
|
|
538
|
+
}
|
|
539
|
+
|
|
430
540
|
// A routine check (an allowed call, a clean result) is one line in either mode; a decision that changed
|
|
431
541
|
// something, and the triage and done-check that frame the turn, are cards unless the mode is compact.
|
|
432
542
|
function SystemOneNode(props) {
|
|
433
543
|
const state = props?.node?.data
|
|
434
544
|
if (!state || !Array.isArray(state.rows) || state.rows.length === 0) return null
|
|
545
|
+
if (state.reflex === 'key') return h(Contained, null, h(KeyNotice, { state }))
|
|
435
546
|
const slim = state.ui === 'compact' || !standsOut(state)
|
|
436
547
|
return h(Contained, null, h(slim ? Compact : Card, { state }))
|
|
437
548
|
}
|
|
@@ -561,13 +672,17 @@ window.__ModuleLoader__.load({
|
|
|
561
672
|
|
|
562
673
|
const ms = num(meta.seconds) === undefined ? undefined : meta.seconds * 1000
|
|
563
674
|
const headline = [plural(num(meta.items) ?? 0, 'item'), plural(num(meta.questions) ?? 0, 'question'), plural(num(meta.requests) ?? 0, 'request')].join(' · ')
|
|
564
|
-
const done = {
|
|
675
|
+
const done = {
|
|
676
|
+
...common, 'data-system-one-verdict': 'done', 'data-system-one-tone': 'ok', 'data-system-one-count': String(meta.items ?? ''),
|
|
677
|
+
'data-system-one-model': fullModel(meta.model) || undefined,
|
|
678
|
+
}
|
|
565
679
|
if (ui === 'compact') {
|
|
566
680
|
return h('div', { className: cx('vsr-s1', 'vsr-s1--compact', 'vsr-s1--ok', open && 'vsr-s1--open', fresh && 'vsr-s1--fresh'), 'data-system-one': 'tool', ...done },
|
|
567
681
|
h('button', { type: 'button', className: 'vsr-s1__chip', 'data-system-one-part': 'toggle', 'aria-expanded': open, onClick: () => setOpen(!open) },
|
|
568
682
|
h(Badge, { id: `${callId}:done`, ms, time: block?.time }),
|
|
569
683
|
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, REFLEX.tool),
|
|
570
684
|
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: headline }, headline),
|
|
685
|
+
open ? h(Model, { model: meta.model }) : null,
|
|
571
686
|
h(Chevron)),
|
|
572
687
|
open ? h(ToolBody, { meta, fresh, cwd, openFile }) : null)
|
|
573
688
|
}
|
|
@@ -583,7 +698,7 @@ window.__ModuleLoader__.load({
|
|
|
583
698
|
h(Badge, { id: `${callId}:done`, ms, time: block?.time }),
|
|
584
699
|
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, REFLEX.tool),
|
|
585
700
|
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: headline }, headline),
|
|
586
|
-
|
|
701
|
+
h(Model, { model: meta.model })),
|
|
587
702
|
h(ToolBody, { meta, fresh, cwd, openFile }))
|
|
588
703
|
}
|
|
589
704
|
|
|
@@ -612,7 +727,13 @@ window.__ModuleLoader__.load({
|
|
|
612
727
|
.vsr-s1__summary--bad{color:var(--vsr-s1-bad)}
|
|
613
728
|
.vsr-s1__verdict{font-weight:600;color:var(--vsr-s1-text)}
|
|
614
729
|
.vsr-s1__verdict--ok{color:var(--vsr-s1-ok)}.vsr-s1__verdict--warn{color:color-mix(in srgb,var(--vsr-s1-warn) 82%,var(--vsr-s1-text))}.vsr-s1__verdict--bad{color:var(--vsr-s1-bad)}.vsr-s1__verdict--info{color:var(--vsr-s1-ember-deep)}.vsr-s1__verdict--muted{color:var(--vsr-s1-text-3)}
|
|
615
|
-
.vsr-s1__model{flex:none;color:var(--vsr-s1-text-
|
|
730
|
+
.vsr-s1__model{flex:none;color:var(--vsr-s1-text-2);font-size:12px;font-weight:700;letter-spacing:-.005em;white-space:nowrap}
|
|
731
|
+
.vsr-s1--notice{display:flex;align-items:center;gap:9px;min-width:0;margin:4px 0;padding:3px 0}
|
|
732
|
+
.vsr-s1--notice .vsr-s1__summary{white-space:normal}
|
|
733
|
+
.vsr-s1__duo{position:relative;display:inline-flex;flex:none;align-items:center;gap:5px;height:22px;padding:0 9px 0 8px;border-radius:999px;color:#fff;font-size:12px;font-weight:650;white-space:nowrap;background:linear-gradient(110deg,var(--vsr-s1-ember) 0%,#B04FD0 58%,#2F7BF6 100%);box-shadow:0 1px 2px rgba(90,60,170,.25),inset 0 1px 0 rgba(255,255,255,.32)}
|
|
734
|
+
.vsr-s1__glyph{flex:none}
|
|
735
|
+
.vsr-s1__links{display:inline-flex;flex:none;gap:10px}
|
|
736
|
+
a.vsr-s1__link{text-decoration:none}
|
|
616
737
|
.vsr-s1__rows{display:grid;grid-template-columns:auto minmax(0,1fr) auto;column-gap:12px;row-gap:8px;margin-top:9px}
|
|
617
738
|
.vsr-s1__rows>*{grid-column:1/-1}
|
|
618
739
|
.vsr-s1__row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-columns:subgrid;column-gap:12px;align-items:start}
|
|
@@ -632,6 +753,18 @@ window.__ModuleLoader__.load({
|
|
|
632
753
|
.vsr-s1__bar>i{position:absolute;inset:0;border-radius:inherit;background:color-mix(in srgb,var(--vsr-s1-ember) 70%,var(--vsr-s1-text-3));transform-origin:left center;transform:scaleX(var(--p))}
|
|
633
754
|
.vsr-s1__bar--ok>i{background:var(--vsr-s1-ok)}.vsr-s1__bar--warn>i{background:var(--vsr-s1-warn)}.vsr-s1__bar--bad>i{background:var(--vsr-s1-bad)}
|
|
634
755
|
.vsr-s1__note{color:var(--vsr-s1-text-2);font-size:12.5px}
|
|
756
|
+
.vsr-s1__span{padding:0 3px;border-radius:4px;color:inherit;background:none;font:inherit}
|
|
757
|
+
.vsr-s1__span--removed{color:var(--vsr-s1-bad);background:color-mix(in srgb,var(--vsr-s1-bad) 15%,transparent);text-decoration:line-through;text-decoration-thickness:1.5px}
|
|
758
|
+
.vsr-s1__span--dangerous{color:var(--vsr-s1-bad);background:color-mix(in srgb,var(--vsr-s1-bad) 17%,transparent);box-shadow:inset 0 -2px 0 var(--vsr-s1-bad);font-weight:650}
|
|
759
|
+
.vsr-s1__span--unsupported{background:color-mix(in srgb,var(--vsr-s1-warn) 24%,transparent);text-decoration:underline wavy color-mix(in srgb,var(--vsr-s1-warn) 85%,var(--vsr-s1-text));text-decoration-thickness:1.5px;text-underline-offset:3px}
|
|
760
|
+
.vsr-s1__span--masked{display:inline-block;padding:0 6px;color:var(--dsw-alias-bg-layer-1,#fff);background:repeating-linear-gradient(135deg,color-mix(in srgb,var(--vsr-s1-text) 80%,transparent) 0 6px,color-mix(in srgb,var(--vsr-s1-text) 66%,transparent) 6px 12px);font-family:var(--vsr-s1-mono);font-size:11px;font-weight:650;letter-spacing:.02em;line-height:17px}
|
|
761
|
+
.vsr-s1__excerpts{display:grid;gap:5px;margin:3px 0 1px}
|
|
762
|
+
.vsr-s1__excerpt{padding:6px 9px;border-left:2px solid color-mix(in srgb,var(--vsr-s1-ember) 50%,transparent);border-radius:0 6px 6px 0;color:var(--vsr-s1-text-2);background:color-mix(in srgb,var(--vsr-s1-text-3) 9%,transparent);font-family:var(--vsr-s1-mono);font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-word}
|
|
763
|
+
.vsr-s1--bad .vsr-s1__excerpt{border-left-color:color-mix(in srgb,var(--vsr-s1-bad) 55%,transparent)}
|
|
764
|
+
.vsr-s1--warn .vsr-s1__excerpt{border-left-color:color-mix(in srgb,var(--vsr-s1-warn) 60%,transparent)}
|
|
765
|
+
.vsr-s1__labels{display:flex;flex-wrap:wrap;gap:4px 6px}
|
|
766
|
+
.vsr-s1__label{display:inline-flex;align-items:center;gap:5px;padding:0 7px;border-radius:5px;color:var(--vsr-s1-text-2);background:color-mix(in srgb,var(--vsr-s1-text-3) 14%,transparent);font-family:var(--vsr-s1-mono);font-size:11.5px;line-height:20px}
|
|
767
|
+
.vsr-s1__label b{color:var(--vsr-s1-text);font-weight:650}
|
|
635
768
|
.vsr-s1__rowms{color:var(--vsr-s1-text-3);font-size:12px;line-height:22px;font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
636
769
|
.vsr-s1__more,.vsr-s1__link{justify-self:start;padding:0;border:0;background:none;color:var(--dsw-alias-link,#2F7BF6);font:inherit;font-size:12.5px;cursor:pointer}
|
|
637
770
|
.vsr-s1__more:hover,.vsr-s1__link:hover{text-decoration:underline}
|
|
@@ -673,6 +806,8 @@ window.__ModuleLoader__.load({
|
|
|
673
806
|
.vsr-s1__badge--fresh::after{content:"";position:absolute;inset:-1px;border:2px solid var(--vsr-s1-ember);border-radius:inherit;pointer-events:none;animation:vsr-s1-ring .85s ease-out .06s both}
|
|
674
807
|
.vsr-s1__row--fresh{animation:vsr-s1-row .34s cubic-bezier(.2,.8,.2,1) .06s both}
|
|
675
808
|
.vsr-s1__row--fresh .vsr-s1__bar>i{animation:vsr-s1-fill .7s cubic-bezier(.2,.8,.2,1) .2s both}
|
|
809
|
+
@keyframes vsr-s1-mark{0%{outline:2px solid color-mix(in srgb,var(--vsr-s1-ember) 70%,transparent);outline-offset:3px}100%{outline:2px solid transparent;outline-offset:0}}
|
|
810
|
+
.vsr-s1__row--fresh .vsr-s1__span{animation:vsr-s1-mark .9s ease-out .35s both}
|
|
676
811
|
.vsr-s1__stack--fresh>i{animation:vsr-s1-grow .6s cubic-bezier(.2,.8,.2,1) both}
|
|
677
812
|
.vsr-s1--running .vsr-s1__dot{animation:vsr-s1-blink 1s ease-in-out infinite}
|
|
678
813
|
.vsr-s1__shimmer{background:linear-gradient(90deg,var(--vsr-s1-text-2) 35%,var(--vsr-s1-ember) 50%,var(--vsr-s1-text-2) 65%);background-size:250% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:vsr-s1-shimmer 1.6s linear infinite}
|