@oar-sh/oar 0.9.21 → 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.
Files changed (69) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +9 -9
  3. package/package.json +1 -1
  4. package/server/claude-cloud-worker/claude-cloud-session-worker.mjs +9 -1
  5. package/server/claude-worker/claude-sdk-adapter.mjs +149 -4
  6. package/server/claude-worker/claude-session-process.mjs +9 -4
  7. package/server/claude-worker/claude-session-worker-main.mjs +10 -1
  8. package/server/copilot-worker/copilot-sdk-session-process.mjs +1 -0
  9. package/server/copilot-worker/copilot-sdk-session-worker.mjs +10 -1
  10. package/server/cursor-worker/cursor-session-worker.mjs +9 -1
  11. package/server/db-schema.mjs +19 -0
  12. package/server/grok-worker/grok-background-tasks.mjs +1 -0
  13. package/server/grok-worker/grok-session-worker.mjs +10 -1
  14. package/server/grok-worker/grok-turn-runner.mjs +1 -0
  15. package/server/migrations/0037-relay-asks-queue-id.mjs +66 -0
  16. package/server/migrations/0038-turn-seq.mjs +92 -0
  17. package/server/public/app/activity-replay-state.mjs +160 -42
  18. package/server/public/app/api-client.js +7 -0
  19. package/server/public/app/ask-user-view.js +4 -3
  20. package/server/public/app/bootstrap.js +62 -4
  21. package/server/public/app/chat-actions-menu-state.mjs +2 -0
  22. package/server/public/app/context-usage-view.mjs +68 -0
  23. package/server/public/app/conversation-view.js +306 -49
  24. package/server/public/app/header-priority-actions.mjs +5 -1
  25. package/server/public/app/held-details.mjs +202 -0
  26. package/server/public/app/inbox-ui.js +70 -79
  27. package/server/public/app/inbox-view.mjs +35 -19
  28. package/server/public/app/journal-view.js +17 -0
  29. package/server/public/app/live-activity-cap.mjs +103 -0
  30. package/server/public/app/questions-panel-ui.js +634 -0
  31. package/server/public/app/questions-stub-view.mjs +40 -0
  32. package/server/public/app/questions-view.mjs +89 -0
  33. package/server/public/app/relay-board-view.js +12 -2
  34. package/server/public/app/relay-thoughts.mjs +15 -1
  35. package/server/public/app/session-history-ui.js +1 -0
  36. package/server/public/app/settings-modal.js +6 -0
  37. package/server/public/app/socket-handlers.js +42 -11
  38. package/server/public/app/stream-view-preference.mjs +60 -0
  39. package/server/public/app/subagent-fold.mjs +6 -3
  40. package/server/public/app/subagent-timeline-view.mjs +12 -5
  41. package/server/public/app/subagent-viewer.mjs +8 -6
  42. package/server/public/app/thoughts-preference.mjs +79 -0
  43. package/server/public/app/turn-stream-view.mjs +124 -0
  44. package/server/public/index.html +391 -214
  45. package/server/repositories/message-repository.mjs +10 -0
  46. package/server/repositories/question-repository.mjs +51 -7
  47. package/server/repositories/relay-turn-rows.mjs +56 -0
  48. package/server/routes/ask-user-routes.mjs +34 -5
  49. package/server/routes/messages-routes.mjs +35 -14
  50. package/server/routes/relay-ask-routes.mjs +15 -5
  51. package/server/routes/sessions-routes.mjs +76 -5
  52. package/server/server-runtime.mjs +178 -131
  53. package/server/services/cloudflared-tunnel-service.mjs +7 -0
  54. package/server/services/idle-timers.mjs +184 -0
  55. package/server/services/queue-wake-hook.mjs +145 -0
  56. package/server/services/queue-waker.mjs +127 -0
  57. package/server/services/relay-ask-service.mjs +64 -5
  58. package/server/services/relay-event-service.mjs +4 -1
  59. package/server/services/remote-relay-dispatcher.mjs +23 -4
  60. package/server/services/session-history-refresh-service.mjs +4 -0
  61. package/server/services/session-worker-supervisor-service.mjs +36 -0
  62. package/server/services/session-worker-websocket-service.mjs +143 -15
  63. package/server/services/ssh-tunnel-manager-service.mjs +7 -0
  64. package/shared/ask-user-bridge.mjs +9 -6
  65. package/shared/relay-asks.mjs +10 -0
  66. package/shared/relay-events.mjs +1 -0
  67. package/shared/worker-runtime/heartbeat.mjs +26 -0
  68. package/shared/worker-runtime/worker-keepalive.mjs +108 -0
  69. package/shared/worker-runtime/worker-websocket-link.mjs +21 -10
@@ -0,0 +1,103 @@
1
+ // "Tool lines shown while an agent works" (Settings › General ›
2
+ // Appearance): how many of its newest tool lines each agent of a running
3
+ // turn keeps in the live bubble, the main agent and every sub-agent apart.
4
+ // A setting of this browser, kept in localStorage like the scroll-on-send
5
+ // one. The slider runs from 10 to 500 by 10 and has one more step at the far
6
+ // end, no limit (stored as '0'). The document and the storage are passed in
7
+ // by the tests.
8
+
9
+ import { IN_FLIGHT_ACTIVITY_LIMIT_PER_THREAD, LIVE_ACTIVITY_CAP } from './activity-replay-state.mjs';
10
+
11
+ export const LIVE_ACTIVITY_CAP_STORAGE_KEY = 'copilot_live_activity_cap';
12
+ export const LIVE_ACTIVITY_CAP_SLIDER_ID = 'live-activity-cap-slider';
13
+ export const LIVE_ACTIVITY_CAP_VALUE_ID = 'live-activity-cap-value';
14
+ // One source with the relay's default and its most per thread.
15
+ export const LIVE_ACTIVITY_CAP_DEFAULT = LIVE_ACTIVITY_CAP;
16
+ export const LIVE_ACTIVITY_CAP_MIN = 10;
17
+ export const LIVE_ACTIVITY_CAP_MAX = IN_FLIGHT_ACTIVITY_LIMIT_PER_THREAD;
18
+ export const LIVE_ACTIVITY_CAP_STEP = 10;
19
+ /** The slider's last step: no limit. */
20
+ export const LIVE_ACTIVITY_CAP_UNLIMITED_POSITION = LIVE_ACTIVITY_CAP_MAX + LIVE_ACTIVITY_CAP_STEP;
21
+ /** The cap that keeps every line. */
22
+ export const LIVE_ACTIVITY_CAP_UNLIMITED = 0;
23
+
24
+ function clampToStep(value) {
25
+ const stepped = Math.round(value / LIVE_ACTIVITY_CAP_STEP) * LIVE_ACTIVITY_CAP_STEP;
26
+ return Math.min(LIVE_ACTIVITY_CAP_MAX, Math.max(LIVE_ACTIVITY_CAP_MIN, stepped));
27
+ }
28
+
29
+ /** The cap a stored value stands for: a count, or 0 for no limit. */
30
+ export function parseLiveActivityCap(stored) {
31
+ const text = String(stored ?? '').trim();
32
+ if (!text) return LIVE_ACTIVITY_CAP_DEFAULT;
33
+ const value = Number(text);
34
+ if (!Number.isFinite(value) || value < 0) return LIVE_ACTIVITY_CAP_DEFAULT;
35
+ if (value === 0) return LIVE_ACTIVITY_CAP_UNLIMITED;
36
+ return clampToStep(value);
37
+ }
38
+
39
+ export function serializeLiveActivityCap(cap) {
40
+ const value = Number(cap);
41
+ if (!Number.isFinite(value) || value <= 0) return '0';
42
+ return String(clampToStep(value));
43
+ }
44
+
45
+ /** The cap at a slider position; the far end is no limit. */
46
+ export function liveActivityCapFromSlider(position) {
47
+ const value = Number(position);
48
+ if (!Number.isFinite(value)) return LIVE_ACTIVITY_CAP_DEFAULT;
49
+ if (value >= LIVE_ACTIVITY_CAP_UNLIMITED_POSITION) return LIVE_ACTIVITY_CAP_UNLIMITED;
50
+ return clampToStep(value);
51
+ }
52
+
53
+ export function sliderPositionForLiveActivityCap(cap) {
54
+ const value = Number(cap);
55
+ return Number.isFinite(value) && value > 0 ? clampToStep(value) : LIVE_ACTIVITY_CAP_UNLIMITED_POSITION;
56
+ }
57
+
58
+ export function formatLiveActivityCap(cap) {
59
+ const value = Number(cap);
60
+ if (!Number.isFinite(value) || value <= 0) return 'No limit';
61
+ return `${clampToStep(value)} lines`;
62
+ }
63
+
64
+ function storage() {
65
+ try { return globalThis.localStorage || null; } catch { return null; }
66
+ }
67
+
68
+ /** The cap in force: a count per agent, or 0 for no limit. */
69
+ export function liveActivityCap(store = storage()) {
70
+ try {
71
+ return parseLiveActivityCap(store?.getItem(LIVE_ACTIVITY_CAP_STORAGE_KEY));
72
+ } catch {
73
+ return LIVE_ACTIVITY_CAP_DEFAULT;
74
+ }
75
+ }
76
+
77
+ function showValue(doc, cap) {
78
+ const text = formatLiveActivityCap(cap);
79
+ const label = doc?.getElementById?.(LIVE_ACTIVITY_CAP_VALUE_ID);
80
+ if (label) label.textContent = text;
81
+ doc?.getElementById?.(LIVE_ACTIVITY_CAP_SLIDER_ID)?.setAttribute?.('aria-valuetext', text);
82
+ }
83
+
84
+ export function syncLiveActivityCapSlider(doc = globalThis.document, store = storage()) {
85
+ const cap = liveActivityCap(store);
86
+ const slider = doc?.getElementById?.(LIVE_ACTIVITY_CAP_SLIDER_ID);
87
+ if (slider) slider.value = String(sliderPositionForLiveActivityCap(cap));
88
+ showValue(doc, cap);
89
+ }
90
+
91
+ /** While the thumb moves: the label follows, nothing is saved. */
92
+ export function previewLiveActivityCap(position, { doc = globalThis.document } = {}) {
93
+ showValue(doc, liveActivityCapFromSlider(position));
94
+ }
95
+
96
+ /** Saves the slider's value; returns the cap. */
97
+ export function updateLiveActivityCap(position, { doc = globalThis.document, store = storage(), onChange = null } = {}) {
98
+ const cap = liveActivityCapFromSlider(position);
99
+ try { store?.setItem(LIVE_ACTIVITY_CAP_STORAGE_KEY, serializeLiveActivityCap(cap)); } catch {}
100
+ syncLiveActivityCapSlider(doc, store);
101
+ if (typeof onChange === 'function') onChange(cap);
102
+ return cap;
103
+ }