@oar-sh/oar 0.9.10 → 0.9.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.
- package/CHANGELOG.md +440 -1
- package/README.md +156 -972
- package/package.json +13 -13
- package/server/README.md +112 -25
- package/server/claude-worker/claude-remote-relay-tool.mjs +2 -0
- package/server/claude-worker/claude-sdk-adapter.mjs +57 -4
- package/server/claude-worker/claude-session-process.mjs +217 -11
- package/server/claude-worker/claude-session-worker.mjs +26 -1
- package/server/claude-worker/task-output-discovery.mjs +126 -0
- package/server/copilot-worker/copilot-sdk-session-process.mjs +235 -14
- package/server/copilot-worker/copilot-sdk-session-worker.mjs +8 -0
- package/server/copilot-worker/copilot-shell-output-mirror.mjs +94 -0
- package/server/copilot-worker/copilot-task-settle.mjs +96 -0
- package/server/db-schema.mjs +68 -2
- package/server/grok-worker/acp-client.mjs +2 -1
- package/server/grok-worker/acp-host-services.mjs +46 -6
- package/server/grok-worker/grok-background-tasks.mjs +241 -0
- package/server/grok-worker/grok-sdk-adapter.mjs +3 -1
- package/server/grok-worker/grok-session-worker.mjs +33 -1
- package/server/grok-worker/grok-turn-runner.mjs +11 -0
- package/server/migrations/0013-previews.mjs +130 -0
- package/server/migrations/0014-conversation-groups.mjs +89 -0
- package/server/migrations/0015-conversation-group-position.mjs +76 -0
- package/server/migrations/0016-share-access-log.mjs +110 -0
- package/server/migrations/0017-conversation-history-indexes.mjs +89 -0
- package/server/public/app/about-ui.js +73 -0
- package/server/public/app/about-view.mjs +234 -0
- package/server/public/app/action-confirmations.js +31 -14
- package/server/public/app/agent-exchange-fold-view.mjs +40 -101
- package/server/public/app/api-client.js +264 -16
- package/server/public/app/ask-user-view.js +17 -15
- package/server/public/app/background-tasks-view.mjs +285 -16
- package/server/public/app/bootstrap.js +253 -37
- package/server/public/app/chat-actions-menu-state.mjs +20 -10
- package/server/public/app/claude-background-command-limit-options.mjs +21 -0
- package/server/public/app/context-menu.mjs +90 -6
- package/server/public/app/conversation-group-drag.mjs +191 -0
- package/server/public/app/conversation-group-order.mjs +265 -0
- package/server/public/app/conversation-group-state.mjs +100 -0
- package/server/public/app/conversation-list-drag.mjs +449 -0
- package/server/public/app/conversation-payload-cache.mjs +357 -0
- package/server/public/app/conversation-turn-state.mjs +81 -0
- package/server/public/app/conversation-view.js +567 -94
- package/server/public/app/conversation-window-retention.mjs +96 -0
- package/server/public/app/cwd-picker.js +1 -1
- package/server/public/app/hidden-messages-view.mjs +312 -0
- package/server/public/app/host-suspend-ui.js +7 -1
- package/server/public/app/journal-view.js +1033 -82
- package/server/public/app/preview-cards.mjs +117 -31
- package/server/public/app/preview-command.mjs +10 -1
- package/server/public/app/relay-board-view.js +19 -6
- package/server/public/app/relay-prompt-sanitizer.mjs +11 -4
- package/server/public/app/relay-restart-error.mjs +16 -0
- package/server/public/app/settings-modal.js +150 -10
- package/server/public/app/settings-tabs.js +1 -1
- package/server/public/app/share-format.mjs +49 -0
- package/server/public/app/share-preview-marks.mjs +167 -0
- package/server/public/app/share-state.js +109 -0
- package/server/public/app/shared-conversations-settings.js +480 -0
- package/server/public/app/socket-handlers.js +138 -20
- package/server/public/app/store.js +121 -30
- package/server/public/app/subagent-row.mjs +3 -3
- package/server/public/app/subagent-viewer.mjs +37 -7
- package/server/public/app/task-console-render.mjs +237 -0
- package/server/public/app/task-console-watch.mjs +42 -0
- package/server/public/app/task-console.mjs +630 -0
- package/server/public/app/task-output-text.mjs +234 -0
- package/server/public/app/thinking-follow.js +0 -4
- package/server/public/app/transcript-island.mjs +73 -0
- package/server/public/app/transcript-jump-bottom-view.mjs +230 -26
- package/server/public/app/transcript-jump-bottom.mjs +170 -22
- package/server/public/app/transcript-reading-anchor.mjs +256 -0
- package/server/public/app/transcript-reload-freshness.mjs +17 -1
- package/server/public/app/transcript-viewport-anchor.mjs +159 -0
- package/server/public/index.html +625 -21
- package/server/relay-tools.md +3 -1
- package/server/relay.mjs +2 -1
- package/server/repositories/conversation-group-repository.mjs +444 -0
- package/server/repositories/message-repository.mjs +9 -0
- package/server/repositories/question-repository.mjs +4 -0
- package/server/repositories/session-repository.mjs +12 -37
- package/server/repositories/share-repository.mjs +322 -0
- package/server/repositories/share-visibility-statements.mjs +10 -0
- package/server/routes/about-routes.mjs +15 -0
- package/server/routes/cache-routes.mjs +4 -0
- package/server/routes/conversation-group-routes.mjs +171 -0
- package/server/routes/messages-routes.mjs +433 -68
- package/server/routes/preview-routes.mjs +9 -1
- package/server/routes/sessions-routes.mjs +901 -253
- package/server/server-runtime.mjs +392 -99
- package/server/services/about-service.mjs +461 -0
- package/server/services/background-task-store.mjs +365 -0
- package/server/services/background-work-view.mjs +228 -0
- package/server/services/cache-rebuild-service.mjs +30 -0
- package/server/services/cli-process-runner.mjs +4 -21
- package/server/services/conversation-history-page.mjs +199 -0
- package/server/services/delete-archive-service.mjs +4 -1
- package/server/services/detached-worker-watch-service.mjs +150 -0
- package/server/services/hidden-message-list.mjs +21 -0
- package/server/services/host-suspend-command.mjs +2 -1
- package/server/services/message-pin-list.mjs +1 -1
- package/server/services/preview-health-probe.mjs +8 -1
- package/server/services/preview-proxy-server.mjs +8 -4
- package/server/services/preview-registry-service.mjs +676 -26
- package/server/services/preview-static-handler.mjs +40 -7
- package/server/services/preview-store.mjs +274 -0
- package/server/services/rate-limit-service.mjs +12 -1
- package/server/services/relay-auth.mjs +183 -0
- package/server/services/relay-cli-launcher-service.mjs +3 -1
- package/server/services/relay-event-service.mjs +17 -0
- package/server/services/relay-prompt-sanitizer.mjs +11 -4
- package/server/services/remote-relay-dispatcher.mjs +187 -7
- package/server/services/request-boundary.mjs +183 -0
- package/server/services/session-activity-tracker.mjs +231 -19
- package/server/services/session-worker-launch-service.mjs +190 -6
- package/server/services/session-worker-process-service.mjs +10 -6
- package/server/services/share-access-log-service.mjs +123 -0
- package/server/services/share-path-redaction.mjs +424 -0
- package/server/services/status-event-service.mjs +7 -3
- package/server/services/task-output-rooms.mjs +259 -0
- package/server/services/task-output-service.mjs +562 -0
- package/server/services/tunnel-worker-path-guard.mjs +24 -41
- package/server/services/windows-autostart-service.mjs +6 -1
- package/server/services/windows-boot-autostart-service.mjs +207 -23
- package/shared/claude-background-command-limit.mjs +83 -0
- package/shared/preview-tool-core.mjs +15 -5
- package/shared/remote-relay-contract.mjs +35 -3
- package/shared/share-path-privacy.mjs +30 -0
- package/shared/task-output-text.mjs +737 -0
- package/shared/windows-system-tools.mjs +106 -0
- package/shared/worker-runtime/background-task-digest.mjs +30 -0
- package/shared/worker-runtime/heartbeat.mjs +24 -0
- package/shared/worker-runtime/kept-posts.mjs +83 -0
- package/shared/worker-runtime/task-output-spool.mjs +181 -0
- package/shared/worker-runtime/worker-websocket-link.mjs +47 -15
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,446 @@
|
|
|
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
|
-
## [
|
|
6
|
+
## [0.9.12] — 2026-10-18
|
|
7
|
+
|
|
8
|
+
Highlights: a background command or monitor in the task panel opens a
|
|
9
|
+
console with its output, live, in colour and with secrets blanked, paging
|
|
10
|
+
back through the whole log and with its own **Stop**. Task rows say when a
|
|
11
|
+
task has gone quiet ("no output for 12 min", amber after a time you set in
|
|
12
|
+
Settings) and show a **✓ 412 ✘ 2** chip when the output is a test run;
|
|
13
|
+
sub-agent rows count their steps, and agents read a task's output on a
|
|
14
|
+
paired relay with `remote_relay` `read_task_output`. Long conversations open
|
|
15
|
+
and page back fast, and switching away and back, or reloading, returns to
|
|
16
|
+
the message you were reading, older pages included; new messages wait below
|
|
17
|
+
a place far up the history instead of skipping the ones in between.
|
|
18
|
+
|
|
19
|
+
### Upgrade notes
|
|
20
|
+
|
|
21
|
+
- Migration 0017 (two indexes for the history of long conversations) runs by
|
|
22
|
+
itself on the first start. The Node.js requirement is unchanged (22.13 or
|
|
23
|
+
newer), and no setting or config key needs changing.
|
|
24
|
+
- Two new settings in **Settings › General**: **Mark a background task as
|
|
25
|
+
quiet after** (10 minutes by default, for the relay) and **Messages kept
|
|
26
|
+
per conversation for switching back** (200 by default, per browser).
|
|
27
|
+
- **Claude background commands may run for 2 hours** before Claude Code
|
|
28
|
+
stops them, and up to 8 hours when Claude asks; **Settings › Providers ›
|
|
29
|
+
Claude** sets the limit. OAR now sets `BASH_DEFAULT_TIMEOUT_MS`, `BASH_MAX_TIMEOUT_MS` and
|
|
30
|
+
`CLAUDE_CODE_AUTO_BACKGROUND_TIMEOUT_MS` for the Claude sessions it starts,
|
|
31
|
+
so values of these in the relay's environment no longer apply. Commands
|
|
32
|
+
that start with `sleep`, and sub-agents' commands, are not moved to the
|
|
33
|
+
background after 2 minutes and may block a turn up to the limit.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **Click a background command to watch its output.** A backgrounded shell
|
|
38
|
+
command or monitor in the composer's task panel opens a console: the last
|
|
39
|
+
2,000 lines, following live, with **Load earlier** paging back through the
|
|
40
|
+
whole log (about 5 MB at most). Progress-bar redraws collapse to their last
|
|
41
|
+
state, repeated lines fold into one with ×N, colours are kept and other
|
|
42
|
+
control codes dropped, secrets are blanked, and the console has its own
|
|
43
|
+
**Stop**. A finished command keeps a dimmed ✓/✘ row for an hour so a failed
|
|
44
|
+
run can still be read. Claude reads the file its CLI writes for the command,
|
|
45
|
+
Copilot a detached shell's log or an attached shell's recent output, and
|
|
46
|
+
Grok now lists its terminals as tasks. A session started before this
|
|
47
|
+
release names no output file; its console says so and that a restart of
|
|
48
|
+
the session helps.
|
|
49
|
+
- **Task rows say when a task has gone quiet** ("no output for 12 min", amber
|
|
50
|
+
after **Settings › General › Mark a background task as quiet after**, 10
|
|
51
|
+
minutes by default) and show a **✓ 412 ✘ 2** chip when the output is a
|
|
52
|
+
vitest, Playwright, node:test, jest, pytest or turbo run (also through
|
|
53
|
+
pnpm); the console header's chip jumps to the first failure, and a run
|
|
54
|
+
that ends shows its final counts within a moment.
|
|
55
|
+
- **Sub-agent rows in the task panel show their step count** ("22 steps"), as
|
|
56
|
+
the rows in the reply already did.
|
|
57
|
+
- **Settings › Providers › Claude › Claude background command limit** (30
|
|
58
|
+
minutes to 8 hours, 2 hours by default) sets how long a command Claude runs
|
|
59
|
+
in the background may take before Claude Code stops it, when Claude gives it
|
|
60
|
+
no timeout of its own; Claude may still ask for up to 8 hours for one
|
|
61
|
+
command. A foreground command moves to the background after 2 minutes, so
|
|
62
|
+
the turn goes on while it runs. Claude is also told to write the output of
|
|
63
|
+
long runs to a log file instead of piping it into `tail`, and to start runs
|
|
64
|
+
that must survive a session restart with `nohup`. A change applies to Claude
|
|
65
|
+
sessions started afterwards; Claude Cloud is not affected.
|
|
66
|
+
- **`remote_relay` action `read_task_output`** gives agents the same tail,
|
|
67
|
+
quiet time and counts of a task on a relay they may read; `read_session`
|
|
68
|
+
lists the task ids with that health.
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
|
|
72
|
+
- **Long conversations open and scroll back fast.** A history page used to
|
|
73
|
+
load and prepare every message of the conversation, so a chat with a few
|
|
74
|
+
thousand messages took about two seconds per page and per live refresh. The
|
|
75
|
+
relay now reads only the requested page from the database (migration 0017
|
|
76
|
+
adds the indexes for it), so a page loads in well under a tenth of a second
|
|
77
|
+
however long the conversation is.
|
|
78
|
+
- Switching back to a conversation already viewed in this tab draws it at
|
|
79
|
+
once from what the page kept of it; the relay's fresh answer is merged into
|
|
80
|
+
it when it arrives.
|
|
81
|
+
- **Settings › General › Messages kept per conversation for switching back**
|
|
82
|
+
(200 by default, 100 to 1,000 or no limit, saved in this browser) sets how
|
|
83
|
+
many loaded messages each of the last eight conversations keeps.
|
|
84
|
+
- **The conversation list shows activity by the title's colour.** The three
|
|
85
|
+
animated dots after a working session's title are gone: a ready session
|
|
86
|
+
that runs a turn or background work keeps the bright green title, an idle
|
|
87
|
+
one turns a darker green (a muted green in the light theme), and the chat
|
|
88
|
+
header follows the same rule. Question, error, offline and archived titles
|
|
89
|
+
keep their colours.
|
|
90
|
+
- The npm package guard allows 7.5 MiB unpacked and 510 entries (was 7.25
|
|
91
|
+
MiB and 490); the task console, the transcript's handling of new
|
|
92
|
+
messages below a place far up the history, the Copilot task report and the
|
|
93
|
+
Claude background command limit grew the server and the app to about 7.37
|
|
94
|
+
MiB and 505 entries.
|
|
95
|
+
|
|
96
|
+
### Fixed
|
|
97
|
+
|
|
98
|
+
- **Copilot background tasks report how they ended.** Finished shells and
|
|
99
|
+
sub-agents of Copilot's SDK engine showed the status *unknown* and no exit
|
|
100
|
+
code, in the task data agents read and wherever the end is shown. The
|
|
101
|
+
worker now reports completed, failed or cancelled, a shell's exit code, and
|
|
102
|
+
a sub-agent's result (or its error) as its summary; a passing status line
|
|
103
|
+
such as *Thinking…* is no longer kept as the final summary.
|
|
104
|
+
- **Cancel on a usage-limit pause removes the relay's held follow-up from the
|
|
105
|
+
open conversation at once.** The *Automatic message from OAR* row was
|
|
106
|
+
deleted on the relay but stayed on the page, and in what the page kept for
|
|
107
|
+
switching back, until a reload. A row deleted while you were elsewhere
|
|
108
|
+
leaves too, also when it was the conversation's newest.
|
|
109
|
+
|
|
110
|
+
- **Switching away from a long conversation and back keeps your place.** After
|
|
111
|
+
loading older messages and scrolling back into them, a switch to another
|
|
112
|
+
conversation and back lost the reading position: with more than 100 messages
|
|
113
|
+
loaded the oldest were dropped, and messages written meanwhile moved the view
|
|
114
|
+
by as many rows. The page now remembers the message you were reading and
|
|
115
|
+
keeps the loaded messages, so you come back to the same message at the same
|
|
116
|
+
place, older pages included; after a reload it opens at that message too.
|
|
117
|
+
- **New messages no longer skip the ones in between while you read far up.**
|
|
118
|
+
Opened at a pin, a search result or the place you were reading after a
|
|
119
|
+
reload, a conversation shows the messages around it. A message or reply that
|
|
120
|
+
arrived then was put right under them, and the messages between were never
|
|
121
|
+
loaded when you scrolled down, only the jump-to-bottom button brought them.
|
|
122
|
+
Now new messages wait: the button counts them, and scrolling down loads
|
|
123
|
+
every message in between, in order, before them. A reply still being
|
|
124
|
+
written shows once you are there. A message you send from there takes you
|
|
125
|
+
to the end, where it, its reply and everything in between show.
|
|
126
|
+
- **Images that load late no longer push the message you are reading down.**
|
|
127
|
+
In a browser without scroll anchoring (Safari, for one), pictures above
|
|
128
|
+
your place that arrived after a switch back, a reload or an older page moved
|
|
129
|
+
the text by their height. The transcript now holds your place while they
|
|
130
|
+
load, and lets go as soon as you scroll.
|
|
131
|
+
|
|
132
|
+
## [0.9.11] — 2026-10-17
|
|
133
|
+
|
|
134
|
+
Highlights: sessions an agent starts now sit in a group under the session
|
|
135
|
+
that started it, with a pill that sums up what runs and what waits for you,
|
|
136
|
+
and rows drag into, out of and within a group. Settings › Sharing lists every
|
|
137
|
+
shared link with Copy, Renew and Stop and an access log of each open (the IP
|
|
138
|
+
address optional), shared views hide the host's paths in one of three modes,
|
|
139
|
+
**Preview as shared** shows what a viewer gets, and a 🙈 list gathers the
|
|
140
|
+
messages hidden from viewers. The relay is harder to reach from outside: ten
|
|
141
|
+
wrong tokens lock an address out for a minute, the live channel accepts only
|
|
142
|
+
the relay's own origin, forwarded headers count only from a trusted proxy, and
|
|
143
|
+
`?token=` signs in the page only. Day/Night is back in the ⋯ menu, next to the
|
|
144
|
+
new **About OAR**.
|
|
145
|
+
|
|
146
|
+
### Upgrade notes
|
|
147
|
+
|
|
148
|
+
- **Behind a reverse proxy on another host or origin, set `trustProxy` and
|
|
149
|
+
`allowedOrigins`.** This is the first release that checks the origin of the
|
|
150
|
+
live Socket.IO channel and that reads the client address, host and scheme
|
|
151
|
+
from `X-Forwarded-*` headers only when the proxy is trusted. A proxy on the
|
|
152
|
+
relay host itself is trusted already (`trustProxy` defaults to
|
|
153
|
+
`"loopback"`). For one on another machine, or one that rewrites the `Host`
|
|
154
|
+
header, add to the config file (`~/.oar/config.json`, or `server/config.json`
|
|
155
|
+
in a git checkout) and restart the relay:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
"trustProxy": "192.0.2.10",
|
|
159
|
+
"allowedOrigins": ["https://relay.example.com"]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`trustProxy` takes what Express's `trust proxy` takes: the proxy's address,
|
|
163
|
+
a subnet such as `"10.0.0.0/8"`, or a hop count such as `1`.
|
|
164
|
+
`allowedOrigins` lists the public origins exactly as the browser shows them
|
|
165
|
+
(scheme, host, a port other than the default). Without them, the page loads
|
|
166
|
+
but its live connection is refused (the relay logs `Refused a handshake from
|
|
167
|
+
origin …`), and every client shares the proxy's address, so one client's
|
|
168
|
+
ten wrong tokens lock the rest out for a minute.
|
|
169
|
+
- **Ten wrong tokens from one address within a minute answer `429`** with
|
|
170
|
+
`Retry-After` until the minute is over. Requests from the relay host itself
|
|
171
|
+
that no proxy forwarded are never counted.
|
|
172
|
+
- **`?token=` works on the page address only.** Scripts that fetch API, file
|
|
173
|
+
or asset URLs with `?token=` must send `Authorization: Bearer <token>`
|
|
174
|
+
instead (or the cookie); a Socket.IO client passes it as `auth.token` (or
|
|
175
|
+
the cookie), not in the query.
|
|
176
|
+
- **Restart web relay, cancelling a queued restart and Empty queue need only
|
|
177
|
+
the token**, from any signed-in device. The session-worker socket and the
|
|
178
|
+
image-operation run answer only requests from the relay host that no tunnel
|
|
179
|
+
or proxy forwarded.
|
|
180
|
+
- Four database migrations (0013 previews, 0014 session groups, 0015 the place
|
|
181
|
+
in a group, 0016 the share access log) run by themselves on the first
|
|
182
|
+
start. The Node.js requirement is unchanged (22.13 or newer).
|
|
183
|
+
|
|
184
|
+
### Added
|
|
185
|
+
|
|
186
|
+
- **Session groups in the sidebar.** A session that an agent starts with the
|
|
187
|
+
`remote_relay` tool now sits under the session that started it. The head
|
|
188
|
+
row carries a fold button and a pill that sums up the members ("3 · 1 waiting
|
|
189
|
+
for you, 2 running"); the members are indented under it, folded away once
|
|
190
|
+
everything in the group has finished unless you fold or unfold it yourself.
|
|
191
|
+
A question or approval waiting in a folded member shows on the head row,
|
|
192
|
+
and a tap on it opens that member. A member's activity lifts the whole
|
|
193
|
+
group to the top of the list. The head row's menu archives the whole group
|
|
194
|
+
(members still working are kept and named) and stops everything running in
|
|
195
|
+
it, and dissolves it; any row's menu adds a conversation to a group,
|
|
196
|
+
moves it, or takes it out, and groups can be named by hand. The `remote_relay` tool's
|
|
197
|
+
`list_sessions` and `read_session` show the group a session is in (agents
|
|
198
|
+
only read it). Migration 0014 adds the `conversation_groups` table and the
|
|
199
|
+
`group_id` column; nothing is backfilled.
|
|
200
|
+
- **Drag and drop for session groups.** Drag a session into a group, out of
|
|
201
|
+
it, or to another place inside it; the order you set stays, and later
|
|
202
|
+
arrivals join at the end. Drop one loose session onto the middle of another
|
|
203
|
+
and the two make a new group. On a phone a long press lifts the row and a
|
|
204
|
+
move drags it; with the keyboard, a member's menu has "Move up" and "Move
|
|
205
|
+
down". Migration 0015 adds the `group_position` column. Rolling back needs
|
|
206
|
+
no data change: older releases ignore the column, and a stale place they
|
|
207
|
+
leave behind is cleared when this release starts again.
|
|
208
|
+
- **A 🙈 list of the messages hidden from shared viewers.** Next to 📍, a 🙈
|
|
209
|
+
button with a count appears while the open conversation hides messages
|
|
210
|
+
from its shared link (never in the shared view itself). It opens a list
|
|
211
|
+
like the pinned one: each row jumps to its message, also one far up in the
|
|
212
|
+
history, and has Unhide; "Unhide all" asks first and leaves only a message
|
|
213
|
+
whose turn is still running hidden, naming it. The count and the list cover
|
|
214
|
+
messages outside the loaded page, and other open tabs and devices follow a
|
|
215
|
+
change without a reload.
|
|
216
|
+
- **Manage your shared links in Settings › Sharing.** Every shared
|
|
217
|
+
conversation is listed with when it was shared and last opened, how often
|
|
218
|
+
and by how many viewers. **Copy link** copies it, **Renew link** gives the
|
|
219
|
+
conversation a new link (the old one stops working at once), and **Stop
|
|
220
|
+
sharing** ends it; the `⋯` menu has **Stop sharing** too while the open
|
|
221
|
+
conversation is shared, and asks first. Each row unfolds into an access
|
|
222
|
+
log: one entry per open of the page (not per refresh) with time, IP
|
|
223
|
+
address, country and browser. The log carries over to a renewed link and
|
|
224
|
+
is deleted when you stop sharing or delete the conversation. Switch off
|
|
225
|
+
**Store viewer IP addresses** to log new opens without the address (the
|
|
226
|
+
status log of shared reads follows it); switching it off also offers to
|
|
227
|
+
remove the addresses already stored, from both logs. Distinct viewers are
|
|
228
|
+
still told apart. Migration 0016 adds the share lineage and the
|
|
229
|
+
`conversation_share_opens` table.
|
|
230
|
+
- **Preview as shared.** The `⋯` menu's new entry opens the conversation as
|
|
231
|
+
a share link shows it, without creating one: what viewers get instead of a
|
|
232
|
+
path is marked green, whatever still looks like a path amber.
|
|
233
|
+
- **Sub-agent records in shared views.** A sub-agent's row in a shared
|
|
234
|
+
conversation now opens its record, read-only and without Stop, filtered
|
|
235
|
+
like the rest of the share.
|
|
236
|
+
|
|
237
|
+
- **Wrong tokens lock an address out for a minute.** Ten wrong tokens from
|
|
238
|
+
one address within a minute (a Bearer header, the cookie, the sign-in field
|
|
239
|
+
or a Socket.IO handshake) make the relay answer that address `429` with
|
|
240
|
+
`Retry-After` until the minute is over, the right token included, and the
|
|
241
|
+
sign-in page says how long to wait. The same stale value repeated counts
|
|
242
|
+
once, so a tab with an old cookie does not lock you out. Requests from the
|
|
243
|
+
relay host itself that no proxy forwarded are never locked out, so the
|
|
244
|
+
relay's own workers and agent tools keep working.
|
|
245
|
+
- **About OAR in the ⋯ menu.** A new entry, "ℹ️ About OAR · <version>",
|
|
246
|
+
opens what this relay is and has done: version, commit (for a git
|
|
247
|
+
checkout) and when the relay started; each provider that is on, with its
|
|
248
|
+
CLI and SDK version and whether it is online; conversations, turns and
|
|
249
|
+
messages since the first conversation, turns per provider, and the usage
|
|
250
|
+
the providers report (Copilot premium requests, Cursor and Grok tokens and
|
|
251
|
+
cost, Claude Cloud cost); uptime, database size and running workers. With
|
|
252
|
+
the opt-in update check on it names the latest version, otherwise it says
|
|
253
|
+
where to turn the check on. Shared viewers do not get the entry. The data
|
|
254
|
+
comes from the new `GET /api/about`, which counts large databases in small
|
|
255
|
+
steps and keeps the totals for a minute.
|
|
256
|
+
|
|
257
|
+
### Changed
|
|
258
|
+
|
|
259
|
+
- **A stopped or renewed share link answers a plain 404**, the page included,
|
|
260
|
+
exactly like a link that never existed, and a shared page that is still open
|
|
261
|
+
stops at its next refresh instead of polling on. The address in the access
|
|
262
|
+
log and in the status log of shared reads is now the one the relay trusts
|
|
263
|
+
through its `trustProxy` setting; a forwarded header from an untrusted peer
|
|
264
|
+
no longer sets it.
|
|
265
|
+
|
|
266
|
+
- **A share link no longer carries the relay host's paths.** The relay
|
|
267
|
+
filters what it serves to shared viewers, by **Paths and file names** in
|
|
268
|
+
Settings › Sharing: show every path, hide the path and keep the file name
|
|
269
|
+
(the default), or hide both. Tool lines, thoughts, replies, attachments and sub-agent records all
|
|
270
|
+
pass through it; before, only the viewer's browser shortened the paths in
|
|
271
|
+
tool lines, and attachments carried their full path on the host. Free text
|
|
272
|
+
is filtered on a best-effort basis: relative paths are left as they are.
|
|
273
|
+
|
|
274
|
+
- **A long press on a sidebar row opens its menu when the finger lifts**, no
|
|
275
|
+
longer while it is still down: a long press that then moves drags the row
|
|
276
|
+
instead. Where rows cannot move (the Archived view, under a filter, on a
|
|
277
|
+
group's own line) the menu still opens during the press.
|
|
278
|
+
|
|
279
|
+
- **A reply to another agent's note is no longer folded away.** Only the
|
|
280
|
+
note itself folds into its row now, "note from linux-test · report builder ·
|
|
281
|
+
answered below"; the session's reply to it always shows, like a reply to
|
|
282
|
+
you, because it may hold a line for you. A turn you steered a message into
|
|
283
|
+
folds its note too, since nothing of yours is behind the row any more. The
|
|
284
|
+
⌄ button's badge counts the note and the reply as two rows.
|
|
285
|
+
|
|
286
|
+
- **A conversation no longer scrolls down by itself while you read further
|
|
287
|
+
up.** It only moves when you are at its end, or when you have just sent a
|
|
288
|
+
message yourself. Anywhere else it stays exactly where it is, whatever
|
|
289
|
+
lands: a reply, a relay event, another agent's note, a question, an approval
|
|
290
|
+
or a plan board. The ⌄ button then tells you: it turns blue with a count
|
|
291
|
+
(or a dot while a reply is still being written) when something new is
|
|
292
|
+
below, and amber with a "?" when a question or an approval waits for your
|
|
293
|
+
answer; a screen reader hears both. The text you are reading also keeps its
|
|
294
|
+
place when the reply you are in the middle of is finished and when the
|
|
295
|
+
conversation reloads. New in Settings › General: "Jump to the end when I
|
|
296
|
+
send a message", on by default and saved in the browser; switch it off and
|
|
297
|
+
your own messages leave you where you are as well.
|
|
298
|
+
|
|
299
|
+
- The npm package guard allows 7.25 MiB unpacked and 490 entries (was 6.75
|
|
300
|
+
MiB and 450); session groups, the stored previews, the background-task
|
|
301
|
+
resync, the transcript anchor, share management, path privacy in shared
|
|
302
|
+
views and About OAR grew the server and the app to about 7.05 MiB and 485
|
|
303
|
+
entries.
|
|
304
|
+
|
|
305
|
+
- **Restart web relay, cancelling a queued restart and Empty queue work from
|
|
306
|
+
every signed-in device.** They were meant for the relay host only, but the
|
|
307
|
+
check let everything through a tunnel or a proxy on the same machine and
|
|
308
|
+
refused only a direct LAN connection; they now need the token and nothing
|
|
309
|
+
else. The other way round, the session-worker socket and the image-operation
|
|
310
|
+
run now answer only requests from the relay host itself: a loopback peer
|
|
311
|
+
with no `cf-ray` or other tunnel marker and no `X-Forwarded-For`,
|
|
312
|
+
`Forwarded` or `X-Real-IP`. A same-host proxy that adds no marker no longer
|
|
313
|
+
reaches them.
|
|
314
|
+
|
|
315
|
+
- **A `?token=` signs in the page only.** The page takes it out of the address
|
|
316
|
+
and signs in with it as before; API, file and asset URLs now accept the
|
|
317
|
+
token in the `Authorization` header or the cookie only, and a Socket.IO
|
|
318
|
+
handshake no longer reads a `token` query.
|
|
319
|
+
|
|
320
|
+
- **The live Socket.IO channel accepts the relay's own origin only** (it
|
|
321
|
+
accepted any). The host compared is the one the browser addressed,
|
|
322
|
+
`X-Forwarded-Host` included when a trusted proxy sends it; for a proxy that
|
|
323
|
+
rewrites the `Host` header, list the public origin in the new
|
|
324
|
+
`allowedOrigins` setting.
|
|
325
|
+
|
|
326
|
+
### Fixed
|
|
327
|
+
|
|
328
|
+
- **Day/Night is back in the ⋯ menu.** Since 0.9.10 the entry showed only in
|
|
329
|
+
a shared view; everywhere else, on every screen size, it was gone from the
|
|
330
|
+
menu. It is there again whenever you are signed in, with or without a
|
|
331
|
+
conversation open, and stays the one entry of a shared view.
|
|
332
|
+
|
|
333
|
+
- **A shared conversation no longer marks every reply "ran on" its own
|
|
334
|
+
provider.** In a shared link to a Claude, Cursor, Grok or OpenAI
|
|
335
|
+
conversation, each reply carried the red `ran on claude` (etc.) chip, as if
|
|
336
|
+
the turn had run on the wrong provider. The shared view now knows which
|
|
337
|
+
provider the conversation is bound to, and shows the chip only when a reply
|
|
338
|
+
really ran on another one; with no provider bound it shows none.
|
|
339
|
+
|
|
340
|
+
- **A wide table in the file reader scrolls sideways.** A markdown table wider
|
|
341
|
+
than the reader made the whole page scroll sideways, and a sideways swipe to
|
|
342
|
+
read the rest of it turned to the next file instead. The table now scrolls
|
|
343
|
+
in its own box, as code blocks do; a swipe that starts on it stays in the
|
|
344
|
+
file.
|
|
345
|
+
|
|
346
|
+
- **A worker no longer stops reconnecting after a relay restart.** On Node
|
|
347
|
+
22, a worker whose reconnect reached a relay that was not ready yet gave up
|
|
348
|
+
for good: its process kept running without a connection, the relay started
|
|
349
|
+
no new one while that process lived, and every message to the session
|
|
350
|
+
stayed queued until the worker was killed and launched by hand. A failed
|
|
351
|
+
connect now always leads to the next attempt, with the usual backoff of up
|
|
352
|
+
to 8 seconds. As a safety net, the relay replaces a worker that has had no
|
|
353
|
+
connection for 60 seconds while a message waits for it: it stops the old
|
|
354
|
+
process and starts a new one, which then takes the message. It never does
|
|
355
|
+
so while a turn or background work of that session is running, and logs a
|
|
356
|
+
`WORKER DETACHED` line when it does.
|
|
357
|
+
|
|
358
|
+
- **A relay restart no longer forgets running background tasks.** A session
|
|
359
|
+
with a background shell or sub-agent still running read as idle after the
|
|
360
|
+
relay restarted: its task panel was empty, **Suspend host** saw nothing
|
|
361
|
+
to wait for, and a watching session could be told `all_idle`. The relay
|
|
362
|
+
now asks each worker for its tasks again on the worker's next heartbeat,
|
|
363
|
+
and the tasks come back with their original start time. A session whose
|
|
364
|
+
worker was started before this update shows "background work, details not
|
|
365
|
+
reported since the relay restarted" until it reports. For the first 45
|
|
366
|
+
seconds after a relay start a suspend waits for sessions that are still
|
|
367
|
+
reporting, and a task that ended while the relay was away still reports
|
|
368
|
+
its end.
|
|
369
|
+
|
|
370
|
+
- **Workers start when no `node` is on the relay's PATH.** A relay started
|
|
371
|
+
by the Windows system-startup task, before anyone signed in, ran fine, but
|
|
372
|
+
none of its workers ever started: they were launched with a bare `node`
|
|
373
|
+
that the task's PATH did not have, Windows reported the failure in a
|
|
374
|
+
dialog no one could see, and the log showed only a heartbeat timeout
|
|
375
|
+
every 90 seconds. Workers now run on the relay's own Node by its full path
|
|
376
|
+
on every platform, tmux included; `COPILOT_WEB_RELAY_NODE` still overrides
|
|
377
|
+
it. That Node's folder is added at the end of a worker's PATH when the PATH
|
|
378
|
+
lacks it, so the CLIs and commands a worker starts find a `node` too; a
|
|
379
|
+
PATH that has one keeps it.
|
|
380
|
+
|
|
381
|
+
- **A worker that cannot be started says why.** On Windows, a launch whose
|
|
382
|
+
`start` command fails or never returns now fails at once, naming the
|
|
383
|
+
program, and the conversation's launch note shows it; before, the relay
|
|
384
|
+
waited for a heartbeat that never came. The relay log names the command
|
|
385
|
+
and the PATH, SystemRoot and ComSpec it was started with, also when a
|
|
386
|
+
launch saw no worker process yet, and a failed process-list read logs its
|
|
387
|
+
exit code and error output. Windows' own programs (PowerShell, schtasks,
|
|
388
|
+
taskkill and others) are called by their full path. Changing the launch
|
|
389
|
+
folder and the Windows autostart setting show the relay's reason when they
|
|
390
|
+
fail, not a bare "Failed to …", and an autostart read that fails is logged.
|
|
391
|
+
|
|
392
|
+
- **The Windows system-startup launcher copes with an early boot.** The
|
|
393
|
+
launcher OAR generates adds Node's folder at the end of PATH and waits up
|
|
394
|
+
to two minutes for the `%TEMP%` folder to exist before it starts the relay
|
|
395
|
+
(a temp folder on a drive that a startup script creates later no longer
|
|
396
|
+
makes the relay and its CLIs fail); a wait that runs out is logged next to
|
|
397
|
+
the launcher. Settings now names how a boot task or launcher differs from
|
|
398
|
+
the generated one (a missing boot delay, an edited launcher) instead of
|
|
399
|
+
treating it as a failure; selecting "At system startup" again regenerates
|
|
400
|
+
both and keeps a changed launcher as a `.bak` copy. A boot task that cannot
|
|
401
|
+
be read no longer breaks the setting.
|
|
402
|
+
|
|
403
|
+
- **Preview links survive a relay restart.** A preview lived only in the
|
|
404
|
+
relay's memory, so an update, a queued restart or a crash turned every
|
|
405
|
+
preview link into a 404, and publishing again gave a new link. Previews are
|
|
406
|
+
now kept in the relay's database and restored when it starts, each checked
|
|
407
|
+
again: a folder preview while its folder is still inside the workspace root,
|
|
408
|
+
a dev-server preview until the machine reboots (on Windows with fast
|
|
409
|
+
startup, until a Restart: Shut down and power-on is not seen as one).
|
|
410
|
+
Publishing the same port or folder again in a conversation returns the same
|
|
411
|
+
link. Deleting a conversation, also through a cache rebuild, closes its
|
|
412
|
+
previews; archiving keeps them. Settings → Previews shows when each preview
|
|
413
|
+
was published and last opened, and the limit of 8 names the oldest ones and
|
|
414
|
+
how to close them. Relay logs no longer carry a preview's token; a publicly
|
|
415
|
+
shared transcript shows a preview card with its label only and removes every
|
|
416
|
+
preview link quoted in its text, also one cut short by a reply still being
|
|
417
|
+
written. A preview the relay cannot check at a start (a busy database, an
|
|
418
|
+
unreadable folder) is not served, shows as such in Settings, and is checked
|
|
419
|
+
again every 15 s for ten minutes. The table comes with migration 0013, which
|
|
420
|
+
runs by itself on the first start; the npm package gains two modules for it.
|
|
421
|
+
|
|
422
|
+
- **An install gets the dependency versions the release was tested with.**
|
|
423
|
+
The package asked for each of its dependencies "this version or newer", so
|
|
424
|
+
an install or update fetched whatever was newest that day, e.g. a newer
|
|
425
|
+
Copilot SDK than any release was tested with. The packages OAR depends on
|
|
426
|
+
directly (the Claude, Copilot and Cursor SDKs among them) are now pinned to
|
|
427
|
+
exact versions; a newer one arrives with an OAR update. Packages those
|
|
428
|
+
depend on still follow their own version ranges.
|
|
429
|
+
|
|
430
|
+
- **Restart web relay no longer reports success when the relay refuses it.**
|
|
431
|
+
A refused request said "Relay restart requested"; it now shows the relay's
|
|
432
|
+
reason, and a request that got no answer says so instead of claiming
|
|
433
|
+
success. The restart after a feature-flag change and cancelling a queued
|
|
434
|
+
restart report their errors the same way, and Empty queue names the reason
|
|
435
|
+
it failed.
|
|
436
|
+
|
|
437
|
+
- **Forwarded headers count only from a trusted proxy everywhere.** The
|
|
438
|
+
shared-view presence limit read `X-Forwarded-For` and `X-Real-IP` and the
|
|
439
|
+
share links read `X-Forwarded-Host` and `X-Forwarded-Proto` straight from the
|
|
440
|
+
request, so a direct client could pick its own rate-limit bucket or the
|
|
441
|
+
host of a new share link. Both now follow the `trustProxy` setting.
|
|
442
|
+
|
|
443
|
+
- **`tunnelMarkerHeaders: []` in the config no longer switches off
|
|
444
|
+
`COPILOT_TUNNEL_MARKER_HEADERS`.** The two lists are merged, with `cf-ray`
|
|
445
|
+
always included.
|
|
7
446
|
|
|
8
447
|
## [0.9.10] — 2026-10-12
|
|
9
448
|
|