agent-office 0.0.10 → 0.0.12
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.
|
@@ -429,14 +429,22 @@ function renderPage(coworker, msgs, humanName) {
|
|
|
429
429
|
const input = document.getElementById('msg-input')
|
|
430
430
|
|
|
431
431
|
let lastSeenId = parseInt(document.querySelector('#messages-inner')?.dataset?.lastId ?? '0', 10)
|
|
432
|
+
let userScrolledUp = false
|
|
432
433
|
|
|
433
434
|
function scrollToBottom() {
|
|
434
|
-
if (outer)
|
|
435
|
+
if (!outer) return
|
|
436
|
+
requestAnimationFrame(() => {
|
|
437
|
+
outer.scrollTop = outer.scrollHeight
|
|
438
|
+
// After snapping, clear the flag so future messages auto-scroll again
|
|
439
|
+
userScrolledUp = false
|
|
440
|
+
})
|
|
435
441
|
}
|
|
436
442
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
443
|
+
// Detect when the user manually scrolls up
|
|
444
|
+
outer.addEventListener('scroll', () => {
|
|
445
|
+
const distFromBottom = outer.scrollHeight - outer.scrollTop - outer.clientHeight
|
|
446
|
+
userScrolledUp = distFromBottom > 80
|
|
447
|
+
})
|
|
440
448
|
|
|
441
449
|
// Auto-grow textarea
|
|
442
450
|
input.addEventListener('input', function() {
|
|
@@ -453,7 +461,7 @@ function renderPage(coworker, msgs, humanName) {
|
|
|
453
461
|
}
|
|
454
462
|
}
|
|
455
463
|
|
|
456
|
-
// After send: clear input, re-enable button,
|
|
464
|
+
// After send: clear input, re-enable button, force scroll and refresh
|
|
457
465
|
function handleSent(event) {
|
|
458
466
|
const form = event.target
|
|
459
467
|
const btn = form.querySelector('.send-btn')
|
|
@@ -462,20 +470,20 @@ function renderPage(coworker, msgs, humanName) {
|
|
|
462
470
|
input.value = ''
|
|
463
471
|
input.style.height = 'auto'
|
|
464
472
|
input.focus()
|
|
465
|
-
|
|
473
|
+
userScrolledUp = false
|
|
466
474
|
lastSeenId = -1
|
|
467
475
|
htmx.trigger(document.getElementById('messages'), 'load')
|
|
468
476
|
}
|
|
469
477
|
}
|
|
470
478
|
|
|
471
|
-
//
|
|
479
|
+
// Scroll to bottom whenever new messages arrive, unless user has scrolled up
|
|
472
480
|
document.addEventListener('htmx:afterSwap', (e) => {
|
|
473
481
|
if (e.detail.target.id !== 'messages') return
|
|
474
482
|
const inner = document.getElementById('messages-inner')
|
|
475
483
|
const newLastId = parseInt(inner?.dataset?.lastId ?? '0', 10)
|
|
476
484
|
if (newLastId > lastSeenId) {
|
|
477
485
|
lastSeenId = newLastId
|
|
478
|
-
if (
|
|
486
|
+
if (!userScrolledUp) scrollToBottom()
|
|
479
487
|
}
|
|
480
488
|
})
|
|
481
489
|
|
|
@@ -39,7 +39,7 @@ export function CronList({ serverUrl, password, onBack, contentHeight, sessionNa
|
|
|
39
39
|
onBack();
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
if (key.escape && (mode === "confirm-delete" || mode === "confirm-enable" || mode === "confirm-disable" || mode === "history")) {
|
|
42
|
+
if (key.escape && (mode === "confirm-delete" || mode === "confirm-enable" || mode === "confirm-disable" || mode === "history" || mode === "view-message")) {
|
|
43
43
|
setMode("list");
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
@@ -81,6 +81,9 @@ export function CronList({ serverUrl, password, onBack, contentHeight, sessionNa
|
|
|
81
81
|
setActionError(null);
|
|
82
82
|
loadHistory(selected.id);
|
|
83
83
|
}
|
|
84
|
+
if (input === "v") {
|
|
85
|
+
setMode("view-message");
|
|
86
|
+
}
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
if (mode === "confirm-delete" || mode === "confirm-enable" || mode === "confirm-disable") {
|
|
@@ -290,6 +293,14 @@ export function CronList({ serverUrl, password, onBack, contentHeight, sessionNa
|
|
|
290
293
|
}
|
|
291
294
|
return null;
|
|
292
295
|
};
|
|
296
|
+
const renderViewMessage = () => {
|
|
297
|
+
if (mode !== "view-message")
|
|
298
|
+
return null;
|
|
299
|
+
const selected = filteredCrons[cursor];
|
|
300
|
+
if (!selected)
|
|
301
|
+
return null;
|
|
302
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { gap: 2, children: [_jsx(Text, { bold: true, children: "Message Preview" }), _jsx(Text, { dimColor: true, children: selected.name })] }), _jsx(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 0, flexDirection: "column", children: _jsx(Text, { wrap: "wrap", children: selected.message }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Esc back" }) })] }));
|
|
303
|
+
};
|
|
293
304
|
const renderHistory = () => {
|
|
294
305
|
if (mode !== "history")
|
|
295
306
|
return null;
|
|
@@ -301,10 +312,10 @@ export function CronList({ serverUrl, password, onBack, contentHeight, sessionNa
|
|
|
301
312
|
const actionPanel = renderActionPanel();
|
|
302
313
|
const panelHeight = actionPanel ? 5 : 0;
|
|
303
314
|
const tableHeight = contentHeight - panelHeight - 5;
|
|
304
|
-
return (_jsxs(Box, { flexDirection: "column", gap: 0, children: [renderCreateSelectSession(), renderCreateFields(), renderHistory(), (mode === "list" || mode === "confirm-delete" || mode === "confirm-enable" || mode === "confirm-disable" || mode === "deleting" || mode === "toggling") && (_jsxs(_Fragment, { children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Cron Jobs" }), selectedSession ? (_jsxs(Text, { color: "cyan", dimColor: true, children: ["[", filteredCrons.length, " jobs for ", selectedSession, "]"] })) : (_jsxs(Text, { dimColor: true, children: ["[", filteredCrons.length, " total]"] })), loading && _jsx(Spinner, {})] }), actionPanel, filteredCrons.length === 0 ? (_jsx(Box, { height: tableHeight, alignItems: "center", justifyContent: "center", children: _jsx(Text, { dimColor: true, children: selectedSession
|
|
315
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 0, children: [renderCreateSelectSession(), renderCreateFields(), renderViewMessage(), renderHistory(), (mode === "list" || mode === "confirm-delete" || mode === "confirm-enable" || mode === "confirm-disable" || mode === "deleting" || mode === "toggling" || mode === "view-message") && (_jsxs(_Fragment, { children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Cron Jobs" }), selectedSession ? (_jsxs(Text, { color: "cyan", dimColor: true, children: ["[", filteredCrons.length, " jobs for ", selectedSession, "]"] })) : (_jsxs(Text, { dimColor: true, children: ["[", filteredCrons.length, " total]"] })), loading && _jsx(Spinner, {})] }), actionPanel, filteredCrons.length === 0 ? (_jsx(Box, { height: tableHeight, alignItems: "center", justifyContent: "center", children: _jsx(Text, { dimColor: true, children: selectedSession
|
|
305
316
|
? `No cron jobs for ${selectedSession}. Press c to create one.`
|
|
306
317
|
: "No cron jobs yet. Press c to create one." }) })) : (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: " NAME".padEnd(20) }), _jsx(Text, { bold: true, color: "cyan", children: "COWORKER".padEnd(15) }), _jsx(Text, { bold: true, color: "cyan", children: "SCHEDULE".padEnd(20) }), _jsx(Text, { bold: true, color: "cyan", children: "NEXT RUN".padEnd(NEXT_RUN_PADDING) }), _jsx(Text, { bold: true, color: "cyan", children: "STATUS" })] }), filteredCrons.map((job, idx) => {
|
|
307
318
|
const selected = idx === cursor;
|
|
308
319
|
return (_jsxs(Box, { gap: 2, children: [_jsxs(Box, { width: 20, children: [_jsx(Text, { color: selected ? "cyan" : undefined, children: selected ? "▶ " : " " }), _jsx(Text, { color: selected ? "cyan" : "green", bold: selected, children: job.name })] }), _jsx(Box, { width: 15, children: _jsx(Text, { color: selected ? "magenta" : undefined, dimColor: !selected, children: job.session_name.padEnd(15) }) }), _jsx(Box, { width: 20, children: _jsx(Text, { dimColor: !selected, children: job.schedule.padEnd(20) }) }), _jsx(Box, { width: NEXT_RUN_PADDING, children: _jsx(Text, { color: job.enabled ? (selected ? "cyan" : "green") : "gray", dimColor: !selected, children: job.enabled ? formatNextRun(job.next_run).padEnd(NEXT_RUN_PADDING) : "DISABLED".padEnd(NEXT_RUN_PADDING) }) }), _jsx(Text, { color: job.enabled ? "green" : "gray", dimColor: !selected, children: job.enabled ? "enabled" : "disabled" })] }, job.id));
|
|
309
|
-
})] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["c create \u00B7 d delete \u00B7 e enable/disable \u00B7 h history \u00B7 f", " ", selectedSession ? "show all" : "filter by coworker", " \u00B7 Esc back"] }) })] }))] }));
|
|
320
|
+
})] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["c create \u00B7 d delete \u00B7 e enable/disable \u00B7 h history \u00B7 v view message \u00B7 f", " ", selectedSession ? "show all" : "filter by coworker", " \u00B7 Esc back"] }) })] }))] }));
|
|
310
321
|
}
|