@oar-sh/oar 0.9.1 → 0.9.3

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 (146) hide show
  1. package/.github/extensions/web-relay/extension.mjs +0 -3
  2. package/.github/extensions/web-relay/polling/heartbeat.mjs +2 -55
  3. package/.github/extensions/web-relay/polling/polling-loop.mjs +0 -1
  4. package/.github/extensions/web-relay/runtime/api-client.mjs +2 -34
  5. package/.github/extensions/web-relay/runtime/config-loader.mjs +2 -104
  6. package/.github/extensions/web-relay/runtime/send-and-wait-errors.mjs +2 -170
  7. package/.github/extensions/web-relay/runtime/session-io.mjs +1 -71
  8. package/.github/extensions/web-relay/runtime/worker-websocket-link.mjs +2 -325
  9. package/.github/extensions/web-relay/skills/prompt-context.mjs +2 -160
  10. package/CHANGELOG.md +269 -0
  11. package/README.md +407 -424
  12. package/bin/oar.js +142 -11
  13. package/package.json +8 -4
  14. package/server/README.md +59 -22
  15. package/server/claude-worker/claude-sdk-adapter.mjs +7 -2
  16. package/server/claude-worker/claude-session-process.mjs +1013 -45
  17. package/server/claude-worker/claude-session-worker.mjs +54 -9
  18. package/server/claude-worker/claude-turn-publisher.mjs +110 -19
  19. package/server/claude-worker/claude-worker-link-wiring.mjs +9 -0
  20. package/server/copilot-sdk-runtime.mjs +12 -3
  21. package/server/copilot-worker/copilot-ask-user-tool.mjs +89 -0
  22. package/server/copilot-worker/copilot-attachments.mjs +35 -2
  23. package/server/copilot-worker/copilot-continuation-signals.mjs +55 -0
  24. package/server/copilot-worker/copilot-model-switch.mjs +425 -0
  25. package/server/copilot-worker/copilot-prompt-context.mjs +20 -8
  26. package/server/copilot-worker/copilot-question-bridge.mjs +129 -16
  27. package/server/copilot-worker/copilot-sdk-adapter.mjs +59 -11
  28. package/server/copilot-worker/copilot-sdk-event-normalizer.mjs +136 -12
  29. package/server/copilot-worker/copilot-sdk-session-process.mjs +2753 -527
  30. package/server/copilot-worker/copilot-sdk-session-worker.mjs +94 -25
  31. package/server/cursor-worker/cursor-session-worker.mjs +5 -5
  32. package/server/cursor-worker/cursor-turn-runner.mjs +50 -4
  33. package/server/db-schema.mjs +61 -1
  34. package/server/features.mjs +155 -41
  35. package/server/grok-worker/grok-session-worker.mjs +5 -5
  36. package/server/grok-worker/grok-turn-runner.mjs +45 -4
  37. package/server/migrations/0004-steer-settle-markers.mjs +119 -0
  38. package/server/public/app/annotate-core.mjs +181 -0
  39. package/server/public/app/annotate-editor.js +617 -0
  40. package/server/public/app/api-client.js +86 -5
  41. package/server/public/app/ask-user-view.js +102 -13
  42. package/server/public/app/attachments-view.js +172 -3
  43. package/server/public/app/background-task-timeout-options.mjs +9 -0
  44. package/server/public/app/background-tasks-view.mjs +34 -19
  45. package/server/public/app/bootstrap.js +153 -69
  46. package/server/public/app/composer-control-state.mjs +52 -34
  47. package/server/public/app/context-tier-options.mjs +24 -4
  48. package/server/public/app/conversation-draft-sync.mjs +187 -0
  49. package/server/public/app/conversation-list-filter.mjs +86 -0
  50. package/server/public/app/conversation-preferences.mjs +47 -10
  51. package/server/public/app/conversation-provider-indicator.mjs +8 -0
  52. package/server/public/app/conversation-view.js +1032 -218
  53. package/server/public/app/emoji-view.js +2 -0
  54. package/server/public/app/font-scaling.js +4 -37
  55. package/server/public/app/journal-view.js +190 -24
  56. package/server/public/app/model-selector-options.mjs +185 -1
  57. package/server/public/app/new-conversation-model-choice.mjs +29 -9
  58. package/server/public/app/pwa-install.js +64 -136
  59. package/server/public/app/question-multi-select.mjs +52 -0
  60. package/server/public/app/reasoning-effort-labels.mjs +13 -3
  61. package/server/public/app/relay-prompt-sanitizer.mjs +26 -3
  62. package/server/public/app/router.js +120 -11
  63. package/server/public/app/settings-modal.js +225 -20
  64. package/server/public/app/settings-tabs.js +1 -1
  65. package/server/public/app/socket-handlers.js +47 -4
  66. package/server/public/app/steered-turn-merge.mjs +100 -0
  67. package/server/public/app/store.js +159 -16
  68. package/server/public/app/sync-outbox.mjs +16 -8
  69. package/server/public/app/tool-activity-emoji.mjs +36 -0
  70. package/server/public/app/transcript-viewport-anchor.mjs +210 -0
  71. package/server/public/app/update-ui.js +194 -0
  72. package/server/public/index.html +483 -24
  73. package/server/public/sw.js +7 -0
  74. package/server/relay-tools.md +2 -0
  75. package/server/relay.mjs +23 -21
  76. package/server/repositories/message-repository.mjs +78 -21
  77. package/server/repositories/question-repository.mjs +19 -1
  78. package/server/repositories/session-repository.mjs +7 -31
  79. package/server/routes/ask-user-routes.mjs +10 -0
  80. package/server/routes/messages-routes.mjs +689 -159
  81. package/server/routes/sessions-routes.mjs +574 -80
  82. package/server/server-runtime.mjs +393 -925
  83. package/server/services/claude-auth-service.mjs +7 -1
  84. package/server/services/cli-install-service.mjs +8 -27
  85. package/server/services/cli-process-runner.mjs +30 -0
  86. package/server/services/copilot-model-discovery-service.mjs +202 -0
  87. package/server/services/data-dir-resolution.mjs +47 -0
  88. package/server/services/grok-auth-service.mjs +9 -1
  89. package/server/services/live-turn-picker.mjs +47 -0
  90. package/server/services/model-variant-catalog-service.mjs +1183 -0
  91. package/server/services/oar-cli-helpers.mjs +6 -2
  92. package/server/services/relay-prompt-sanitizer.mjs +30 -3
  93. package/server/services/relay-question-context.mjs +46 -0
  94. package/server/services/sdk-session-import-service.mjs +144 -16
  95. package/server/services/sdk-session-sync-service.mjs +84 -27
  96. package/server/services/session-worker-registry-service.mjs +116 -3
  97. package/server/services/session-worker-supervisor-service.mjs +7 -1
  98. package/server/services/session-worker-websocket-service.mjs +119 -24
  99. package/server/services/status-event-service.mjs +8 -2
  100. package/server/services/steer-resend.mjs +45 -0
  101. package/server/services/update-check-service.mjs +220 -0
  102. package/server/services/update-install-service.mjs +279 -0
  103. package/server/services/windows-autostart-service.mjs +42 -6
  104. package/server/services/windows-boot-autostart-service.mjs +487 -0
  105. package/shared/ask-user-bridge.mjs +37 -5
  106. package/shared/background-task-timeout.mjs +12 -4
  107. package/shared/claude-model-catalog.mjs +49 -0
  108. package/shared/context-window-fallbacks.mjs +1 -0
  109. package/shared/control-poller.mjs +4 -1
  110. package/shared/copilot-model-order.mjs +182 -0
  111. package/shared/media-embed-instructions.mjs +35 -0
  112. package/shared/model-descriptors.mjs +181 -30
  113. package/shared/model-id.mjs +6 -0
  114. package/shared/pwa-app-name.mjs +44 -0
  115. package/shared/question-multi-select.mjs +16 -0
  116. package/shared/relay-stop-failure.mjs +15 -0
  117. package/shared/slash-command-guard.mjs +76 -0
  118. package/shared/steer-note.mjs +66 -0
  119. package/shared/steer-settle-failure.mjs +89 -0
  120. package/shared/steer-settle-markers.mjs +18 -0
  121. package/shared/update-semver.mjs +50 -0
  122. package/shared/worker-crash-guard.mjs +40 -14
  123. package/shared/worker-runtime/api-client.mjs +34 -0
  124. package/shared/worker-runtime/config-loader.mjs +104 -0
  125. package/shared/worker-runtime/heartbeat.mjs +109 -0
  126. package/shared/worker-runtime/prompt-context.mjs +160 -0
  127. package/shared/worker-runtime/runner-link-wiring.mjs +44 -0
  128. package/shared/worker-runtime/send-and-wait-errors.mjs +170 -0
  129. package/shared/worker-runtime/worker-websocket-link.mjs +436 -0
  130. package/server/claude-worker/claude-session-test-harness.mjs +0 -236
  131. package/server/claude-worker/fixtures/workflow-run-record.json +0 -1
  132. package/server/copilot-worker/copilot-sdk-test-harness.mjs +0 -329
  133. package/server/copilot-worker/fixtures/abort-turn.json +0 -588
  134. package/server/copilot-worker/fixtures/ask-user-turn.json +0 -1154
  135. package/server/copilot-worker/fixtures/background-timer-continuation.json +0 -445
  136. package/server/copilot-worker/fixtures/background-timer-turn.json +0 -497
  137. package/server/copilot-worker/fixtures/happy-turn.json +0 -566
  138. package/server/copilot-worker/fixtures/quota-turn.json +0 -647
  139. package/server/copilot-worker/fixtures/reasoning-turn.json +0 -625
  140. package/server/copilot-worker/fixtures/resume-turn.json +0 -700
  141. package/server/copilot-worker/fixtures/subagent-turn.json +0 -1378
  142. package/server/copilot-worker/fixtures/tool-permission-turn.json +0 -1293
  143. package/server/routes/messages-routes-test-harness.mjs +0 -111
  144. package/server/services/fixtures/claude-auth-stub.sh +0 -62
  145. package/server/services/fixtures/cli-install-stub.sh +0 -75
  146. package/server/services/fixtures/grok-stub.sh +0 -86
@@ -0,0 +1,194 @@
1
+ import { getUpdateState, setUpdateState, showTransientRelayNotice } from './store.js';
2
+ import {
3
+ applyUpdate,
4
+ cancelUpdate,
5
+ checkForUpdateNow,
6
+ dismissUpdate,
7
+ loadUpdateState,
8
+ setUpdateAutoCheck,
9
+ } from './api-client.js';
10
+
11
+ // The Updates section of Settings → General. Automatic checking is opt-in
12
+ // (zero telemetry by default), so the toggle drives real network behavior and
13
+ // the copy around it must stay honest. Everything server-provided (versions,
14
+ // notes URLs, npm logs) renders via textContent/setAttribute — never markup.
15
+
16
+ let renderedLogKey = '';
17
+ let actionInFlight = false;
18
+
19
+ function byId(id) {
20
+ return document.getElementById(id);
21
+ }
22
+
23
+ function setHidden(id, hidden) {
24
+ const element = byId(id);
25
+ if (element) element.hidden = !!hidden;
26
+ }
27
+
28
+ export function renderUpdateSection() {
29
+ const state = getUpdateState();
30
+ const check = state?.check || null;
31
+ const install = state?.install || null;
32
+ const checkKilled = state?.checkKilled === true;
33
+
34
+ const toggle = byId('update-auto-check-toggle');
35
+ if (toggle) {
36
+ toggle.checked = check?.autoCheckEnabled === true;
37
+ toggle.disabled = checkKilled || actionInFlight;
38
+ }
39
+ const checkBtn = byId('update-check-now-btn');
40
+ if (checkBtn) checkBtn.disabled = checkKilled || actionInFlight;
41
+ setHidden('update-check-killed-help', !checkKilled);
42
+
43
+ const lastChecked = byId('update-last-checked');
44
+ if (lastChecked) {
45
+ let text = '';
46
+ if (!checkKilled) {
47
+ text = check?.lastCheckedAt
48
+ ? `Last checked ${new Date(check.lastCheckedAt).toLocaleString()}`
49
+ : 'Never checked.';
50
+ if (check?.schemaUnsupported) {
51
+ text += ' The relay could not read the update feed — try updating manually.';
52
+ }
53
+ }
54
+ lastChecked.textContent = text;
55
+ }
56
+
57
+ const showCard = check?.available === true && (!check.dismissed || check.critical === true);
58
+ setHidden('update-available-card', !showCard);
59
+ if (showCard) {
60
+ const text = byId('update-available-text');
61
+ if (text) {
62
+ text.textContent = `OAR ${check.version} available${check.critical ? ' — critical update' : ''}`;
63
+ }
64
+ const notesLink = byId('update-notes-link');
65
+ if (notesLink) {
66
+ const notesUrl = typeof check.notesUrl === 'string' ? check.notesUrl : '';
67
+ if (notesUrl.startsWith('https://')) {
68
+ notesLink.setAttribute('href', notesUrl);
69
+ notesLink.hidden = false;
70
+ } else {
71
+ notesLink.removeAttribute('href');
72
+ notesLink.hidden = true;
73
+ }
74
+ }
75
+ const applyBtn = byId('update-apply-btn');
76
+ if (applyBtn) {
77
+ applyBtn.hidden = state?.installMethod !== 'npm-global' || install?.active === true;
78
+ applyBtn.disabled = actionInFlight;
79
+ }
80
+ setHidden('update-git-hint', state?.installMethod !== 'git-checkout');
81
+ const dismissBtn = byId('update-dismiss-btn');
82
+ if (dismissBtn) {
83
+ dismissBtn.hidden = check.critical === true;
84
+ dismissBtn.disabled = actionInFlight;
85
+ }
86
+ }
87
+
88
+ const installVisible = !!install && install.state !== 'idle';
89
+ setHidden('update-install-status', !installVisible);
90
+ setHidden('update-install-log', !installVisible || !install?.log);
91
+ const cancelBtn = byId('update-cancel-btn');
92
+ if (cancelBtn) {
93
+ cancelBtn.hidden = install?.state !== 'running';
94
+ cancelBtn.disabled = actionInFlight;
95
+ }
96
+ if (installVisible) {
97
+ const status = byId('update-install-status');
98
+ if (status) {
99
+ status.dataset.state = install.state;
100
+ status.textContent = install.state === 'running'
101
+ ? `Updating to ${install.targetVersion}…`
102
+ : install.state === 'success'
103
+ ? 'npm finished — the relay restarts when the queue is idle.'
104
+ : `Update failed: ${install.error || 'unknown error'}`;
105
+ }
106
+ const logPre = byId('update-install-log-pre');
107
+ const logKey = `${install.startedAt || ''}|${install.logSeq || 0}`;
108
+ if (logPre && logKey !== renderedLogKey) {
109
+ renderedLogKey = logKey;
110
+ logPre.textContent = install.log || '';
111
+ logPre.scrollTop = logPre.scrollHeight;
112
+ }
113
+ }
114
+
115
+ const outcome = install?.lastOutcome || null;
116
+ setHidden('update-outcome', !outcome);
117
+ if (outcome) {
118
+ const text = byId('update-outcome-text');
119
+ if (text) {
120
+ text.textContent = outcome.status === 'success'
121
+ ? `Updated to ${outcome.version}.`
122
+ : `Update to ${outcome.attemptedVersion || outcome.version || 'a new version'} did not apply.`;
123
+ }
124
+ const outcomeLog = byId('update-outcome-log');
125
+ if (outcomeLog) {
126
+ const tail = outcome.status === 'failure' ? String(outcome.logTail || '') : '';
127
+ outcomeLog.textContent = tail;
128
+ outcomeLog.hidden = !tail;
129
+ }
130
+ const dismissBtn = byId('update-outcome-dismiss-btn');
131
+ if (dismissBtn) dismissBtn.disabled = actionInFlight;
132
+ }
133
+ }
134
+
135
+ export async function refreshUpdateSection() {
136
+ const payload = await loadUpdateState();
137
+ if (payload?.update) setUpdateState(payload.update);
138
+ renderUpdateSection();
139
+ return payload;
140
+ }
141
+
142
+ async function runUpdateAction(request, failureMessage) {
143
+ if (actionInFlight) return;
144
+ actionInFlight = true;
145
+ renderUpdateSection();
146
+ try {
147
+ const payload = await request();
148
+ if (!payload) {
149
+ showTransientRelayNotice(failureMessage);
150
+ return;
151
+ }
152
+ if (payload.update) setUpdateState(payload.update);
153
+ } finally {
154
+ actionInFlight = false;
155
+ renderUpdateSection();
156
+ }
157
+ }
158
+
159
+ export async function updateAutoCheckSetting(enabled) {
160
+ // On failure the final render snaps the checkbox back to the stored state.
161
+ await runUpdateAction(() => setUpdateAutoCheck(enabled === true), 'Failed to save the update-check setting.');
162
+ }
163
+
164
+ export async function checkForUpdatesNow() {
165
+ // The service swallows network failures by design (the auto-poller must be
166
+ // silent), so an explicit click needs its own feedback: an unchanged
167
+ // check timestamp means the manifest was never reached.
168
+ const before = getUpdateState()?.check?.lastCheckedAt || null;
169
+ await runUpdateAction(() => checkForUpdateNow(), 'Update check failed.');
170
+ const after = getUpdateState()?.check?.lastCheckedAt || null;
171
+ if (after === before) {
172
+ showTransientRelayNotice('Update check failed — the update server could not be reached.');
173
+ }
174
+ }
175
+
176
+ export async function cancelRunningUpdate() {
177
+ await runUpdateAction(() => cancelUpdate(), 'Failed to cancel the update.');
178
+ }
179
+
180
+ export async function applyAvailableUpdate() {
181
+ const version = getUpdateState()?.check?.version;
182
+ if (!version) return;
183
+ await runUpdateAction(() => applyUpdate(version), 'Failed to start the update.');
184
+ }
185
+
186
+ export async function dismissAvailableUpdate() {
187
+ const version = getUpdateState()?.check?.version;
188
+ if (!version) return;
189
+ await runUpdateAction(() => dismissUpdate({ version }), 'Failed to dismiss the update.');
190
+ }
191
+
192
+ export async function dismissUpdateOutcome() {
193
+ await runUpdateAction(() => dismissUpdate({ outcome: true }), 'Failed to dismiss.');
194
+ }