@oar-sh/oar 0.9.9 → 0.9.11
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 +561 -1
- package/README.md +162 -909
- package/bin/bat/oar.bat +46 -46
- package/package.json +14 -14
- package/server/README.md +369 -13
- package/server/claude-worker/claude-remote-relay-tool.mjs +10 -0
- package/server/claude-worker/claude-session-process.mjs +121 -9
- package/server/claude-worker/claude-session-worker.mjs +9 -1
- package/server/claude-worker/claude-turn-publisher.mjs +3 -0
- package/server/claude-worker/sdk-message-normalizer.mjs +31 -4
- package/server/claude-worker/subagent-timeline-recorder.mjs +572 -0
- package/server/copilot-worker/copilot-sdk-session-process.mjs +79 -12
- package/server/copilot-worker/copilot-sdk-session-worker.mjs +6 -0
- package/server/cursor-worker/cursor-sdk-adapter.mjs +56 -2
- package/server/db-schema.mjs +95 -2
- package/server/grok-worker/acp-client.mjs +2 -1
- package/server/grok-worker/acp-host-services.mjs +4 -3
- package/server/migrations/0009-subagent-timeline.mjs +135 -0
- package/server/migrations/0010-subagent-timeline-pruning.mjs +89 -0
- package/server/migrations/0011-relay-event-subscriptions.mjs +125 -0
- package/server/migrations/0012-cross-relay-event-subscriptions.mjs +116 -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/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 +187 -0
- package/server/public/app/api-client.js +312 -16
- package/server/public/app/archive-confirm.mjs +28 -0
- package/server/public/app/ask-user-view.js +17 -12
- package/server/public/app/attachments-view.js +516 -6
- package/server/public/app/background-tasks-view.mjs +18 -26
- package/server/public/app/bootstrap.js +336 -59
- package/server/public/app/chat-actions-menu-state.mjs +126 -0
- package/server/public/app/claude-cloud-conversation-ui.js +10 -22
- package/server/public/app/composer-control-state.mjs +16 -0
- package/server/public/app/composer-keyboard.mjs +54 -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-turn-state.mjs +81 -0
- package/server/public/app/conversation-view.js +436 -117
- package/server/public/app/cwd-picker.js +1 -1
- package/server/public/app/explorer-edit-state.mjs +68 -0
- package/server/public/app/hidden-messages-view.mjs +312 -0
- package/server/public/app/host-suspend-ui.js +13 -4
- package/server/public/app/journal-view.js +930 -45
- package/server/public/app/no-conversation-state.mjs +58 -0
- package/server/public/app/preview-cards.mjs +117 -31
- package/server/public/app/preview-command.mjs +10 -1
- package/server/public/app/provider-readiness.mjs +120 -0
- package/server/public/app/relay-board-view.js +19 -3
- package/server/public/app/relay-event-subscriptions-ui.js +184 -0
- package/server/public/app/relay-event-view.mjs +234 -0
- package/server/public/app/relay-restart-error.mjs +16 -0
- package/server/public/app/settings-modal.js +93 -9
- 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 +137 -40
- package/server/public/app/store.js +115 -32
- package/server/public/app/subagent-row.mjs +138 -0
- package/server/public/app/subagent-timeline-view.mjs +186 -0
- package/server/public/app/subagent-viewer-watch.mjs +50 -0
- package/server/public/app/subagent-viewer.mjs +558 -0
- package/server/public/app/task-row-format.mjs +29 -0
- package/server/public/app/transcript-jump-bottom-view.mjs +464 -0
- package/server/public/app/transcript-jump-bottom.mjs +210 -0
- package/server/public/app/transcript-reload-freshness.mjs +25 -0
- package/server/public/app/transcript-viewport-anchor.mjs +140 -0
- package/server/public/app/update-ui.js +1 -1
- package/server/public/app/viewer-history.mjs +5 -3
- package/server/public/index.html +774 -12
- package/server/relay-tools.md +2 -1
- package/server/relay.mjs +2 -1
- package/server/repositories/conversation-group-repository.mjs +444 -0
- package/server/repositories/message-repository.mjs +30 -3
- package/server/repositories/question-repository.mjs +9 -3
- package/server/repositories/remote-relay-repository.mjs +6 -2
- 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/repositories/subagent-timeline-statements.mjs +170 -0
- package/server/routes/about-routes.mjs +15 -0
- package/server/routes/ask-user-routes.mjs +3 -0
- package/server/routes/cache-routes.mjs +4 -0
- package/server/routes/conversation-group-routes.mjs +171 -0
- package/server/routes/messages-routes.mjs +698 -114
- package/server/routes/preview-routes.mjs +9 -1
- package/server/routes/relay-event-routes.mjs +157 -0
- package/server/routes/remote-relay-routes.mjs +15 -0
- package/server/routes/sessions-routes.mjs +843 -193
- package/server/server-runtime.mjs +559 -160
- package/server/services/about-service.mjs +461 -0
- package/server/services/background-task-store.mjs +128 -0
- package/server/services/background-work-view.mjs +228 -0
- package/server/services/cache-rebuild-service.mjs +30 -0
- package/server/services/delete-archive-service.mjs +4 -1
- package/server/services/detached-worker-watch-service.mjs +150 -0
- package/server/services/explorer-entry-name.mjs +26 -0
- package/server/services/explorer-mutations.mjs +122 -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 +49 -27
- 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/push-dispatch-service.mjs +18 -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-link-service.mjs +289 -0
- package/server/services/relay-event-service.mjs +1952 -0
- package/server/services/relay-shutdown-gate.mjs +31 -0
- package/server/services/remote-relay-caller-context.mjs +52 -7
- package/server/services/remote-relay-dispatcher.mjs +551 -7
- package/server/services/remote-relay-registry-service.mjs +11 -1
- package/server/services/request-boundary.mjs +183 -0
- package/server/services/session-activity-tracker.mjs +695 -0
- package/server/services/session-history-refresh-service.mjs +7 -0
- 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/stale-attempt-log-limiter.mjs +96 -0
- package/server/services/stale-recovery-clock-guard.mjs +57 -0
- package/server/services/stale-subagent-run-sweep.mjs +109 -0
- package/server/services/status-event-service.mjs +7 -3
- package/server/services/subagent-record-retention.mjs +164 -0
- package/server/services/subagent-timeline-service.mjs +328 -0
- package/server/services/subagent-viewer-rooms.mjs +119 -0
- package/server/services/tunnel-worker-path-guard.mjs +24 -41
- package/server/services/upgrade-socket-guard.mjs +16 -0
- package/server/services/windows-autostart-service.mjs +6 -1
- package/server/services/windows-boot-autostart-service.mjs +207 -23
- package/shared/preview-tool-core.mjs +15 -5
- package/shared/relay-events.mjs +371 -0
- package/shared/remote-relay-contract.mjs +160 -6
- package/shared/share-path-privacy.mjs +30 -0
- package/shared/subagent-record-retention.mjs +31 -0
- package/shared/subagent-timeline.mjs +79 -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/worker-websocket-link.mjs +47 -15
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,567 @@
|
|
|
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.11] — 2026-10-17
|
|
7
|
+
|
|
8
|
+
Highlights: sessions an agent starts now sit in a group under the session
|
|
9
|
+
that started it, with a pill that sums up what runs and what waits for you,
|
|
10
|
+
and rows drag into, out of and within a group. Settings › Sharing lists every
|
|
11
|
+
shared link with Copy, Renew and Stop and an access log of each open (the IP
|
|
12
|
+
address optional), shared views hide the host's paths in one of three modes,
|
|
13
|
+
**Preview as shared** shows what a viewer gets, and a 🙈 list gathers the
|
|
14
|
+
messages hidden from viewers. The relay is harder to reach from outside: ten
|
|
15
|
+
wrong tokens lock an address out for a minute, the live channel accepts only
|
|
16
|
+
the relay's own origin, forwarded headers count only from a trusted proxy, and
|
|
17
|
+
`?token=` signs in the page only. Day/Night is back in the ⋯ menu, next to the
|
|
18
|
+
new **About OAR**.
|
|
19
|
+
|
|
20
|
+
### Upgrade notes
|
|
21
|
+
|
|
22
|
+
- **Behind a reverse proxy on another host or origin, set `trustProxy` and
|
|
23
|
+
`allowedOrigins`.** This is the first release that checks the origin of the
|
|
24
|
+
live Socket.IO channel and that reads the client address, host and scheme
|
|
25
|
+
from `X-Forwarded-*` headers only when the proxy is trusted. A proxy on the
|
|
26
|
+
relay host itself is trusted already (`trustProxy` defaults to
|
|
27
|
+
`"loopback"`). For one on another machine, or one that rewrites the `Host`
|
|
28
|
+
header, add to the config file (`~/.oar/config.json`, or `server/config.json`
|
|
29
|
+
in a git checkout) and restart the relay:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
"trustProxy": "192.0.2.10",
|
|
33
|
+
"allowedOrigins": ["https://relay.example.com"]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`trustProxy` takes what Express's `trust proxy` takes: the proxy's address,
|
|
37
|
+
a subnet such as `"10.0.0.0/8"`, or a hop count such as `1`.
|
|
38
|
+
`allowedOrigins` lists the public origins exactly as the browser shows them
|
|
39
|
+
(scheme, host, a port other than the default). Without them, the page loads
|
|
40
|
+
but its live connection is refused (the relay logs `Refused a handshake from
|
|
41
|
+
origin …`), and every client shares the proxy's address, so one client's
|
|
42
|
+
ten wrong tokens lock the rest out for a minute.
|
|
43
|
+
- **Ten wrong tokens from one address within a minute answer `429`** with
|
|
44
|
+
`Retry-After` until the minute is over. Requests from the relay host itself
|
|
45
|
+
that no proxy forwarded are never counted.
|
|
46
|
+
- **`?token=` works on the page address only.** Scripts that fetch API, file
|
|
47
|
+
or asset URLs with `?token=` must send `Authorization: Bearer <token>`
|
|
48
|
+
instead (or the cookie); a Socket.IO client passes it as `auth.token` (or
|
|
49
|
+
the cookie), not in the query.
|
|
50
|
+
- **Restart web relay, cancelling a queued restart and Empty queue need only
|
|
51
|
+
the token**, from any signed-in device. The session-worker socket and the
|
|
52
|
+
image-operation run answer only requests from the relay host that no tunnel
|
|
53
|
+
or proxy forwarded.
|
|
54
|
+
- Four database migrations (0013 previews, 0014 session groups, 0015 the place
|
|
55
|
+
in a group, 0016 the share access log) run by themselves on the first
|
|
56
|
+
start. The Node.js requirement is unchanged (22.13 or newer).
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
- **Session groups in the sidebar.** A session that an agent starts with the
|
|
61
|
+
`remote_relay` tool now sits under the session that started it. The head
|
|
62
|
+
row carries a fold button and a pill that sums up the members ("3 · 1 waiting
|
|
63
|
+
for you, 2 running"); the members are indented under it, folded away once
|
|
64
|
+
everything in the group has finished unless you fold or unfold it yourself.
|
|
65
|
+
A question or approval waiting in a folded member shows on the head row,
|
|
66
|
+
and a tap on it opens that member. A member's activity lifts the whole
|
|
67
|
+
group to the top of the list. The head row's menu archives the whole group
|
|
68
|
+
(members still working are kept and named) and stops everything running in
|
|
69
|
+
it, and dissolves it; any row's menu adds a conversation to a group,
|
|
70
|
+
moves it, or takes it out, and groups can be named by hand. The `remote_relay` tool's
|
|
71
|
+
`list_sessions` and `read_session` show the group a session is in (agents
|
|
72
|
+
only read it). Migration 0014 adds the `conversation_groups` table and the
|
|
73
|
+
`group_id` column; nothing is backfilled.
|
|
74
|
+
- **Drag and drop for session groups.** Drag a session into a group, out of
|
|
75
|
+
it, or to another place inside it; the order you set stays, and later
|
|
76
|
+
arrivals join at the end. Drop one loose session onto the middle of another
|
|
77
|
+
and the two make a new group. On a phone a long press lifts the row and a
|
|
78
|
+
move drags it; with the keyboard, a member's menu has "Move up" and "Move
|
|
79
|
+
down". Migration 0015 adds the `group_position` column. Rolling back needs
|
|
80
|
+
no data change: older releases ignore the column, and a stale place they
|
|
81
|
+
leave behind is cleared when this release starts again.
|
|
82
|
+
- **A 🙈 list of the messages hidden from shared viewers.** Next to 📍, a 🙈
|
|
83
|
+
button with a count appears while the open conversation hides messages
|
|
84
|
+
from its shared link (never in the shared view itself). It opens a list
|
|
85
|
+
like the pinned one: each row jumps to its message, also one far up in the
|
|
86
|
+
history, and has Unhide; "Unhide all" asks first and leaves only a message
|
|
87
|
+
whose turn is still running hidden, naming it. The count and the list cover
|
|
88
|
+
messages outside the loaded page, and other open tabs and devices follow a
|
|
89
|
+
change without a reload.
|
|
90
|
+
- **Manage your shared links in Settings › Sharing.** Every shared
|
|
91
|
+
conversation is listed with when it was shared and last opened, how often
|
|
92
|
+
and by how many viewers. **Copy link** copies it, **Renew link** gives the
|
|
93
|
+
conversation a new link (the old one stops working at once), and **Stop
|
|
94
|
+
sharing** ends it; the `⋯` menu has **Stop sharing** too while the open
|
|
95
|
+
conversation is shared, and asks first. Each row unfolds into an access
|
|
96
|
+
log: one entry per open of the page (not per refresh) with time, IP
|
|
97
|
+
address, country and browser. The log carries over to a renewed link and
|
|
98
|
+
is deleted when you stop sharing or delete the conversation. Switch off
|
|
99
|
+
**Store viewer IP addresses** to log new opens without the address (the
|
|
100
|
+
status log of shared reads follows it); switching it off also offers to
|
|
101
|
+
remove the addresses already stored, from both logs. Distinct viewers are
|
|
102
|
+
still told apart. Migration 0016 adds the share lineage and the
|
|
103
|
+
`conversation_share_opens` table.
|
|
104
|
+
- **Preview as shared.** The `⋯` menu's new entry opens the conversation as
|
|
105
|
+
a share link shows it, without creating one: what viewers get instead of a
|
|
106
|
+
path is marked green, whatever still looks like a path amber.
|
|
107
|
+
- **Sub-agent records in shared views.** A sub-agent's row in a shared
|
|
108
|
+
conversation now opens its record, read-only and without Stop, filtered
|
|
109
|
+
like the rest of the share.
|
|
110
|
+
|
|
111
|
+
- **Wrong tokens lock an address out for a minute.** Ten wrong tokens from
|
|
112
|
+
one address within a minute (a Bearer header, the cookie, the sign-in field
|
|
113
|
+
or a Socket.IO handshake) make the relay answer that address `429` with
|
|
114
|
+
`Retry-After` until the minute is over, the right token included, and the
|
|
115
|
+
sign-in page says how long to wait. The same stale value repeated counts
|
|
116
|
+
once, so a tab with an old cookie does not lock you out. Requests from the
|
|
117
|
+
relay host itself that no proxy forwarded are never locked out, so the
|
|
118
|
+
relay's own workers and agent tools keep working.
|
|
119
|
+
- **About OAR in the ⋯ menu.** A new entry, "ℹ️ About OAR · <version>",
|
|
120
|
+
opens what this relay is and has done: version, commit (for a git
|
|
121
|
+
checkout) and when the relay started; each provider that is on, with its
|
|
122
|
+
CLI and SDK version and whether it is online; conversations, turns and
|
|
123
|
+
messages since the first conversation, turns per provider, and the usage
|
|
124
|
+
the providers report (Copilot premium requests, Cursor and Grok tokens and
|
|
125
|
+
cost, Claude Cloud cost); uptime, database size and running workers. With
|
|
126
|
+
the opt-in update check on it names the latest version, otherwise it says
|
|
127
|
+
where to turn the check on. Shared viewers do not get the entry. The data
|
|
128
|
+
comes from the new `GET /api/about`, which counts large databases in small
|
|
129
|
+
steps and keeps the totals for a minute.
|
|
130
|
+
|
|
131
|
+
### Changed
|
|
132
|
+
|
|
133
|
+
- **A stopped or renewed share link answers a plain 404**, the page included,
|
|
134
|
+
exactly like a link that never existed, and a shared page that is still open
|
|
135
|
+
stops at its next refresh instead of polling on. The address in the access
|
|
136
|
+
log and in the status log of shared reads is now the one the relay trusts
|
|
137
|
+
through its `trustProxy` setting; a forwarded header from an untrusted peer
|
|
138
|
+
no longer sets it.
|
|
139
|
+
|
|
140
|
+
- **A share link no longer carries the relay host's paths.** The relay
|
|
141
|
+
filters what it serves to shared viewers, by **Paths and file names** in
|
|
142
|
+
Settings › Sharing: show every path, hide the path and keep the file name
|
|
143
|
+
(the default), or hide both. Tool lines, thoughts, replies, attachments and sub-agent records all
|
|
144
|
+
pass through it; before, only the viewer's browser shortened the paths in
|
|
145
|
+
tool lines, and attachments carried their full path on the host. Free text
|
|
146
|
+
is filtered on a best-effort basis: relative paths are left as they are.
|
|
147
|
+
|
|
148
|
+
- **A long press on a sidebar row opens its menu when the finger lifts**, no
|
|
149
|
+
longer while it is still down: a long press that then moves drags the row
|
|
150
|
+
instead. Where rows cannot move (the Archived view, under a filter, on a
|
|
151
|
+
group's own line) the menu still opens during the press.
|
|
152
|
+
|
|
153
|
+
- **A reply to another agent's note is no longer folded away.** Only the
|
|
154
|
+
note itself folds into its row now, "note from linux-test · report builder ·
|
|
155
|
+
answered below"; the session's reply to it always shows, like a reply to
|
|
156
|
+
you, because it may hold a line for you. A turn you steered a message into
|
|
157
|
+
folds its note too, since nothing of yours is behind the row any more. The
|
|
158
|
+
⌄ button's badge counts the note and the reply as two rows.
|
|
159
|
+
|
|
160
|
+
- **A conversation no longer scrolls down by itself while you read further
|
|
161
|
+
up.** It only moves when you are at its end, or when you have just sent a
|
|
162
|
+
message yourself. Anywhere else it stays exactly where it is, whatever
|
|
163
|
+
lands: a reply, a relay event, another agent's note, a question, an approval
|
|
164
|
+
or a plan board. The ⌄ button then tells you: it turns blue with a count
|
|
165
|
+
(or a dot while a reply is still being written) when something new is
|
|
166
|
+
below, and amber with a "?" when a question or an approval waits for your
|
|
167
|
+
answer; a screen reader hears both. The text you are reading also keeps its
|
|
168
|
+
place when the reply you are in the middle of is finished and when the
|
|
169
|
+
conversation reloads. New in Settings › General: "Jump to the end when I
|
|
170
|
+
send a message", on by default and saved in the browser; switch it off and
|
|
171
|
+
your own messages leave you where you are as well.
|
|
172
|
+
|
|
173
|
+
- The npm package guard allows 7.25 MiB unpacked and 490 entries (was 6.75
|
|
174
|
+
MiB and 450); session groups, the stored previews, the background-task
|
|
175
|
+
resync, the transcript anchor, share management, path privacy in shared
|
|
176
|
+
views and About OAR grew the server and the app to about 7.05 MiB and 485
|
|
177
|
+
entries.
|
|
178
|
+
|
|
179
|
+
- **Restart web relay, cancelling a queued restart and Empty queue work from
|
|
180
|
+
every signed-in device.** They were meant for the relay host only, but the
|
|
181
|
+
check let everything through a tunnel or a proxy on the same machine and
|
|
182
|
+
refused only a direct LAN connection; they now need the token and nothing
|
|
183
|
+
else. The other way round, the session-worker socket and the image-operation
|
|
184
|
+
run now answer only requests from the relay host itself: a loopback peer
|
|
185
|
+
with no `cf-ray` or other tunnel marker and no `X-Forwarded-For`,
|
|
186
|
+
`Forwarded` or `X-Real-IP`. A same-host proxy that adds no marker no longer
|
|
187
|
+
reaches them.
|
|
188
|
+
|
|
189
|
+
- **A `?token=` signs in the page only.** The page takes it out of the address
|
|
190
|
+
and signs in with it as before; API, file and asset URLs now accept the
|
|
191
|
+
token in the `Authorization` header or the cookie only, and a Socket.IO
|
|
192
|
+
handshake no longer reads a `token` query.
|
|
193
|
+
|
|
194
|
+
- **The live Socket.IO channel accepts the relay's own origin only** (it
|
|
195
|
+
accepted any). The host compared is the one the browser addressed,
|
|
196
|
+
`X-Forwarded-Host` included when a trusted proxy sends it; for a proxy that
|
|
197
|
+
rewrites the `Host` header, list the public origin in the new
|
|
198
|
+
`allowedOrigins` setting.
|
|
199
|
+
|
|
200
|
+
### Fixed
|
|
201
|
+
|
|
202
|
+
- **Day/Night is back in the ⋯ menu.** Since 0.9.10 the entry showed only in
|
|
203
|
+
a shared view; everywhere else, on every screen size, it was gone from the
|
|
204
|
+
menu. It is there again whenever you are signed in, with or without a
|
|
205
|
+
conversation open, and stays the one entry of a shared view.
|
|
206
|
+
|
|
207
|
+
- **A shared conversation no longer marks every reply "ran on" its own
|
|
208
|
+
provider.** In a shared link to a Claude, Cursor, Grok or OpenAI
|
|
209
|
+
conversation, each reply carried the red `ran on claude` (etc.) chip, as if
|
|
210
|
+
the turn had run on the wrong provider. The shared view now knows which
|
|
211
|
+
provider the conversation is bound to, and shows the chip only when a reply
|
|
212
|
+
really ran on another one; with no provider bound it shows none.
|
|
213
|
+
|
|
214
|
+
- **A wide table in the file reader scrolls sideways.** A markdown table wider
|
|
215
|
+
than the reader made the whole page scroll sideways, and a sideways swipe to
|
|
216
|
+
read the rest of it turned to the next file instead. The table now scrolls
|
|
217
|
+
in its own box, as code blocks do; a swipe that starts on it stays in the
|
|
218
|
+
file.
|
|
219
|
+
|
|
220
|
+
- **A worker no longer stops reconnecting after a relay restart.** On Node
|
|
221
|
+
22, a worker whose reconnect reached a relay that was not ready yet gave up
|
|
222
|
+
for good: its process kept running without a connection, the relay started
|
|
223
|
+
no new one while that process lived, and every message to the session
|
|
224
|
+
stayed queued until the worker was killed and launched by hand. A failed
|
|
225
|
+
connect now always leads to the next attempt, with the usual backoff of up
|
|
226
|
+
to 8 seconds. As a safety net, the relay replaces a worker that has had no
|
|
227
|
+
connection for 60 seconds while a message waits for it: it stops the old
|
|
228
|
+
process and starts a new one, which then takes the message. It never does
|
|
229
|
+
so while a turn or background work of that session is running, and logs a
|
|
230
|
+
`WORKER DETACHED` line when it does.
|
|
231
|
+
|
|
232
|
+
- **A relay restart no longer forgets running background tasks.** A session
|
|
233
|
+
with a background shell or sub-agent still running read as idle after the
|
|
234
|
+
relay restarted: its task panel was empty, **Suspend host** saw nothing
|
|
235
|
+
to wait for, and a watching session could be told `all_idle`. The relay
|
|
236
|
+
now asks each worker for its tasks again on the worker's next heartbeat,
|
|
237
|
+
and the tasks come back with their original start time. A session whose
|
|
238
|
+
worker was started before this update shows "background work, details not
|
|
239
|
+
reported since the relay restarted" until it reports. For the first 45
|
|
240
|
+
seconds after a relay start a suspend waits for sessions that are still
|
|
241
|
+
reporting, and a task that ended while the relay was away still reports
|
|
242
|
+
its end.
|
|
243
|
+
|
|
244
|
+
- **Workers start when no `node` is on the relay's PATH.** A relay started
|
|
245
|
+
by the Windows system-startup task, before anyone signed in, ran fine, but
|
|
246
|
+
none of its workers ever started: they were launched with a bare `node`
|
|
247
|
+
that the task's PATH did not have, Windows reported the failure in a
|
|
248
|
+
dialog no one could see, and the log showed only a heartbeat timeout
|
|
249
|
+
every 90 seconds. Workers now run on the relay's own Node by its full path
|
|
250
|
+
on every platform, tmux included; `COPILOT_WEB_RELAY_NODE` still overrides
|
|
251
|
+
it. That Node's folder is added at the end of a worker's PATH when the PATH
|
|
252
|
+
lacks it, so the CLIs and commands a worker starts find a `node` too; a
|
|
253
|
+
PATH that has one keeps it.
|
|
254
|
+
|
|
255
|
+
- **A worker that cannot be started says why.** On Windows, a launch whose
|
|
256
|
+
`start` command fails or never returns now fails at once, naming the
|
|
257
|
+
program, and the conversation's launch note shows it; before, the relay
|
|
258
|
+
waited for a heartbeat that never came. The relay log names the command
|
|
259
|
+
and the PATH, SystemRoot and ComSpec it was started with, also when a
|
|
260
|
+
launch saw no worker process yet, and a failed process-list read logs its
|
|
261
|
+
exit code and error output. Windows' own programs (PowerShell, schtasks,
|
|
262
|
+
taskkill and others) are called by their full path. Changing the launch
|
|
263
|
+
folder and the Windows autostart setting show the relay's reason when they
|
|
264
|
+
fail, not a bare "Failed to …", and an autostart read that fails is logged.
|
|
265
|
+
|
|
266
|
+
- **The Windows system-startup launcher copes with an early boot.** The
|
|
267
|
+
launcher OAR generates adds Node's folder at the end of PATH and waits up
|
|
268
|
+
to two minutes for the `%TEMP%` folder to exist before it starts the relay
|
|
269
|
+
(a temp folder on a drive that a startup script creates later no longer
|
|
270
|
+
makes the relay and its CLIs fail); a wait that runs out is logged next to
|
|
271
|
+
the launcher. Settings now names how a boot task or launcher differs from
|
|
272
|
+
the generated one (a missing boot delay, an edited launcher) instead of
|
|
273
|
+
treating it as a failure; selecting "At system startup" again regenerates
|
|
274
|
+
both and keeps a changed launcher as a `.bak` copy. A boot task that cannot
|
|
275
|
+
be read no longer breaks the setting.
|
|
276
|
+
|
|
277
|
+
- **Preview links survive a relay restart.** A preview lived only in the
|
|
278
|
+
relay's memory, so an update, a queued restart or a crash turned every
|
|
279
|
+
preview link into a 404, and publishing again gave a new link. Previews are
|
|
280
|
+
now kept in the relay's database and restored when it starts, each checked
|
|
281
|
+
again: a folder preview while its folder is still inside the workspace root,
|
|
282
|
+
a dev-server preview until the machine reboots (on Windows with fast
|
|
283
|
+
startup, until a Restart: Shut down and power-on is not seen as one).
|
|
284
|
+
Publishing the same port or folder again in a conversation returns the same
|
|
285
|
+
link. Deleting a conversation, also through a cache rebuild, closes its
|
|
286
|
+
previews; archiving keeps them. Settings → Previews shows when each preview
|
|
287
|
+
was published and last opened, and the limit of 8 names the oldest ones and
|
|
288
|
+
how to close them. Relay logs no longer carry a preview's token; a publicly
|
|
289
|
+
shared transcript shows a preview card with its label only and removes every
|
|
290
|
+
preview link quoted in its text, also one cut short by a reply still being
|
|
291
|
+
written. A preview the relay cannot check at a start (a busy database, an
|
|
292
|
+
unreadable folder) is not served, shows as such in Settings, and is checked
|
|
293
|
+
again every 15 s for ten minutes. The table comes with migration 0013, which
|
|
294
|
+
runs by itself on the first start; the npm package gains two modules for it.
|
|
295
|
+
|
|
296
|
+
- **An install gets the dependency versions the release was tested with.**
|
|
297
|
+
The package asked for each of its dependencies "this version or newer", so
|
|
298
|
+
an install or update fetched whatever was newest that day, e.g. a newer
|
|
299
|
+
Copilot SDK than any release was tested with. The packages OAR depends on
|
|
300
|
+
directly (the Claude, Copilot and Cursor SDKs among them) are now pinned to
|
|
301
|
+
exact versions; a newer one arrives with an OAR update. Packages those
|
|
302
|
+
depend on still follow their own version ranges.
|
|
303
|
+
|
|
304
|
+
- **Restart web relay no longer reports success when the relay refuses it.**
|
|
305
|
+
A refused request said "Relay restart requested"; it now shows the relay's
|
|
306
|
+
reason, and a request that got no answer says so instead of claiming
|
|
307
|
+
success. The restart after a feature-flag change and cancelling a queued
|
|
308
|
+
restart report their errors the same way, and Empty queue names the reason
|
|
309
|
+
it failed.
|
|
310
|
+
|
|
311
|
+
- **Forwarded headers count only from a trusted proxy everywhere.** The
|
|
312
|
+
shared-view presence limit read `X-Forwarded-For` and `X-Real-IP` and the
|
|
313
|
+
share links read `X-Forwarded-Host` and `X-Forwarded-Proto` straight from the
|
|
314
|
+
request, so a direct client could pick its own rate-limit bucket or the
|
|
315
|
+
host of a new share link. Both now follow the `trustProxy` setting.
|
|
316
|
+
|
|
317
|
+
- **`tunnelMarkerHeaders: []` in the config no longer switches off
|
|
318
|
+
`COPILOT_TUNNEL_MARKER_HEADERS`.** The two lists are merged, with `cf-ray`
|
|
319
|
+
always included.
|
|
320
|
+
|
|
321
|
+
## [0.9.10] — 2026-10-12
|
|
322
|
+
|
|
323
|
+
Highlights: sessions watch other sessions. An agent subscribes to sessions on
|
|
324
|
+
its own relay or on a paired one and is woken by what happens there:
|
|
325
|
+
questions waiting for an answer, errors, replies, finished background work,
|
|
326
|
+
sessions gone quiet. A subscription only notifies; it approves nothing, and
|
|
327
|
+
the first one in a conversation asks you on a card. Also new: a sub-agent's
|
|
328
|
+
whole record opens in a viewer, a note between agents and its reply fold into
|
|
329
|
+
one row, `remote_relay` reports what the provider plans have left, the file
|
|
330
|
+
browser creates, renames and deletes folders and files, a ⌄ button jumps back
|
|
331
|
+
to the latest message, archiving an active session asks first, and Settings
|
|
332
|
+
opens with no conversation open.
|
|
333
|
+
|
|
334
|
+
### Upgrade notes
|
|
335
|
+
|
|
336
|
+
- **Running sessions pick up the new tools when their worker restarts.** A
|
|
337
|
+
session worker builds its `remote_relay` tool when it starts, so a worker
|
|
338
|
+
that was already running before the update offers neither `subscribe` nor
|
|
339
|
+
`usage`, and records no sub-agent timeline, until it is restarted: **☠️
|
|
340
|
+
Kill session** on an idle session is enough, the next message starts a new
|
|
341
|
+
worker. The database migrations run by themselves on the first start.
|
|
342
|
+
|
|
343
|
+
### Added
|
|
344
|
+
|
|
345
|
+
- **A session can watch other sessions and be woken by what happens there.**
|
|
346
|
+
With `remote_relay`'s new `subscribe` an agent asks to be told about
|
|
347
|
+
questions waiting for an answer, errors (a failed turn, the usage limit, a
|
|
348
|
+
worker that died), replies, background agents and shell tasks that finish
|
|
349
|
+
or fail, sessions that went quiet while working, and the moment nothing
|
|
350
|
+
runs any more, for listed sessions or all of them. OAR writes a short event
|
|
351
|
+
message into the watcher's conversation: a new turn when it is idle, a
|
|
352
|
+
steer into the running turn where the provider steers, the next turn
|
|
353
|
+
otherwise. The message says it is automated and approves nothing, and shows
|
|
354
|
+
as a compact row, never as one of your messages. Events within 30 s come
|
|
355
|
+
together; past 20 wake-ups an hour the rest comes as a digest every ten
|
|
356
|
+
minutes, while questions and errors still come at once. An optional
|
|
357
|
+
heartbeat says the watching works while anything runs. Subscriptions
|
|
358
|
+
survive a restart and end on unsubscribe, when the watcher or the watched
|
|
359
|
+
session is archived, or after firing once. The first subscribe of a
|
|
360
|
+
conversation, and any to all sessions, asks you on an approval card;
|
|
361
|
+
`transfer_subscriptions` hands every subscription of an old watcher to a
|
|
362
|
+
new one after your approval. The watcher's header shows **watching N
|
|
363
|
+
sessions** with an Unsubscribe button per subscription, and a watched
|
|
364
|
+
session shows a **watched** badge.
|
|
365
|
+
|
|
366
|
+
- **Watch sessions on a paired relay.** `subscribe`, `unsubscribe`,
|
|
367
|
+
`list_subscriptions` and `transfer_subscriptions` also take a paired
|
|
368
|
+
relay, with the same events and options. The relay must be unlocked in
|
|
369
|
+
the conversation and allow at least reading, and the other relay must
|
|
370
|
+
accept other relays' agents; the approval card names that relay, and
|
|
371
|
+
nothing is asked there. This relay fetches the events every few seconds
|
|
372
|
+
over the pairing (a pairing in one direction is enough), and they arrive
|
|
373
|
+
like those of its own sessions, their lines starting with the relay's
|
|
374
|
+
name. If the link drops, the other relay keeps what happens (up to 500
|
|
375
|
+
events per subscription, for 7 days) and delivers it as one row tagged
|
|
376
|
+
**replayed** once it answers again, questions and errors first, between
|
|
377
|
+
"link lost" and "link restored". Subscriptions survive restarts of either
|
|
378
|
+
relay and end on unsubscribe (reaching the other relay later if it was
|
|
379
|
+
offline), when the watcher or the watched session is archived, or when
|
|
380
|
+
the pairing is removed. An older relay answers that it needs an update.
|
|
381
|
+
|
|
382
|
+
- **list_sessions and read_session say what a session is doing.** `state`
|
|
383
|
+
is `running_turn`, `background_only` or `idle`, and `tasks` lists its
|
|
384
|
+
background agents and shell tasks with when they started, when they last
|
|
385
|
+
did something, how they ended and the exit code where it is known. A
|
|
386
|
+
session with background agents running no longer reads as inactive.
|
|
387
|
+
|
|
388
|
+
- **Agents can check what the provider plans have left.** `remote_relay`'s
|
|
389
|
+
new `usage` action answers, for the relay an agent runs on or a paired
|
|
390
|
+
one, what each provider's plan has left: Cursor's spend against its
|
|
391
|
+
limit and when it resets, Claude's windows and whether a usage limit has
|
|
392
|
+
paused turns, Copilot and Grok where they are tracked; a provider that is
|
|
393
|
+
not set up says so. It needs only read permission and returns no account
|
|
394
|
+
names, addresses or tokens.
|
|
395
|
+
|
|
396
|
+
- **Notes between agents fold away.** A prompt another agent sent a
|
|
397
|
+
session, from a paired relay or from this one, and the session's reply to
|
|
398
|
+
it show as one row, "note from linux-test · report builder · replied",
|
|
399
|
+
which opens to both, on a desktop and on a phone. Your own messages and
|
|
400
|
+
the replies to them stay as they are, and a turn you steered a message
|
|
401
|
+
into, or one with a question or card open for you, is never folded. A
|
|
402
|
+
note still being worked on stays open and folds by itself once it is
|
|
403
|
+
answered; one you fold or open yourself stays as you left it.
|
|
404
|
+
|
|
405
|
+
- **Open a sub-agent's whole record.** A sub-agent's title in the composer's
|
|
406
|
+
background-task panel opens a viewer with everything the agent did, in
|
|
407
|
+
order: its thoughts, every tool call with its full input and its result,
|
|
408
|
+
its reply text and the agents it started itself, live while it runs. The
|
|
409
|
+
finished reply lists the turn's sub-agents as the same rows, with model,
|
|
410
|
+
type, tokens, time and how they ended, so the record stays one click away.
|
|
411
|
+
A child agent opens in place, and back returns to its parent. Stop is in
|
|
412
|
+
the viewer too. Claude records everything; Copilot and Cursor show what
|
|
413
|
+
they report. A tool result is kept to its first 4 KB, and a record to 2000
|
|
414
|
+
entries. Only a page with the viewer open receives the record as it grows.
|
|
415
|
+
|
|
416
|
+
- **Choose how long sub-agent tool output is kept.** Settings → General →
|
|
417
|
+
**Keep sub-agent tool output** offers 7, 14, 30 or 90 days (the default)
|
|
418
|
+
or always. Once a finished agent's record is older than that, its tool
|
|
419
|
+
inputs and results are removed, once a day; its thoughts, its reply, its
|
|
420
|
+
notes and the one-line summary of each tool call stay, and the viewer says
|
|
421
|
+
what was removed.
|
|
422
|
+
|
|
423
|
+
- **Folders can be created in the file browser.** A **📁+ New folder**
|
|
424
|
+
button in the toolbar opens a row at the top of the folder pane; the name
|
|
425
|
+
is typed there and Enter creates the folder inside the open one and opens
|
|
426
|
+
it. It works in the repository, on the drives and in the session folder,
|
|
427
|
+
and in the folder picker of **New chat** and **Change CWD**, so a new
|
|
428
|
+
project folder can be made and picked in one go. A taken name or a name
|
|
429
|
+
the system refuses is reported under the input.
|
|
430
|
+
|
|
431
|
+
- **Files and folders can be renamed and deleted in the file browser.** A
|
|
432
|
+
right-click, or a long press on a phone, on a folder in the tree or a file
|
|
433
|
+
in the folder pane opens a menu with **Rename** and **Delete**; a folder's
|
|
434
|
+
menu also offers **New folder here**. Rename edits the name in place: Enter
|
|
435
|
+
saves, Escape cancels, and an unchanged name is a cancel. Delete asks in a
|
|
436
|
+
dialog that says what goes: a file, an empty folder, or a folder with so
|
|
437
|
+
many files and folders in it; for a folder with content the folder's name
|
|
438
|
+
must be typed before the red button enables. Links are never followed or
|
|
439
|
+
changed; roots (the repository root, `/`, a drive, the session folder)
|
|
440
|
+
cannot be renamed or deleted, and the session folder is read-only apart
|
|
441
|
+
from new folders.
|
|
442
|
+
|
|
443
|
+
- **Jump back to the latest message.** A round ⌄ button above the composer
|
|
444
|
+
fades in once the transcript is about a screen above its end, and its
|
|
445
|
+
badge counts the rows that arrived since (an agent's folded exchange
|
|
446
|
+
counts once). A click goes back to the end, smoothly up to three screens
|
|
447
|
+
away and at once beyond, and the transcript follows new rows again; from
|
|
448
|
+
a search result or a pin deep in the history it loads the end.
|
|
449
|
+
|
|
450
|
+
### Changed
|
|
451
|
+
|
|
452
|
+
- **Archiving a session whose process is still active asks first.** A green
|
|
453
|
+
session, idle or working, now opens "Archive this session? Its process is
|
|
454
|
+
still active." from the row's 🗄, its menu and the chat menu alike; Cancel
|
|
455
|
+
or Escape keeps it. An inactive session archives at once, as before.
|
|
456
|
+
|
|
457
|
+
- **A message from another device no longer pulls a reader who scrolled up
|
|
458
|
+
down to the end.** Another client's message, an agent's prompt included,
|
|
459
|
+
is followed like any live row: only while the transcript is at its end.
|
|
460
|
+
|
|
461
|
+
- The npm package guard allows 6.75 MiB unpacked (was 6.5 MiB); the
|
|
462
|
+
sub-agent records and the event subscriptions, now across paired relays,
|
|
463
|
+
grew the server.
|
|
464
|
+
|
|
465
|
+
### Fixed
|
|
466
|
+
|
|
467
|
+
- **A dropped websocket can no longer take the relay down.** A browser that
|
|
468
|
+
reset its connection while a preview's websocket, or any websocket to the
|
|
469
|
+
relay, was still being set up ended the whole relay with `read ECONNRESET`.
|
|
470
|
+
|
|
471
|
+
- **A queued relay restart no longer waits forever on a busy relay.** The
|
|
472
|
+
restart used to wait for the whole queue to empty while new messages kept
|
|
473
|
+
being handed to workers, so each new turn postponed it again. It now waits
|
|
474
|
+
for the running turns only; queued messages are held until the relay is
|
|
475
|
+
back and run then. The banner says which.
|
|
476
|
+
|
|
477
|
+
- **Waking from sleep no longer restarts the running turns.** After the host
|
|
478
|
+
slept for hours, every worker heartbeat looked hours old the moment the
|
|
479
|
+
relay's timer fired again, so live turns were recovered as stale and their
|
|
480
|
+
messages delivered a second time while the workers' own replies were
|
|
481
|
+
refused, hundreds of warnings in minutes. The relay now notices the clock
|
|
482
|
+
jump and gives live workers a full inactivity window to report before
|
|
483
|
+
anything is recovered; a superseded attempt's refusals are logged once and
|
|
484
|
+
summarized, not line by line.
|
|
485
|
+
|
|
486
|
+
- **A Cursor turn waiting on a long command is no longer ended as stalled.**
|
|
487
|
+
When the agent started a command in the background and then waited for
|
|
488
|
+
it, the wait counted as a model request, and the turn was ended after five
|
|
489
|
+
minutes of quiet. The wait now gets the 30 minutes a running tool gets.
|
|
490
|
+
|
|
491
|
+
- **An event's fields cannot add lines to a watcher's event message.** A
|
|
492
|
+
line break in a session title, a task description or a field of a paired
|
|
493
|
+
relay's event could start a line without the `[relay event]` prefix. Every
|
|
494
|
+
field is now written as one line, and what a paired relay sends is stored
|
|
495
|
+
field by field from a fixed list, never as the payload it sent.
|
|
496
|
+
|
|
497
|
+
- **The relay event tables no longer grow without bound.** Delivered events
|
|
498
|
+
and ended subscriptions were never deleted, and the retention check for
|
|
499
|
+
paired relays scanned the whole event table every 30 seconds. Delivered
|
|
500
|
+
events now go after two hours (the wake-up count reads the last hour),
|
|
501
|
+
ended subscriptions after a week, and the check uses its index.
|
|
502
|
+
|
|
503
|
+
- **The "watching N sessions" list opens in full.** The header cut it off,
|
|
504
|
+
so on a phone it did not show at all. It now opens under the chip on top
|
|
505
|
+
of the page, and Escape or a tap elsewhere closes it.
|
|
506
|
+
|
|
507
|
+
- **Sub-agent runs a worker never closed no longer count as running work.**
|
|
508
|
+
A run whose worker went away without reporting its end stayed `running`
|
|
509
|
+
for good, so a subscription to all sessions never saw `all_idle` and
|
|
510
|
+
reported the session stalled over and over, and the suspend watchdog saw
|
|
511
|
+
work. Such runs are now closed shortly after the relay starts and every
|
|
512
|
+
ten minutes (never while their worker is alive), and a run row not touched
|
|
513
|
+
for a day is not counted meanwhile.
|
|
514
|
+
|
|
515
|
+
- **A background agent's output stays with the turn that started it.** Its
|
|
516
|
+
thoughts and tool calls no longer land in a later turn's reply, and between
|
|
517
|
+
turns they are no longer lost.
|
|
518
|
+
|
|
519
|
+
- **A background agent no longer shows as finished the moment it starts.**
|
|
520
|
+
Its row now ends when the agent does.
|
|
521
|
+
|
|
522
|
+
- **A sub-agent stopped by a failed turn or a worker crash settles on screen
|
|
523
|
+
without a reload.** The update used to arrive without its turn, and the
|
|
524
|
+
page ignored it.
|
|
525
|
+
|
|
526
|
+
- **The transcript keeps following the live reply when a background task
|
|
527
|
+
starts.** The task panel appearing, opening or growing shrank the
|
|
528
|
+
transcript from below and left it that much short of the end, so the next
|
|
529
|
+
live row stopped following. It now stays at the end.
|
|
530
|
+
|
|
531
|
+
- **The transcript follows the agent's reply as it streams in.** Each piece
|
|
532
|
+
of streamed text was scrolled to before it was shown, so the first new
|
|
533
|
+
line left the reader short of the end and the rest was not followed.
|
|
534
|
+
|
|
535
|
+
- **Going back to the end while a turn finishes sticks.** The reload at the
|
|
536
|
+
end of a turn put a reader back where they were when it was asked for, so
|
|
537
|
+
scrolling to the end, or pressing ⌄, during it was undone and the next
|
|
538
|
+
rows were not followed. It now keeps where the reader is when it lands.
|
|
539
|
+
|
|
540
|
+
- **⌄ no longer opens the keyboard on a phone.** The composer is no longer
|
|
541
|
+
focused when the page loads on a phone, and ⌄ keeps it focused only while
|
|
542
|
+
the keyboard is already open, so a tap on it just scrolls.
|
|
543
|
+
|
|
544
|
+
- **A message that arrives while the conversation reloads stays on screen.**
|
|
545
|
+
A reload asked for just before another client's message or a reply landed
|
|
546
|
+
rebuilt the transcript without it, until the next reload. The reload now
|
|
547
|
+
asks again when rows arrived on the way.
|
|
548
|
+
|
|
549
|
+
- **A message sent right after switching conversations shows up where it was
|
|
550
|
+
sent.** A quick run through the list, or a click back on the conversation
|
|
551
|
+
still open, could hand the view to an earlier click once the draft of the
|
|
552
|
+
conversation left behind had saved. The message then went to that
|
|
553
|
+
conversation, or its bubble and the live reply stayed hidden until the
|
|
554
|
+
conversation was opened again. A click now opens its conversation at once.
|
|
555
|
+
|
|
556
|
+
- **The live reply stays on screen right after a send.** A poll answer read
|
|
557
|
+
just before the agent took the message could end the turn on the page, and
|
|
558
|
+
a reply update lost on a busy connection left the bubble empty; both waited
|
|
559
|
+
for the conversation to be opened again.
|
|
560
|
+
|
|
561
|
+
- **Settings opens with no conversation open.** On a fresh install the ⋯
|
|
562
|
+
menu did nothing until a chat existed, so no provider could be turned on.
|
|
563
|
+
The menu now works on an empty screen, with the entries that need a
|
|
564
|
+
conversation left out, and the empty screen and New Chat point to
|
|
565
|
+
Settings → Providers until a provider is ready instead of starting a
|
|
566
|
+
Copilot chat that cannot run.
|
|
7
567
|
|
|
8
568
|
## [0.9.9] — 2026-10-07
|
|
9
569
|
|