@oar-sh/oar 0.9.20 → 0.9.22
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/CHANGELOG.md +325 -0
- package/README.md +13 -13
- package/bin/oar.js +2 -2
- package/package.json +1 -1
- package/server/claude-cloud-worker/claude-cloud-session-process.mjs +231 -1
- package/server/claude-cloud-worker/claude-cloud-session-worker.mjs +31 -2
- package/server/claude-cloud-worker/claude-cloud-worker-steering.mjs +34 -0
- package/server/claude-worker/claude-sdk-adapter.mjs +149 -4
- package/server/claude-worker/claude-session-process.mjs +16 -4
- package/server/claude-worker/claude-session-worker-main.mjs +18 -2
- package/server/copilot-worker/copilot-sdk-session-process.mjs +75 -1
- package/server/copilot-worker/copilot-sdk-session-worker.mjs +18 -2
- package/server/cursor-worker/cursor-session-worker.mjs +21 -2
- package/server/cursor-worker/cursor-worker-steering.mjs +20 -0
- package/server/db-schema.mjs +19 -0
- package/server/grok-worker/grok-background-tasks.mjs +10 -0
- package/server/grok-worker/grok-session-worker.mjs +22 -2
- package/server/grok-worker/grok-turn-runner.mjs +4 -0
- package/server/grok-worker/grok-worker-steering.mjs +23 -0
- package/server/migrations/0037-relay-asks-queue-id.mjs +66 -0
- package/server/migrations/0038-turn-seq.mjs +92 -0
- package/server/public/app/about-ui.js +1 -1
- package/server/public/app/about-view.mjs +19 -0
- package/server/public/app/action-confirmations.js +1 -1
- package/server/public/app/activity-replay-state.mjs +160 -42
- package/server/public/app/api-client.js +11 -2
- package/server/public/app/ask-user-view.js +24 -9
- package/server/public/app/attachments-view.js +1 -1
- package/server/public/app/back-guard.mjs +31 -5
- package/server/public/app/bootstrap.js +618 -72
- package/server/public/app/chat-actions-menu-state.mjs +141 -4
- package/server/public/app/chat-header-meta.mjs +27 -0
- package/server/public/app/claude-billing-toggle-ui.js +2 -1
- package/server/public/app/claude-cloud-conversation-ui.js +2 -2
- package/server/public/app/composer-settings-label.mjs +90 -0
- package/server/public/app/composer-settings-ui.js +442 -0
- package/server/public/app/context-menu.mjs +36 -5
- package/server/public/app/context-usage-view.mjs +68 -0
- package/server/public/app/conversation-deep-link.mjs +15 -11
- package/server/public/app/conversation-group-drag.mjs +12 -2
- package/server/public/app/conversation-group-order.mjs +9 -2
- package/server/public/app/conversation-group-state.mjs +47 -10
- package/server/public/app/conversation-origin-ui.js +17 -1
- package/server/public/app/conversation-view.js +309 -49
- package/server/public/app/cwd-menu-placement.mjs +18 -6
- package/server/public/app/cwd-picker.js +36 -6
- package/server/public/app/emoji-view.js +1 -1
- package/server/public/app/font-scaling.js +26 -0
- package/server/public/app/header-priority-actions.mjs +238 -0
- package/server/public/app/held-details.mjs +202 -0
- package/server/public/app/hidden-messages-view.mjs +4 -0
- package/server/public/app/inbox-ui.js +88 -81
- package/server/public/app/inbox-view.mjs +35 -19
- package/server/public/app/journal-view.js +328 -58
- package/server/public/app/live-activity-cap.mjs +103 -0
- package/server/public/app/phone-landscape-ui.js +225 -0
- package/server/public/app/phone-landscape.mjs +99 -0
- package/server/public/app/phone-typing-state.mjs +104 -0
- package/server/public/app/pinned-messages-view.mjs +5 -0
- package/server/public/app/push-settings.js +2 -2
- package/server/public/app/pwa-install.js +24 -3
- package/server/public/app/questions-panel-ui.js +634 -0
- package/server/public/app/questions-stub-view.mjs +40 -0
- package/server/public/app/questions-view.mjs +89 -0
- package/server/public/app/relay-board-view.js +12 -2
- package/server/public/app/relay-event-subscriptions-ui.js +71 -22
- package/server/public/app/relay-event-view.mjs +38 -0
- package/server/public/app/relay-restart-ui.js +2 -2
- package/server/public/app/relay-schedule-view.mjs +32 -6
- package/server/public/app/relay-schedules-ui.js +69 -20
- package/server/public/app/relay-thoughts.mjs +15 -1
- package/server/public/app/remote-relay-origin-view.mjs +41 -23
- package/server/public/app/session-history-ui.js +251 -0
- package/server/public/app/session-history.mjs +599 -0
- package/server/public/app/settings-modal.js +67 -6
- package/server/public/app/settings-tabs.js +12 -0
- package/server/public/app/share-state.js +1 -1
- package/server/public/app/shared-conversations-settings.js +2 -2
- package/server/public/app/socket-handlers.js +47 -13
- package/server/public/app/status-view.mjs +18 -2
- package/server/public/app/store.js +87 -16
- package/server/public/app/stream-view-preference.mjs +60 -0
- package/server/public/app/subagent-fold.mjs +6 -3
- package/server/public/app/subagent-timeline-view.mjs +12 -5
- package/server/public/app/subagent-viewer.mjs +35 -8
- package/server/public/app/tab-strip-fade.mjs +101 -0
- package/server/public/app/tap-actions.js +66 -0
- package/server/public/app/thoughts-preference.mjs +79 -0
- package/server/public/app/turn-stream-view.mjs +124 -0
- package/server/public/app/usage-limit-ui.js +63 -2
- package/server/public/app/viewer-history.mjs +13 -2
- package/server/public/index.html +2603 -1767
- package/server/relay-tools.md +1 -0
- package/server/repositories/message-repository.mjs +33 -0
- package/server/repositories/question-repository.mjs +51 -7
- package/server/repositories/relay-turn-rows.mjs +56 -0
- package/server/repositories/session-repository.mjs +19 -0
- package/server/routes/ask-user-routes.mjs +34 -5
- package/server/routes/claude-cloud-routes.mjs +19 -0
- package/server/routes/messages-routes.mjs +92 -15
- package/server/routes/relay-ask-routes.mjs +15 -5
- package/server/routes/sessions-routes.mjs +117 -12
- package/server/server-runtime.mjs +367 -170
- package/server/services/about-service.mjs +22 -53
- package/server/services/claude-billing-swap-service.mjs +7 -20
- package/server/services/claude-cloud-session-service.mjs +47 -5
- package/server/services/cloudflared-tunnel-service.mjs +7 -0
- package/server/services/idle-timers.mjs +184 -0
- package/server/services/queue-wake-hook.mjs +145 -0
- package/server/services/queue-waker.mjs +127 -0
- package/server/services/relay-ask-service.mjs +64 -5
- package/server/services/relay-event-service.mjs +4 -1
- package/server/services/remote-relay-dispatcher.mjs +84 -18
- package/server/services/session-activity-tracker.mjs +1 -1
- package/server/services/session-history-refresh-service.mjs +4 -0
- package/server/services/session-launch-mutex-service.mjs +23 -0
- package/server/services/session-worker-registry-service.mjs +36 -0
- package/server/services/session-worker-supervisor-service.mjs +36 -0
- package/server/services/session-worker-websocket-service.mjs +183 -31
- package/server/services/ssh-tunnel-manager-service.mjs +7 -0
- package/server/services/worker-recycle-service.mjs +772 -0
- package/server/services/worker-replacement.mjs +197 -0
- package/shared/ask-user-bridge.mjs +9 -6
- package/shared/build-id.mjs +128 -0
- package/shared/relay-asks.mjs +10 -0
- package/shared/relay-events.mjs +1 -0
- package/shared/worker-runtime/heartbeat.mjs +31 -0
- package/shared/worker-runtime/simple-steering-state.mjs +38 -0
- package/shared/worker-runtime/worker-keepalive.mjs +108 -0
- package/shared/worker-runtime/worker-websocket-link.mjs +44 -10
- package/shared/worker-runtime/working-directory.mjs +1 -1
|
@@ -211,6 +211,9 @@ export function pageConversationRows(rows, groups = null, { limit = 40, beforeCo
|
|
|
211
211
|
* match a filter (a group shows when any row matches: its head as context
|
|
212
212
|
* with the matching members, or whole when the head or its name matches).
|
|
213
213
|
*
|
|
214
|
+
* `keepVisibleId` is the open conversation: a member of a folded group with
|
|
215
|
+
* that id still shows under its head, as `{ kind: 'member', kept: true }`.
|
|
216
|
+
*
|
|
214
217
|
* With `emptyGroups`, an owner's group an agent emptied (`keptEmptyAt`, no
|
|
215
218
|
* row here) shows too: a head item without members (`group.empty`), placed
|
|
216
219
|
* by the time it was emptied; under a filter only when its name matches.
|
|
@@ -220,8 +223,9 @@ export function arrangeConversationList(rows, groups = null, {
|
|
|
220
223
|
matches = null,
|
|
221
224
|
groupNameMatches = null,
|
|
222
225
|
emptyGroups = false,
|
|
226
|
+
keepVisibleId = null,
|
|
223
227
|
} = {}) {
|
|
224
|
-
const items = arrangeGroupedRows(rows, groups, { isOpen, matches, groupNameMatches });
|
|
228
|
+
const items = arrangeGroupedRows(rows, groups, { isOpen, matches, groupNameMatches, keepVisibleId: toText(keepVisibleId) });
|
|
225
229
|
if (!emptyGroups || !groups) return items;
|
|
226
230
|
const present = new Set((Array.isArray(rows) ? rows : []).map(rowGroupId).filter(Boolean));
|
|
227
231
|
const entries = typeof groups.entries === 'function' && typeof groups.get === 'function' ? [...groups.entries()] : Object.entries(groups);
|
|
@@ -250,7 +254,7 @@ export function arrangeConversationList(rows, groups = null, {
|
|
|
250
254
|
return out;
|
|
251
255
|
}
|
|
252
256
|
|
|
253
|
-
function arrangeGroupedRows(rows, groups, { isOpen, matches, groupNameMatches }) {
|
|
257
|
+
function arrangeGroupedRows(rows, groups, { isOpen, matches, groupNameMatches, keepVisibleId = '' }) {
|
|
254
258
|
const ordered = orderConversationRows(rows, groups);
|
|
255
259
|
const activity = groupActivityTimes(ordered);
|
|
256
260
|
const items = [];
|
|
@@ -294,6 +298,9 @@ function arrangeGroupedRows(rows, groups, { isOpen, matches, groupNameMatches })
|
|
|
294
298
|
items.push({ kind: 'head', conversation: headRow, group });
|
|
295
299
|
if (group.open) {
|
|
296
300
|
for (const member of shownMembers) items.push({ kind: 'member', conversation: member, group });
|
|
301
|
+
} else if (keepVisibleId) {
|
|
302
|
+
const kept = shownMembers.find((member) => rowId(member) === keepVisibleId);
|
|
303
|
+
if (kept) items.push({ kind: 'member', conversation: kept, group, kept: true });
|
|
297
304
|
}
|
|
298
305
|
}
|
|
299
306
|
return items;
|
|
@@ -42,12 +42,24 @@ export function summarizeGroupMembers(states = []) {
|
|
|
42
42
|
export function groupSummaryText(summary) {
|
|
43
43
|
const count = Number(summary?.count || 0);
|
|
44
44
|
if (!count) return '';
|
|
45
|
+
const activity = groupActivityText(summary);
|
|
46
|
+
if (!activity) return groupSessionCountText(count);
|
|
47
|
+
return `${count} · ${activity}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** "1 waiting for you, 2 running", or "" while nothing waits, runs or failed. */
|
|
51
|
+
export function groupActivityText(summary) {
|
|
45
52
|
const parts = [];
|
|
46
|
-
if (summary
|
|
47
|
-
if (summary
|
|
48
|
-
if (summary
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
if (Number(summary?.waiting) > 0) parts.push(`${summary.waiting} waiting for you`);
|
|
54
|
+
if (Number(summary?.running) > 0) parts.push(`${summary.running} running`);
|
|
55
|
+
if (Number(summary?.error) > 0) parts.push(`${summary.error} failed`);
|
|
56
|
+
return parts.join(', ');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** "1 session", "4 sessions". */
|
|
60
|
+
export function groupSessionCountText(count) {
|
|
61
|
+
const n = Number(count) || 0;
|
|
62
|
+
return `${n} session${n === 1 ? '' : 's'}`;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
/** Whether a group has something going on: a member runs or waits. */
|
|
@@ -55,14 +67,39 @@ export function groupIsActive(summary) {
|
|
|
55
67
|
return Number(summary?.running || 0) > 0 || Number(summary?.waiting || 0) > 0;
|
|
56
68
|
}
|
|
57
69
|
|
|
70
|
+
/**
|
|
71
|
+
* A member's colour in its group's name: 'waiting', 'running', 'ready' (idle
|
|
72
|
+
* with a live worker, the darker green) or 'offline'. A failed member does
|
|
73
|
+
* not colour the name; the pill says so.
|
|
74
|
+
*/
|
|
75
|
+
export function memberTone({ memberState = 'idle', visualState = '' } = {}) {
|
|
76
|
+
if (memberState === 'waiting' || memberState === 'running') return memberState;
|
|
77
|
+
return String(visualState || '').trim().toLowerCase() === 'ready' ? 'ready' : 'offline';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The colour of a group's name from its members' tones: red while one waits
|
|
82
|
+
* for the user, bright green while one works, the darker green while one is
|
|
83
|
+
* ready, else the plain title colour. Returns 'question' | 'working' |
|
|
84
|
+
* 'ready' | 'offline'.
|
|
85
|
+
*/
|
|
86
|
+
export function groupTitleTone(tones = []) {
|
|
87
|
+
const list = Array.isArray(tones) ? tones : [];
|
|
88
|
+
if (list.includes('waiting')) return 'question';
|
|
89
|
+
if (list.includes('running')) return 'working';
|
|
90
|
+
if (list.includes('ready')) return 'ready';
|
|
91
|
+
return 'offline';
|
|
92
|
+
}
|
|
93
|
+
|
|
58
94
|
/**
|
|
59
95
|
* Open or folded. The user's choice ('open' | 'folded') wins; otherwise a
|
|
60
|
-
* group is open while active and folded once everything is finished.
|
|
61
|
-
* group
|
|
62
|
-
*
|
|
96
|
+
* group is open while active and folded once everything is finished. Every
|
|
97
|
+
* group under a title filter is always open. A folded group that holds the
|
|
98
|
+
* open conversation still shows that row (arrangeConversationList's
|
|
99
|
+
* keepVisibleId).
|
|
63
100
|
*/
|
|
64
|
-
export function resolveGroupFold({ choice = null, active = false,
|
|
65
|
-
if (
|
|
101
|
+
export function resolveGroupFold({ choice = null, active = false, filterActive = false } = {}) {
|
|
102
|
+
if (filterActive) return true;
|
|
66
103
|
if (choice === 'open') return true;
|
|
67
104
|
if (choice === 'folded') return false;
|
|
68
105
|
return active === true;
|
|
@@ -6,7 +6,23 @@
|
|
|
6
6
|
// marker is all there is), and neither has one a person started.
|
|
7
7
|
|
|
8
8
|
import { conversations, currentConvId, IS_SHARED_VIEW } from './store.js';
|
|
9
|
-
import { renderConversationHeaderOriginHtml } from './remote-relay-origin-view.mjs';
|
|
9
|
+
import { conversationOriginInfo, renderConversationHeaderOriginHtml } from './remote-relay-origin-view.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The ︙ entry that stands in for the line where the meta line is hidden
|
|
13
|
+
* (phone landscape): `{ label: 'Started by an agent in “title”',
|
|
14
|
+
* conversationId }` while the line is a button that opens that conversation,
|
|
15
|
+
* else null.
|
|
16
|
+
*/
|
|
17
|
+
export function conversationOriginMenuEntry() {
|
|
18
|
+
if (IS_SHARED_VIEW) return null;
|
|
19
|
+
const id = String(currentConvId || '').trim();
|
|
20
|
+
const conversation = id ? (conversations[id] || null) : null;
|
|
21
|
+
if (!conversation) return null;
|
|
22
|
+
const info = conversationOriginInfo(conversation, { conversations, linkable: true });
|
|
23
|
+
if (!info || info.kind !== 'local' || !info.linkable || !info.conversationId) return null;
|
|
24
|
+
return { label: info.label, conversationId: info.conversationId };
|
|
25
|
+
}
|
|
10
26
|
|
|
11
27
|
let renderedHtml = '';
|
|
12
28
|
|