koneck 2.73.1 → 2.74.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-client.d.ts","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"ui-client.d.ts","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAgzKrC"}
|
package/dist/web/ui-client.js
CHANGED
|
@@ -260,29 +260,85 @@ function renderAgents(agents) {
|
|
|
260
260
|
|
|
261
261
|
function renderAsk(e) {
|
|
262
262
|
const box = el('div', 'ask');
|
|
263
|
+
// Findable later: another tab may answer this, and the answer has to reach every copy of the card.
|
|
264
|
+
box.dataset.ask = e.askId;
|
|
263
265
|
box.appendChild(el('div', 'q', 'Allow ' + e.tool + '?'));
|
|
264
266
|
box.appendChild(el('div', 'a', e.args));
|
|
265
267
|
const btns = el('div', 'btns');
|
|
266
|
-
|
|
268
|
+
|
|
269
|
+
/*
|
|
270
|
+
* A card that has been answered says which answer it got.
|
|
271
|
+
*
|
|
272
|
+
* The buttons were disabled and a line was appended, and that was not enough to read as anything:
|
|
273
|
+
* nothing styles a disabled button here, so all three kept their colour and their border and sat
|
|
274
|
+
* there looking exactly as clickable as before. Reported as the click doing nothing.
|
|
275
|
+
*
|
|
276
|
+
* So the card itself changes state — the chosen button is filled and ticked, the others fade, the
|
|
277
|
+
* amber "waiting" border becomes the colour of the decision — and the outcome line is a result
|
|
278
|
+
* rather than another line of grey argument text.
|
|
279
|
+
*/
|
|
280
|
+
const settle = (chosenButton, text, allowed) => {
|
|
281
|
+
box.classList.add('answered', allowed ? 'wasyes' : 'wasno');
|
|
282
|
+
for (const b of btns.querySelectorAll('button')) {
|
|
283
|
+
b.disabled = true;
|
|
284
|
+
if (b === chosenButton) b.classList.add('chosen');
|
|
285
|
+
}
|
|
286
|
+
const said = box.querySelector('.said') || el('div', 'said');
|
|
287
|
+
said.textContent = (allowed ? '✓ ' : '✗ ') + text;
|
|
288
|
+
if (!said.parentNode) box.appendChild(said);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const answer = async (allow, always, button) => {
|
|
292
|
+
// Disabled the moment it is pressed, so a second click cannot answer the same question twice
|
|
293
|
+
// while the first is still in flight.
|
|
267
294
|
for (const b of btns.querySelectorAll('button')) b.disabled = true;
|
|
268
295
|
try {
|
|
269
296
|
await api('/api/answer', { method: 'POST',
|
|
270
297
|
body: JSON.stringify({ session: state.session, ask: e.askId,
|
|
271
298
|
allow: allow, always: always === true }) });
|
|
272
|
-
} catch (err) {
|
|
273
|
-
|
|
274
|
-
|
|
299
|
+
} catch (err) {
|
|
300
|
+
// It did not go through, so the question is still open and the buttons come back.
|
|
301
|
+
for (const b of btns.querySelectorAll('button')) b.disabled = false;
|
|
302
|
+
const failed = box.querySelector('.said') || el('div', 'said');
|
|
303
|
+
failed.textContent = '✗ ' + err.message;
|
|
304
|
+
if (!failed.parentNode) box.appendChild(failed);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
settle(button,
|
|
308
|
+
allow ? (always ? 'allowed, and will not be asked again' : 'allowed') : 'refused',
|
|
309
|
+
allow);
|
|
275
310
|
};
|
|
276
|
-
|
|
311
|
+
|
|
312
|
+
const yes = el('button', 'yes', 'Allow');
|
|
313
|
+
yes.onclick = () => answer(true, false, yes);
|
|
277
314
|
// Agreeing to a tool once should not mean agreeing to it forty times.
|
|
278
315
|
const all = el('button', 'always', 'Always allow ' + e.tool);
|
|
279
|
-
all.onclick = () => answer(true, true);
|
|
280
|
-
const no = el('button', 'no', 'Refuse');
|
|
316
|
+
all.onclick = () => answer(true, true, all);
|
|
317
|
+
const no = el('button', 'no', 'Refuse');
|
|
318
|
+
no.onclick = () => answer(false, false, no);
|
|
281
319
|
btns.appendChild(yes); btns.appendChild(all); btns.appendChild(no);
|
|
282
320
|
box.appendChild(btns);
|
|
321
|
+
|
|
322
|
+
/* Answered elsewhere — another tab, or the terminal — while this card is still on screen. */
|
|
323
|
+
box.settleFromElsewhere = (allowed) => {
|
|
324
|
+
if (box.classList.contains('answered')) return;
|
|
325
|
+
settle(allowed ? yes : no, allowed ? 'allowed' : 'refused', allowed);
|
|
326
|
+
};
|
|
283
327
|
return add(box);
|
|
284
328
|
}
|
|
285
329
|
|
|
330
|
+
/**
|
|
331
|
+
* An answer that came from somewhere else.
|
|
332
|
+
*
|
|
333
|
+
* The same session can be open in two tabs and in a terminal at once, and only one of them answers.
|
|
334
|
+
* Without this the others keep showing live buttons for a question that is already settled, and
|
|
335
|
+
* pressing one gets a refusal from the server for an ask that no longer exists.
|
|
336
|
+
*/
|
|
337
|
+
function settleAsk(askId, allowed) {
|
|
338
|
+
const card = document.querySelector('.ask[data-ask="' + CSS.escape(String(askId)) + '"]');
|
|
339
|
+
if (card && card.settleFromElsewhere) card.settleFromElsewhere(allowed);
|
|
340
|
+
}
|
|
341
|
+
|
|
286
342
|
/**
|
|
287
343
|
* The running state, shown where it cannot scroll away.
|
|
288
344
|
*
|
|
@@ -471,12 +527,13 @@ function onEvent(e) {
|
|
|
471
527
|
break;
|
|
472
528
|
}
|
|
473
529
|
case 'plan': renderPlan(e.steps); break;
|
|
474
|
-
case 'agents': renderAgents(e.agents); break;
|
|
530
|
+
case 'agents': renderAgents(e.agents); trackAgents(e.agents); break;
|
|
475
531
|
case 'tokens':
|
|
476
532
|
$('stat').innerHTML = '<b>' + num(e.total) + '</b> tokens'
|
|
477
533
|
+ (e.cost > 0 ? ' · $' + e.cost.toFixed(4) : '');
|
|
478
534
|
break;
|
|
479
535
|
case 'ask': renderAsk(e); break;
|
|
536
|
+
case 'ask-done': settleAsk(e.askId, e.allowed); break;
|
|
480
537
|
case 'notice':
|
|
481
538
|
add(el('div', 'notice ' + (e.level === 'info' ? 'info' : ''), e.text));
|
|
482
539
|
break;
|
|
@@ -4061,8 +4118,11 @@ $('pvclose').onclick = async () => {
|
|
|
4061
4118
|
const follow = {
|
|
4062
4119
|
on: (() => { try { return localStorage.getItem('koneck.follow') !== 'off'; } catch (e) { return true; } })(),
|
|
4063
4120
|
path: null,
|
|
4064
|
-
/** 'code' | 'diff' | 'term' — what the body is currently showing. */
|
|
4121
|
+
/** 'code' | 'diff' | 'term' | 'call' | 'agent' — what the body is currently showing. */
|
|
4065
4122
|
kind: null,
|
|
4123
|
+
/** The sub-agents as they last reported, and which one the body is showing. */
|
|
4124
|
+
agents: [],
|
|
4125
|
+
agentIndex: null,
|
|
4066
4126
|
verb: '',
|
|
4067
4127
|
busy: false,
|
|
4068
4128
|
pending: null,
|
|
@@ -4243,6 +4303,84 @@ function trailPush(entry) {
|
|
|
4243
4303
|
drawTrail(key);
|
|
4244
4304
|
}
|
|
4245
4305
|
|
|
4306
|
+
/*
|
|
4307
|
+
* Sub-agents in the panel, one tab each.
|
|
4308
|
+
*
|
|
4309
|
+
* A fan-out was watchable only as a block in the transcript, which scrolls away — while the panel,
|
|
4310
|
+
* the one place whose job is to show what is happening now, sat on the spawn_agents call showing
|
|
4311
|
+
* the arguments it was given. Four agents working for half an hour and the panel showed the same
|
|
4312
|
+
* JSON the whole time.
|
|
4313
|
+
*
|
|
4314
|
+
* So each agent gets a chip beside the files, and selecting one shows what that agent was asked to
|
|
4315
|
+
* do and how it is getting on. The chips update in place as the agents report, so the row is a live
|
|
4316
|
+
* picture rather than a list of names.
|
|
4317
|
+
*/
|
|
4318
|
+
function trackAgents(agents) {
|
|
4319
|
+
follow.agents = agents || [];
|
|
4320
|
+
if (follow.agents.length === 0) return;
|
|
4321
|
+
$('watch').hidden = false;
|
|
4322
|
+
|
|
4323
|
+
for (const a of follow.agents) {
|
|
4324
|
+
trailPush({
|
|
4325
|
+
label: 'agent ' + (a.index + 1),
|
|
4326
|
+
verb: a.status === 'done' ? 'finished' : a.status === 'failed' ? 'failed' : 'working',
|
|
4327
|
+
kind: 'agent',
|
|
4328
|
+
agentIndex: a.index,
|
|
4329
|
+
// A failed agent's chip is marked, the same as a failed tool call's is.
|
|
4330
|
+
ok: a.status === 'done' ? true : a.status === 'failed' ? false : undefined,
|
|
4331
|
+
});
|
|
4332
|
+
}
|
|
4333
|
+
// If an agent view is on screen, keep it current rather than waiting for another click.
|
|
4334
|
+
if (follow.kind === 'agent') drawAgent(follow.agentIndex);
|
|
4335
|
+
}
|
|
4336
|
+
|
|
4337
|
+
/** How long an agent has been at it, or how long it took. */
|
|
4338
|
+
function agentElapsed(a) {
|
|
4339
|
+
const end = a.endedAt || Date.now();
|
|
4340
|
+
return ms(Math.max(0, end - (a.startedAt || end)));
|
|
4341
|
+
}
|
|
4342
|
+
|
|
4343
|
+
/**
|
|
4344
|
+
* One agent, or all of them.
|
|
4345
|
+
*
|
|
4346
|
+
* The task is shown in full and not truncated: a sub-agent's brief is the only description of what
|
|
4347
|
+
* it is doing, and half of it answers nothing. It is also the thing worth reading when an agent
|
|
4348
|
+
* comes back having done the wrong work.
|
|
4349
|
+
*/
|
|
4350
|
+
function drawAgent(index) {
|
|
4351
|
+
const host = $('wbody');
|
|
4352
|
+
host.innerHTML = '';
|
|
4353
|
+
follow.kind = 'agent';
|
|
4354
|
+
follow.agentIndex = index;
|
|
4355
|
+
|
|
4356
|
+
const list = index === null || index === undefined
|
|
4357
|
+
? follow.agents
|
|
4358
|
+
: follow.agents.filter((a) => a.index === index);
|
|
4359
|
+
if (list.length === 0) {
|
|
4360
|
+
host.appendChild(el('div', 'wempty', 'No sub-agents are running.'));
|
|
4361
|
+
return;
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4364
|
+
for (const a of list) {
|
|
4365
|
+
const card = el('div', 'agcard ' + a.status);
|
|
4366
|
+
const head = el('div', 'aghead');
|
|
4367
|
+
head.appendChild(el('span', 'agn', 'agent ' + (a.index + 1)));
|
|
4368
|
+
head.appendChild(el('span', 'ags ' + a.status, a.status));
|
|
4369
|
+
head.appendChild(el('span', 'aggap'));
|
|
4370
|
+
head.appendChild(el('span', 'agm', agentElapsed(a)));
|
|
4371
|
+
card.appendChild(head);
|
|
4372
|
+
|
|
4373
|
+
const meta = el('div', 'agmeta');
|
|
4374
|
+
meta.appendChild(el('span', null, a.turns + (a.turns === 1 ? ' turn' : ' turns')));
|
|
4375
|
+
meta.appendChild(el('span', null, num(a.tokens) + ' tokens'));
|
|
4376
|
+
if (a.branch) meta.appendChild(el('span', null, a.branch));
|
|
4377
|
+
card.appendChild(meta);
|
|
4378
|
+
|
|
4379
|
+
card.appendChild(el('div', 'agtask', a.task || '(no description)'));
|
|
4380
|
+
host.appendChild(card);
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4246
4384
|
function drawTrail(activeLabel) {
|
|
4247
4385
|
const host = $('wtrail');
|
|
4248
4386
|
host.innerHTML = '';
|
|
@@ -4266,6 +4404,12 @@ function drawTrail(activeLabel) {
|
|
|
4266
4404
|
drawTrail(t.label);
|
|
4267
4405
|
return;
|
|
4268
4406
|
}
|
|
4407
|
+
if (t.kind === 'agent') {
|
|
4408
|
+
watchHead(t.verb, 'agent ' + (t.agentIndex + 1));
|
|
4409
|
+
drawAgent(t.agentIndex);
|
|
4410
|
+
drawTrail(t.label);
|
|
4411
|
+
return;
|
|
4412
|
+
}
|
|
4269
4413
|
// A call with nothing to open is still worth walking back to: what was asked, and how it
|
|
4270
4414
|
// went. Without this the chip was there and clicking it did nothing.
|
|
4271
4415
|
if (t.kind === 'call') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-client.js","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"ui-client.js","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8yKlB,CAAC;AACF,CAAC"}
|
package/dist/web/ui-css.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-css.d.ts","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AA8CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"ui-css.d.ts","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AA8CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwsC3C"}
|
package/dist/web/ui-css.js
CHANGED
|
@@ -264,6 +264,35 @@ header{height:47px;flex:0 0 47px;border-bottom:1px solid var(--line);display:fle
|
|
|
264
264
|
.ask .yes{border-color:var(--green);color:var(--green)}
|
|
265
265
|
.ask .always{border-color:var(--cyan);color:var(--cyan)}
|
|
266
266
|
.ask .no{border-color:var(--red);color:var(--red)}
|
|
267
|
+
/*
|
|
268
|
+
* A card that has been answered.
|
|
269
|
+
*
|
|
270
|
+
* Nothing styled a disabled button, so after clicking Allow all three kept their colour and their
|
|
271
|
+
* border and sat there looking exactly as clickable as before — which reads as the click having
|
|
272
|
+
* done nothing at all. The state has to be visible in the card, not only in a line of text
|
|
273
|
+
* underneath it.
|
|
274
|
+
*/
|
|
275
|
+
.ask.answered{border-color:var(--line-2)}
|
|
276
|
+
.ask.answered.wasyes{border-color:var(--green)}
|
|
277
|
+
.ask.answered.wasno{border-color:var(--red)}
|
|
278
|
+
/* The ones not taken recede rather than disappear: what was on offer is part of the record. */
|
|
279
|
+
.ask .btns button:disabled{opacity:.32;cursor:default;border-color:var(--line);
|
|
280
|
+
color:var(--dim);background:none}
|
|
281
|
+
/*
|
|
282
|
+
* And the one that was taken stays lit, filled, and keeps its own colour.
|
|
283
|
+
*
|
|
284
|
+
* Written to outrank the disabled rule on specificity rather than with !important. The first
|
|
285
|
+
* version was ".ask .yes.chosen" — three classes against the disabled rule's three classes and an
|
|
286
|
+
* element, so it lost, and the chosen button rendered with no background at all. Measured in the
|
|
287
|
+
* browser as rgba(0,0,0,0), which is exactly the flat look this was meant to fix.
|
|
288
|
+
*/
|
|
289
|
+
.ask .btns button.chosen{opacity:1;font-weight:600}
|
|
290
|
+
.ask .btns button.yes.chosen{background:var(--green);border-color:var(--green);color:var(--bg)}
|
|
291
|
+
.ask .btns button.always.chosen{background:var(--cyan);border-color:var(--cyan);color:var(--cyan-ink)}
|
|
292
|
+
.ask .btns button.no.chosen{background:var(--red);border-color:var(--red);color:var(--bg)}
|
|
293
|
+
.ask .said{margin-top:10px;font-size:12px;color:var(--muted)}
|
|
294
|
+
.ask.wasyes .said{color:var(--green)}
|
|
295
|
+
.ask.wasno .said{color:var(--red)}
|
|
267
296
|
|
|
268
297
|
.busy{display:flex;align-items:center;gap:10px;color:var(--amber);font-size:12.5px;margin:8px 0}
|
|
269
298
|
.sp{width:11px;height:11px;border:2px solid var(--amber);border-right-color:transparent;
|
|
@@ -924,6 +953,32 @@ dialog:has(.dlg.wide){max-width:560px}
|
|
|
924
953
|
.wchip.on .dot{background:var(--cyan)}
|
|
925
954
|
.wchip.bad .dot{background:var(--red)}
|
|
926
955
|
|
|
956
|
+
/*
|
|
957
|
+
* Sub-agents in the panel.
|
|
958
|
+
*
|
|
959
|
+
* A fan-out used to be visible only in the transcript, which scrolls away, while the panel sat on
|
|
960
|
+
* the spawn_agents call showing its arguments — four agents working for half an hour and the same
|
|
961
|
+
* JSON on screen throughout.
|
|
962
|
+
*/
|
|
963
|
+
.agcard{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel-2);
|
|
964
|
+
margin:10px 13px;padding:10px 12px}
|
|
965
|
+
.agcard.running{border-color:var(--amber)}
|
|
966
|
+
.agcard.done{border-color:var(--green)}
|
|
967
|
+
.agcard.failed{border-color:var(--red)}
|
|
968
|
+
.aghead{display:flex;align-items:center;gap:9px;font-size:12px}
|
|
969
|
+
.aghead .agn{font-family:var(--mono);color:var(--ink);font-weight:600}
|
|
970
|
+
.aghead .aggap{flex:1}
|
|
971
|
+
.aghead .agm{color:var(--dim);font-variant-numeric:tabular-nums;font-size:11px}
|
|
972
|
+
.ags{font-size:10px;letter-spacing:.06em;text-transform:uppercase;padding:1px 7px;
|
|
973
|
+
border-radius:999px;border:1px solid var(--line-2);color:var(--dim)}
|
|
974
|
+
.ags.running{border-color:var(--amber);color:var(--amber)}
|
|
975
|
+
.ags.done{border-color:var(--green);color:var(--green)}
|
|
976
|
+
.ags.failed{border-color:var(--red);color:var(--red)}
|
|
977
|
+
.agmeta{display:flex;gap:12px;margin-top:6px;font-size:11px;color:var(--muted)}
|
|
978
|
+
/* The brief in full: half a sub-agent's instructions answers nothing about what it is doing. */
|
|
979
|
+
.agtask{margin-top:8px;font-family:var(--mono);font-size:11.5px;line-height:1.55;
|
|
980
|
+
color:var(--muted);white-space:pre-wrap;word-break:break-word}
|
|
981
|
+
|
|
927
982
|
@media (max-width:1100px){ .watch{display:none} }
|
|
928
983
|
|
|
929
984
|
/*
|
package/dist/web/ui-css.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-css.js","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;;;;;;;;;;;;;;;;;gBAiBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI
|
|
1
|
+
{"version":3,"file":"ui-css.js","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;;;;;;;;;;;;;;;;;gBAiBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgrC9B,CAAC;AACF,CAAC"}
|