@atolis-hq/wake 0.2.72 → 0.2.74
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.
|
@@ -65,6 +65,13 @@ export const indexHtml = `<!DOCTYPE html>
|
|
|
65
65
|
.card:hover { border-color: var(--accent); }
|
|
66
66
|
.card .title { font-weight: 600; margin-bottom: 0.25rem; }
|
|
67
67
|
.card .meta { color: #9aa2ad; font-size: 0.72rem; }
|
|
68
|
+
.item-summary { margin: 0.45rem 0 0.75rem; }
|
|
69
|
+
.item-summary .meta { color: #9aa2ad; font-size: 0.78rem; }
|
|
70
|
+
.item-summary .card-stats { font-size: 0.76rem; }
|
|
71
|
+
.item-summary .child-run { max-width: 560px; }
|
|
72
|
+
.detail-kv { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem 0.7rem; align-items: baseline; margin: 0.75rem 0 1rem; font-size: 0.8rem; }
|
|
73
|
+
.detail-kv dt { margin: 0; color: #9aa2ad; }
|
|
74
|
+
.detail-kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
|
|
68
75
|
.child-run { display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 0.45rem; align-items: center; margin-top: 0.45rem; padding: 0.4rem; border-radius: 6px; background: #181c22; border: 1px solid #334155; color: #cbd5e1; font-size: 0.72rem; }
|
|
69
76
|
.child-run .dot { width: 0.48rem; height: 0.48rem; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.14); }
|
|
70
77
|
.child-run .dot-watch { background: #ffcf7f; box-shadow: 0 0 0 3px rgba(255, 207, 127, 0.14); }
|
|
@@ -171,6 +178,21 @@ export const indexHtml = `<!DOCTYPE html>
|
|
|
171
178
|
<script>
|
|
172
179
|
const API = '/api/v1';
|
|
173
180
|
const CONDITIONS = ['ready', 'scheduled', 'active', 'needs-human', 'error', 'finished'];
|
|
181
|
+
const COND_PILL = {
|
|
182
|
+
ready: 'pill-ready',
|
|
183
|
+
active: 'pill-active',
|
|
184
|
+
scheduled: 'pill-scheduled',
|
|
185
|
+
'needs-human': 'pill-needs-human',
|
|
186
|
+
error: 'pill-error',
|
|
187
|
+
finished: 'pill-finished',
|
|
188
|
+
};
|
|
189
|
+
const COND_CARD = {
|
|
190
|
+
ready: 'card-ready',
|
|
191
|
+
active: 'card-active',
|
|
192
|
+
scheduled: 'card-scheduled',
|
|
193
|
+
'needs-human': 'card-needs-human',
|
|
194
|
+
error: 'card-error',
|
|
195
|
+
};
|
|
174
196
|
let currentView = 'board';
|
|
175
197
|
let analyticsWindow = '1d';
|
|
176
198
|
let analyticsMetric = 'runs-over-time';
|
|
@@ -306,53 +328,17 @@ async function renderBoard(context) {
|
|
|
306
328
|
const board = await getJson('/board', context.signal);
|
|
307
329
|
if (!isActiveRequest(context.requestId)) return;
|
|
308
330
|
const main = document.getElementById('main');
|
|
309
|
-
const COND_PILL = {
|
|
310
|
-
ready: 'pill-ready',
|
|
311
|
-
active: 'pill-active',
|
|
312
|
-
scheduled: 'pill-scheduled',
|
|
313
|
-
'needs-human': 'pill-needs-human',
|
|
314
|
-
error: 'pill-error',
|
|
315
|
-
finished: 'pill-finished',
|
|
316
|
-
};
|
|
317
|
-
const COND_CARD = {
|
|
318
|
-
ready: 'card-ready',
|
|
319
|
-
active: 'card-active',
|
|
320
|
-
scheduled: 'card-scheduled',
|
|
321
|
-
'needs-human': 'card-needs-human',
|
|
322
|
-
error: 'card-error',
|
|
323
|
-
};
|
|
324
|
-
const renderChildRun = (run) => el('div', { class: 'child-run' }, [
|
|
325
|
-
el('span', { class: 'dot' + (run.isWatcher ? ' dot-watch' : '') }),
|
|
326
|
-
el('div', { class: 'run-title', text: (run.isWatcher ? '⟳ ' : '') + run.action + ' running' }),
|
|
327
|
-
el('div', {
|
|
328
|
-
class: 'run-meta',
|
|
329
|
-
text: [run.runnerName, run.tier, fmtMs(run.ageMs)].filter(Boolean).join(' · '),
|
|
330
|
-
}),
|
|
331
|
-
]);
|
|
332
331
|
const columns = el('div', { class: 'columns' }, CONDITIONS.map((cond) => {
|
|
333
332
|
const items = board.filter((c) => c.condition === cond);
|
|
334
333
|
if (cond === 'finished') items.sort((a, b) => a.timeInStageMs - b.timeInStageMs);
|
|
335
334
|
const cards = items.map((item) => {
|
|
336
|
-
const nonWakeLabels = (item.labels || []).filter((l) => !l.startsWith('wake:'));
|
|
337
|
-
const pillClass = 'pill ' + (COND_PILL[item.condition] || 'pill-finished');
|
|
338
335
|
const cardCondClass = COND_CARD[item.condition] ?? '';
|
|
339
|
-
const statsText = item.totalRuns + ' runs | ' + fmtCost(item.totalCostUsd) + ' | ' + fmtCompact(item.totalTokens) + ' tokens';
|
|
340
|
-
const isFinished = item.condition === 'finished';
|
|
341
336
|
return el('div', {
|
|
342
337
|
class: 'card' + (cardCondClass ? ' ' + cardCondClass : ''),
|
|
343
|
-
onclick: () => openItemModal(item.repo, item.number),
|
|
338
|
+
onclick: () => openItemModal(item.repo, item.number, item),
|
|
344
339
|
}, [
|
|
345
340
|
el('div', { class: 'title', text: item.repo + '#' + item.number + ' ' + item.title }),
|
|
346
|
-
|
|
347
|
-
el('span', { class: pillClass, text: item.condition }),
|
|
348
|
-
document.createTextNode('| ' + item.workflow + ' | ' + item.stage + (isFinished ? '' : ' | ' + fmtMs(item.timeInStageMs) + ' in stage')),
|
|
349
|
-
]),
|
|
350
|
-
el('div', { class: 'card-stats', text: statsText }),
|
|
351
|
-
...(nonWakeLabels.length > 0
|
|
352
|
-
? [el('div', { class: 'meta', style: 'margin-top:0.2rem;' }, nonWakeLabels.map((label) => el('span', { class: 'chip chip-label', text: label })))]
|
|
353
|
-
: []),
|
|
354
|
-
...(item.activeMainRun ? [renderChildRun(item.activeMainRun)] : []),
|
|
355
|
-
...((item.activeChildRuns || []).map(renderChildRun)),
|
|
341
|
+
...renderCardSummaryNodes(item),
|
|
356
342
|
]);
|
|
357
343
|
});
|
|
358
344
|
return el('div', { class: 'col' + (items.length === 0 ? ' col-empty' : '') }, [
|
|
@@ -363,6 +349,36 @@ async function renderBoard(context) {
|
|
|
363
349
|
main.replaceChildren(columns);
|
|
364
350
|
}
|
|
365
351
|
|
|
352
|
+
function renderChildRun(run) {
|
|
353
|
+
return el('div', { class: 'child-run' }, [
|
|
354
|
+
el('span', { class: 'dot' + (run.isWatcher ? ' dot-watch' : '') }),
|
|
355
|
+
el('div', { class: 'run-title', text: (run.isWatcher ? 'watcher ' : '') + run.action + ' running' }),
|
|
356
|
+
el('div', {
|
|
357
|
+
class: 'run-meta',
|
|
358
|
+
text: [run.runnerName, run.tier, fmtMs(run.ageMs)].filter(Boolean).join(' | '),
|
|
359
|
+
}),
|
|
360
|
+
]);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function renderCardSummaryNodes(item) {
|
|
364
|
+
const nonWakeLabels = (item.labels || []).filter((l) => !l.startsWith('wake:'));
|
|
365
|
+
const pillClass = 'pill ' + (COND_PILL[item.condition] || 'pill-finished');
|
|
366
|
+
const statsText = item.totalRuns + ' runs | ' + fmtCost(item.totalCostUsd) + ' | ' + fmtCompact(item.totalTokens) + ' tokens';
|
|
367
|
+
const isFinished = item.condition === 'finished';
|
|
368
|
+
return [
|
|
369
|
+
el('div', { class: 'meta', style: 'display:flex;align-items:center;gap:0.3rem;flex-wrap:wrap;margin-top:0.2rem;' }, [
|
|
370
|
+
el('span', { class: pillClass, text: item.condition }),
|
|
371
|
+
document.createTextNode('| ' + item.workflow + ' | ' + item.stage + (isFinished ? '' : ' | ' + fmtMs(item.timeInStageMs) + ' in stage')),
|
|
372
|
+
]),
|
|
373
|
+
el('div', { class: 'card-stats', text: statsText }),
|
|
374
|
+
...(nonWakeLabels.length > 0
|
|
375
|
+
? [el('div', { class: 'meta', style: 'margin-top:0.2rem;' }, nonWakeLabels.map((label) => el('span', { class: 'chip chip-label', text: label })))]
|
|
376
|
+
: []),
|
|
377
|
+
...(item.activeMainRun ? [renderChildRun(item.activeMainRun)] : []),
|
|
378
|
+
...((item.activeChildRuns || []).map(renderChildRun)),
|
|
379
|
+
];
|
|
380
|
+
}
|
|
381
|
+
|
|
366
382
|
function resourceUriToUrl(resourceUri) {
|
|
367
383
|
const parts = resourceUri.split(':');
|
|
368
384
|
if (parts.length < 3) return null;
|
|
@@ -378,7 +394,7 @@ function resourceUriToUrl(resourceUri) {
|
|
|
378
394
|
return null;
|
|
379
395
|
}
|
|
380
396
|
|
|
381
|
-
async function openItemModal(repo, number) {
|
|
397
|
+
async function openItemModal(repo, number, boardItem) {
|
|
382
398
|
const overlay = document.getElementById('modal-overlay');
|
|
383
399
|
const title = document.getElementById('modal-title');
|
|
384
400
|
const tabs = document.getElementById('modal-tabs');
|
|
@@ -430,22 +446,34 @@ async function openItemModal(repo, number) {
|
|
|
430
446
|
const transcripts = await getJson('/work-items/' + encodeURIComponent(detail.item.workItemKey) + '/transcripts');
|
|
431
447
|
return renderTranscripts(transcripts);
|
|
432
448
|
}
|
|
433
|
-
return renderItemDetails(detail);
|
|
449
|
+
return renderItemDetails(detail, boardItem);
|
|
434
450
|
}
|
|
435
451
|
|
|
436
452
|
await switchItemTab('details');
|
|
437
453
|
}
|
|
438
454
|
|
|
439
|
-
function renderItemDetails(detail) {
|
|
455
|
+
function renderItemDetails(detail, boardItem) {
|
|
440
456
|
const body = el('div');
|
|
441
457
|
const repo = detail.item.issue.repo;
|
|
442
458
|
const number = detail.item.issue.number;
|
|
443
459
|
const headLink = el('a', { href: detail.item.issue.url, target: '_blank', rel: 'noopener noreferrer', text: repo + '#' + number });
|
|
444
460
|
body.appendChild(el('h3', {}, [headLink]));
|
|
445
461
|
body.appendChild(el('p', { text: detail.item.issue.title }));
|
|
446
|
-
|
|
462
|
+
if (boardItem) {
|
|
463
|
+
body.appendChild(el('div', { class: 'item-summary' }, renderCardSummaryNodes(boardItem)));
|
|
464
|
+
}
|
|
465
|
+
const details = [];
|
|
466
|
+
if (detail.item.wake.sessionId) {
|
|
467
|
+
details.push(['Session', detail.item.wake.sessionId]);
|
|
468
|
+
}
|
|
447
469
|
if (detail.item.wake.workspacePath) {
|
|
448
|
-
|
|
470
|
+
details.push(['Workspace', detail.item.wake.workspacePath]);
|
|
471
|
+
}
|
|
472
|
+
if (details.length > 0) {
|
|
473
|
+
body.appendChild(el('dl', { class: 'detail-kv' }, details.flatMap(([label, value]) => [
|
|
474
|
+
el('dt', { text: label }),
|
|
475
|
+
el('dd', { text: value }),
|
|
476
|
+
])));
|
|
449
477
|
}
|
|
450
478
|
const isFrozen = typeof detail.item.context.frozenAt === 'string';
|
|
451
479
|
const actionBar = el('div', { class: 'action-bar' });
|
|
@@ -4,44 +4,20 @@ import { buildResourceUri } from '../../domain/resource-uri.js';
|
|
|
4
4
|
import { isTerminalStage } from '../../domain/stages.js';
|
|
5
5
|
import { isWorkItemDeleted, isWorkItemFrozen } from '../../domain/work-item-lifecycle.js';
|
|
6
6
|
import { workflowForProjection, workflowNameForProjection } from '../../domain/workflows.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
process.kill(pid, 0);
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
catch (error) {
|
|
25
|
-
return error.code !== 'ESRCH';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function readLockInfo(lockFile, now) {
|
|
29
|
-
try {
|
|
30
|
-
const metadata = parseLockMetadata(await readFile(lockFile, 'utf8'));
|
|
31
|
-
if (metadata === null) {
|
|
32
|
-
return { present: true };
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
present: true,
|
|
36
|
-
pid: metadata.pid,
|
|
37
|
-
acquiredAt: metadata.acquiredAt,
|
|
38
|
-
ageMs: now.getTime() - Date.parse(metadata.acquiredAt),
|
|
39
|
-
pidAlive: isPidAlive(metadata.pid),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return { present: false };
|
|
44
|
-
}
|
|
7
|
+
import { readFileLockStatus } from '../../lib/lock.js';
|
|
8
|
+
async function readLockInfo(lockFile, now, processInspector) {
|
|
9
|
+
const status = await readFileLockStatus(lockFile, {
|
|
10
|
+
now,
|
|
11
|
+
...(processInspector === undefined ? {} : { processInspector }),
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
present: status.present,
|
|
15
|
+
...(status.metadata === undefined ? {} : { pid: status.metadata.pid }),
|
|
16
|
+
...(status.metadata === undefined ? {} : { acquiredAt: status.metadata.acquiredAt }),
|
|
17
|
+
...(status.ageMs === undefined ? {} : { ageMs: status.ageMs }),
|
|
18
|
+
pidAlive: status.active,
|
|
19
|
+
...(status.staleReason === undefined ? {} : { staleReason: status.staleReason }),
|
|
20
|
+
};
|
|
45
21
|
}
|
|
46
22
|
/**
|
|
47
23
|
* Reproduces the sentinel-driven part of policy eligibility for display purposes only.
|
|
@@ -188,8 +164,8 @@ export async function buildStatus(input) {
|
|
|
188
164
|
buildBoard(input),
|
|
189
165
|
]);
|
|
190
166
|
const [tickLock, runnerLock] = await Promise.all([
|
|
191
|
-
readLockInfo(input.stateStore.paths.tickLockFile, input.now),
|
|
192
|
-
readLockInfo(input.stateStore.paths.runnerLockFile, input.now),
|
|
167
|
+
readLockInfo(input.stateStore.paths.tickLockFile, input.now, input.processInspector),
|
|
168
|
+
readLockInfo(input.stateStore.paths.runnerLockFile, input.now, input.processInspector),
|
|
193
169
|
]);
|
|
194
170
|
const tickLockLive = tickLock.present && tickLock.pidAlive === true;
|
|
195
171
|
const runnerLockLive = runnerLock.present && runnerLock.pidAlive === true;
|
package/dist/src/version.js
CHANGED