@vllm-sr/dsh 0.3.1 → 0.4.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 +72 -4
- package/package.json +11 -2
- package/src/index.js +73 -12
- package/src/items.js +3 -2
- package/src/records.js +78 -0
- package/src/shield.js +3 -1
- package/src/tool.js +34 -5
- package/web/client.js +730 -0
package/web/client.js
ADDED
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vllm-sr/dsh in DeepSeek Harness's Web UI: System One's decisions, drawn in Chat.
|
|
3
|
+
*
|
|
4
|
+
* The host half records each decision System One makes in the session (src/records.js). This browser half turns the
|
|
5
|
+
* records into Chat rows, one card or one compact line per System One call, grouped by turn, step and reflex, and draws
|
|
6
|
+
* the system_one tool's row from its result. Everything it shows comes from those records and results.
|
|
7
|
+
*
|
|
8
|
+
* Plain JavaScript in the Web UI's client-module format, with no build step: React comes from the page's shared module
|
|
9
|
+
* table. The Web UI does not start when a browser plugin fails to, so this one requires no service, attaches each part
|
|
10
|
+
* only once its service exists, and contains its own errors. The Web UI joins plugin scripts into one classic script,
|
|
11
|
+
* so nothing may be declared outside the factory.
|
|
12
|
+
*/
|
|
13
|
+
window.__ModuleLoader__.load({
|
|
14
|
+
id: '@vllm-sr/dsh',
|
|
15
|
+
factory: (require) => {
|
|
16
|
+
var module = { exports: {} }
|
|
17
|
+
var exports = module.exports
|
|
18
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
19
|
+
exports.inject = []
|
|
20
|
+
exports.apply = function apply() {}
|
|
21
|
+
try {
|
|
22
|
+
const React = require('react')
|
|
23
|
+
const h = React.createElement
|
|
24
|
+
|
|
25
|
+
const PACKAGE = '@vllm-sr/dsh'
|
|
26
|
+
const RECORD_TYPE = 'plugin:vllm-sr/dsh/system-one'
|
|
27
|
+
const NODE_KIND = 'vllm-sr.system-one'
|
|
28
|
+
const TOOL_NAME = 'system_one'
|
|
29
|
+
// a decision younger than this animates the first time this page draws it; history stays still
|
|
30
|
+
const FRESH_MS = 20000
|
|
31
|
+
const ROWS_SHOWN = 4
|
|
32
|
+
|
|
33
|
+
const REFLEX = { triage: 'Triage', guard: 'Guard', shield: 'Shield', done: 'Done-check', tool: 'Batch' }
|
|
34
|
+
const KINDS = { code: 'Code', data: 'Data', research: 'Research', writing: 'Writing', ops: 'Ops', chat: 'Chat' }
|
|
35
|
+
const EFFORT = ['Trivial', 'Small', 'Medium', 'Large']
|
|
36
|
+
const RISK = ['Safe', 'Normal', 'Dangerous', 'Critical']
|
|
37
|
+
const HUES = ['#2F9BFF', '#14C4E8', '#7357F6', '#F2A100', '#A95BF2', '#1F9D5B', '#4A6CFF', '#EF5630']
|
|
38
|
+
const RAMP = ['#14C4E8', '#2F9BFF', '#7357F6', '#A95BF2', '#F2A100', '#EF5630', '#D9441F']
|
|
39
|
+
const SEVERITY = { muted: 0, ok: 1, info: 2, warn: 3, bad: 4 }
|
|
40
|
+
|
|
41
|
+
const GUARD = {
|
|
42
|
+
allow: { label: 'Allowed', short: 'allowed', tone: 'ok' },
|
|
43
|
+
ask: { label: 'Asked you', short: 'asked you', tone: 'warn' },
|
|
44
|
+
deny: { label: 'Blocked', short: 'blocked', tone: 'bad' },
|
|
45
|
+
}
|
|
46
|
+
const OUTCOME = {
|
|
47
|
+
allowed: { label: 'You allowed it', short: 'allowed by you', tone: 'ok' },
|
|
48
|
+
rejected: { label: 'You rejected it', short: 'rejected by you', tone: 'bad' },
|
|
49
|
+
cancelled: { label: 'Not run', short: 'not run', tone: 'muted' },
|
|
50
|
+
failed: { label: 'Call failed', short: 'failed', tone: 'muted' },
|
|
51
|
+
}
|
|
52
|
+
const SHIELD = {
|
|
53
|
+
clean: { label: 'Clean', short: 'clean', tone: 'ok' },
|
|
54
|
+
removed: { label: 'Injection removed', short: 'injection removed', tone: 'bad' },
|
|
55
|
+
flagged: { label: 'Injection found', short: 'injection found', tone: 'bad' },
|
|
56
|
+
}
|
|
57
|
+
const DONE = {
|
|
58
|
+
complete: { label: 'Done', tone: 'ok' },
|
|
59
|
+
waiting: { label: 'Waiting on you', tone: 'info' },
|
|
60
|
+
unfinished: { label: 'Sent back', tone: 'warn' },
|
|
61
|
+
unchecked: { label: 'Sent back to verify', tone: 'warn' },
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const num = value => (typeof value === 'number' && Number.isFinite(value) ? value : undefined)
|
|
65
|
+
const p2 = value => (num(value) === undefined ? '?' : value.toFixed(2))
|
|
66
|
+
const secs = ms => (num(ms) === undefined ? '' : `${(ms / 1000).toFixed(2)} s`)
|
|
67
|
+
const shortModel = model => (typeof model === 'string' ? model.replace(/^vllm-sr\//, '') : '')
|
|
68
|
+
const plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`
|
|
69
|
+
const clamp01 = value => Math.min(1, Math.max(0, value))
|
|
70
|
+
const level = (labels, score) => labels[Math.min(labels.length - 1, Math.max(0, Math.round(score)))]
|
|
71
|
+
const yesOf = answer => num(answer?.yes)
|
|
72
|
+
const scoreOf = answer => num(answer?.score)
|
|
73
|
+
const cx = (...names) => names.filter(Boolean).join(' ')
|
|
74
|
+
const text = value => (typeof value === 'string' ? value : '')
|
|
75
|
+
const basename = path => text(path).split(/[\\/]/).filter(Boolean).pop() ?? text(path)
|
|
76
|
+
|
|
77
|
+
// ---- the session records, folded into one Chat node per group ----
|
|
78
|
+
|
|
79
|
+
function recordOf(event) {
|
|
80
|
+
if (!event || event.type !== RECORD_TYPE || event.ignorable !== true) return undefined
|
|
81
|
+
const data = event.data
|
|
82
|
+
return data && typeof data === 'object' && data.v === 1 && typeof data.reflex === 'string' ? data : undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// one card per triage of a turn, per guard or shield step (parallel calls share it), per done-check
|
|
86
|
+
function groupOf(data, seq) {
|
|
87
|
+
const turn = Number.isSafeInteger(data.turn) ? data.turn : undefined
|
|
88
|
+
const step = Number.isSafeInteger(data.step) ? data.step : undefined
|
|
89
|
+
if (data.reflex === 'triage' && turn !== undefined) return `t${turn}:triage`
|
|
90
|
+
if ((data.reflex === 'guard' || data.reflex === 'shield') && turn !== undefined && step !== undefined) return `t${turn}:s${step}:${data.reflex}`
|
|
91
|
+
return `r${seq}`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function fold(state, event) {
|
|
95
|
+
const data = recordOf(event)
|
|
96
|
+
const base = state ?? { reflex: data?.reflex ?? 'unknown', ui: data?.ui === 'compact' ? 'compact' : 'card', rows: [] }
|
|
97
|
+
if (!data) return base
|
|
98
|
+
// the answer to an approval the guard asked for completes that call's row
|
|
99
|
+
if (typeof data.outcome === 'string' && data.callId !== undefined) {
|
|
100
|
+
const at = base.rows.findIndex(row => row.callId === data.callId && row.outcome === undefined)
|
|
101
|
+
if (at >= 0) {
|
|
102
|
+
const rows = base.rows.slice()
|
|
103
|
+
rows[at] = { ...rows[at], outcome: data.outcome }
|
|
104
|
+
return { ...base, rows }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { ...base, rows: [...base.rows, { ...data, seq: event.seq, time: event.time }] }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Triage and done-check frame the turn and stay visible when it folds; so does a guard or shield card that
|
|
111
|
+
// stopped something. A routine one sits with the work it checked and folds with it.
|
|
112
|
+
function standsOut(state) {
|
|
113
|
+
if (state.reflex !== 'guard' && state.reflex !== 'shield') return true
|
|
114
|
+
return state.rows.some(row => SEVERITY[viewOf(state.reflex, row).tone] >= SEVERITY.warn)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const definition = {
|
|
118
|
+
kind: NODE_KIND,
|
|
119
|
+
target: 'chat',
|
|
120
|
+
match: {
|
|
121
|
+
[RECORD_TYPE](event) {
|
|
122
|
+
const data = recordOf(event)
|
|
123
|
+
// every record is complete on its own, so any of them can open its group's card
|
|
124
|
+
return data ? { id: groupOf(data, event.seq), role: 'start' } : null
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
start: (_context, match) => fold(undefined, match.event),
|
|
128
|
+
update: (context, match) => fold(context.state, match.event),
|
|
129
|
+
publication: () => 'immediate',
|
|
130
|
+
buildViewNode(context) {
|
|
131
|
+
const state = context.state
|
|
132
|
+
if (!state || state.rows.length === 0) return null
|
|
133
|
+
const first = context.start ?? context.matches[0]
|
|
134
|
+
return {
|
|
135
|
+
key: context.key,
|
|
136
|
+
kind: NODE_KIND,
|
|
137
|
+
id: context.id,
|
|
138
|
+
target: 'chat',
|
|
139
|
+
anchorSeq: first?.event?.seq ?? state.rows[0].seq,
|
|
140
|
+
location: first?.location ?? { kind: 'unresolved' },
|
|
141
|
+
visibility: 'visible',
|
|
142
|
+
groupTree: standsOut(state) ? 'turn' : undefined,
|
|
143
|
+
data: state,
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ---- what each decision says ----
|
|
149
|
+
|
|
150
|
+
function errorView(row, fallback) {
|
|
151
|
+
return {
|
|
152
|
+
verdict: 'error', label: 'Unavailable', short: 'unavailable', tone: fallback?.tone ?? 'muted', error: text(row.error),
|
|
153
|
+
subject: row.call ? { tool: row.tool, text: row.call } : undefined, facts: [],
|
|
154
|
+
note: `System One did not answer (${text(row.error)})${fallback ? `, ${fallback.text}` : ''}.`,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function triageView(row) {
|
|
159
|
+
if (row.error) return errorView(row)
|
|
160
|
+
const a = row.answers ?? {}
|
|
161
|
+
const kind = text(a.kind?.choice)
|
|
162
|
+
const confidence = num(a.kind?.confidence)
|
|
163
|
+
const effort = scoreOf(a.effort)
|
|
164
|
+
const unclear = yesOf(a.unclear)
|
|
165
|
+
const risky = yesOf(a.risky)
|
|
166
|
+
const kindLabel = KINDS[kind] ?? (kind || '?')
|
|
167
|
+
const effortLabel = effort === undefined ? '?' : level(EFFORT, effort)
|
|
168
|
+
const flags = [unclear >= 0.6 && 'unclear', risky >= 0.5 && 'risky'].filter(Boolean)
|
|
169
|
+
const hints = Array.isArray(row.hints) ? row.hints.filter(hint => typeof hint === 'string') : []
|
|
170
|
+
return {
|
|
171
|
+
verdict: 'brief', label: kindLabel, short: kindLabel.toLowerCase(), tone: 'info',
|
|
172
|
+
headline: [`${kindLabel} work`, `${effortLabel.toLowerCase()} effort`, ...flags].join(' · '),
|
|
173
|
+
facts: [
|
|
174
|
+
{ id: 'kind', label: 'Kind', value: `${kindLabel} ${p2(confidence)}`, bar: confidence },
|
|
175
|
+
{ id: 'effort', label: 'Effort', value: effort === undefined ? '?' : `${effortLabel} · ${effort.toFixed(1)} of 3`, bar: effort === undefined ? undefined : effort / 3 },
|
|
176
|
+
{ id: 'unclear', label: 'Unclear', value: p2(unclear), bar: unclear, tone: unclear >= 0.6 ? 'warn' : undefined },
|
|
177
|
+
{ id: 'risky', label: 'Risky', value: p2(risky), bar: risky, tone: risky >= 0.5 ? 'bad' : undefined },
|
|
178
|
+
],
|
|
179
|
+
note: hints.length ? `Brief for System Two: ${hints.join(' ')}` : undefined,
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function guardView(row) {
|
|
184
|
+
const outcome = OUTCOME[row.outcome]
|
|
185
|
+
if (row.error) {
|
|
186
|
+
const fallback = { allow: { text: 'so the call ran', tone: 'muted' }, ask: { text: 'so you were asked', tone: 'warn' }, deny: { text: 'so the call was blocked', tone: 'bad' } }[row.verdict]
|
|
187
|
+
return { ...errorView(row, fallback), outcome, outcomeKey: outcome ? row.outcome : undefined }
|
|
188
|
+
}
|
|
189
|
+
const subject = { tool: row.tool, text: row.call }
|
|
190
|
+
const verdict = GUARD[row.verdict]
|
|
191
|
+
if (!verdict) return { verdict: row.outcome ?? 'unknown', ...(outcome ?? { label: 'Reviewed', short: 'reviewed', tone: 'muted' }), outcomeKey: outcome ? row.outcome : undefined, subject, facts: [] }
|
|
192
|
+
const a = row.answers ?? {}
|
|
193
|
+
const risk = scoreOf(a.risk)
|
|
194
|
+
const leaks = yesOf(a.exfiltration)
|
|
195
|
+
const onTask = yesOf(a.on_task)
|
|
196
|
+
const facts = []
|
|
197
|
+
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
|
+
if (leaks !== undefined) facts.push({ id: 'leaks', label: 'Leaks secrets', value: p2(leaks), bar: leaks, tone: leaks >= 0.7 ? 'bad' : undefined })
|
|
199
|
+
if (onTask !== undefined) facts.push({ id: 'on-task', label: 'On task', value: p2(onTask), bar: onTask, tone: onTask < 0.15 ? 'warn' : undefined })
|
|
200
|
+
return {
|
|
201
|
+
verdict: row.verdict, ...verdict, subject, facts, outcome, outcomeKey: outcome ? row.outcome : undefined, verdictTone: verdict.tone,
|
|
202
|
+
tone: outcome && SEVERITY[outcome.tone] > SEVERITY[verdict.tone] ? outcome.tone : verdict.tone,
|
|
203
|
+
note: row.verdict !== 'allow' && row.why ? `Because ${row.why}.` : undefined,
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function shieldView(row) {
|
|
208
|
+
if (row.error) return errorView(row, { text: 'so the result was passed on unscreened', tone: 'muted' })
|
|
209
|
+
const verdict = SHIELD[row.verdict] ?? SHIELD.clean
|
|
210
|
+
const lines = num(row.removedLines) ?? 0
|
|
211
|
+
return {
|
|
212
|
+
verdict: row.verdict, ...verdict, subject: { tool: row.tool, text: row.call },
|
|
213
|
+
facts: [
|
|
214
|
+
{ id: 'passages', label: 'Passages', value: String(num(row.passages) ?? '?') },
|
|
215
|
+
{ id: 'injection', label: 'Injection', value: p2(row.maxP), bar: num(row.maxP), tone: row.maxP >= 0.5 ? 'bad' : 'ok' },
|
|
216
|
+
],
|
|
217
|
+
note: row.verdict === 'removed' ? `Removed ${plural(lines, 'line')} that gave orders to AI agents before System Two read the result.`
|
|
218
|
+
: row.verdict === 'flagged' ? `Found ${plural(lines, 'line')} that give orders to AI agents; the result was withheld.` : undefined,
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function doneView(row) {
|
|
223
|
+
if (row.error) return errorView(row, { text: 'so the turn ended as it was', tone: 'muted' })
|
|
224
|
+
const a = row.answers ?? {}
|
|
225
|
+
const why = DONE[row.why] ? row.why : row.verdict === 'continue' ? 'unfinished' : 'complete'
|
|
226
|
+
const verdict = DONE[why]
|
|
227
|
+
const round = `${num(row.steers) ?? '?'} of ${num(row.maxSteers) ?? '?'}`
|
|
228
|
+
return {
|
|
229
|
+
verdict: row.verdict === 'continue' ? 'continue' : 'stop', ...verdict, why, short: verdict.label.toLowerCase(),
|
|
230
|
+
headline: row.verdict === 'continue' ? `${verdict.label} to System Two (${round})` : why === 'waiting' ? 'Waiting on you' : 'The work is done',
|
|
231
|
+
facts: [
|
|
232
|
+
{ id: 'complete', label: 'Complete', value: p2(yesOf(a.complete)), bar: yesOf(a.complete), tone: yesOf(a.complete) < 0.5 ? 'warn' : 'ok' },
|
|
233
|
+
{ id: 'checked', label: 'Checked', value: p2(yesOf(a.checked)), bar: yesOf(a.checked) },
|
|
234
|
+
{ id: 'waiting', label: 'Waiting on you', value: p2(yesOf(a.waiting)), bar: yesOf(a.waiting) },
|
|
235
|
+
],
|
|
236
|
+
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}).` : undefined,
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function viewOf(reflex, row) {
|
|
242
|
+
switch (reflex) {
|
|
243
|
+
case 'triage': return triageView(row)
|
|
244
|
+
case 'guard': return guardView(row)
|
|
245
|
+
case 'shield': return shieldView(row)
|
|
246
|
+
case 'done': return doneView(row)
|
|
247
|
+
default: return row.error ? errorView(row) : { verdict: 'unknown', label: 'Decision', short: 'decision', tone: 'muted', facts: [] }
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function worstOf(views) {
|
|
252
|
+
return views.reduce((worst, view) => (SEVERITY[view.tone] > SEVERITY[worst.tone] ? view : worst), views[0])
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function headlineOf(reflex, views) {
|
|
256
|
+
if (views.length === 1) {
|
|
257
|
+
const view = views[0]
|
|
258
|
+
if (view.headline) return view.headline
|
|
259
|
+
const said = [view.label, view.outcome?.label].filter(Boolean).join(' → ')
|
|
260
|
+
return view.subject?.tool ? `${said} · ${view.subject.tool}` : said
|
|
261
|
+
}
|
|
262
|
+
const counts = new Map()
|
|
263
|
+
for (const view of views) {
|
|
264
|
+
const key = view.outcome?.short ?? view.short
|
|
265
|
+
counts.set(key, (counts.get(key) ?? 0) + 1)
|
|
266
|
+
}
|
|
267
|
+
const noun = reflex === 'guard' ? 'call' : reflex === 'shield' ? 'result' : 'decision'
|
|
268
|
+
return [plural(views.length, noun), ...[...counts].map(([short, n]) => `${n} ${short}`)].join(' · ')
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// one line: the verdict, then what it was about and its leading number
|
|
272
|
+
function compactLine(view) {
|
|
273
|
+
const label = view.outcome ? `${view.label} → ${view.outcome.label}` : view.label
|
|
274
|
+
const rest = []
|
|
275
|
+
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))
|
|
277
|
+
if (lead) rest.push(`${lead.label.toLowerCase()} ${lead.value}`)
|
|
278
|
+
if (view.error) rest.push(view.error)
|
|
279
|
+
return { label, tone: view.tone, rest: rest.join(' · ') }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ---- drawing ----
|
|
283
|
+
|
|
284
|
+
const seen = new Set()
|
|
285
|
+
// true once per decision, when this page first draws it while it is fresh
|
|
286
|
+
function firstSight(id, time) {
|
|
287
|
+
if (seen.has(id)) return false
|
|
288
|
+
if (seen.size > 4000) seen.clear()
|
|
289
|
+
seen.add(id)
|
|
290
|
+
return num(time) !== undefined && Math.abs(Date.now() - time) < FRESH_MS
|
|
291
|
+
}
|
|
292
|
+
const useFresh = (id, time) => React.useState(() => firstSight(id, time))[0]
|
|
293
|
+
const idOf = row => `${row.time}:${row.seq}:${row.reflex}:${row.callId ?? ''}`
|
|
294
|
+
|
|
295
|
+
class Contained extends React.Component {
|
|
296
|
+
constructor(props) {
|
|
297
|
+
super(props)
|
|
298
|
+
this.state = { failed: false }
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
static getDerivedStateFromError() {
|
|
302
|
+
return { failed: true }
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
componentDidCatch(error) {
|
|
306
|
+
console.warn(`[${PACKAGE}] a System One card failed to draw:`, error)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
render() {
|
|
310
|
+
return this.state.failed ? null : this.props.children
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function Badge({ id, ms, time }) {
|
|
315
|
+
const fresh = useFresh(`badge:${id}`, time)
|
|
316
|
+
return h('span', { className: cx('vsr-s1__badge', fresh && 'vsr-s1__badge--fresh'), 'data-system-one-part': 'badge' },
|
|
317
|
+
h('i', { className: 'vsr-s1__dot', 'aria-hidden': true }),
|
|
318
|
+
h('span', { className: 'vsr-s1__name' }, 'System One'),
|
|
319
|
+
secs(ms) ? h('span', { className: 'vsr-s1__ms', 'data-system-one-part': 'latency' }, secs(ms)) : null)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function Pill({ tone, children, arrow, part }) {
|
|
323
|
+
return h('span', { className: cx('vsr-s1__pill', `vsr-s1__pill--${tone}`, arrow && 'vsr-s1__pill--then'), 'data-system-one-part': part }, children)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function Fact({ id, label, value, bar, tone }) {
|
|
327
|
+
return h('span', { className: 'vsr-s1__fact', 'data-system-one-fact': id },
|
|
328
|
+
h('span', { className: 'vsr-s1__fact-label' }, label),
|
|
329
|
+
num(bar) === undefined ? null : h('span', { className: cx('vsr-s1__bar', tone && `vsr-s1__bar--${tone}`), style: { '--p': clamp01(bar) }, 'aria-hidden': true }, h('i')),
|
|
330
|
+
h('b', null, value))
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function Row({ row, view, single }) {
|
|
334
|
+
const fresh = useFresh(`row:${idOf(row)}`, row.time)
|
|
335
|
+
return h('div', {
|
|
336
|
+
className: cx('vsr-s1__row', fresh && 'vsr-s1__row--fresh'),
|
|
337
|
+
'data-system-one-decision': view.verdict,
|
|
338
|
+
'data-system-one-outcome': view.outcomeKey,
|
|
339
|
+
'data-system-one-call': row.callId,
|
|
340
|
+
},
|
|
341
|
+
h('span', { className: 'vsr-s1__verdicts' },
|
|
342
|
+
h(Pill, { tone: view.verdictTone ?? view.tone, part: 'verdict' }, view.label),
|
|
343
|
+
view.outcome ? h(Pill, { tone: view.outcome.tone, arrow: true, part: 'outcome' }, view.outcome.label) : null),
|
|
344
|
+
h('div', { className: 'vsr-s1__main' },
|
|
345
|
+
view.subject?.text ? h('div', { className: 'vsr-s1__subject', 'data-system-one-part': 'subject' },
|
|
346
|
+
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,
|
|
348
|
+
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,
|
|
349
|
+
view.note ? h('div', { className: 'vsr-s1__note', 'data-system-one-part': 'note' }, view.note) : null),
|
|
350
|
+
!single && secs(row.ms) ? h('span', { className: 'vsr-s1__rowms', 'data-system-one-part': 'latency' }, secs(row.ms)) : null)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function Rows({ reflex, rows, views }) {
|
|
354
|
+
const [all, setAll] = React.useState(false)
|
|
355
|
+
const hidden = all ? 0 : Math.max(0, rows.length - ROWS_SHOWN)
|
|
356
|
+
return h('div', { className: 'vsr-s1__rows', 'data-system-one-part': 'rows' },
|
|
357
|
+
hidden > 0 ? h('button', { type: 'button', className: 'vsr-s1__more', 'data-system-one-part': 'more', onClick: () => setAll(true) }, `Show ${plural(hidden, `earlier ${reflex === 'guard' ? 'call' : 'result'}`)}`) : null,
|
|
358
|
+
rows.slice(hidden).map((row, index) => h(Row, { key: idOf(row), row, view: views[hidden + index], single: rows.length === 1 })))
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const whole = value => (Number.isSafeInteger(value) ? String(value) : undefined)
|
|
362
|
+
|
|
363
|
+
// a public contract (README.md, "Selectors"); React leaves out an attribute whose value is undefined
|
|
364
|
+
function attributes(kind, state, worst) {
|
|
365
|
+
return {
|
|
366
|
+
'data-system-one': kind,
|
|
367
|
+
'data-system-one-reflex': state.reflex,
|
|
368
|
+
'data-system-one-verdict': worst.verdict,
|
|
369
|
+
'data-system-one-outcome': worst.outcomeKey,
|
|
370
|
+
'data-system-one-why': worst.why,
|
|
371
|
+
'data-system-one-tone': worst.tone,
|
|
372
|
+
'data-system-one-count': String(state.rows.length),
|
|
373
|
+
'data-system-one-turn': whole(state.rows[0].turn),
|
|
374
|
+
'data-system-one-step': state.reflex === 'guard' || state.reflex === 'shield' ? whole(state.rows[0].step) : undefined,
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function Card({ state }) {
|
|
379
|
+
const views = state.rows.map(row => viewOf(state.reflex, row))
|
|
380
|
+
const worst = worstOf(views)
|
|
381
|
+
const last = state.rows[state.rows.length - 1]
|
|
382
|
+
const headline = headlineOf(state.reflex, views)
|
|
383
|
+
const fresh = useFresh(`card:${idOf(state.rows[0])}`, state.rows[0].time)
|
|
384
|
+
const reflex = REFLEX[state.reflex] ?? state.reflex
|
|
385
|
+
return h('section', {
|
|
386
|
+
className: cx('vsr-s1', 'vsr-s1--card', `vsr-s1--${worst.tone}`, fresh && 'vsr-s1--fresh'),
|
|
387
|
+
role: 'group',
|
|
388
|
+
'aria-label': `System One ${reflex}: ${headline}`,
|
|
389
|
+
...attributes('card', state, worst),
|
|
390
|
+
},
|
|
391
|
+
h('span', { className: 'vsr-s1__sheen', 'aria-hidden': true }),
|
|
392
|
+
h('div', { className: 'vsr-s1__head', 'data-system-one-part': 'head' },
|
|
393
|
+
h(Badge, { key: idOf(last), id: idOf(last), ms: last.ms, time: last.time }),
|
|
394
|
+
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, reflex),
|
|
395
|
+
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: headline }, headline),
|
|
396
|
+
last.model ? h('span', { className: 'vsr-s1__model', 'data-system-one-part': 'model', title: last.model }, shortModel(last.model)) : null),
|
|
397
|
+
h(Rows, { reflex: state.reflex, rows: state.rows, views }))
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function Chevron() {
|
|
401
|
+
return h('svg', { className: 'vsr-s1__chev', viewBox: '0 0 16 16', width: 12, height: 12, 'aria-hidden': true },
|
|
402
|
+
h('path', { d: 'M6 3.5 10.5 8 6 12.5', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' }))
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function Compact({ state }) {
|
|
406
|
+
const views = state.rows.map(row => viewOf(state.reflex, row))
|
|
407
|
+
const worst = worstOf(views)
|
|
408
|
+
const last = state.rows[state.rows.length - 1]
|
|
409
|
+
const [open, setOpen] = React.useState(false)
|
|
410
|
+
const fresh = useFresh(`card:${idOf(state.rows[0])}`, state.rows[0].time)
|
|
411
|
+
const reflex = REFLEX[state.reflex] ?? state.reflex
|
|
412
|
+
const line = views.length === 1 ? compactLine(views[0]) : { label: headlineOf(state.reflex, views), tone: undefined, rest: '' }
|
|
413
|
+
const said = line.rest ? `${line.label} · ${line.rest}` : line.label
|
|
414
|
+
return h('div', {
|
|
415
|
+
className: cx('vsr-s1', 'vsr-s1--compact', `vsr-s1--${worst.tone}`, open && 'vsr-s1--open', fresh && 'vsr-s1--fresh'),
|
|
416
|
+
role: 'group',
|
|
417
|
+
'aria-label': `System One ${reflex}: ${said}`,
|
|
418
|
+
...attributes('compact', state, worst),
|
|
419
|
+
},
|
|
420
|
+
h('button', { type: 'button', className: 'vsr-s1__chip', 'data-system-one-part': 'toggle', 'aria-expanded': open, onClick: () => setOpen(!open) },
|
|
421
|
+
h(Badge, { key: idOf(last), id: idOf(last), ms: last.ms, time: last.time }),
|
|
422
|
+
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, reflex),
|
|
423
|
+
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: said },
|
|
424
|
+
h('span', { className: cx('vsr-s1__verdict', line.tone && `vsr-s1__verdict--${line.tone}`), 'data-system-one-part': 'verdict' }, line.label),
|
|
425
|
+
line.rest ? ` · ${line.rest}` : null),
|
|
426
|
+
h(Chevron)),
|
|
427
|
+
open ? h(Rows, { reflex: state.reflex, rows: state.rows, views }) : null)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// A routine check (an allowed call, a clean result) is one line in either mode; a decision that changed
|
|
431
|
+
// something, and the triage and done-check that frame the turn, are cards unless the mode is compact.
|
|
432
|
+
function SystemOneNode(props) {
|
|
433
|
+
const state = props?.node?.data
|
|
434
|
+
if (!state || !Array.isArray(state.rows) || state.rows.length === 0) return null
|
|
435
|
+
const slim = state.ui === 'compact' || !standsOut(state)
|
|
436
|
+
return h(Contained, null, h(slim ? Compact : Card, { state }))
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// ---- the system_one tool's row ----
|
|
440
|
+
|
|
441
|
+
function parseArgs(raw) {
|
|
442
|
+
try {
|
|
443
|
+
const args = typeof raw === 'string' ? JSON.parse(raw) : raw
|
|
444
|
+
return args && typeof args === 'object' ? args : {}
|
|
445
|
+
} catch {
|
|
446
|
+
return {}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function questionCount(questions) {
|
|
451
|
+
const parsed = typeof questions === 'string' ? parseArgs(questions) : questions
|
|
452
|
+
return parsed && typeof parsed === 'object' ? Object.keys(parsed).length : 0
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function resultText(block) {
|
|
456
|
+
return (Array.isArray(block?.content) ? block.content : []).filter(part => part?.type === 'text').map(part => part.text).join('\n').trim()
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function relative(path, cwd) {
|
|
460
|
+
const value = text(path)
|
|
461
|
+
const root = text(cwd).replace(/[\\/]+$/, '')
|
|
462
|
+
return root && value.startsWith(`${root}/`) ? value.slice(root.length + 1) : value
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function Stack({ parts, fresh }) {
|
|
466
|
+
const total = parts.reduce((sum, part) => sum + part.n, 0)
|
|
467
|
+
return h('span', { className: cx('vsr-s1__stack', fresh && 'vsr-s1__stack--fresh'), 'data-system-one-part': 'stack', 'aria-hidden': true },
|
|
468
|
+
total > 0 ? parts.filter(part => part.n > 0).map((part, index) => h('i', { key: part.label, style: { flexGrow: part.n, background: part.color, animationDelay: `${0.12 + index * 0.06}s` } })) : null)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// the model writes the option names; a long one is cut in the legend and kept whole in its tooltip
|
|
472
|
+
const LABEL_CHARS = 28
|
|
473
|
+
const shortLabel = label => (label.length > LABEL_CHARS ? `${label.slice(0, LABEL_CHARS - 1).trimEnd()}…` : label)
|
|
474
|
+
|
|
475
|
+
function Legend({ parts, extra, failed }) {
|
|
476
|
+
return h('span', { className: 'vsr-s1__legend', 'data-system-one-part': 'legend' },
|
|
477
|
+
parts.map(part => h('span', { key: part.label, className: 'vsr-s1__key', title: `${part.label}: ${part.n}` },
|
|
478
|
+
h('i', { className: 'vsr-s1__swatch', style: { background: part.color } }),
|
|
479
|
+
`${shortLabel(part.label)} `, h('b', null, String(part.n)))),
|
|
480
|
+
extra ? h('span', { className: 'vsr-s1__key vsr-s1__key--note' }, extra) : null,
|
|
481
|
+
failed ? h('span', { className: 'vsr-s1__key vsr-s1__key--bad', 'data-system-one-part': 'failed' }, `${failed} failed`) : null)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function questionParts(summary) {
|
|
485
|
+
if (summary?.type === 'choice') {
|
|
486
|
+
const counts = Object.entries(summary.counts ?? {}).sort((x, y) => y[1] - x[1])
|
|
487
|
+
const head = counts.slice(0, 6).map(([label, n], index) => ({ label, n, color: HUES[index % HUES.length] }))
|
|
488
|
+
const rest = counts.slice(6).reduce((sum, [, n]) => sum + n, 0)
|
|
489
|
+
return {
|
|
490
|
+
parts: rest ? [...head, { label: 'other', n: rest, color: 'var(--vsr-s1-text-3)' }] : head,
|
|
491
|
+
extra: summary.unsureCount ? `${summary.unsureCount} unsure` : undefined,
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (summary?.type === 'noul') {
|
|
495
|
+
return { parts: [{ label: 'yes', n: summary.yes ?? 0, color: '#EF5630' }, { label: 'no', n: summary.no ?? 0, color: 'var(--vsr-s1-track)' }] }
|
|
496
|
+
}
|
|
497
|
+
if (summary?.type === 'score') {
|
|
498
|
+
const levels = Object.entries(summary.levels ?? {})
|
|
499
|
+
return {
|
|
500
|
+
parts: levels.map(([label, n], index) => ({ label, n, color: RAMP[Math.round((index / Math.max(1, levels.length - 1)) * (RAMP.length - 1))] })),
|
|
501
|
+
extra: num(summary.mean) !== undefined ? `mean ${summary.mean}` : undefined,
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (summary?.type === 'box') return { parts: [], extra: plural(summary.boxes?.length ?? 0, 'box', 'boxes') }
|
|
505
|
+
return { parts: [] }
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function Question({ id, summary, fresh }) {
|
|
509
|
+
const { parts, extra } = questionParts(summary)
|
|
510
|
+
return h('div', { className: 'vsr-s1__q', 'data-system-one-question': id },
|
|
511
|
+
h('code', { className: 'vsr-s1__qname', title: id }, id),
|
|
512
|
+
h('div', { className: 'vsr-s1__qbody' },
|
|
513
|
+
parts.length ? h(Stack, { parts, fresh }) : null,
|
|
514
|
+
h(Legend, { parts, extra, failed: num(summary?.failed) || undefined })))
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
function ToolBody({ meta, fresh, cwd, openFile }) {
|
|
518
|
+
const entries = Object.entries(meta.summary ?? {})
|
|
519
|
+
return h('div', { className: 'vsr-s1__rows', 'data-system-one-part': 'rows' },
|
|
520
|
+
entries.map(([id, summary]) => h(Question, { key: id, id, summary, fresh })),
|
|
521
|
+
meta.output ? h('div', { className: 'vsr-s1__foot', 'data-system-one-part': 'results' },
|
|
522
|
+
'Results ',
|
|
523
|
+
typeof openFile === 'function'
|
|
524
|
+
? h('button', { type: 'button', className: 'vsr-s1__link', onClick: () => openFile(meta.output) }, relative(meta.output, cwd))
|
|
525
|
+
: h('code', null, relative(meta.output, cwd))) : null)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function ToolRow(props) {
|
|
529
|
+
const { block, phase, callId, cwd, openFile } = props
|
|
530
|
+
const args = parseArgs(phase === 'result' ? block?.call?.argsRaw : block?.argsRaw)
|
|
531
|
+
const meta = phase === 'result' && block?.meta && block.meta.systemOne === 1 ? block.meta : undefined
|
|
532
|
+
const ui = meta?.ui ?? 'card'
|
|
533
|
+
const fresh = useFresh(`tool:${callId}:${phase}`, phase === 'result' ? block?.time : Date.now())
|
|
534
|
+
const [open, setOpen] = React.useState(false)
|
|
535
|
+
const source = args.file ? basename(args.file) : Array.isArray(args.images) ? plural(args.images.length, 'image') : Array.isArray(args.items) ? plural(args.items.length, 'item') : ''
|
|
536
|
+
const asked = questionCount(args.questions)
|
|
537
|
+
const common = { 'data-system-one-reflex': 'tool', 'data-system-one-call': callId }
|
|
538
|
+
|
|
539
|
+
if (phase !== 'result') {
|
|
540
|
+
const line = phase === 'preparing' ? 'Preparing a batch' : `Answering ${plural(asked, 'question')}${source ? ` over ${source}` : ''}`
|
|
541
|
+
return h('div', { className: 'vsr-s1 vsr-s1--compact vsr-s1--running', 'data-system-one': 'tool', ...common, 'data-system-one-verdict': 'running', 'data-system-one-tone': 'info' },
|
|
542
|
+
h('div', { className: 'vsr-s1__chip vsr-s1__chip--static' },
|
|
543
|
+
h(Badge, { id: `${callId}:running`, time: Date.now() }),
|
|
544
|
+
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, REFLEX.tool),
|
|
545
|
+
h('span', { className: 'vsr-s1__summary vsr-s1__shimmer', 'data-system-one-part': 'summary' }, line)))
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (block?.isError || !meta || ui === 'off') {
|
|
549
|
+
const body = resultText(block)
|
|
550
|
+
const first = body.split('\n')[0] || (block?.isError ? 'The batch failed' : 'Done')
|
|
551
|
+
return h('div', {
|
|
552
|
+
className: cx('vsr-s1', 'vsr-s1--compact', 'vsr-s1--plain', block?.isError && 'vsr-s1--bad', open && 'vsr-s1--open'),
|
|
553
|
+
'data-system-one': 'tool', ...common, 'data-system-one-verdict': block?.isError ? 'error' : 'done', 'data-system-one-tone': block?.isError ? 'bad' : 'muted',
|
|
554
|
+
},
|
|
555
|
+
h('button', { type: 'button', className: 'vsr-s1__chip', 'data-system-one-part': 'toggle', 'aria-expanded': open, onClick: () => setOpen(!open) },
|
|
556
|
+
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, 'System One'),
|
|
557
|
+
h('span', { className: cx('vsr-s1__summary', block?.isError && 'vsr-s1__summary--bad'), 'data-system-one-part': 'summary', title: first }, first),
|
|
558
|
+
h(Chevron)),
|
|
559
|
+
open ? h('pre', { className: 'vsr-s1__raw', 'data-system-one-part': 'raw' }, body) : null)
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
const ms = num(meta.seconds) === undefined ? undefined : meta.seconds * 1000
|
|
563
|
+
const headline = [plural(num(meta.items) ?? 0, 'item'), plural(num(meta.questions) ?? 0, 'question'), plural(num(meta.requests) ?? 0, 'request')].join(' · ')
|
|
564
|
+
const done = { ...common, 'data-system-one-verdict': 'done', 'data-system-one-tone': 'ok', 'data-system-one-count': String(meta.items ?? '') }
|
|
565
|
+
if (ui === 'compact') {
|
|
566
|
+
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
|
+
h('button', { type: 'button', className: 'vsr-s1__chip', 'data-system-one-part': 'toggle', 'aria-expanded': open, onClick: () => setOpen(!open) },
|
|
568
|
+
h(Badge, { id: `${callId}:done`, ms, time: block?.time }),
|
|
569
|
+
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, REFLEX.tool),
|
|
570
|
+
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: headline }, headline),
|
|
571
|
+
h(Chevron)),
|
|
572
|
+
open ? h(ToolBody, { meta, fresh, cwd, openFile }) : null)
|
|
573
|
+
}
|
|
574
|
+
return h('section', {
|
|
575
|
+
className: cx('vsr-s1', 'vsr-s1--card', 'vsr-s1--ok', 'vsr-s1--tool', fresh && 'vsr-s1--fresh'),
|
|
576
|
+
role: 'group',
|
|
577
|
+
'aria-label': `System One batch: ${headline}`,
|
|
578
|
+
'data-system-one': 'tool',
|
|
579
|
+
...done,
|
|
580
|
+
},
|
|
581
|
+
h('span', { className: 'vsr-s1__sheen', 'aria-hidden': true }),
|
|
582
|
+
h('div', { className: 'vsr-s1__head', 'data-system-one-part': 'head' },
|
|
583
|
+
h(Badge, { id: `${callId}:done`, ms, time: block?.time }),
|
|
584
|
+
h('span', { className: 'vsr-s1__reflex', 'data-system-one-part': 'reflex' }, REFLEX.tool),
|
|
585
|
+
h('span', { className: 'vsr-s1__summary', 'data-system-one-part': 'summary', title: headline }, headline),
|
|
586
|
+
meta.model ? h('span', { className: 'vsr-s1__model', 'data-system-one-part': 'model', title: meta.model }, shortModel(meta.model)) : null),
|
|
587
|
+
h(ToolBody, { meta, fresh, cwd, openFile }))
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function SystemOneToolRow(props) {
|
|
591
|
+
return h(Contained, null, h(ToolRow, props))
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// ---- styles: the Web UI's theme tokens, with System One's ember from the launch film ----
|
|
595
|
+
|
|
596
|
+
const CSS = `
|
|
597
|
+
.vsr-s1{--vsr-s1-ember:#EF5630;--vsr-s1-ember-deep:#D9441F;--vsr-s1-gold:#F5B82E;--vsr-s1-ok:var(--dsw-alias-state-success-primary,#1F9D5B);--vsr-s1-warn:var(--dsw-alias-state-warn-primary,#E8A100);--vsr-s1-bad:var(--dsw-alias-state-error-primary,#E5484D);--vsr-s1-info:var(--dsw-alias-brand-primary,#2F7BF6);--vsr-s1-text:var(--dsw-alias-label-primary,#1F2329);--vsr-s1-text-2:var(--dsw-alias-label-secondary,#545961);--vsr-s1-text-3:var(--dsw-alias-label-tertiary,#8A8F98);--vsr-s1-line:var(--dsw-alias-border-l2,rgba(127,127,127,.22));--vsr-s1-track:color-mix(in srgb,var(--vsr-s1-text-3) 28%,transparent);--vsr-s1-mono:ui-monospace,SFMono-Regular,"JetBrains Mono",Menlo,Consolas,monospace;position:relative;box-sizing:border-box;width:100%;margin:6px 0;color:var(--vsr-s1-text);font-size:13.5px;line-height:1.45;text-align:left}
|
|
598
|
+
.vsr-s1 *{box-sizing:border-box}
|
|
599
|
+
.vsr-s1--card{padding:11px 14px 12px 17px;border:1px solid color-mix(in srgb,var(--vsr-s1-ember) 30%,var(--vsr-s1-line));border-radius:12px;background:linear-gradient(180deg,color-mix(in srgb,var(--vsr-s1-ember) 7%,transparent),color-mix(in srgb,var(--vsr-s1-ember) 2.5%,transparent))}
|
|
600
|
+
.vsr-s1--card.vsr-s1--bad{border-color:color-mix(in srgb,var(--vsr-s1-bad) 50%,var(--vsr-s1-line));background:linear-gradient(180deg,color-mix(in srgb,var(--vsr-s1-bad) 9%,transparent),color-mix(in srgb,var(--vsr-s1-bad) 3%,transparent))}
|
|
601
|
+
.vsr-s1--card.vsr-s1--warn{border-color:color-mix(in srgb,var(--vsr-s1-warn) 50%,var(--vsr-s1-line));background:linear-gradient(180deg,color-mix(in srgb,var(--vsr-s1-warn) 9%,transparent),color-mix(in srgb,var(--vsr-s1-warn) 3%,transparent))}
|
|
602
|
+
.vsr-s1__sheen{position:absolute;inset:0;border-radius:inherit;overflow:hidden;pointer-events:none}
|
|
603
|
+
.vsr-s1__sheen::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(180deg,var(--vsr-s1-ember),var(--vsr-s1-gold))}
|
|
604
|
+
.vsr-s1--bad>.vsr-s1__sheen::before{background:var(--vsr-s1-bad)}
|
|
605
|
+
.vsr-s1--warn>.vsr-s1__sheen::before{background:var(--vsr-s1-warn)}
|
|
606
|
+
.vsr-s1__head{position:relative;display:flex;align-items:center;gap:9px;min-width:0}
|
|
607
|
+
.vsr-s1__badge{position:relative;display:inline-flex;flex:none;align-items:center;gap:6px;height:22px;padding:0 9px 0 8px;border-radius:999px;color:#fff;font-size:12px;font-weight:650;letter-spacing:-.005em;white-space:nowrap;background:linear-gradient(160deg,var(--vsr-s1-ember) 0%,var(--vsr-s1-ember-deep) 100%);box-shadow:0 1px 2px rgba(217,68,31,.28),inset 0 1px 0 rgba(255,255,255,.35)}
|
|
608
|
+
.vsr-s1__dot{flex:none;width:6px;height:6px;border-radius:50%;background:#fff;box-shadow:0 0 6px #fff}
|
|
609
|
+
.vsr-s1__ms{padding-left:7px;border-left:1px solid rgba(255,255,255,.5);font-weight:750;font-variant-numeric:tabular-nums}
|
|
610
|
+
.vsr-s1__reflex{flex:none;font-weight:650;color:var(--vsr-s1-text);white-space:nowrap}
|
|
611
|
+
.vsr-s1__summary{flex:1;min-width:0;overflow:hidden;color:var(--vsr-s1-text-2);white-space:nowrap;text-overflow:ellipsis}
|
|
612
|
+
.vsr-s1__summary--bad{color:var(--vsr-s1-bad)}
|
|
613
|
+
.vsr-s1__verdict{font-weight:600;color:var(--vsr-s1-text)}
|
|
614
|
+
.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-3);font-size:12px;white-space:nowrap}
|
|
616
|
+
.vsr-s1__rows{display:grid;grid-template-columns:auto minmax(0,1fr) auto;column-gap:12px;row-gap:8px;margin-top:9px}
|
|
617
|
+
.vsr-s1__rows>*{grid-column:1/-1}
|
|
618
|
+
.vsr-s1__row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-columns:subgrid;column-gap:12px;align-items:start}
|
|
619
|
+
.vsr-s1__verdicts{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-width:92px}
|
|
620
|
+
.vsr-s1__pill{--tone:var(--vsr-s1-text-3);display:inline-flex;align-items:center;gap:6px;padding:1px 8px 1px 7px;border-radius:6px;color:var(--tone);background:color-mix(in srgb,var(--tone) 13%,transparent);font-size:12px;font-weight:650;line-height:20px;white-space:nowrap}
|
|
621
|
+
.vsr-s1__pill::before{content:"";flex:none;width:6px;height:6px;border-radius:50%;background:currentColor}
|
|
622
|
+
.vsr-s1__pill--then::before{width:auto;height:auto;border-radius:0;background:none;content:"\\21B3"}
|
|
623
|
+
.vsr-s1__pill--ok{--tone:var(--vsr-s1-ok)}.vsr-s1__pill--warn{--tone:color-mix(in srgb,var(--vsr-s1-warn) 82%,var(--vsr-s1-text))}.vsr-s1__pill--bad{--tone:var(--vsr-s1-bad)}.vsr-s1__pill--info{--tone:var(--vsr-s1-ember-deep)}.vsr-s1__pill--muted{--tone:var(--vsr-s1-text-3)}
|
|
624
|
+
.vsr-s1__main{display:grid;gap:3px;min-width:0}
|
|
625
|
+
.vsr-s1__subject{display:flex;align-items:baseline;gap:7px;min-width:0;line-height:22px}
|
|
626
|
+
.vsr-s1__tool{flex:none;color:var(--vsr-s1-text-2);font-weight:600}
|
|
627
|
+
.vsr-s1__code{min-width:0;overflow:hidden;color:var(--vsr-s1-text);font-family:var(--vsr-s1-mono);font-size:12.5px;white-space:nowrap;text-overflow:ellipsis;background:none;padding:0}
|
|
628
|
+
.vsr-s1__facts{display:flex;flex-wrap:wrap;gap:3px 16px;color:var(--vsr-s1-text-2);font-size:12.5px;line-height:22px}
|
|
629
|
+
.vsr-s1__fact{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
|
|
630
|
+
.vsr-s1__fact b{color:var(--vsr-s1-text);font-weight:600;font-variant-numeric:tabular-nums}
|
|
631
|
+
.vsr-s1__bar{position:relative;width:34px;height:4px;border-radius:2px;overflow:hidden;background:var(--vsr-s1-track)}
|
|
632
|
+
.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
|
+
.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
|
+
.vsr-s1__note{color:var(--vsr-s1-text-2);font-size:12.5px}
|
|
635
|
+
.vsr-s1__rowms{color:var(--vsr-s1-text-3);font-size:12px;line-height:22px;font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
636
|
+
.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
|
+
.vsr-s1__more:hover,.vsr-s1__link:hover{text-decoration:underline}
|
|
638
|
+
.vsr-s1--compact{margin:4px 0}
|
|
639
|
+
.vsr-s1__chip{display:flex;align-items:center;gap:9px;width:100%;min-width:0;padding:3px 0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
640
|
+
.vsr-s1__chip--static{cursor:default}
|
|
641
|
+
.vsr-s1__chev{flex:none;color:var(--vsr-s1-text-3);transition:transform .16s ease}
|
|
642
|
+
.vsr-s1--open .vsr-s1__chev{transform:rotate(90deg)}
|
|
643
|
+
.vsr-s1--compact>.vsr-s1__rows{margin:4px 0 8px 3px;padding-left:12px;border-left:2px solid color-mix(in srgb,var(--vsr-s1-ember) 45%,transparent)}
|
|
644
|
+
.vsr-s1--plain .vsr-s1__reflex{color:var(--vsr-s1-text-2)}
|
|
645
|
+
.vsr-s1__raw{margin:4px 0 8px;padding:8px 10px;max-height:320px;overflow:auto;border-radius:8px;background:color-mix(in srgb,var(--vsr-s1-text-3) 10%,transparent);font-family:var(--vsr-s1-mono);font-size:12px;white-space:pre-wrap}
|
|
646
|
+
.vsr-s1__q{display:grid;grid-template-columns:minmax(80px,140px) minmax(0,1fr);column-gap:14px;align-items:start}
|
|
647
|
+
.vsr-s1__qname{overflow:hidden;color:var(--vsr-s1-text);font-family:var(--vsr-s1-mono);font-size:12.5px;line-height:16px;white-space:nowrap;text-overflow:ellipsis;background:none;padding:0}
|
|
648
|
+
.vsr-s1__qbody{display:grid;gap:4px;min-width:0}
|
|
649
|
+
.vsr-s1__stack{display:flex;gap:2px;height:8px;margin-top:4px;border-radius:4px;overflow:hidden;background:var(--vsr-s1-track)}
|
|
650
|
+
.vsr-s1__stack>i{display:block;min-width:3px;height:100%;transform-origin:left center}
|
|
651
|
+
.vsr-s1__legend{display:flex;flex-wrap:wrap;gap:1px 14px;color:var(--vsr-s1-text-2);font-size:12.5px}
|
|
652
|
+
.vsr-s1__key{display:inline-flex;align-items:center;white-space:nowrap}
|
|
653
|
+
.vsr-s1__key b{margin-left:4px;color:var(--vsr-s1-text);font-weight:600;font-variant-numeric:tabular-nums}
|
|
654
|
+
.vsr-s1__key--note{color:var(--vsr-s1-text-3)}
|
|
655
|
+
.vsr-s1__key--bad{color:var(--vsr-s1-bad);font-weight:600}
|
|
656
|
+
.vsr-s1__swatch{flex:none;width:8px;height:8px;margin-right:6px;border-radius:2px}
|
|
657
|
+
.vsr-s1__foot{color:var(--vsr-s1-text-3);font-size:12.5px}
|
|
658
|
+
.vsr-s1__foot code{font-family:var(--vsr-s1-mono)}
|
|
659
|
+
@keyframes vsr-s1-in{from{opacity:0;transform:translateY(8px) scale(.985)}to{opacity:1;transform:none}}
|
|
660
|
+
@keyframes vsr-s1-glow{0%{box-shadow:0 0 0 0 rgba(239,86,48,0)}25%{box-shadow:0 0 0 5px rgba(239,86,48,.2),0 8px 28px rgba(239,86,48,.18)}100%{box-shadow:0 0 0 0 rgba(239,86,48,0),0 0 0 rgba(239,86,48,0)}}
|
|
661
|
+
@keyframes vsr-s1-sweep{from{transform:translateX(-110%)}to{transform:translateX(110%)}}
|
|
662
|
+
@keyframes vsr-s1-pop{0%{transform:scale(.55)}55%{transform:scale(1.09)}100%{transform:scale(1)}}
|
|
663
|
+
@keyframes vsr-s1-ring{0%{opacity:.7;transform:scale(1)}100%{opacity:0;transform:scale(1.45,2.1)}}
|
|
664
|
+
@keyframes vsr-s1-row{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}
|
|
665
|
+
@keyframes vsr-s1-fill{from{transform:scaleX(0)}}
|
|
666
|
+
@keyframes vsr-s1-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
|
|
667
|
+
@keyframes vsr-s1-blink{0%,100%{opacity:1}50%{opacity:.25}}
|
|
668
|
+
@keyframes vsr-s1-shimmer{from{background-position:120% 0}to{background-position:-20% 0}}
|
|
669
|
+
.vsr-s1--fresh{animation:vsr-s1-in .3s cubic-bezier(.2,.8,.2,1) both}
|
|
670
|
+
.vsr-s1--card.vsr-s1--fresh{animation:vsr-s1-in .3s cubic-bezier(.2,.8,.2,1) both,vsr-s1-glow 1.3s ease-out .08s both}
|
|
671
|
+
.vsr-s1--fresh>.vsr-s1__sheen::after{content:"";position:absolute;top:0;bottom:0;left:0;width:100%;background:linear-gradient(100deg,transparent 30%,rgba(255,170,110,.32) 50%,transparent 70%);animation:vsr-s1-sweep 1s cubic-bezier(.3,.7,.2,1) .1s both}
|
|
672
|
+
.vsr-s1__badge--fresh{animation:vsr-s1-pop .55s cubic-bezier(.3,1.5,.5,1) both}
|
|
673
|
+
.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
|
+
.vsr-s1__row--fresh{animation:vsr-s1-row .34s cubic-bezier(.2,.8,.2,1) .06s both}
|
|
675
|
+
.vsr-s1__row--fresh .vsr-s1__bar>i{animation:vsr-s1-fill .7s cubic-bezier(.2,.8,.2,1) .2s both}
|
|
676
|
+
.vsr-s1__stack--fresh>i{animation:vsr-s1-grow .6s cubic-bezier(.2,.8,.2,1) both}
|
|
677
|
+
.vsr-s1--running .vsr-s1__dot{animation:vsr-s1-blink 1s ease-in-out infinite}
|
|
678
|
+
.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}
|
|
679
|
+
@media (prefers-reduced-motion:reduce){.vsr-s1,.vsr-s1 *,.vsr-s1 *::before,.vsr-s1 *::after{animation:none!important;transition:none!important}.vsr-s1__shimmer{color:var(--vsr-s1-text-2)}}
|
|
680
|
+
`
|
|
681
|
+
if (typeof document !== 'undefined') {
|
|
682
|
+
const tagId = `${PACKAGE}/system-one.css`
|
|
683
|
+
if (document.querySelector(`style[data-plugin-css=${JSON.stringify(tagId)}]`) === null) {
|
|
684
|
+
const tag = document.createElement('style')
|
|
685
|
+
tag.dataset.plugin = PACKAGE
|
|
686
|
+
tag.dataset.pluginCss = tagId
|
|
687
|
+
tag.textContent = CSS
|
|
688
|
+
document.head.appendChild(tag)
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// ---- wiring: each part attaches when its service is there ----
|
|
693
|
+
|
|
694
|
+
function contained(what, run) {
|
|
695
|
+
try {
|
|
696
|
+
return run()
|
|
697
|
+
} catch (error) {
|
|
698
|
+
console.warn(`[${PACKAGE}] ${what} is off:`, error)
|
|
699
|
+
return undefined
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function slot(scoped, name, key, component) {
|
|
704
|
+
if (typeof scoped.slots?.inject !== 'function') return
|
|
705
|
+
scoped.slots.inject(name, () => contained(`the ${name} entry`, () => scoped.slots.register({ name, key }, component)) ?? (() => {}))
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
function apply(ctx) {
|
|
709
|
+
contained('the System One cards', () => ctx.inject(['uiConversation'], scoped => {
|
|
710
|
+
contained('the System One cards', () => scoped.uiConversation.events.register(definition))
|
|
711
|
+
}))
|
|
712
|
+
contained('the System One views', () => ctx.inject(['slots'], scoped => {
|
|
713
|
+
slot(scoped, 'conversation.chat.node', NODE_KIND, SystemOneNode)
|
|
714
|
+
slot(scoped, 'tool.call.toolview', TOOL_NAME, SystemOneToolRow)
|
|
715
|
+
}))
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
exports.apply = apply
|
|
719
|
+
exports.definition = definition
|
|
720
|
+
exports.viewOf = viewOf
|
|
721
|
+
exports.SystemOneNode = SystemOneNode
|
|
722
|
+
exports.SystemOneToolRow = SystemOneToolRow
|
|
723
|
+
exports.RECORD_TYPE = RECORD_TYPE
|
|
724
|
+
exports.NODE_KIND = NODE_KIND
|
|
725
|
+
} catch (error) {
|
|
726
|
+
console.warn('[@vllm-sr/dsh] the System One views are off:', error)
|
|
727
|
+
}
|
|
728
|
+
return module.exports
|
|
729
|
+
},
|
|
730
|
+
})
|