@oar-sh/oar 0.9.11 → 0.9.13

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 (90) hide show
  1. package/CHANGELOG.md +332 -0
  2. package/README.md +10 -10
  3. package/package.json +1 -1
  4. package/server/README.md +201 -12
  5. package/server/claude-worker/claude-remote-relay-tool.mjs +2 -0
  6. package/server/claude-worker/claude-sdk-adapter.mjs +57 -4
  7. package/server/claude-worker/claude-session-process.mjs +179 -0
  8. package/server/claude-worker/claude-session-worker.mjs +17 -0
  9. package/server/claude-worker/task-output-discovery.mjs +152 -0
  10. package/server/copilot-worker/copilot-continuation-signals.mjs +11 -5
  11. package/server/copilot-worker/copilot-sdk-session-process.mjs +169 -3
  12. package/server/copilot-worker/copilot-sdk-session-worker.mjs +2 -0
  13. package/server/copilot-worker/copilot-shell-output-mirror.mjs +94 -0
  14. package/server/copilot-worker/copilot-task-settle.mjs +96 -0
  15. package/server/db-schema.mjs +19 -0
  16. package/server/grok-worker/acp-host-services.mjs +48 -6
  17. package/server/grok-worker/grok-background-tasks.mjs +248 -0
  18. package/server/grok-worker/grok-sdk-adapter.mjs +3 -1
  19. package/server/grok-worker/grok-session-worker.mjs +33 -1
  20. package/server/grok-worker/grok-turn-runner.mjs +11 -0
  21. package/server/migrations/0017-conversation-history-indexes.mjs +89 -0
  22. package/server/migrations/0018-background-task-rows.mjs +101 -0
  23. package/server/public/app/action-confirmations.js +12 -15
  24. package/server/public/app/api-client.js +70 -3
  25. package/server/public/app/background-tasks-view.mjs +334 -16
  26. package/server/public/app/bootstrap.js +102 -5
  27. package/server/public/app/claude-background-command-limit-options.mjs +21 -0
  28. package/server/public/app/conversation-payload-cache.mjs +357 -0
  29. package/server/public/app/conversation-preferences.mjs +10 -4
  30. package/server/public/app/conversation-turn-state.mjs +1 -1
  31. package/server/public/app/conversation-view.js +462 -8
  32. package/server/public/app/conversation-window-retention.mjs +96 -0
  33. package/server/public/app/host-suspend-ui.js +45 -44
  34. package/server/public/app/journal-view.js +259 -67
  35. package/server/public/app/push-settings.js +1 -0
  36. package/server/public/app/relay-prompt-sanitizer.mjs +20 -6
  37. package/server/public/app/relay-restart-note-view.mjs +36 -0
  38. package/server/public/app/relay-restart-ui.js +568 -0
  39. package/server/public/app/settings-modal.js +162 -2
  40. package/server/public/app/socket-handlers.js +59 -7
  41. package/server/public/app/store.js +25 -0
  42. package/server/public/app/subagent-viewer.mjs +7 -1
  43. package/server/public/app/task-console-render.mjs +401 -0
  44. package/server/public/app/task-console-watch.mjs +42 -0
  45. package/server/public/app/task-console.mjs +730 -0
  46. package/server/public/app/task-output-text.mjs +243 -0
  47. package/server/public/app/transcript-island.mjs +73 -0
  48. package/server/public/app/transcript-jump-bottom-view.mjs +42 -8
  49. package/server/public/app/transcript-jump-bottom.mjs +68 -11
  50. package/server/public/app/transcript-reading-anchor.mjs +256 -0
  51. package/server/public/app/transcript-reload-freshness.mjs +17 -1
  52. package/server/public/app/transcript-viewport-anchor.mjs +20 -1
  53. package/server/public/index.html +306 -6
  54. package/server/relay-tools.md +6 -0
  55. package/server/repositories/message-repository.mjs +11 -0
  56. package/server/repositories/question-repository.mjs +4 -0
  57. package/server/repositories/remote-relay-repository.mjs +4 -2
  58. package/server/routes/messages-routes.mjs +397 -23
  59. package/server/routes/relay-board-routes.mjs +19 -2
  60. package/server/routes/relay-restart-routes.mjs +73 -0
  61. package/server/routes/sessions-routes.mjs +208 -66
  62. package/server/server-runtime.mjs +269 -137
  63. package/server/services/about-service.mjs +13 -12
  64. package/server/services/background-task-persistence.mjs +133 -0
  65. package/server/services/background-task-store.mjs +470 -6
  66. package/server/services/cli-process-runner.mjs +4 -21
  67. package/server/services/conversation-history-page.mjs +199 -0
  68. package/server/services/conversation-model-fallback.mjs +57 -0
  69. package/server/services/host-suspend-command.mjs +2 -1
  70. package/server/services/preview-proxy-server.mjs +14 -1
  71. package/server/services/process-list-service.mjs +2 -1
  72. package/server/services/provider-model-selection.mjs +195 -0
  73. package/server/services/push-dispatch-service.mjs +9 -2
  74. package/server/services/relay-event-service.mjs +27 -9
  75. package/server/services/relay-prompt-sanitizer.mjs +18 -4
  76. package/server/services/relay-restart-picture.mjs +209 -0
  77. package/server/services/relay-restart-queue.mjs +380 -0
  78. package/server/services/relay-shutdown-gate.mjs +4 -1
  79. package/server/services/remote-relay-dispatcher.mjs +316 -20
  80. package/server/services/restart-resume-service.mjs +303 -0
  81. package/server/services/session-activity-tracker.mjs +6 -2
  82. package/server/services/session-worker-process-service.mjs +6 -4
  83. package/server/services/task-output-rooms.mjs +259 -0
  84. package/server/services/task-output-service.mjs +761 -0
  85. package/shared/claude-background-command-limit.mjs +83 -0
  86. package/shared/relay-events.mjs +55 -2
  87. package/shared/remote-relay-contract.mjs +47 -10
  88. package/shared/task-output-text.mjs +850 -0
  89. package/shared/worker-runtime/task-output-spool.mjs +181 -0
  90. package/shared/worker-runtime/worker-websocket-link.mjs +96 -20
package/CHANGELOG.md CHANGED
@@ -3,6 +3,338 @@
3
3
  All notable changes to OAR are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow semver.
5
5
 
6
+ ## [0.9.13] — 2026-10-20
7
+
8
+ Highlights: a queued relay restart now shows every page what it waits for,
9
+ which messages it holds and which background tasks keep running, and after a
10
+ time you set it asks instead of waiting forever; it never restarts by itself
11
+ while turns run, and can tell the sessions a restart cut off to carry on
12
+ (opt-in). The task console survives a relay restart, marks where a `| tail`
13
+ holds output back, keeps the task's row in view, and counts a test run over
14
+ its whole log. A message
15
+ sent without a model keeps the conversation's model, effort and mode,
16
+ `remote_relay` refuses a model the provider does not list, watching agents
17
+ are no longer woken by every finished shell command, workers reconnect after
18
+ a hung restart, and the unit suite passes on Windows again.
19
+
20
+ ### Upgrade notes
21
+
22
+ - Migration 0018 (the table `background_task_rows`) runs by itself on the
23
+ first start. Rows the runtime before this update held in memory are lost
24
+ one last time at the restart into it. The Node.js requirement is unchanged
25
+ (22.13 or newer).
26
+ - New settings in **Settings › General**: **Ask after a queued relay restart
27
+ has waited** (30 minutes by default) and **After a relay restart, tell
28
+ interrupted sessions to carry on** (off by default); a new push event,
29
+ **Queued relay restart waited its maximum time** (Settings › Notifications),
30
+ is on by default.
31
+ - **Watching agents:** a subscription that named no events now leaves out
32
+ successful shell commands (sub-agent ends and failures still wake it); one
33
+ that named its events keeps them. Name `task_finished` to get every task end.
34
+ - **Scripts that post `/api/message` without a model** to an existing
35
+ conversation now get the conversation's own model, effort and mode, or a
36
+ `409 CONVERSATION_MODEL_UNAVAILABLE` when that model left the catalog,
37
+ instead of the relay's first model.
38
+ - The npm package guard allows 7.75 MiB unpacked and 520 entries (was 7.5
39
+ MiB and 510); the restart queue, the stored task rows and the restart note
40
+ grew the server and the app to about 7.57 MiB and 514 entries.
41
+
42
+ ### Added
43
+
44
+ - **After a relay restart, tell interrupted sessions to carry on** (Settings
45
+ › General, off by default, a setting of the relay). A turn a restart cut
46
+ off for good (the agent had already taken the message, so it cannot run
47
+ again) used to stop without the agent ever hearing of it. With the setting
48
+ on, its session gets one compact **relay** note once the relay is back:
49
+ when the relay restarted, and to check what it was doing and carry on.
50
+ The user's message is never sent again, and nothing goes to idle sessions,
51
+ to turns the relay requeues (they run again by themselves), to archived
52
+ conversations or while a usage-limit pause holds the session; a message
53
+ queued meanwhile goes first.
54
+ - **The task console marks where a `| tail` holds the output back.** A
55
+ command piped into `tail` (`npm test 2>&1 | tail -40`) writes nothing
56
+ until it ends, so its console looked stuck. When the task's command line
57
+ shows such a pipe (`tail -f` and `head` pass lines on and are left
58
+ alone), the console marks where the output stops, with a hint to log to a
59
+ file instead, until more output comes or the task ends; the row's quiet
60
+ hint says the same on hover. The Claude, Copilot and Grok workers now report a
61
+ shell task's command line on its row (scrubbed of credentials by the relay
62
+ and cut at 2,000 characters; `read_session` passes it on).
63
+ - **Load earlier in the console's header.** It sat only above the first
64
+ line, out of reach while following the end of a long log; the header now
65
+ has it too whenever there is earlier output.
66
+
67
+ - **A queued relay restart shows what it waits for, and asks instead of
68
+ waiting forever.** **🌄 Restart web relay** first lists the sessions with
69
+ a running turn it would wait for, the messages it would hold, and the
70
+ sessions with background tasks (commands, monitors, sub-agents), each with
71
+ whether it keeps running; **Restart when idle** queues the restart,
72
+ **Restart now** does not wait. While a restart is queued every page shows a
73
+ banner: *Relay restart queued — waiting for N sessions*, the sessions as
74
+ links, how long it has waited, that new messages are held until then, the
75
+ background tasks, and **Restart now** (it asks first and names the
76
+ sessions it does not wait for) and **Cancel restart**. A new setting,
77
+ **Ask after a queued relay restart has waited** (Settings › General,
78
+ 30 minutes by default, 5 minutes to 4 hours or no limit), bounds the wait:
79
+ after it the banner asks *restart now, keep waiting or cancel?* and a push
80
+ notification (a new event, on by default) asks the same. It never
81
+ restarts while the turns run, and still restarts as soon as they end;
82
+ **Keep waiting** waits another period.
83
+ `POST /api/relay/shutdown` answers with the same picture (`waitingFor`,
84
+ `held`, `backgroundTasks` with `survives`), so an agent that requests a
85
+ restart can tell the user, and takes `immediate: true`; `GET
86
+ /api/relay/shutdown` and `POST /api/relay/shutdown/keep-waiting` are new.
87
+
88
+ ### Changed
89
+
90
+ - **The open console leaves the task's row in view.** On a screen wider
91
+ than a phone the console now ends above the task's row in the composer
92
+ panel, so the row's ✓/✘ chip, clock and **Stop** stay visible and live
93
+ beside it; on a phone it stays full-screen, with the same chip in its
94
+ header.
95
+ - **One wording for a task without output.** The row's hover title said
96
+ "output not available for this provider" and the console "Output is not
97
+ available for this provider."; both now use the sentence, from the same
98
+ text the relay answers with.
99
+ - **A watching agent is no longer woken for every shell command that ended
100
+ well.** A relay event subscription that names no `events` now gets
101
+ `subagent_finished` instead of `task_finished`: a background sub-agent that
102
+ finished still wakes the watcher, and so does any task that failed or
103
+ exited non-zero (`task_failed`), but a shell command that ended well does
104
+ not. A busy worker ends one every minute or so, and each was a turn of the
105
+ watcher on its whole context (35 during one 20-minute wait were seen).
106
+ Name `task_finished` in `events` to get every task end, as before.
107
+ Existing subscriptions that named no events switch to the new default by
108
+ themselves; those that named their events keep them. A paired relay on an
109
+ older OAR applies its own default and refuses `subagent_finished` by name.
110
+
111
+ ### Fixed
112
+
113
+ - **A message sent without a model keeps the conversation's model and
114
+ effort.** A message to an existing Copilot conversation that named no model
115
+ (sent by a script or an agent, not by the composer) ran on the first model
116
+ of the catalog with effort `none`, which some models refuse, and then saved
117
+ that model and effort as the conversation's own, so the composer showed
118
+ them from then on. Such a message now runs on the conversation's model and
119
+ effort, and saves nothing it did not name. If the conversation's model has
120
+ left the catalog, the send is refused with a message saying so instead of
121
+ switching to another model. OpenAI, Claude, Cursor and Grok conversations
122
+ keep their effort the same way, and so does the follow-up of a plan
123
+ board's action. A message that names no mode runs in the conversation's
124
+ mode instead of agent mode, and no longer switches a plan-mode
125
+ conversation to agent. A message whose turn failed can be sent again at
126
+ once: it no longer counts as a duplicate of itself.
127
+ - **Test counts of a long run no longer drop out.** The relay counted a
128
+ test run from the last 64 KB of its output only, so a live run that wrote
129
+ more lost its runner's first line: the chip disappeared or undercounted.
130
+ A run still going is now counted over its whole log, read on as it grows
131
+ (and read again in bounded steps after a relay restart); the closing
132
+ summary still decides once it is there.
133
+ - **Credentials in background-task rows are blanked.** A task's
134
+ description, summary and last tool call went to the pages, `read_session`
135
+ and the stored console rows as the worker sent them, and a Grok terminal's
136
+ (or a Copilot shell's) description is its command line. The relay now
137
+ scrubs them like the console output. The scrubber also catches `curl -u
138
+ name:password` (also attached), `--password`/`--token`/`--secret`
139
+ values, `mysql -p…`, `docker login -p`, `sshpass -p`, `redis-cli -a`,
140
+ `aws_secret_access_key` in a file or `aws configure set`, Slack webhook
141
+ paths, `?key=`/`&sig=`/`&token=` query values and an `Authorization`
142
+ header in any case and with any scheme word, and leaves a reference such
143
+ as `$(cat ~/.token)` or `$API_TOKEN` alone.
144
+ - **Inverse text in the task console.** vitest's RUN, PASS and FAIL badges
145
+ (SGR 7) showed as plain words; inverse text now swaps its colours, so
146
+ they show filled.
147
+ - **The task console survives a relay restart.** Its rows lived in the
148
+ relay's memory: after a restart a running command came back to the panel
149
+ once its worker reported, but the dimmed rows of commands that had
150
+ finished within the hour were gone, and a console open at the time said
151
+ the output was no longer available. The rows are now kept in the database
152
+ (migration 0018): finished rows come back with their ✓ or ✘ for the rest
153
+ of their hour, and a running command's console reads its output at once.
154
+ Such a command is shown as running again only when its worker says so
155
+ (until then its console says it waits for the worker, without **Stop**);
156
+ one whose worker did not survive the restart is marked finished with an
157
+ unknown result (a neutral ? instead of ✓ or ✘) after about a minute and a
158
+ half, its output still readable.
159
+ - **A scroll right after older messages load is no longer undone.** The page
160
+ put the reader back where they were when the older page arrived, a frame
161
+ later: scrolling in that frame (up again after the jump-to-bottom button,
162
+ for instance) was reverted, and could leave you at the end, following new
163
+ rows you meant to read later.
164
+ - **The jump-to-bottom badge counts a message that arrives just as you scroll
165
+ up.** One that landed before the page had noted the scroll, a frame and on
166
+ a busy page up to a tenth of a second, was taken as already seen.
167
+ - **The background-task panel no longer shrinks back for a moment.** While
168
+ the agent works the page re-reads the conversation, and an answer read
169
+ before the panel grew put the smaller set of tasks back until the next
170
+ read. The panel jumped, and a reader following the newest messages could be
171
+ left above them.
172
+ - **A worker reconnects after a relay restart even when its connect hangs.**
173
+ A worker's link to the relay was retried only once the socket reported an
174
+ error or a close. A connect that never finished, a socket the relay
175
+ accepted but never greeted, or a close that never completed while the
176
+ relay hung in its shutdown left the worker without a connection and
177
+ without a next attempt, and messages to its session stayed queued; the
178
+ relay's replacement of such a worker does not step in while the session
179
+ is working. The link now gives up a socket that has not completed its
180
+ handshake within 15 seconds, does not wait for a close after the relay
181
+ says it is shutting down, and retries a socket that fails to construct.
182
+ There is always exactly one next attempt, with the usual backoff of up to
183
+ 8 seconds, which now starts over only after a completed handshake. Failed
184
+ attempts log one line each in the worker log, at most one a minute after
185
+ the first three.
186
+ - **`remote_relay` refuses a model the provider does not list.**
187
+ `create_session` passed any model id on, so a Copilot id written with a
188
+ hyphen ("gpt-5-4" for "gpt-5.4") created a session on another model, which
189
+ every later `send` with that id failed to reach. A model in
190
+ `create_session` or `send` is now checked against the list New Chat offers
191
+ for the provider on the target relay, before any approval card: an unknown
192
+ one is refused with the close matches and the valid ids ("Unknown model
193
+ 'gpt-5-4' for Copilot on relay …; did you mean 'gpt-5.4'?"), and nothing is created
194
+ or sent. Claude also takes `opus`, `sonnet` and `haiku` (the newest listed
195
+ model of that name), and a Copilot id with its effort (`gpt-5.4-high`) runs
196
+ as that model with that effort. When the relay has no list for the provider yet, the
197
+ model goes on unchecked and the answer says so. A relay also refuses an
198
+ unknown Copilot model when another relay's agent starts a session on it.
199
+ - **A preview's websocket is dropped when the browser hangs up before the dev
200
+ server answers.** A browser that closed its connection with a plain FIN
201
+ while the upgrade was still waiting on the dev server left both sides
202
+ open, even when a reset followed: the request
203
+ to the dev server stayed pending, and the preview lane could not stop
204
+ until the dev server answered. Both sides are now dropped, and stopping
205
+ the lane also drops upgrades still waiting on the dev server.
206
+ - **The unit test suite passes and finishes on Windows again.** A preview
207
+ test waited forever for a websocket hang-up (fixed in the product, above),
208
+ and several tests expected bare program names or Unix paths where Windows
209
+ resolves the full path of its own tools; two unlocks recorded in the same
210
+ millisecond are now listed in the order they were recorded.
211
+
212
+ ## [0.9.12] — 2026-10-18
213
+
214
+ Highlights: a background command or monitor in the task panel opens a
215
+ console with its output, live, in colour and with secrets blanked, paging
216
+ back through the whole log and with its own **Stop**. Task rows say when a
217
+ task has gone quiet ("no output for 12 min", amber after a time you set in
218
+ Settings) and show a **✓ 412 ✘ 2** chip when the output is a test run;
219
+ sub-agent rows count their steps, and agents read a task's output on a
220
+ paired relay with `remote_relay` `read_task_output`. Long conversations open
221
+ and page back fast, and switching away and back, or reloading, returns to
222
+ the message you were reading, older pages included; new messages wait below
223
+ a place far up the history instead of skipping the ones in between.
224
+
225
+ ### Upgrade notes
226
+
227
+ - Migration 0017 (two indexes for the history of long conversations) runs by
228
+ itself on the first start. The Node.js requirement is unchanged (22.13 or
229
+ newer), and no setting or config key needs changing.
230
+ - Two new settings in **Settings › General**: **Mark a background task as
231
+ quiet after** (10 minutes by default, for the relay) and **Messages kept
232
+ per conversation for switching back** (200 by default, per browser).
233
+ - **Claude background commands may run for 2 hours** before Claude Code
234
+ stops them, and up to 8 hours when Claude asks; **Settings › Providers ›
235
+ Claude** sets the limit. OAR now sets `BASH_DEFAULT_TIMEOUT_MS`, `BASH_MAX_TIMEOUT_MS` and
236
+ `CLAUDE_CODE_AUTO_BACKGROUND_TIMEOUT_MS` for the Claude sessions it starts,
237
+ so values of these in the relay's environment no longer apply. Commands
238
+ that start with `sleep`, and sub-agents' commands, are not moved to the
239
+ background after 2 minutes and may block a turn up to the limit.
240
+
241
+ ### Added
242
+
243
+ - **Click a background command to watch its output.** A backgrounded shell
244
+ command or monitor in the composer's task panel opens a console: the last
245
+ 2,000 lines, following live, with **Load earlier** paging back through the
246
+ whole log (about 5 MB at most). Progress-bar redraws collapse to their last
247
+ state, repeated lines fold into one with ×N, colours are kept and other
248
+ control codes dropped, secrets are blanked, and the console has its own
249
+ **Stop**. A finished command keeps a dimmed ✓/✘ row for an hour so a failed
250
+ run can still be read. Claude reads the file its CLI writes for the command,
251
+ Copilot a detached shell's log or an attached shell's recent output, and
252
+ Grok now lists its terminals as tasks. A session started before this
253
+ release names no output file; its console says so and that a restart of
254
+ the session helps.
255
+ - **Task rows say when a task has gone quiet** ("no output for 12 min", amber
256
+ after **Settings › General › Mark a background task as quiet after**, 10
257
+ minutes by default) and show a **✓ 412 ✘ 2** chip when the output is a
258
+ vitest, Playwright, node:test, jest, pytest or turbo run (also through
259
+ pnpm); the console header's chip jumps to the first failure, and a run
260
+ that ends shows its final counts within a moment.
261
+ - **Sub-agent rows in the task panel show their step count** ("22 steps"), as
262
+ the rows in the reply already did.
263
+ - **Settings › Providers › Claude › Claude background command limit** (30
264
+ minutes to 8 hours, 2 hours by default) sets how long a command Claude runs
265
+ in the background may take before Claude Code stops it, when Claude gives it
266
+ no timeout of its own; Claude may still ask for up to 8 hours for one
267
+ command. A foreground command moves to the background after 2 minutes, so
268
+ the turn goes on while it runs. Claude is also told to write the output of
269
+ long runs to a log file instead of piping it into `tail`, and to start runs
270
+ that must survive a session restart with `nohup`. A change applies to Claude
271
+ sessions started afterwards; Claude Cloud is not affected.
272
+ - **`remote_relay` action `read_task_output`** gives agents the same tail,
273
+ quiet time and counts of a task on a relay they may read; `read_session`
274
+ lists the task ids with that health.
275
+
276
+ ### Changed
277
+
278
+ - **Long conversations open and scroll back fast.** A history page used to
279
+ load and prepare every message of the conversation, so a chat with a few
280
+ thousand messages took about two seconds per page and per live refresh. The
281
+ relay now reads only the requested page from the database (migration 0017
282
+ adds the indexes for it), so a page loads in well under a tenth of a second
283
+ however long the conversation is.
284
+ - Switching back to a conversation already viewed in this tab draws it at
285
+ once from what the page kept of it; the relay's fresh answer is merged into
286
+ it when it arrives.
287
+ - **Settings › General › Messages kept per conversation for switching back**
288
+ (200 by default, 100 to 1,000 or no limit, saved in this browser) sets how
289
+ many loaded messages each of the last eight conversations keeps.
290
+ - **The conversation list shows activity by the title's colour.** The three
291
+ animated dots after a working session's title are gone: a ready session
292
+ that runs a turn or background work keeps the bright green title, an idle
293
+ one turns a darker green (a muted green in the light theme), and the chat
294
+ header follows the same rule. Question, error, offline and archived titles
295
+ keep their colours.
296
+ - The npm package guard allows 7.5 MiB unpacked and 510 entries (was 7.25
297
+ MiB and 490); the task console, the transcript's handling of new
298
+ messages below a place far up the history, the Copilot task report and the
299
+ Claude background command limit grew the server and the app to about 7.37
300
+ MiB and 505 entries.
301
+
302
+ ### Fixed
303
+
304
+ - **Copilot background tasks report how they ended.** Finished shells and
305
+ sub-agents of Copilot's SDK engine showed the status *unknown* and no exit
306
+ code, in the task data agents read and wherever the end is shown. The
307
+ worker now reports completed, failed or cancelled, a shell's exit code, and
308
+ a sub-agent's result (or its error) as its summary; a passing status line
309
+ such as *Thinking…* is no longer kept as the final summary.
310
+ - **Cancel on a usage-limit pause removes the relay's held follow-up from the
311
+ open conversation at once.** The *Automatic message from OAR* row was
312
+ deleted on the relay but stayed on the page, and in what the page kept for
313
+ switching back, until a reload. A row deleted while you were elsewhere
314
+ leaves too, also when it was the conversation's newest.
315
+
316
+ - **Switching away from a long conversation and back keeps your place.** After
317
+ loading older messages and scrolling back into them, a switch to another
318
+ conversation and back lost the reading position: with more than 100 messages
319
+ loaded the oldest were dropped, and messages written meanwhile moved the view
320
+ by as many rows. The page now remembers the message you were reading and
321
+ keeps the loaded messages, so you come back to the same message at the same
322
+ place, older pages included; after a reload it opens at that message too.
323
+ - **New messages no longer skip the ones in between while you read far up.**
324
+ Opened at a pin, a search result or the place you were reading after a
325
+ reload, a conversation shows the messages around it. A message or reply that
326
+ arrived then was put right under them, and the messages between were never
327
+ loaded when you scrolled down, only the jump-to-bottom button brought them.
328
+ Now new messages wait: the button counts them, and scrolling down loads
329
+ every message in between, in order, before them. A reply still being
330
+ written shows once you are there. A message you send from there takes you
331
+ to the end, where it, its reply and everything in between show.
332
+ - **Images that load late no longer push the message you are reading down.**
333
+ In a browser without scroll anchoring (Safari, for one), pictures above
334
+ your place that arrived after a switch back, a reload or an older page moved
335
+ the text by their height. The transcript now holds your place while they
336
+ load, and lets go as soon as you scroll.
337
+
6
338
  ## [0.9.11] — 2026-10-17
7
339
 
8
340
  Highlights: sessions an agent starts now sit in a group under the session
package/README.md CHANGED
@@ -45,29 +45,29 @@ flowchart LR
45
45
  <table>
46
46
  <tr>
47
47
  <td width="42%" rowspan="4" valign="top">
48
- <a href="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-mobile.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.11" alt="OAR on a phone: a finished agent turn in a conversation, with the composer below"></picture></a>
48
+ <a href="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-mobile.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.13" alt="OAR on a phone: a finished agent turn in a conversation, with the composer below"></picture></a>
49
49
  <br><sub>On a phone: the same conversations, installable as an app.</sub>
50
50
  </td>
51
51
  <td width="58%" valign="top">
52
- <a href="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-agents.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.11" alt="Background subagents running in parallel in the task panel, each with live token counts, elapsed time, and its own Stop button"></picture></a>
52
+ <a href="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-agents.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.13" alt="Background subagents running in parallel in the task panel, each with live token counts, elapsed time, and its own Stop button"></picture></a>
53
53
  <br><sub>Agents working in parallel, each with live token counts and its own Stop.</sub>
54
54
  </td>
55
55
  </tr>
56
56
  <tr>
57
57
  <td valign="top">
58
- <a href="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-question.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.11" alt="A question card in the middle of a turn: the agent offers several choices and a free-text reply"></picture></a>
58
+ <a href="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-question.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.13" alt="A question card in the middle of a turn: the agent offers several choices and a free-text reply"></picture></a>
59
59
  <br><sub>When the agent needs a decision, it asks, and waits for your answer.</sub>
60
60
  </td>
61
61
  </tr>
62
62
  <tr>
63
63
  <td valign="top">
64
- <a href="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pingcf-thoughts.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.11" alt="An expanded Thoughts block showing the agent's reasoning above its reply"></picture></a>
64
+ <a href="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pingcf-thoughts.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.13" alt="An expanded Thoughts block showing the agent's reasoning above its reply"></picture></a>
65
65
  <br><sub>Read the reasoning, not just the answer.</sub>
66
66
  </td>
67
67
  </tr>
68
68
  <tr>
69
69
  <td valign="top">
70
- <a href="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pagewright-watching.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.11" alt="A session watching two other sessions: a finished reply arrives as a compact relay-event row, the watching 2 sessions list is open with Unsubscribe, and a request to also watch a session on a paired relay waits on an Allow / Deny card"></picture></a>
70
+ <a href="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pagewright-watching.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.13" alt="A session watching two other sessions: a finished reply arrives as a compact relay-event row, the watching 2 sessions list is open with Unsubscribe, and a request to also watch a session on a paired relay waits on an Allow / Deny card"></picture></a>
71
71
  <br><sub>Agents that watch agents: woken by events, approving nothing.</sub>
72
72
  </td>
73
73
  </tr>
@@ -116,11 +116,11 @@ API keys are entered in **⚙️ Settings** and stay on the relay host. The Clau
116
116
  <table>
117
117
  <tr>
118
118
  <td width="62%" valign="top">
119
- <a href="https://oar.sh/assets/shots/cfmail-steering.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-steering.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/cfmail-steering.png?v=0.9.11" alt="A running Claude turn with a message steered into it mid-turn, the reply streaming with its tool calls, and the Steer button in the composer"></picture></a>
119
+ <a href="https://oar.sh/assets/shots/cfmail-steering.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-steering.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/cfmail-steering.png?v=0.9.13" alt="A running Claude turn with a message steered into it mid-turn, the reply streaming with its tool calls, and the Steer button in the composer"></picture></a>
120
120
  <br><sub>Send a message while the agent works, and it steers the running turn.</sub>
121
121
  </td>
122
122
  <td width="38%" valign="top">
123
- <a href="https://oar.sh/assets/shots/usage-copilot-compact.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/usage-copilot-compact.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/usage-copilot-compact.png?v=0.9.11" alt="The GitHub Copilot card in Check Usage: premium requests and plan quota with reset dates, and the cost of the last turn"></picture></a>
123
+ <a href="https://oar.sh/assets/shots/usage-copilot-compact.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/usage-copilot-compact.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/usage-copilot-compact.png?v=0.9.13" alt="The GitHub Copilot card in Check Usage: premium requests and plan quota with reset dates, and the cost of the last turn"></picture></a>
124
124
  <br><sub>What each plan has left, in one place.</sub>
125
125
  </td>
126
126
  </tr>
@@ -129,7 +129,7 @@ API keys are entered in **⚙️ Settings** and stay on the relay host. The Clau
129
129
  - **Watch a turn live**: the reply, the agent's thoughts and every tool call appear as they happen, and each sub-agent gets a bubble of its own. **Stop** is always one tap away ([While a turn runs](docs/web-ui.md#while-a-turn-runs)).
130
130
  - **Steer or queue**: a message sent during a turn goes into it (Claude, Copilot) or waits behind it ([While a turn runs](docs/web-ui.md#while-a-turn-runs)).
131
131
  - **Answer questions**: the agent asks on a card with one-click choices, checkmarks or free text, and waits for you ([Question cards](docs/web-ui.md#question-cards)).
132
- - **Background work**: a task panel lists the commands and sub-agents that outlive a reply, each with its own **Stop** and its full record ([Background tasks](docs/web-ui.md#background-tasks)).
132
+ - **Background work**: a task panel lists the commands and sub-agents that outlive a reply, each with its own **Stop** and its full record; a command's console shows its output live, says when it has gone quiet and counts a test run's passes and failures ([Background tasks](docs/web-ui.md#background-tasks)).
133
133
  - **Choose how the agent works**: `ask`, `plan`, `agent` or `autopilot`, plus model and reasoning effort, per message ([Relay modes](docs/web-ui.md#relay-modes)).
134
134
  - **Files and git**: browse the workspace, preview files, review git changes in a diff viewer, and publish a dev server as a preview link ([Files, git, and previews](docs/web-ui.md#files-git-and-previews), [preview servers](docs/preview-servers.md)).
135
135
  - **Usage and context**: plan limits and credits of every provider, and what fills the model's context window ([Usage and context](docs/web-ui.md#usage-and-context)).
@@ -137,7 +137,7 @@ API keys are entered in **⚙️ Settings** and stay on the relay host. The Clau
137
137
  - **Share** a conversation as a read-only link, hide single messages and the host's paths from it, and see when it was opened ([Sharing](docs/web-ui.md#sharing)).
138
138
  - **On your phone**: install OAR as an app and get push notifications ([Notifications and the app](docs/web-ui.md#notifications-and-the-app)).
139
139
 
140
- The full tour is in [Using the web UI](docs/web-ui.md); every setting and config key is in [Settings and configuration](docs/configuration.md). What changed in each release is in the [changelog](CHANGELOG.md), with [0.9.11](CHANGELOG.md#0911--2026-10-17) as the latest.
140
+ The full tour is in [Using the web UI](docs/web-ui.md); every setting and config key is in [Settings and configuration](docs/configuration.md). What changed in each release is in the [changelog](CHANGELOG.md), with [0.9.13](CHANGELOG.md#0913--2026-10-20) as the latest.
141
141
 
142
142
  ## Remote access
143
143
 
@@ -188,7 +188,7 @@ flowchart LR
188
188
 
189
189
  You stay in charge: per paired relay you decide whether agents may only read, also prompt, or do everything, and in the `ask` and `plan` modes every write asks you first. A subscription only notifies; it approves nothing.
190
190
 
191
- <p><a href="https://oar.sh/assets/shots/pagewright-cross-relay.png?v=0.9.11"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pagewright-cross-relay.light.png?v=0.9.11"><img src="https://oar.sh/assets/shots/pagewright-cross-relay.png?v=0.9.11" alt="A session watching two sessions on a paired relay: a reply arrives as a relay-event row, and after a short outage the events the other relay kept arrive as one replayed row" width="720"></picture></a></p>
191
+ <p><a href="https://oar.sh/assets/shots/pagewright-cross-relay.png?v=0.9.13"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pagewright-cross-relay.light.png?v=0.9.13"><img src="https://oar.sh/assets/shots/pagewright-cross-relay.png?v=0.9.13" alt="A session watching two sessions on a paired relay: a reply arrives as a relay-event row, and after a short outage the events the other relay kept arrive as one replayed row" width="720"></picture></a></p>
192
192
 
193
193
  How pairing, permissions and limits work is in [Agents working together](docs/agents-together.md).
194
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oar-sh/oar",
3
- "version": "0.9.11",
3
+ "version": "0.9.13",
4
4
  "type": "module",
5
5
  "description": "OAR — Open Agent Relay: drive your local coding agents from any browser",
6
6
  "license": "MIT",