tr-plugin-meta-harness 0.0.0-stage → 0.3.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 +64 -2
- package/capability/BRICK.md +59 -0
- package/capability/index.mjs +534 -0
- package/cli.mjs +139 -0
- package/package.json +20 -4
- package/plugin.json +376 -0
- package/skills/meta-harness/SKILL.md +37 -0
- package/src/adapters/dsh.mjs +446 -0
- package/src/alerts.mjs +23 -0
- package/src/coordinator.mjs +398 -0
- package/src/documentation.mjs +152 -0
- package/src/executor.mjs +82 -0
- package/src/learner.mjs +90 -0
- package/src/router.mjs +415 -0
- package/src/runtime.mjs +36 -0
- package/src/setup.mjs +35 -0
- package/src/tracker.mjs +133 -0
- package/src/worker.mjs +233 -0
- package/ui/DESIGN.md +32 -0
- package/ui/card.js +845 -0
package/ui/card.js
ADDED
|
@@ -0,0 +1,845 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta Harness — Multi-Agent Coordination & Inspection Console
|
|
3
|
+
*
|
|
4
|
+
* Bespoke operator interface for terminal coding agent fleet management.
|
|
5
|
+
* Displays real-time agent discovery matrix, mesh node targets, authentication
|
|
6
|
+
* postures, quotas/RAM, SWE-bench/Terminal-Bench benchmarks, and RouteLLM router.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const DASH = '\u2014';
|
|
10
|
+
|
|
11
|
+
function escapeHtml(str) {
|
|
12
|
+
if (str === null || str === undefined) return '';
|
|
13
|
+
return String(str).replace(/[&<>"']/g, c => ({
|
|
14
|
+
'&': '&',
|
|
15
|
+
'<': '<',
|
|
16
|
+
'>': '>',
|
|
17
|
+
'"': '"',
|
|
18
|
+
"'": '''
|
|
19
|
+
}[c]));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class CommandFleetCard extends HTMLElement {
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
25
|
+
this.agents = [];
|
|
26
|
+
this.selectedAgent = null;
|
|
27
|
+
this.selectedNode = 'local';
|
|
28
|
+
this.nodes = [];
|
|
29
|
+
this.executing = false;
|
|
30
|
+
this.screen = 'fleet'; // 'fleet' | 'router' | 'quotas' | 'benchmarks'
|
|
31
|
+
this.quotas = null;
|
|
32
|
+
this.benchmarks = null;
|
|
33
|
+
this.routeResult = null;
|
|
34
|
+
this.routeInput = '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
connectedCallback() {
|
|
38
|
+
if (!this.shadowRoot) {
|
|
39
|
+
this.attachShadow({ mode: 'open' });
|
|
40
|
+
}
|
|
41
|
+
this.render();
|
|
42
|
+
this.refreshFleet();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async setScreen(screen) {
|
|
46
|
+
this.screen = screen;
|
|
47
|
+
this.render();
|
|
48
|
+
if (screen === 'quotas' && !this.quotas) {
|
|
49
|
+
await this.refreshQuotas();
|
|
50
|
+
} else if (screen === 'benchmarks' && !this.benchmarks) {
|
|
51
|
+
await this.refreshBenchmarks();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async refreshFleet() {
|
|
56
|
+
if (!this.host) return;
|
|
57
|
+
try {
|
|
58
|
+
const res = await this.host.run('status', ['--json']);
|
|
59
|
+
let parsed = [];
|
|
60
|
+
if (Array.isArray(res)) {
|
|
61
|
+
parsed = res;
|
|
62
|
+
} else if (res && typeof res === 'object') {
|
|
63
|
+
if (Array.isArray(res.agents)) parsed = res.agents;
|
|
64
|
+
if (res.documentation) this.docsFresh = Boolean(res.documentation.ok);
|
|
65
|
+
} else if (typeof res === 'string' && res.trim().startsWith('{')) {
|
|
66
|
+
try {
|
|
67
|
+
const obj = JSON.parse(res);
|
|
68
|
+
if (Array.isArray(obj.agents)) parsed = obj.agents;
|
|
69
|
+
if (obj.documentation) this.docsFresh = Boolean(obj.documentation.ok);
|
|
70
|
+
} catch {}
|
|
71
|
+
} else if (typeof res === 'string' && res.trim().startsWith('[')) {
|
|
72
|
+
try { parsed = JSON.parse(res); } catch {}
|
|
73
|
+
}
|
|
74
|
+
this.agents = parsed;
|
|
75
|
+
|
|
76
|
+
if (this.agents.length > 0 && !this.selectedAgent) {
|
|
77
|
+
this.selectedAgent = this.agents[0].id || this.agents[0].name;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Query mesh nodes
|
|
81
|
+
try {
|
|
82
|
+
const nodeRes = await this.host.run('nodes', ['--json']);
|
|
83
|
+
if (Array.isArray(nodeRes)) this.nodes = nodeRes;
|
|
84
|
+
else if (nodeRes && Array.isArray(nodeRes.nodes)) this.nodes = nodeRes.nodes;
|
|
85
|
+
else if (nodeRes && Array.isArray(nodeRes.targets)) this.nodes = nodeRes.targets;
|
|
86
|
+
} catch {
|
|
87
|
+
this.nodes = [{ id: 'local', name: 'This Node' }];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.render();
|
|
91
|
+
} catch {
|
|
92
|
+
this.agents = [];
|
|
93
|
+
this.render();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async refreshQuotas() {
|
|
98
|
+
if (!this.host) return;
|
|
99
|
+
try {
|
|
100
|
+
const res = await this.host.run('quota', ['--node', this.selectedNode, '--json']);
|
|
101
|
+
const parsed = typeof res === 'string' ? JSON.parse(res) : res;
|
|
102
|
+
this.quotas = parsed?.quotas || null;
|
|
103
|
+
this.render();
|
|
104
|
+
} catch {
|
|
105
|
+
this.quotas = null;
|
|
106
|
+
this.render();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async refreshBenchmarks() {
|
|
111
|
+
if (!this.host) return;
|
|
112
|
+
try {
|
|
113
|
+
const res = await this.host.run('benchmarks', ['--json']);
|
|
114
|
+
const parsed = typeof res === 'string' ? JSON.parse(res) : res;
|
|
115
|
+
this.benchmarks = parsed?.matrix || null;
|
|
116
|
+
this.render();
|
|
117
|
+
} catch {
|
|
118
|
+
this.benchmarks = null;
|
|
119
|
+
this.render();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async executeRoute(task) {
|
|
124
|
+
if (!this.host || !task) return;
|
|
125
|
+
this.executing = true;
|
|
126
|
+
this.render();
|
|
127
|
+
try {
|
|
128
|
+
const res = await this.host.run('route', [task, '--json']);
|
|
129
|
+
this.routeResult = typeof res === 'string' ? JSON.parse(res) : res;
|
|
130
|
+
} catch (err) {
|
|
131
|
+
this.routeResult = { ok: false, error: err.message };
|
|
132
|
+
} finally {
|
|
133
|
+
this.executing = false;
|
|
134
|
+
this.render();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async selectAgent(id) {
|
|
139
|
+
this.selectedAgent = id;
|
|
140
|
+
this.render();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async switchNode(nodeId) {
|
|
144
|
+
this.selectedNode = nodeId;
|
|
145
|
+
this.render();
|
|
146
|
+
await this.refreshFleet();
|
|
147
|
+
if (this.screen === 'quotas') {
|
|
148
|
+
await this.refreshQuotas();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async refreshDocs() {
|
|
153
|
+
if (!this.host || this.executing) return;
|
|
154
|
+
this.executing = true;
|
|
155
|
+
this.render();
|
|
156
|
+
try {
|
|
157
|
+
await this.host.run('docs-ensure', ['--json']);
|
|
158
|
+
await this.refreshFleet();
|
|
159
|
+
} catch {
|
|
160
|
+
await this.refreshFleet();
|
|
161
|
+
} finally {
|
|
162
|
+
this.executing = false;
|
|
163
|
+
this.render();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
render() {
|
|
168
|
+
const root = this.shadowRoot;
|
|
169
|
+
if (!root) return;
|
|
170
|
+
|
|
171
|
+
const installedAgents = this.agents.filter(a => a.installed !== false);
|
|
172
|
+
const active = this.agents.find(a => (a.id || a.name) === this.selectedAgent) || this.agents[0];
|
|
173
|
+
|
|
174
|
+
root.innerHTML = `
|
|
175
|
+
<style>
|
|
176
|
+
:host {
|
|
177
|
+
--face-bg: #0c1427;
|
|
178
|
+
--face-surface: #1e293b;
|
|
179
|
+
--face-line: #1e293b;
|
|
180
|
+
--face-text: #f1f5f9;
|
|
181
|
+
--face-muted: #94a3b8;
|
|
182
|
+
--face-brand: #3b82f6;
|
|
183
|
+
--face-brand-hover: #60a5fa;
|
|
184
|
+
--face-accent: #38bdf8;
|
|
185
|
+
--face-ok: #10b981;
|
|
186
|
+
--face-warn: #f59e0b;
|
|
187
|
+
--face-danger: #ef4444;
|
|
188
|
+
--face-dark: #0c1427;
|
|
189
|
+
|
|
190
|
+
display: block;
|
|
191
|
+
font-family: var(--font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
|
|
192
|
+
color: var(--text-primary, var(--face-text));
|
|
193
|
+
background: var(--bg-secondary, var(--face-bg));
|
|
194
|
+
border: 1px solid var(--border, var(--face-line));
|
|
195
|
+
border-radius: 8px;
|
|
196
|
+
padding: 16px;
|
|
197
|
+
box-sizing: border-box;
|
|
198
|
+
overflow: hidden;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@media (prefers-reduced-motion: reduce) {
|
|
202
|
+
*, ::before, ::after {
|
|
203
|
+
animation-duration: 0.01ms !important;
|
|
204
|
+
animation-iteration-count: 1 !important;
|
|
205
|
+
transition-duration: 0.01ms !important;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Header Bar */
|
|
210
|
+
.header {
|
|
211
|
+
display: flex;
|
|
212
|
+
align-items: center;
|
|
213
|
+
justify-content: space-between;
|
|
214
|
+
flex-wrap: wrap;
|
|
215
|
+
gap: 12px;
|
|
216
|
+
padding-bottom: 14px;
|
|
217
|
+
border-bottom: 1px solid var(--border, var(--face-line));
|
|
218
|
+
margin-bottom: 14px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.brand-group {
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
gap: 10px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.wordmark-badge {
|
|
228
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
229
|
+
font-size: 13px;
|
|
230
|
+
font-weight: 800;
|
|
231
|
+
letter-spacing: 0.05em;
|
|
232
|
+
color: var(--card-accent, var(--face-accent));
|
|
233
|
+
background: rgba(59, 130, 246, 0.12);
|
|
234
|
+
padding: 6px 10px;
|
|
235
|
+
border-radius: 6px;
|
|
236
|
+
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.title-meta {
|
|
240
|
+
display: flex;
|
|
241
|
+
flex-direction: column;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.plugin-title {
|
|
245
|
+
font-size: 14px;
|
|
246
|
+
font-weight: 700;
|
|
247
|
+
color: var(--text-primary, var(--face-text));
|
|
248
|
+
margin: 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.plugin-subtitle {
|
|
252
|
+
font-size: 11px;
|
|
253
|
+
color: var(--text-secondary, var(--face-muted));
|
|
254
|
+
margin: 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.status-chip {
|
|
258
|
+
display: flex;
|
|
259
|
+
align-items: center;
|
|
260
|
+
gap: 6px;
|
|
261
|
+
font-size: 11px;
|
|
262
|
+
font-weight: 600;
|
|
263
|
+
color: var(--face-ok);
|
|
264
|
+
background: rgba(16, 185, 129, 0.1);
|
|
265
|
+
border: 1px solid rgba(16, 185, 129, 0.25);
|
|
266
|
+
border-radius: 20px;
|
|
267
|
+
padding: 4px 10px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* Screen Navigation Tabs */
|
|
271
|
+
.tabs-bar {
|
|
272
|
+
display: flex;
|
|
273
|
+
gap: 8px;
|
|
274
|
+
margin-bottom: 14px;
|
|
275
|
+
border-bottom: 1px solid var(--border, var(--face-line));
|
|
276
|
+
padding-bottom: 8px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.tab-btn {
|
|
280
|
+
font-size: 12px;
|
|
281
|
+
font-weight: 600;
|
|
282
|
+
padding: 6px 12px;
|
|
283
|
+
border-radius: 6px;
|
|
284
|
+
border: 1px solid transparent;
|
|
285
|
+
background: transparent;
|
|
286
|
+
color: var(--text-secondary, var(--face-muted));
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
min-height: 44px;
|
|
289
|
+
display: flex;
|
|
290
|
+
align-items: center;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.tab-btn[data-active="true"] {
|
|
294
|
+
background: rgba(59, 130, 246, 0.15);
|
|
295
|
+
color: var(--face-accent);
|
|
296
|
+
border-color: rgba(59, 130, 246, 0.4);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* Node Selector & Action Controls */
|
|
300
|
+
.node-bar {
|
|
301
|
+
display: flex;
|
|
302
|
+
align-items: center;
|
|
303
|
+
justify-content: space-between;
|
|
304
|
+
flex-wrap: wrap;
|
|
305
|
+
gap: 10px;
|
|
306
|
+
margin-bottom: 14px;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.node-toggles {
|
|
310
|
+
display: flex;
|
|
311
|
+
gap: 6px;
|
|
312
|
+
flex-wrap: wrap;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.btn-node {
|
|
316
|
+
font-size: 11px;
|
|
317
|
+
font-weight: 600;
|
|
318
|
+
padding: 6px 12px;
|
|
319
|
+
border-radius: 5px;
|
|
320
|
+
border: 1px solid var(--border, var(--face-line));
|
|
321
|
+
background: rgba(30, 41, 59, 0.5);
|
|
322
|
+
color: var(--text-secondary, var(--face-muted));
|
|
323
|
+
cursor: pointer;
|
|
324
|
+
min-height: 44px;
|
|
325
|
+
display: flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.btn-node[data-active="true"] {
|
|
330
|
+
background: rgba(59, 130, 246, 0.2);
|
|
331
|
+
border-color: rgba(59, 130, 246, 0.5);
|
|
332
|
+
color: var(--text-primary, var(--face-text));
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.btn-action {
|
|
336
|
+
font-size: 11px;
|
|
337
|
+
font-weight: 600;
|
|
338
|
+
padding: 6px 12px;
|
|
339
|
+
border-radius: 5px;
|
|
340
|
+
background: rgba(59, 130, 246, 0.15);
|
|
341
|
+
border: 1px solid rgba(59, 130, 246, 0.4);
|
|
342
|
+
color: var(--face-accent);
|
|
343
|
+
cursor: pointer;
|
|
344
|
+
min-height: 44px;
|
|
345
|
+
display: flex;
|
|
346
|
+
align-items: center;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* Workspace Grid (Fleet View) */
|
|
350
|
+
.workspace-grid {
|
|
351
|
+
display: grid;
|
|
352
|
+
grid-template-columns: 240px 1fr;
|
|
353
|
+
gap: 14px;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
@media (max-width: 768px) {
|
|
357
|
+
.workspace-grid {
|
|
358
|
+
grid-template-columns: 1fr;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.roster-card {
|
|
363
|
+
background: rgba(15, 23, 42, 0.6);
|
|
364
|
+
border: 1px solid var(--border, var(--face-line));
|
|
365
|
+
border-radius: 6px;
|
|
366
|
+
padding: 8px;
|
|
367
|
+
max-height: 380px;
|
|
368
|
+
overflow-y: auto;
|
|
369
|
+
display: flex;
|
|
370
|
+
flex-direction: column;
|
|
371
|
+
gap: 4px;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.agent-item {
|
|
375
|
+
display: flex;
|
|
376
|
+
align-items: center;
|
|
377
|
+
justify-content: space-between;
|
|
378
|
+
padding: 8px 10px;
|
|
379
|
+
border-radius: 4px;
|
|
380
|
+
border: 1px solid transparent;
|
|
381
|
+
background: transparent;
|
|
382
|
+
cursor: pointer;
|
|
383
|
+
text-align: left;
|
|
384
|
+
width: 100%;
|
|
385
|
+
min-height: 44px;
|
|
386
|
+
box-sizing: border-box;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.agent-item:hover {
|
|
390
|
+
background: rgba(30, 41, 59, 0.4);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.agent-item[data-selected="true"] {
|
|
394
|
+
background: rgba(59, 130, 246, 0.15);
|
|
395
|
+
border-color: rgba(59, 130, 246, 0.4);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.agent-meta-left {
|
|
399
|
+
display: flex;
|
|
400
|
+
flex-direction: column;
|
|
401
|
+
gap: 2px;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.agent-name {
|
|
405
|
+
font-size: 12px;
|
|
406
|
+
font-weight: 700;
|
|
407
|
+
color: var(--text-primary, var(--face-text));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.agent-version {
|
|
411
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
412
|
+
font-size: 10px;
|
|
413
|
+
color: var(--text-secondary, var(--face-muted));
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.agent-badges {
|
|
417
|
+
display: flex;
|
|
418
|
+
flex-direction: column;
|
|
419
|
+
align-items: flex-end;
|
|
420
|
+
gap: 3px;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.badge-status {
|
|
424
|
+
font-size: 9px;
|
|
425
|
+
font-weight: 700;
|
|
426
|
+
padding: 2px 6px;
|
|
427
|
+
border-radius: 10px;
|
|
428
|
+
letter-spacing: 0.02em;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.badge-online {
|
|
432
|
+
background: rgba(16, 185, 129, 0.15);
|
|
433
|
+
color: var(--face-ok);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.badge-offline {
|
|
437
|
+
background: rgba(239, 68, 68, 0.15);
|
|
438
|
+
color: var(--face-danger);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.badge-auth-ok {
|
|
442
|
+
background: rgba(56, 189, 248, 0.15);
|
|
443
|
+
color: var(--face-accent);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.badge-auth-needed {
|
|
447
|
+
background: rgba(245, 158, 11, 0.15);
|
|
448
|
+
color: var(--face-warn);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.inspector-panel {
|
|
452
|
+
background: rgba(15, 23, 42, 0.6);
|
|
453
|
+
border: 1px solid var(--border, var(--face-line));
|
|
454
|
+
border-radius: 6px;
|
|
455
|
+
padding: 14px;
|
|
456
|
+
display: flex;
|
|
457
|
+
flex-direction: column;
|
|
458
|
+
gap: 14px;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.inspector-title {
|
|
462
|
+
font-size: 14px;
|
|
463
|
+
font-weight: 700;
|
|
464
|
+
margin: 0;
|
|
465
|
+
color: var(--text-primary, var(--face-text));
|
|
466
|
+
padding-bottom: 8px;
|
|
467
|
+
border-bottom: 1px solid var(--border, var(--face-line));
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.property-grid {
|
|
471
|
+
display: grid;
|
|
472
|
+
grid-template-columns: repeat(2, 1fr);
|
|
473
|
+
gap: 10px;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.property-box {
|
|
477
|
+
background: rgba(30, 41, 59, 0.4);
|
|
478
|
+
border: 1px solid var(--border, var(--face-line));
|
|
479
|
+
border-radius: 5px;
|
|
480
|
+
padding: 8px 10px;
|
|
481
|
+
display: flex;
|
|
482
|
+
flex-direction: column;
|
|
483
|
+
gap: 3px;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.property-label {
|
|
487
|
+
font-size: 10px;
|
|
488
|
+
color: var(--text-secondary, var(--face-muted));
|
|
489
|
+
text-transform: uppercase;
|
|
490
|
+
letter-spacing: 0.05em;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.property-val {
|
|
494
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
495
|
+
font-size: 12px;
|
|
496
|
+
font-weight: 700;
|
|
497
|
+
color: var(--text-primary, var(--face-text));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.permission-pills {
|
|
501
|
+
display: flex;
|
|
502
|
+
flex-wrap: wrap;
|
|
503
|
+
gap: 6px;
|
|
504
|
+
margin-top: 6px;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.pill-permission {
|
|
508
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
509
|
+
font-size: 10px;
|
|
510
|
+
padding: 4px 8px;
|
|
511
|
+
border-radius: 4px;
|
|
512
|
+
background: rgba(15, 23, 42, 0.8);
|
|
513
|
+
border: 1px solid var(--border, var(--face-line));
|
|
514
|
+
color: var(--text-secondary, var(--face-muted));
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.pill-active {
|
|
518
|
+
color: var(--face-ok);
|
|
519
|
+
border-color: rgba(16, 185, 129, 0.4);
|
|
520
|
+
background: rgba(16, 185, 129, 0.1);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/* Quotas & Benchmarks Tables */
|
|
524
|
+
.table-panel {
|
|
525
|
+
background: rgba(15, 23, 42, 0.6);
|
|
526
|
+
border: 1px solid var(--border, var(--face-line));
|
|
527
|
+
border-radius: 6px;
|
|
528
|
+
padding: 12px;
|
|
529
|
+
overflow-x: auto;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
.data-table {
|
|
533
|
+
width: 100%;
|
|
534
|
+
border-collapse: collapse;
|
|
535
|
+
font-size: 11px;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.data-table th {
|
|
539
|
+
text-align: left;
|
|
540
|
+
padding: 8px 10px;
|
|
541
|
+
border-bottom: 1px solid var(--border, var(--face-line));
|
|
542
|
+
color: var(--text-secondary, var(--face-muted));
|
|
543
|
+
font-weight: 600;
|
|
544
|
+
text-transform: uppercase;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.data-table td {
|
|
548
|
+
padding: 8px 10px;
|
|
549
|
+
border-bottom: 1px solid rgba(30, 41, 59, 0.4);
|
|
550
|
+
color: var(--text-primary, var(--face-text));
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/* Router Interactive Form */
|
|
554
|
+
.router-panel {
|
|
555
|
+
background: rgba(15, 23, 42, 0.6);
|
|
556
|
+
border: 1px solid var(--border, var(--face-line));
|
|
557
|
+
border-radius: 6px;
|
|
558
|
+
padding: 14px;
|
|
559
|
+
display: flex;
|
|
560
|
+
flex-direction: column;
|
|
561
|
+
gap: 12px;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.input-row {
|
|
565
|
+
display: flex;
|
|
566
|
+
gap: 8px;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.task-input {
|
|
570
|
+
flex: 1;
|
|
571
|
+
background: rgba(30, 41, 59, 0.6);
|
|
572
|
+
border: 1px solid var(--border, var(--face-line));
|
|
573
|
+
border-radius: 5px;
|
|
574
|
+
color: var(--text-primary, var(--face-text));
|
|
575
|
+
padding: 8px 12px;
|
|
576
|
+
font-size: 12px;
|
|
577
|
+
min-height: 44px;
|
|
578
|
+
box-sizing: border-box;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.empty-agents-box {
|
|
582
|
+
padding: 36px 16px;
|
|
583
|
+
text-align: center;
|
|
584
|
+
font-size: 12px;
|
|
585
|
+
color: var(--text-secondary, var(--face-muted));
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/* Footer Telemetry */
|
|
589
|
+
.footer-bar {
|
|
590
|
+
display: flex;
|
|
591
|
+
justify-content: space-between;
|
|
592
|
+
align-items: center;
|
|
593
|
+
padding-top: 12px;
|
|
594
|
+
margin-top: 14px;
|
|
595
|
+
border-top: 1px solid var(--border, var(--face-line));
|
|
596
|
+
font-size: 10px;
|
|
597
|
+
color: var(--text-secondary, var(--face-muted));
|
|
598
|
+
}
|
|
599
|
+
</style>
|
|
600
|
+
|
|
601
|
+
<div class="header">
|
|
602
|
+
<div class="brand-group">
|
|
603
|
+
<div class="wordmark-badge">META HARNESS</div>
|
|
604
|
+
<div class="title-meta">
|
|
605
|
+
<h3 class="plugin-title">Meta Harness Fleet</h3>
|
|
606
|
+
<p class="plugin-subtitle">Multi-agent runtime coordination, quotas & benchmarks</p>
|
|
607
|
+
</div>
|
|
608
|
+
</div>
|
|
609
|
+
<div class="status-chip">
|
|
610
|
+
${installedAgents.length > 0 ? `${installedAgents.length} Agents Discovered` : 'Scanning Fleet'}
|
|
611
|
+
</div>
|
|
612
|
+
</div>
|
|
613
|
+
|
|
614
|
+
<div class="tabs-bar">
|
|
615
|
+
<button class="tab-btn" data-active="${this.screen === 'fleet'}" data-screen="fleet" type="button">Fleet Roster</button>
|
|
616
|
+
<button class="tab-btn" data-active="${this.screen === 'quotas'}" data-screen="quotas" type="button">Quotas & RAM</button>
|
|
617
|
+
<button class="tab-btn" data-active="${this.screen === 'benchmarks'}" data-screen="benchmarks" type="button">Benchmarks</button>
|
|
618
|
+
<button class="tab-btn" data-active="${this.screen === 'router'}" data-screen="router" type="button">Smart Router</button>
|
|
619
|
+
</div>
|
|
620
|
+
|
|
621
|
+
<div class="node-bar">
|
|
622
|
+
<div class="node-toggles">
|
|
623
|
+
${(this.nodes.length > 0 ? this.nodes : [{ id: 'local', name: 'This Node' }]).map(node => `
|
|
624
|
+
<button class="btn-node" data-active="${this.selectedNode === (node.id || node)}" type="button" data-node-id="${escapeHtml(node.id || node)}">
|
|
625
|
+
${escapeHtml(node.name || node.id || node)}
|
|
626
|
+
</button>
|
|
627
|
+
`).join('')}
|
|
628
|
+
</div>
|
|
629
|
+
<button class="btn-action" type="button" id="btn-docs" ${this.executing ? 'disabled' : ''}>
|
|
630
|
+
${this.executing ? 'Working...' : 'Sync Documentation'}
|
|
631
|
+
</button>
|
|
632
|
+
</div>
|
|
633
|
+
|
|
634
|
+
${this.screen === 'fleet' ? `
|
|
635
|
+
<div class="workspace-grid">
|
|
636
|
+
<div class="roster-card">
|
|
637
|
+
${this.agents.length > 0 ? this.agents.map(a => `
|
|
638
|
+
<button class="agent-item" data-selected="${(a.id || a.name) === this.selectedAgent}" type="button" data-agent-id="${escapeHtml(a.id || a.name)}">
|
|
639
|
+
<div class="agent-meta-left">
|
|
640
|
+
<span class="agent-name">${escapeHtml(a.name || a.id)}</span>
|
|
641
|
+
<span class="agent-version">${escapeHtml(a.version || DASH)}</span>
|
|
642
|
+
</div>
|
|
643
|
+
<div class="agent-badges">
|
|
644
|
+
<span class="badge-status ${a.installed !== false ? 'badge-online' : 'badge-offline'}">
|
|
645
|
+
${a.installed !== false ? 'Installed' : 'Missing'}
|
|
646
|
+
</span>
|
|
647
|
+
<span class="badge-status ${a.authenticated !== false ? 'badge-auth-ok' : 'badge-auth-needed'}">
|
|
648
|
+
${a.authenticated !== false ? 'Auth OK' : 'Sign-in'}
|
|
649
|
+
</span>
|
|
650
|
+
</div>
|
|
651
|
+
</button>
|
|
652
|
+
`).join('') : `
|
|
653
|
+
<div class="empty-agents-box">Scanning for terminal coding agents...</div>
|
|
654
|
+
`}
|
|
655
|
+
</div>
|
|
656
|
+
|
|
657
|
+
<div class="inspector-panel">
|
|
658
|
+
${active ? `
|
|
659
|
+
<h4 class="inspector-title">${escapeHtml(active.name || active.id)} Details</h4>
|
|
660
|
+
<div class="property-grid">
|
|
661
|
+
<div class="property-box">
|
|
662
|
+
<span class="property-label">Runtime Binary</span>
|
|
663
|
+
<span class="property-val">${escapeHtml(active.binary || active.id || DASH)}</span>
|
|
664
|
+
</div>
|
|
665
|
+
<div class="property-box">
|
|
666
|
+
<span class="property-label">Installed Version</span>
|
|
667
|
+
<span class="property-val">${escapeHtml(active.version || DASH)}</span>
|
|
668
|
+
</div>
|
|
669
|
+
<div class="property-box">
|
|
670
|
+
<span class="property-label">Primary Model</span>
|
|
671
|
+
<span class="property-val">${escapeHtml(active.primaryModel || 'Default Model')}</span>
|
|
672
|
+
</div>
|
|
673
|
+
<div class="property-box">
|
|
674
|
+
<span class="property-label">Documentation</span>
|
|
675
|
+
<span class="property-val" style="color: ${this.docsFresh ? 'var(--face-ok)' : 'var(--face-muted)'};">
|
|
676
|
+
${this.docsFresh ? 'Verified Fresh' : 'Documentation Checked'}
|
|
677
|
+
</span>
|
|
678
|
+
</div>
|
|
679
|
+
</div>
|
|
680
|
+
|
|
681
|
+
<div>
|
|
682
|
+
<span class="property-label">Permission Enforcement Gates</span>
|
|
683
|
+
<div class="permission-pills">
|
|
684
|
+
<span class="pill-permission pill-active">Read Safe</span>
|
|
685
|
+
<span class="pill-permission pill-active">Write Gated</span>
|
|
686
|
+
<span class="pill-permission pill-active">Send Guarded</span>
|
|
687
|
+
<span class="pill-permission">Destructive Locked</span>
|
|
688
|
+
</div>
|
|
689
|
+
</div>
|
|
690
|
+
` : `
|
|
691
|
+
<div class="empty-agents-box">Select an agent from the fleet roster to inspect configuration.</div>
|
|
692
|
+
`}
|
|
693
|
+
</div>
|
|
694
|
+
</div>
|
|
695
|
+
` : ''}
|
|
696
|
+
|
|
697
|
+
${this.screen === 'quotas' ? `
|
|
698
|
+
<div class="table-panel">
|
|
699
|
+
<table class="data-table">
|
|
700
|
+
<thead>
|
|
701
|
+
<tr>
|
|
702
|
+
<th>Harness / System</th>
|
|
703
|
+
<th>Type</th>
|
|
704
|
+
<th>Usage %</th>
|
|
705
|
+
<th>5h Rolling Left</th>
|
|
706
|
+
<th>Weekly Left</th>
|
|
707
|
+
<th>Status</th>
|
|
708
|
+
</tr>
|
|
709
|
+
</thead>
|
|
710
|
+
<tbody>
|
|
711
|
+
${this.quotas?.system ? `
|
|
712
|
+
<tr>
|
|
713
|
+
<td><strong>System Host Memory</strong></td>
|
|
714
|
+
<td>Hardware RAM</td>
|
|
715
|
+
<td>${this.quotas.system.memoryUtilizationPercent}%</td>
|
|
716
|
+
<td colspan="2">${this.quotas.system.freeMemGB} GB free / ${this.quotas.system.totalMemGB} GB total</td>
|
|
717
|
+
<td><span class="badge-status badge-online">Operational</span></td>
|
|
718
|
+
</tr>
|
|
719
|
+
` : ''}
|
|
720
|
+
${this.quotas ? Object.entries(this.quotas).filter(([k]) => k !== 'system').map(([k, q]) => `
|
|
721
|
+
<tr>
|
|
722
|
+
<td><strong>${escapeHtml(k.toUpperCase())}</strong></td>
|
|
723
|
+
<td>${escapeHtml(q.billingModel || (q.metered ? 'Metered Credits' : 'Subscription'))}</td>
|
|
724
|
+
<td>${typeof q.usagePercent === 'number' ? `${q.usagePercent}%` : DASH}</td>
|
|
725
|
+
<td>${typeof q.rolling5hRemainingPercent === 'number' ? `${q.rolling5hRemainingPercent}%` : DASH}</td>
|
|
726
|
+
<td>${typeof q.weeklyRemainingPercent === 'number' ? `${q.weeklyRemainingPercent}%` : (q.quotaNote ? escapeHtml(q.quotaNote) : DASH)}</td>
|
|
727
|
+
<td>
|
|
728
|
+
<span class="badge-status ${q.status === 'optimal' || q.status === 'ready' ? 'badge-online' : (q.status === 'not_installed' ? 'badge-offline' : 'badge-auth-needed')}">
|
|
729
|
+
${escapeHtml(q.status)}
|
|
730
|
+
</span>
|
|
731
|
+
</td>
|
|
732
|
+
</tr>
|
|
733
|
+
`).join('') : `
|
|
734
|
+
<tr><td colspan="6" style="text-align:center;">Loading quota telemetry...</td></tr>
|
|
735
|
+
`}
|
|
736
|
+
</tbody>
|
|
737
|
+
</table>
|
|
738
|
+
</div>
|
|
739
|
+
` : ''}
|
|
740
|
+
|
|
741
|
+
${this.screen === 'benchmarks' ? `
|
|
742
|
+
<div class="table-panel">
|
|
743
|
+
<table class="data-table">
|
|
744
|
+
<thead>
|
|
745
|
+
<tr>
|
|
746
|
+
<th>Harness</th>
|
|
747
|
+
<th>Provider</th>
|
|
748
|
+
<th>SWE-bench Pro</th>
|
|
749
|
+
<th>Terminal-Bench 2</th>
|
|
750
|
+
<th>ELO Rating</th>
|
|
751
|
+
<th>Local Pass Rate</th>
|
|
752
|
+
</tr>
|
|
753
|
+
</thead>
|
|
754
|
+
<tbody>
|
|
755
|
+
${this.benchmarks ? Object.entries(this.benchmarks).map(([k, b]) => `
|
|
756
|
+
<tr>
|
|
757
|
+
<td><strong>${escapeHtml(k.toUpperCase())}</strong></td>
|
|
758
|
+
<td>${escapeHtml(b.provider)}</td>
|
|
759
|
+
<td>${typeof b.sweBenchPro === 'number' ? `${b.sweBenchPro}%` : DASH}</td>
|
|
760
|
+
<td>${typeof b.terminalBench2 === 'number' ? `${b.terminalBench2}%` : DASH}</td>
|
|
761
|
+
<td>${typeof b.artificialAnalysisElo === 'number' ? b.artificialAnalysisElo : DASH}</td>
|
|
762
|
+
<td>${b.localPassRatePercent !== null ? `${b.localPassRatePercent}% (${b.localRuns} runs)` : DASH}</td>
|
|
763
|
+
</tr>
|
|
764
|
+
`).join('') : `
|
|
765
|
+
<tr><td colspan="6" style="text-align:center;">Loading benchmark matrix...</td></tr>
|
|
766
|
+
`}
|
|
767
|
+
</tbody>
|
|
768
|
+
</table>
|
|
769
|
+
</div>
|
|
770
|
+
` : ''}
|
|
771
|
+
|
|
772
|
+
${this.screen === 'router' ? `
|
|
773
|
+
<div class="router-panel">
|
|
774
|
+
<div class="input-row">
|
|
775
|
+
<input class="task-input" id="task-input" type="text" placeholder="Enter task to evaluate complexity and optimal harness..." value="${escapeHtml(this.routeInput)}" />
|
|
776
|
+
<button class="btn-action" id="btn-route" type="button" ${this.executing ? 'disabled' : ''}>Evaluate Route</button>
|
|
777
|
+
</div>
|
|
778
|
+
|
|
779
|
+
${this.routeResult ? `
|
|
780
|
+
<div class="inspector-panel" style="background: rgba(30, 41, 59, 0.3);">
|
|
781
|
+
<h4 class="inspector-title">Route Recommendation: ${escapeHtml(this.routeResult.selected?.toUpperCase())} (${escapeHtml(this.routeResult.tier?.toUpperCase())} TIER)</h4>
|
|
782
|
+
<div class="property-grid">
|
|
783
|
+
<div class="property-box">
|
|
784
|
+
<span class="property-label">Complexity Score</span>
|
|
785
|
+
<span class="property-val">${this.routeResult.complexity?.score}/100</span>
|
|
786
|
+
</div>
|
|
787
|
+
<div class="property-box">
|
|
788
|
+
<span class="property-label">Active Factors</span>
|
|
789
|
+
<span class="property-val">${(this.routeResult.complexity?.factors || []).join(', ') || 'Standard task'}</span>
|
|
790
|
+
</div>
|
|
791
|
+
</div>
|
|
792
|
+
</div>
|
|
793
|
+
` : ''}
|
|
794
|
+
</div>
|
|
795
|
+
` : ''}
|
|
796
|
+
|
|
797
|
+
<div class="footer-bar">
|
|
798
|
+
<span>Target: ${this.selectedNode.toUpperCase()} MESH NODE</span>
|
|
799
|
+
<span>Fleet Version: v0.3.0</span>
|
|
800
|
+
</div>
|
|
801
|
+
`;
|
|
802
|
+
|
|
803
|
+
// Event listeners
|
|
804
|
+
root.querySelectorAll('.tab-btn').forEach(btn => {
|
|
805
|
+
btn.addEventListener('click', () => {
|
|
806
|
+
const screen = btn.getAttribute('data-screen');
|
|
807
|
+
if (screen) this.setScreen(screen);
|
|
808
|
+
});
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
root.querySelectorAll('.btn-node').forEach(btn => {
|
|
812
|
+
btn.addEventListener('click', () => {
|
|
813
|
+
const id = btn.getAttribute('data-node-id');
|
|
814
|
+
if (id) this.switchNode(id);
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
root.querySelectorAll('.agent-item').forEach(btn => {
|
|
819
|
+
btn.addEventListener('click', () => {
|
|
820
|
+
const id = btn.getAttribute('data-agent-id');
|
|
821
|
+
if (id) this.selectAgent(id);
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
root.querySelector('#btn-docs')?.addEventListener('click', () => this.refreshDocs());
|
|
826
|
+
|
|
827
|
+
const taskInput = root.querySelector('#task-input');
|
|
828
|
+
if (taskInput) {
|
|
829
|
+
taskInput.addEventListener('input', (e) => {
|
|
830
|
+
this.routeInput = e.target.value;
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
root.querySelector('#btn-route')?.addEventListener('click', () => {
|
|
835
|
+
if (this.routeInput) this.executeRoute(this.routeInput);
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (!customElements.get('meta-harness-card')) {
|
|
841
|
+
customElements.define('meta-harness-card', CommandFleetCard);
|
|
842
|
+
}
|
|
843
|
+
if (!customElements.get('command-fleet-card')) {
|
|
844
|
+
customElements.define('command-fleet-card', CommandFleetCard);
|
|
845
|
+
}
|