reflectt-node 0.1.2 → 0.1.4
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 +25 -2
- package/dist/cli.js +22 -10
- package/dist/cli.js.map +1 -1
- package/dist/cloud.d.ts.map +1 -1
- package/dist/cloud.js +63 -0
- package/dist/cloud.js.map +1 -1
- package/dist/context-budget.d.ts.map +1 -1
- package/dist/context-budget.js +7 -3
- package/dist/context-budget.js.map +1 -1
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +1 -0
- package/dist/dashboard.js.map +1 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +101 -16
- package/dist/doctor.js.map +1 -1
- package/dist/insight-task-bridge.d.ts +21 -0
- package/dist/insight-task-bridge.d.ts.map +1 -1
- package/dist/insight-task-bridge.js +13 -1
- package/dist/insight-task-bridge.js.map +1 -1
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +7 -8
- package/dist/preflight.js.map +1 -1
- package/dist/request-tracker.d.ts +7 -0
- package/dist/request-tracker.d.ts.map +1 -1
- package/dist/request-tracker.js +65 -5
- package/dist/request-tracker.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -1
- package/dist/server.js.map +1 -1
- package/package.json +5 -6
- package/public/dashboard.js +19 -8
- package/public/intensity-mock.html +413 -0
- package/public/polls-mock.html +610 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reflectt-node",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Coordinate your AI agent team. Shared tasks, memory, reflections, and presence. Self-host for free.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -32,14 +32,13 @@
|
|
|
32
32
|
"prepack": "chmod +x dist/cli.js"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
35
|
-
"reflectt",
|
|
36
|
-
"openclaw",
|
|
37
35
|
"ai-agents",
|
|
38
36
|
"agent-coordination",
|
|
39
37
|
"task-management",
|
|
40
38
|
"self-hosted",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
39
|
+
"ai",
|
|
40
|
+
"developer-tools",
|
|
41
|
+
"reflectt"
|
|
43
42
|
],
|
|
44
43
|
"author": "Team Reflectt",
|
|
45
44
|
"license": "Apache-2.0",
|
package/public/dashboard.js
CHANGED
|
@@ -164,6 +164,14 @@ function formatProductiveText(agent) {
|
|
|
164
164
|
function esc(s) { const d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; }
|
|
165
165
|
function formatBytes(b) { if (!b || b < 1024) return b + ' B'; if (b < 1048576) return (b/1024).toFixed(1) + ' KB'; return (b/1048576).toFixed(1) + ' MB'; }
|
|
166
166
|
function truncate(s, n) { return s && s.length > n ? s.slice(0, n) + '…' : (s || ''); }
|
|
167
|
+
function humanizeMinutes(m) {
|
|
168
|
+
if (m == null || m === '') return '—';
|
|
169
|
+
const n = Number(m);
|
|
170
|
+
if (!Number.isFinite(n) || n >= 9999) return '—';
|
|
171
|
+
if (n < 60) return n + 'm';
|
|
172
|
+
if (n < 1440) return Math.round(n / 60) + 'h';
|
|
173
|
+
return Math.round(n / 1440) + 'd';
|
|
174
|
+
}
|
|
167
175
|
function renderTaskTags(tags) {
|
|
168
176
|
if (!Array.isArray(tags) || tags.length === 0) return '';
|
|
169
177
|
const shown = tags.filter(Boolean).slice(0, 3);
|
|
@@ -495,7 +503,7 @@ function renderCompliance(compliance) {
|
|
|
495
503
|
|
|
496
504
|
const chipsHtml = chips.map(c => {
|
|
497
505
|
const state = complianceState(c.value, c.threshold);
|
|
498
|
-
return '<div class="sla-chip ' + state + '"><span>' + esc(c.label) + '</span><strong>' +
|
|
506
|
+
return '<div class="sla-chip ' + state + '"><span>' + esc(c.label) + '</span><strong>' + humanizeMinutes(c.value) + '</strong></div>';
|
|
499
507
|
}).join('');
|
|
500
508
|
|
|
501
509
|
const rows = agents.map(a => {
|
|
@@ -504,7 +512,7 @@ function renderCompliance(compliance) {
|
|
|
504
512
|
return '<tr>' +
|
|
505
513
|
'<td>' + esc(a.agent) + '</td>' +
|
|
506
514
|
'<td>' + taskCell + '</td>' +
|
|
507
|
-
'<td>' +
|
|
515
|
+
'<td>' + humanizeMinutes(a.lastValidStatusAgeMin) + '</td>' +
|
|
508
516
|
'<td>' + a.expectedCadenceMin + 'm</td>' +
|
|
509
517
|
'<td><span class="state-pill ' + a.state + ' compliance-state-' + a.state + '">' + esc(a.state) + '</span></td>' +
|
|
510
518
|
'<td><button class="copy-template-btn" data-agent="' + esc(a.agent) + '" data-task="' + esc(taskValue) + '" onclick="copyStatusTemplate(this.dataset.agent, this.dataset.task)">Copy template</button></td>' +
|
|
@@ -781,10 +789,12 @@ function renderKanban() {
|
|
|
781
789
|
kanban.innerHTML = cols.map(col => {
|
|
782
790
|
const items = grouped[col];
|
|
783
791
|
const isDone = col === 'done';
|
|
784
|
-
const
|
|
785
|
-
const
|
|
792
|
+
const isTodo = col === 'todo';
|
|
793
|
+
const colLimit = isDone ? 3 : isTodo ? 10 : items.length;
|
|
794
|
+
const cards = items.length === 0
|
|
786
795
|
? '<div class="empty">—</div>'
|
|
787
|
-
:
|
|
796
|
+
: items.map((t, idx) => {
|
|
797
|
+
const isHidden = idx >= colLimit;
|
|
788
798
|
const assigneeAgent = t.assignee ? AGENTS.find(a => a.name === t.assignee) : null;
|
|
789
799
|
const assigneeDisplay = t.assignee
|
|
790
800
|
? `<span class="assignee-tag">👤 ${esc(t.assignee)}${assigneeAgent ? ' <span class="role-small">' + esc(assigneeAgent.role) + '</span>' : ''}</span>`
|
|
@@ -793,7 +803,7 @@ function renderKanban() {
|
|
|
793
803
|
? `<div style="margin-top:4px"><span class="assignee-tag" style="font-family:monospace;font-size:10px;color:var(--accent)">🌿 ${esc(t.metadata.branch)}</span></div>`
|
|
794
804
|
: '';
|
|
795
805
|
return `
|
|
796
|
-
<div class="task-card" data-task-id="${t.id}">
|
|
806
|
+
<div class="task-card${isHidden ? ' hidden' : ''}" data-task-id="${t.id}">
|
|
797
807
|
<div class="task-title">${esc(truncate(t.title, 60))}</div>
|
|
798
808
|
<div class="task-meta">
|
|
799
809
|
${t.priority ? '<span class="priority-badge ' + t.priority + '">' + t.priority + '</span>' : ''}
|
|
@@ -808,8 +818,9 @@ function renderKanban() {
|
|
|
808
818
|
${renderQaContract(t)}
|
|
809
819
|
</div>`;
|
|
810
820
|
}).join('');
|
|
811
|
-
const
|
|
812
|
-
|
|
821
|
+
const hasMore = items.length > colLimit;
|
|
822
|
+
const extra = hasMore
|
|
823
|
+
? `<button class="done-toggle" onclick="this.parentElement.querySelectorAll('.task-card.hidden').forEach(c=>c.classList.remove('hidden'));this.remove()">+ ${items.length - colLimit} more</button>` : '';
|
|
813
824
|
return `<div class="kanban-col" data-status="${col}">
|
|
814
825
|
<div class="kanban-col-header">${col} <span class="cnt">${items.length}</span></div>
|
|
815
826
|
${cards}${extra}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Agent Intensity Toggle — Design Mock</title>
|
|
7
|
+
<style>
|
|
8
|
+
/* === Reflectt Node Tokens (subset) === */
|
|
9
|
+
:root {
|
|
10
|
+
--bg: #0a0e14;
|
|
11
|
+
--surface: #141920;
|
|
12
|
+
--surface-raised: #1a2028;
|
|
13
|
+
--border: #252d38;
|
|
14
|
+
--border-subtle: #1e2530;
|
|
15
|
+
--text: #d4dae3;
|
|
16
|
+
--text-bright: #eef1f5;
|
|
17
|
+
--text-muted: #6b7a8d;
|
|
18
|
+
--accent: #4da6ff;
|
|
19
|
+
--accent-dim: rgba(77, 166, 255, 0.12);
|
|
20
|
+
--yellow: #d4a017;
|
|
21
|
+
--yellow-dim: rgba(212, 160, 23, 0.12);
|
|
22
|
+
--orange: #e08a20;
|
|
23
|
+
--orange-dim: rgba(224, 138, 32, 0.12);
|
|
24
|
+
--green: #3fb950;
|
|
25
|
+
--green-dim: rgba(63, 185, 80, 0.12);
|
|
26
|
+
--red: #f85149;
|
|
27
|
+
--radius-sm: 6px;
|
|
28
|
+
--radius-md: 8px;
|
|
29
|
+
--space-2: 8px;
|
|
30
|
+
--space-3: 12px;
|
|
31
|
+
--space-4: 16px;
|
|
32
|
+
--space-5: 20px;
|
|
33
|
+
--text-xs: 10px;
|
|
34
|
+
--text-sm: 11px;
|
|
35
|
+
--text-base: 13px;
|
|
36
|
+
--text-md: 14px;
|
|
37
|
+
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
38
|
+
--font-weight-normal: 400;
|
|
39
|
+
--font-weight-medium: 500;
|
|
40
|
+
--font-weight-semibold: 600;
|
|
41
|
+
--focus-ring: 0 0 0 2px rgba(77, 166, 255, 0.5);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
45
|
+
|
|
46
|
+
body {
|
|
47
|
+
font-family: var(--font-family);
|
|
48
|
+
background: var(--bg);
|
|
49
|
+
color: var(--text);
|
|
50
|
+
min-height: 100vh;
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
align-items: center;
|
|
54
|
+
padding: 40px 20px;
|
|
55
|
+
-webkit-font-smoothing: antialiased;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
h1 {
|
|
59
|
+
font-size: 18px;
|
|
60
|
+
font-weight: 700;
|
|
61
|
+
color: var(--text-bright);
|
|
62
|
+
margin-bottom: 8px;
|
|
63
|
+
}
|
|
64
|
+
.subtitle {
|
|
65
|
+
font-size: var(--text-base);
|
|
66
|
+
color: var(--text-muted);
|
|
67
|
+
margin-bottom: 32px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* === Mock Dashboard Panel === */
|
|
71
|
+
.panel {
|
|
72
|
+
background: var(--surface);
|
|
73
|
+
border: 1px solid var(--border);
|
|
74
|
+
border-radius: var(--radius-md);
|
|
75
|
+
width: 100%;
|
|
76
|
+
max-width: 480px;
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
}
|
|
79
|
+
.panel-header {
|
|
80
|
+
padding: var(--space-3) var(--space-4);
|
|
81
|
+
border-bottom: 1px solid var(--border);
|
|
82
|
+
font-size: var(--text-md);
|
|
83
|
+
font-weight: var(--font-weight-semibold);
|
|
84
|
+
color: var(--text-bright);
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 8px;
|
|
88
|
+
}
|
|
89
|
+
.panel-body {
|
|
90
|
+
padding: var(--space-4) var(--space-5);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* === Runtime Stats (mock) === */
|
|
94
|
+
.runtime-stats {
|
|
95
|
+
display: grid;
|
|
96
|
+
grid-template-columns: 1fr 1fr;
|
|
97
|
+
gap: var(--space-3);
|
|
98
|
+
margin-bottom: 0;
|
|
99
|
+
}
|
|
100
|
+
.stat {
|
|
101
|
+
display: flex;
|
|
102
|
+
flex-direction: column;
|
|
103
|
+
gap: 2px;
|
|
104
|
+
}
|
|
105
|
+
.stat-label {
|
|
106
|
+
font-size: var(--text-xs);
|
|
107
|
+
color: var(--text-muted);
|
|
108
|
+
text-transform: uppercase;
|
|
109
|
+
letter-spacing: 0.05em;
|
|
110
|
+
}
|
|
111
|
+
.stat-value {
|
|
112
|
+
font-size: var(--text-md);
|
|
113
|
+
font-weight: var(--font-weight-semibold);
|
|
114
|
+
color: var(--text);
|
|
115
|
+
}
|
|
116
|
+
.stat-value.online { color: var(--green); }
|
|
117
|
+
|
|
118
|
+
/* === Intensity Control === */
|
|
119
|
+
.intensity-control {
|
|
120
|
+
margin-top: var(--space-4);
|
|
121
|
+
padding-top: var(--space-4);
|
|
122
|
+
border-top: 1px solid var(--border);
|
|
123
|
+
}
|
|
124
|
+
.intensity-label {
|
|
125
|
+
font-size: var(--text-sm);
|
|
126
|
+
font-weight: var(--font-weight-semibold);
|
|
127
|
+
color: var(--text);
|
|
128
|
+
margin-bottom: var(--space-2);
|
|
129
|
+
}
|
|
130
|
+
.intensity-segments {
|
|
131
|
+
display: flex;
|
|
132
|
+
gap: 2px;
|
|
133
|
+
background: var(--surface);
|
|
134
|
+
border: 1px solid var(--border);
|
|
135
|
+
border-radius: var(--radius-md);
|
|
136
|
+
padding: 3px;
|
|
137
|
+
}
|
|
138
|
+
.intensity-seg {
|
|
139
|
+
flex: 1;
|
|
140
|
+
padding: 8px 12px;
|
|
141
|
+
border: 1px solid transparent;
|
|
142
|
+
border-radius: var(--radius-sm);
|
|
143
|
+
background: transparent;
|
|
144
|
+
color: var(--text-muted);
|
|
145
|
+
font-size: var(--text-sm);
|
|
146
|
+
font-weight: var(--font-weight-medium);
|
|
147
|
+
cursor: pointer;
|
|
148
|
+
transition: all 150ms ease;
|
|
149
|
+
min-height: 44px;
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
justify-content: center;
|
|
153
|
+
gap: 4px;
|
|
154
|
+
font-family: inherit;
|
|
155
|
+
}
|
|
156
|
+
.intensity-seg:focus-visible {
|
|
157
|
+
outline: none;
|
|
158
|
+
box-shadow: var(--focus-ring);
|
|
159
|
+
}
|
|
160
|
+
.intensity-seg:hover:not(.active) {
|
|
161
|
+
color: var(--text);
|
|
162
|
+
background: rgba(255,255,255,0.03);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Active states — color-coded by level */
|
|
166
|
+
.intensity-seg.active[data-level="low"] {
|
|
167
|
+
background: var(--yellow-dim);
|
|
168
|
+
color: var(--yellow);
|
|
169
|
+
border-color: var(--yellow);
|
|
170
|
+
font-weight: var(--font-weight-semibold);
|
|
171
|
+
}
|
|
172
|
+
.intensity-seg.active[data-level="normal"] {
|
|
173
|
+
background: var(--accent-dim);
|
|
174
|
+
color: var(--accent);
|
|
175
|
+
border-color: var(--accent);
|
|
176
|
+
font-weight: var(--font-weight-semibold);
|
|
177
|
+
}
|
|
178
|
+
.intensity-seg.active[data-level="high"] {
|
|
179
|
+
background: var(--orange-dim);
|
|
180
|
+
color: var(--orange);
|
|
181
|
+
border-color: var(--orange);
|
|
182
|
+
font-weight: var(--font-weight-semibold);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.intensity-desc {
|
|
186
|
+
font-size: var(--text-xs);
|
|
187
|
+
color: var(--text-muted);
|
|
188
|
+
margin-top: var(--space-2);
|
|
189
|
+
line-height: 1.5;
|
|
190
|
+
min-height: 30px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* === Toast === */
|
|
194
|
+
.toast {
|
|
195
|
+
position: fixed;
|
|
196
|
+
bottom: 24px;
|
|
197
|
+
left: 50%;
|
|
198
|
+
transform: translateX(-50%) translateY(80px);
|
|
199
|
+
background: var(--surface-raised);
|
|
200
|
+
border: 1px solid var(--border);
|
|
201
|
+
border-radius: var(--radius-md);
|
|
202
|
+
padding: 10px 20px;
|
|
203
|
+
font-size: var(--text-sm);
|
|
204
|
+
color: var(--text);
|
|
205
|
+
opacity: 0;
|
|
206
|
+
transition: all 300ms ease;
|
|
207
|
+
pointer-events: none;
|
|
208
|
+
white-space: nowrap;
|
|
209
|
+
}
|
|
210
|
+
.toast.show {
|
|
211
|
+
transform: translateX(-50%) translateY(0);
|
|
212
|
+
opacity: 1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* === Mapping Table === */
|
|
216
|
+
.mapping-section {
|
|
217
|
+
margin-top: 40px;
|
|
218
|
+
width: 100%;
|
|
219
|
+
max-width: 640px;
|
|
220
|
+
}
|
|
221
|
+
.mapping-section h2 {
|
|
222
|
+
font-size: 15px;
|
|
223
|
+
font-weight: 700;
|
|
224
|
+
color: var(--text-bright);
|
|
225
|
+
margin-bottom: 12px;
|
|
226
|
+
}
|
|
227
|
+
table {
|
|
228
|
+
width: 100%;
|
|
229
|
+
border-collapse: collapse;
|
|
230
|
+
font-size: var(--text-sm);
|
|
231
|
+
}
|
|
232
|
+
th, td {
|
|
233
|
+
padding: 8px 12px;
|
|
234
|
+
text-align: left;
|
|
235
|
+
border-bottom: 1px solid var(--border);
|
|
236
|
+
}
|
|
237
|
+
th {
|
|
238
|
+
color: var(--text-muted);
|
|
239
|
+
font-weight: var(--font-weight-semibold);
|
|
240
|
+
text-transform: uppercase;
|
|
241
|
+
letter-spacing: 0.05em;
|
|
242
|
+
font-size: var(--text-xs);
|
|
243
|
+
}
|
|
244
|
+
td { color: var(--text); }
|
|
245
|
+
td.highlight { color: var(--accent); font-weight: var(--font-weight-medium); }
|
|
246
|
+
|
|
247
|
+
/* === Footer === */
|
|
248
|
+
.mock-footer {
|
|
249
|
+
margin-top: 40px;
|
|
250
|
+
font-size: var(--text-xs);
|
|
251
|
+
color: var(--text-muted);
|
|
252
|
+
text-align: center;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@media (hover: hover) and (pointer: fine) {
|
|
256
|
+
.intensity-seg:hover:not(.active) {
|
|
257
|
+
color: var(--text);
|
|
258
|
+
background: rgba(255,255,255,0.03);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
@media not all and (hover: hover) {
|
|
262
|
+
.intensity-seg:hover:not(.active) {
|
|
263
|
+
color: var(--text-muted);
|
|
264
|
+
background: transparent;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
</style>
|
|
268
|
+
</head>
|
|
269
|
+
<body>
|
|
270
|
+
|
|
271
|
+
<h1>Agent Intensity Toggle</h1>
|
|
272
|
+
<p class="subtitle">Design mock — where it lives in the dashboard</p>
|
|
273
|
+
|
|
274
|
+
<!-- Mock Runtime Truth Card panel -->
|
|
275
|
+
<div class="panel">
|
|
276
|
+
<div class="panel-header">🧭 Runtime Truth Card</div>
|
|
277
|
+
<div class="panel-body">
|
|
278
|
+
|
|
279
|
+
<!-- Existing runtime stats (mock) -->
|
|
280
|
+
<div class="runtime-stats">
|
|
281
|
+
<div class="stat">
|
|
282
|
+
<span class="stat-label">Agents</span>
|
|
283
|
+
<span class="stat-value online">6 online</span>
|
|
284
|
+
</div>
|
|
285
|
+
<div class="stat">
|
|
286
|
+
<span class="stat-label">Tasks</span>
|
|
287
|
+
<span class="stat-value">3 active</span>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="stat">
|
|
290
|
+
<span class="stat-label">Heartbeat</span>
|
|
291
|
+
<span class="stat-value">30s</span>
|
|
292
|
+
</div>
|
|
293
|
+
<div class="stat">
|
|
294
|
+
<span class="stat-label">Uptime</span>
|
|
295
|
+
<span class="stat-value">4h 22m</span>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
|
|
299
|
+
<!-- ✨ NEW: Intensity Control -->
|
|
300
|
+
<div class="intensity-control" role="radiogroup" aria-label="Agent intensity">
|
|
301
|
+
<div class="intensity-label">⚡ Agent Intensity</div>
|
|
302
|
+
<div class="intensity-segments">
|
|
303
|
+
<button role="radio" aria-checked="false" data-level="low" class="intensity-seg" onclick="setIntensity('low')">
|
|
304
|
+
🐢 Low
|
|
305
|
+
</button>
|
|
306
|
+
<button role="radio" aria-checked="true" data-level="normal" class="intensity-seg active" onclick="setIntensity('normal')">
|
|
307
|
+
⚡ Normal
|
|
308
|
+
</button>
|
|
309
|
+
<button role="radio" aria-checked="false" data-level="high" class="intensity-seg" onclick="setIntensity('high')">
|
|
310
|
+
🔥 High
|
|
311
|
+
</button>
|
|
312
|
+
</div>
|
|
313
|
+
<div class="intensity-desc" id="intensity-desc">
|
|
314
|
+
Agents work at standard pace. Tasks processed each heartbeat.
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<!-- Mapping reference table -->
|
|
322
|
+
<div class="mapping-section">
|
|
323
|
+
<h2>What each level changes</h2>
|
|
324
|
+
<table>
|
|
325
|
+
<thead>
|
|
326
|
+
<tr>
|
|
327
|
+
<th>Setting</th>
|
|
328
|
+
<th>🐢 Low</th>
|
|
329
|
+
<th>⚡ Normal</th>
|
|
330
|
+
<th>🔥 High</th>
|
|
331
|
+
</tr>
|
|
332
|
+
</thead>
|
|
333
|
+
<tbody>
|
|
334
|
+
<tr>
|
|
335
|
+
<td>Heartbeat</td>
|
|
336
|
+
<td>2× slower</td>
|
|
337
|
+
<td class="highlight">Default</td>
|
|
338
|
+
<td>2× faster</td>
|
|
339
|
+
</tr>
|
|
340
|
+
<tr>
|
|
341
|
+
<td>Tasks / cycle</td>
|
|
342
|
+
<td>Max 1</td>
|
|
343
|
+
<td class="highlight">Config default</td>
|
|
344
|
+
<td>Unlimited</td>
|
|
345
|
+
</tr>
|
|
346
|
+
<tr>
|
|
347
|
+
<td>Approval</td>
|
|
348
|
+
<td>All manual</td>
|
|
349
|
+
<td class="highlight">Routine auto</td>
|
|
350
|
+
<td>All auto (except close)</td>
|
|
351
|
+
</tr>
|
|
352
|
+
<tr>
|
|
353
|
+
<td>Parallel tasks</td>
|
|
354
|
+
<td>No</td>
|
|
355
|
+
<td class="highlight">No</td>
|
|
356
|
+
<td>Yes</td>
|
|
357
|
+
</tr>
|
|
358
|
+
</tbody>
|
|
359
|
+
</table>
|
|
360
|
+
</div>
|
|
361
|
+
|
|
362
|
+
<!-- Toast -->
|
|
363
|
+
<div class="toast" id="toast"></div>
|
|
364
|
+
|
|
365
|
+
<div class="mock-footer">
|
|
366
|
+
Design mock by pixel 🎨 · task-1772244618727-695h6hdsk · reflectt-node
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<script>
|
|
370
|
+
const COPY = {
|
|
371
|
+
low: 'Agents check in less often. Tasks batch up.',
|
|
372
|
+
normal: 'Agents work at standard pace. Tasks processed each heartbeat.',
|
|
373
|
+
high: 'Agents move fast. Parallel tasks enabled.',
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
const TOAST_MSG = {
|
|
377
|
+
low: '🐢 Intensity → Low — agents will slow down',
|
|
378
|
+
normal: '⚡ Intensity → Normal — standard pace',
|
|
379
|
+
high: '🔥 Intensity → High — agents moving fast',
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
function setIntensity(level) {
|
|
383
|
+
document.querySelectorAll('.intensity-seg').forEach(btn => {
|
|
384
|
+
const active = btn.dataset.level === level;
|
|
385
|
+
btn.classList.toggle('active', active);
|
|
386
|
+
btn.setAttribute('aria-checked', active);
|
|
387
|
+
});
|
|
388
|
+
document.getElementById('intensity-desc').textContent = COPY[level];
|
|
389
|
+
showToast(TOAST_MSG[level]);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
let toastTimer;
|
|
393
|
+
function showToast(msg) {
|
|
394
|
+
const el = document.getElementById('toast');
|
|
395
|
+
el.textContent = msg;
|
|
396
|
+
el.classList.add('show');
|
|
397
|
+
clearTimeout(toastTimer);
|
|
398
|
+
toastTimer = setTimeout(() => el.classList.remove('show'), 2500);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Keyboard nav for radiogroup
|
|
402
|
+
document.querySelector('.intensity-segments').addEventListener('keydown', e => {
|
|
403
|
+
const btns = [...document.querySelectorAll('.intensity-seg')];
|
|
404
|
+
const idx = btns.indexOf(document.activeElement);
|
|
405
|
+
if (idx < 0) return;
|
|
406
|
+
let next;
|
|
407
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') next = btns[(idx + 1) % btns.length];
|
|
408
|
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') next = btns[(idx - 1 + btns.length) % btns.length];
|
|
409
|
+
if (next) { e.preventDefault(); next.focus(); next.click(); }
|
|
410
|
+
});
|
|
411
|
+
</script>
|
|
412
|
+
</body>
|
|
413
|
+
</html>
|